diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/1c7c6fb2382a1ffb7303101cf049a745.svg b/1c7c6fb2382a1ffb7303101cf049a745.svg new file mode 100644 index 0000000000..41b65a6f33 --- /dev/null +++ b/1c7c6fb2382a1ffb7303101cf049a745.svg @@ -0,0 +1 @@ +Client(e.g. Node.js,MetaMask)Oasis Web3GatewayOasis NodeSapphireParaTime ClientOasis NodeSapphire ParaTimeCompute 🔒Oasis NodeKey Manager🔒R is cacheduntil the endof epochopt[Encrypt Transaction]opt[Encrypted Transaction]alt[EncryptedTransaction][UnencryptedTransaction]Proposer node addstransaction, state andreceipt in new blockWait for new blockopt[EncryptedTransaction-]Create transactioncall data1Get ephemeralpublic key R2Get ephemeralpublic key R3Get ephemeralpublic key R4Derive per-epochper-runtimekeypair R, R'5Ephemeral public key R6Ephemeralpublic key R7Ephemeralpublic key R8Generate X25519keypair C, C'9Derive shared keyK' = X25519(C', R)10Encrypt call datawith Deoxys-II usingshared key K'11Attach C12Sign transactionwith User'sSecp256k1/Ed25519key13eth_sendRawTx14eth_sendRawTx15Validatetransaction16eth_sendRawTx17Get ephemeralprivate key R'18Check runtimepolicy for caller19Derive per-epochper-runtimekeypair R, R'20Ephemeralprivate key R'21Derive shared keyK' = X25519(C, R')22Decrypt Deoxys-IIenvelope using K'23Get c10l contractstate keypair S, S'24Check runtimepolicy for caller25Derive per-contractper-runtimekeypair S, S'26Contract statekeypair S, S'27Fetch contract code28C10l contract executionusing S, S' to read andwrite storage29Obtain newstate root30Transaction receipt:encrypt tx status with K',unencrypted logs31Transaction receipt:unencrypted tx statusand logs32Transactionreceipt33Decrypt tx statusfrom receiptusing K'34Client(e.g. Node.js,MetaMask)Oasis Web3GatewayOasis NodeSapphireParaTime ClientOasis NodeSapphire ParaTimeCompute 🔒Oasis NodeKey Manager🔒 \ No newline at end of file diff --git a/275e2a9ae4c6d8823cf28823a9edad80.svg b/275e2a9ae4c6d8823cf28823a9edad80.svg new file mode 100644 index 0000000000..7e419a2cda --- /dev/null +++ b/275e2a9ae4c6d8823cf28823a9edad80.svg @@ -0,0 +1 @@ +Client(e.g. Node.js,MetaMask)Oasis Web3GatewayOasis NodeSapphireParaTime ClientOasis NodeSapphire ParaTimeCompute 🔒Oasis NodeKey Manager🔒R is cacheduntil the endof epochopt[Encrypt Call]opt[Sign Call]opt[Encrypted Call]opt[EncryptedCall]opt[EncryptedCall]Create calldata1Get ephemeralpublic key R2Get ephemeralpublic key R3Get ephemeralpublic key R4Derive per-epochper-runtimekeypair R, R'5Ephemeral public key R6Ephemeralpublic key R7Ephemeralpublic key R8Generate X25519keypair C, C'9Derive shared keyK' = X25519(C', R)10Encrypt call datawith Deoxys-II usingshared key K'11Attach C12Sign callwith User'sSecp256k1/Ed25519key13eth_call14eth_call15Validate call16eth_call17Get ephemeralprivate key R'18Check runtimepolicy for caller19Derive per-epochper-runtimekeypair R, R'20Ephemeralprivate key R'21Derive shared keyK' = X25519(C, R')22Decrypt Deoxys-IIenvelope using K'23Get c10l contractstate keypair S, S'24Check runtimepolicy for caller25Derive per-contractper-runtimekeypair S, S'26Contract statekeypair S, S'27Fetch contract code28C10l contract executionusing S, S' to readstorage29Encrypt callresult with K'30Call result31Call result32Call result33Decrypt call resultusing K'34Client(e.g. Node.js,MetaMask)Oasis Web3GatewayOasis NodeSapphireParaTime ClientOasis NodeSapphire ParaTimeCompute 🔒Oasis NodeKey Manager🔒 \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000000..70d60ddf37 --- /dev/null +++ b/404.html @@ -0,0 +1,16 @@ + + + + + +Page Not Found | Oasis Documentation + + + + +
+
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

+ + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000000..228470ff3b --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +docs.oasis.io diff --git a/ac606558d6f27b4be4291abfe7a419d1.svg b/ac606558d6f27b4be4291abfe7a419d1.svg new file mode 100644 index 0000000000..744bd64e51 --- /dev/null +++ b/ac606558d6f27b4be4291abfe7a419d1.svg @@ -0,0 +1 @@ +Jan 2021Mar 2021May 2021Jul 2021Sep 2021Nov 2021Jan 2022Mar 2022May 2022Jul 2022Sep 2022Nov 2022Jan 2023Mar 2023May 2023Jul 2023Sep 2023Nov 2023Jan 2024Mar 2024May 2024Jul 2024Sep 2024Nov 20240%2%4%6%8%10%12%14%16%18%20%Staking Rewards Schedule (time estimated from epoch interval)Estimated Annualized Rewards \ No newline at end of file diff --git a/adrs/0000-architectural-decision-records/index.html b/adrs/0000-architectural-decision-records/index.html new file mode 100644 index 0000000000..67e3df4558 --- /dev/null +++ b/adrs/0000-architectural-decision-records/index.html @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/adrs/0001-tm-multi-root-apphash/index.html b/adrs/0001-tm-multi-root-apphash/index.html new file mode 100644 index 0000000000..16f23fd47a --- /dev/null +++ b/adrs/0001-tm-multi-root-apphash/index.html @@ -0,0 +1,32 @@ + + + + + +ADR 0001: Multiple Roots Under the Tendermint Application Hash | Oasis Documentation + + + + +
+
Skip to main content

ADR 0001: Multiple Roots Under the Tendermint Application Hash

Component

Oasis Core

Changelog

  • 2020-08-06: Added consequence for state checkpoints
  • 2020-07-28: Initial version

Status

Accepted

Context

Currently the Tendermint ABCI application hash is equal to the consensus state +root for a specific height. In order to allow additional uses, like proving to +light clients that specific events have been emitted in a block, we should make +the application hash be derivable from potentially different kinds of roots.

Decision

The proposed design is to derive the Tendermint ABCI application hash by hashing +all the different roots as follows:

AppHash := H(Context || Root_0 || ... || Root_n)

Where:

  • H is the SHA-512/256 hash function.
  • Context is the string oasis-core/tendermint: roots.
  • Root_i is the fixed-size SHA-512/256 root hash of the specified root.

Currently, the only root would be the existing consensus state root at index 0.

To implement this change the following modifications would be required:

  • Update the ABCI multiplexer's Commit method to calculate and return the +application hash using the scheme specified above.

  • Update the consensus API SignedHeader response to include the +UntrustedStateRoot (the untrusted prefix denotes that the user must verify +that the state root corresponds to AppHash provided in the signed header in +Meta).

    When new roots will be added in the future, both Block and SignedHeader +will need to include them all.

Alternatives

The proposed design is simple and assumes that the number of additional roots is +small and thus can always be included in signed headers. An alternative scheme +would be to Merkelize the roots in a binary Merkle tree (like the one used for +our MKVS), but this would add complexity and likely require more round trips for +common use cases.

Consequences

Positive

  • This would open the path to including different kinds of provable data (e.g., +in addition to state) as part of any consensus-layer block.

Negative

  • As this changes the application hash, this would be a breaking change for the +consensus layer.

  • Since we are simply hashing all the roots together, all of them need to be +included in the signed headers returned to light clients.

Neutral

  • Consensus state checkpoints will need to contain data for multiple roots.

References

+ + + + \ No newline at end of file diff --git a/adrs/0002-go-modules-compatible-git-tags/index.html b/adrs/0002-go-modules-compatible-git-tags/index.html new file mode 100644 index 0000000000..6149b08c77 --- /dev/null +++ b/adrs/0002-go-modules-compatible-git-tags/index.html @@ -0,0 +1,51 @@ + + + + + +ADR 0002: Go Modules Compatible Git Tags | Oasis Documentation + + + + +
+
Skip to main content

ADR 0002: Go Modules Compatible Git Tags

Component

Oasis Core

Changelog

  • 2020-09-04: Initial version

Status

Accepted

Context

Projects that depend on Oasis Core's Go module, i.e. +github.com/oasisprotocol/oasis-core/go, need a way to depend on its particular +version.

Go Modules only allow Semantic Versioning 2.0.0 for +versioning of the modules which makes it hard to work +with Oasis Core's CalVer (calendar versioning) scheme.

The currently used scheme for Go Modules compatible Git tags is:

go/v0.YY.MINOR[.MICRO]

where:

  • YY represents the short year (e.g. 19, 20, 21, ...),

  • MINOR represents the minor version starting with zero (e.g. 0, 1, 2, +3, ...),

  • MICRO represents the final number in the version (sometimes referred to as +the "patch" segment) (e.g. 0, 1, 2, 3, ...).

    If the MICRO version is 0, it is omitted.

It turns out this only works for Oasis Core versions with the MICRO version +of 0 since the Go Modules compatible Git tag omits the .MICRO part and is +thus compatible with Go Modules versioning requirements.

Decision

The proposed design is to tag Oasis Core releases with the following Go Modules +compatible Git tags (in addition to the ordinary Git tags):

go/v0.YY0MINOR.MICRO

where:

  • YY represents the short year (e.g. 19, 20, 21, ...),
  • 0MINOR represents the zero-padded minor version starting with zero (e.g. +00, 01, 02, ..., 10, 11, ...),
  • MICRO represents the final number in the version (sometimes referred to as +the "patch" segment) (e.g. 0, 1, 2, 3, ...).

Here are some examples of how the ordinary and the corresponding Go Modules +compatible Git tags would look like:

VersionOrdinary Git tagGo Modules compatible Git tag
20.9v20.9go/v0.2009.0
20.9.1v20.9.1go/v0.2009.1
20.9.2v20.9.2go/v0.2009.2
20.10v20.10go/v0.2010.0
20.10.1v20.10.1go/v0.2010.1
20.10.2v20.10.2go/v0.2010.2
.........
21.0v21.0go/v0.2100.0
21.0.1v21.0.1go/v0.2100.1
21.0.2v21.0.2go/v0.2100.2
21.1v21.1go/v0.2101.0
21.1.1v21.1.1go/v0.2101.1
21.1.2v21.1.2go/v0.2101.2
.........

Using such a scheme makes the version of the Oasis Core Go module fully +compatible with the Go Modules versioning requirements and thus +enables users to use the familiar Go tools to check for new module versions, +i.e. go list -m -u all, or to obtain and require a module, i.e. +go get github.com/oasisprotocol/oasis-core/go@latest.

Alternatives

An alternative scheme would be to use the following Go Modules compatible Git +tags:

go/v0.YY.MINOR-MICRO

where:

  • YY represents the short year (e.g. 19, 20, 21, ...),
  • MINOR represents the minor version starting with zero (e.g. 0, 1, 2, +3, ...),
  • MICRO represents the final number in the version (sometimes referred to as +the "patch" segment) (e.g. 0, 1, 2, 3, ...).

Using the -MICRO suffix would make Go treat all such versions as a +Go Modules pre-release version.

The consequence of that would be that all Go tools would treat such versions as +pre-releases.

For example, let's say the Oasis Core Go module would have the following Go +version tags:

  • go/v0.20.9
  • go/v0.20.10-0
  • go/v0.20.10-1

and a module that depends on the Oasis Core Go module would currently require +version v0.20.9.

One downside would be that the go list -m -u all command would not notify a +user that an update, i.e. version v0.20.10-1, is available.

The second downside would be that using the +go get github.com/oasisprotocol/oasis-core/go@latest command would treat +version v0.20.9 as the latest version and download and require this version of +the Oasis Core Go module instead of the real latest version, v0.20.10-1 in +this example.

Consequences

Positive

  • This allow users to depend on a bugfix/patch release of the Oasis Core Go +module in a Go Modules versioning requirements compatible way, +i.e. without having to resort to pinning the requirement to a particular +Oasis Core commit.

Negative

  • The connection between an ordinary Git tag and a Go Modules compatible Git tag +is not very obvious.

    For example, it might not be immediately obvious that v21.0 and +go/v0.2100.0 refer to the same thing.

  • Using a zero-padded minor version fixed to two characters would limit the +number of releases in a year to 100 releases.

References

+ + + + \ No newline at end of file diff --git a/adrs/0003-consensus-runtime-token-transfer/index.html b/adrs/0003-consensus-runtime-token-transfer/index.html new file mode 100644 index 0000000000..e2b39a178a --- /dev/null +++ b/adrs/0003-consensus-runtime-token-transfer/index.html @@ -0,0 +1,130 @@ + + + + + +ADR 0003: Consensus/Runtime Token Transfer | Oasis Documentation + + + + +
+
Skip to main content

ADR 0003: Consensus/Runtime Token Transfer

Component

Oasis Core

Changelog

  • 2020-09-16: Beneficiary allowance, add message results
  • 2020-09-08: Initial draft

Status

Accepted

Context

Currently each runtime can define its own token (or none at all) and there is no +mechanism that would support transfer of consensus layer tokens into a runtime +and back out.

Introducing such a mechanism would allow the consensus layer tokens to be used +inside runtimes for various functions. This ADR proposes such a mechanism.

Decision

On a high level, this proposal adds support for consensus/runtime token +transfers as follows:

  • Each staking account can set an allowance for beneficiaries. Each staking +account can set an allowance, a maximum amount a beneficiary can withdraw from +the given account. Beneficiaries are identified by their address. This is +similar to approve/transferFrom calls defined by the ERC-20 Token Standard. +Previously such functionality was already present but was removed in +oasis-core#2021.

  • Each runtime itself has an account in the consensus layer. This account +contains the balance of tokens which are managed exclusively by the runtime +and do not belong to any specific regular account in the consensus layer.

    It is not possible to transfer directly into a runtime account and doing so +may result in funds to be locked without a way to reclaim them.

    The only way to perform any operations on runtime accounts is through the use +of messages emitted by the runtime during each round. These messages are +subject to discrepancy detection and instruct the consensus layer what to do.

Combined, the two mechanisms enable account holders to set an allowance in the +benefit of runtimes so that the runtimes can withdraw up to the allowed amount +from the account holder's address.

Addresses

This proposal introduces the following new address context for the runtime +accounts:

oasis-core/address: runtime

Initial version for the address context is 0. To derive the address, the +standard address derivation scheme is used, with the runtime's 32-byte +identifier used as the data part.

State

This proposal introduces/updates the following consensus state in the staking +module:

General Accounts

The general account data structure is modified to include an additional field +storing the allowances as follows:

type GeneralAccount struct {
// ... existing fields omitted ...

Allowances map[Address]quantity.Quantity `json:"allowances,omitempty"`
}

Transaction Methods

This proposal adds the following new transaction methods in the staking module:

Allow

Allow enables an account holder to set an allowance for a beneficiary.

Method name:

staking.Allow

Body:

type Allow struct {
Beneficiary Address `json:"beneficiary"`
Negative bool `json:"negative,omitempty"`
AmountChange quantity.Quantity `json:"amount_change"`
}

Fields:

  • beneficiary specifies the beneficiary account address.
  • amount_change specifies the absolute value of the amount of base units to +change the allowance for.
  • negative specifies whether the amount_change should be subtracted instead +of added.

The transaction signer implicitly specifies the general account. Upon executing +the allow the following actions are performed:

  • If either the disable_transfers staking consensus parameter is set to true +or the max_allowances staking consensus parameter is set to zero, the method +fails with ErrForbidden.

  • It is checked whether either the transaction signer address or the +beneficiary address are reserved. If any are reserved, the method fails with +ErrForbidden.

  • Address specified by beneficiary is compared with the transaction signer +address. If the addresses are the same, the method fails with +ErrInvalidArgument.

  • The account indicated by the signer is loaded.

  • If the allow would create a new allowance and the maximum number of allowances +for an account has been reached, the method fails with ErrTooManyAllowances.

  • The set of allowances is updated so that the allowance is updated as specified +by amount_change/negative. In case the change would cause the allowance to +be equal to zero or negative, the allowance is removed.

  • The account is saved.

  • The corresponding AllowanceChangeEvent is emitted with the following +structure:

    type AllowanceChangeEvent struct {
    Owner Address `json:"owner"`
    Beneficiary Address `json:"beneficiary"`
    Allowance quantity.Quantity `json:"allowance"`
    Negative bool `json:"negative,omitempty"`
    AmountChange quantity.Quantity `json:"amount_change"`
    }

    Where allowance contains the new total allowance, the amount_change +contains the absolute amount the allowance has changed for and negative +specifies whether the allowance has been reduced rather than increased. The +event is emitted even if the new allowance is zero.

Withdraw

Withdraw enables a beneficiary to withdraw from the given account.

Method name:

staking.Withdraw

Body:

type Withdraw struct {
From Address `json:"from"`
Amount quantity.Quantity `json:"amount"`
}

Fields:

  • from specifies the account address to withdraw from.
  • amount specifies the amount of base units to withdraw.

The transaction signer implicitly specifies the destination general account. +Upon executing the withdrawal the following actions are performed:

  • If either the disable_transfers staking consensus parameter is set to true +or the max_allowances staking consensus parameter is set to zero, the method +fails with ErrForbidden.

  • It is checked whether either the transaction signer address or the +from address are reserved. If any are reserved, the method fails with +ErrForbidden.

  • Address specified by from is compared with the transaction signer address. +If the addresses are the same, the method fails with ErrInvalidArgument.

  • The source account indicated by from is loaded.

  • The destination account indicated by the transaction signer is loaded.

  • amount is deducted from the corresponding allowance in the source account. +If this would cause the allowance to go negative, the method fails with +ErrForbidden.

  • amount is deducted from the source general account balance. If this would +cause the balance to go negative, the method fails with +ErrInsufficientBalance.

  • amount is added to the destination general account balance.

  • Both source and destination accounts are saved.

  • The corresponding TransferEvent is emitted.

  • The corresponding AllowanceChangeEvent is emitted with the updated +allowance.

Queries

This proposal adds the following new query methods in the staking module by +updating the staking.Backend interface as follows:

type Backend interface {
// ... existing methods omitted ...

// Allowance looks up the allowance for the given owner/beneficiary combination.
Allowance(ctx context.Context, query *AllowanceQuery) (*quantity.Quantity, error)
}

// AllowanceQuery is an allowance query.
type AllowanceQuery struct {
Height int64 `json:"height"`
Owner Address `json:"owner"`
Beneficiary Address `json:"beneficiary"`
}

Messages

Since this is the first proposal that introduces a new runtime message type that +can be emitted from a runtime during a round, it also defines some general +properties of runtime messages and the dispatch mechanism:

  • Each message has an associated gas cost that needs to be paid by the +submitter (e.g. as part of the roothash.ExecutorCommit method call). The gas +cost is split among the committee members.

  • There is a maximum number of messages that can be emitted by a runtime during +a given round. The limit is defined both globally (e.g. a roothash consensus +parameter) and per-runtime (which needs to be equal to or lower than the +global limit).

  • Messages are serialized using a sum type describing all possible messages, +where each message type is assigned a field name:

    type Message struct {
    Message1 *Message1 `json:"message1,omitempty"`
    Message2 *Message2 `json:"message2,omitempty"`
    // ...
    }
  • All messages are versioned by embeding the cbor.Versioned structure which +provides a single uint16 field v.

  • A change is made to how messages are included in commitments, to reduce the +size of submitted transactions.

    The ComputeResultsHeader is changed so that the Messages field is replaced +with a MessagesHash field containing a hash of the CBOR-encoded messages +emitted by the runtime.

    At the same time ComputeBody is changed to include an additional field +Messages as follows:

    type ComputeBody struct {
    // ... existing fields omitted ...
    Messages []*block.Message `json:"messages,omitempty"`
    }

    The Messages field must only be populated in the commitment by the +transaction scheduler and must match the MessagesHash.

  • If any of the included messages is deemed malformed, the round fails and the +runtime state is not updated.

  • In order to support messages that fail to execute, a new roothash event is +emitted for each executed message:

    type MessageEvent struct {
    Index uint32 `json:"index,omitempty"`
    Module string `json:"module,omitempty"`
    Code uint32 `json:"code,omitempty"`
    }

    Where the index specifies the index of the executed message and the module +and code specify the module and error code accoording to Oasis Core error +encoding convention (note that the usual human readable message field is not +included).

This proposal introduces the following runtime messages:

Staking Method Call

The staking method call message enables a runtime to call one of the supported +staking module methods.

Field name:

staking

Body:

type StakingMessage struct {
cbor.Versioned

Transfer *staking.Transfer `json:"transfer,omitempty"`
Withdraw *staking.Withdraw `json:"withdraw,omitempty"`
}

Fields:

  • v must be set to 0.
  • transfer indicates that the staking.Transfer method should be executed.
  • withdraw indicates that the staking.Withdraw method should be executed.

Exactly one of the supported method fields needs to be non-nil, otherwise the +message is considered malformed.

Consensus Parameters

Staking

This proposal introduces the following new consensus parameters in the staking +module:

  • max_allowances (uint32) specifies the maximum number of allowances an +account can store. Zero means that allowance functionality is disabled.

Roothash

This proposal introduces the following new consensus parameters in the roothash +module:

  • max_runtime_messages (uint32) specifies the global limit on the number of +messages that can be emitted in each round by the runtime. The default value +of 0 disables the use of runtime messages.

Runtime Host Protocol

This proposal modifies the runtime host protocol as follows:

Host to Runtime: Initialization

The existing RuntimeInfoRequest message body is updated to contain a field +denoting the consensus backend used by the host and its consensus protocol +version as follows:

type RuntimeInfoRequest struct {
ConsensusBackend string `json:"consensus_backend"`
ConsensusProtocolVersion uint64 `json:"consensus_protocol_version"`

// ... existing fields omitted ...
}

This information can be used by the runtime to ensure that it supports the +consensus layer used by the host. In case the backend and/or protocol version is +not supported, the runtime should return an error and terminate. In case the +runtime does not interact with the consensus layer it may ignore the consensus +layer information.

Host to Runtime: Transaction Batch Dispatch

The existing RuntimeExecuteTxBatchRequest and RuntimeCheckTxBatchRequest +message bodies are updated to include the consensus layer light block at the +last finalized round height (specified in .Block.Header.Round) and the list of +MessageEvents emitted while processing the runtime messages emitted in the +previous round as follows:

type RuntimeExecuteTxBatchRequest struct {
// ConsensusBlock is the consensus light block at the last finalized round
// height (e.g., corresponding to .Block.Header.Round).
ConsensusBlock consensus.LightBlock `json:"consensus_block"`

// MessageResults are the results of executing messages emitted by the
// runtime in the previous round (sorted by .Index).
MessageResults []roothash.MessageEvent `json:"message_results,omitempty"`

// ... existing fields omitted ...
}

type RuntimeCheckTxBatchRequest struct {
// ConsensusBlock is the consensus light block at the last finalized round
// height (e.g., corresponding to .Block.Header.Round).
ConsensusBlock consensus.LightBlock `json:"consensus_block"`

// ... existing fields omitted ...
}

The information from the light block can be used to access consensus layer +state.

Runtime to Host: Read-only Storage Access

The existing HostStorageSyncRequest message body is updated to include an +endpoint identifier as follows:

type HostStorageSyncRequest struct {
// Endpoint is the storage endpoint to which this request should be routed.
Endpoint string `json:"endpoint,omitempty"`

// ... existing fields omitted ...
}

The newly introduced endpoint field can take the following values:

  • runtime (or empty string) denotes the runtime state endpoint. The empty +value is allowed for backwards compatibility as this was the only endpoint +available before this proposal.

  • consensus denotes the consensus state endpoint, providing access to +consensus state.

Rust Runtime Support Library

The Rust runtime support library (oasis-core-runtime) must be updated to +support the updated message structures. Additionally, there needs to be basic +support for interpreting the data from the Tendermint consensus layer backend:

  • Decoding light blocks.

  • Decoding staking-related state structures.

The Tendermint-specific functionality should be part of a separate crate.

Expected User/Consensus/Runtime Flow

Scenario:

Account holder has 100 tokens in her account in the consensus layer staking +ledger and would like to spend 50 tokens to execute an action in runtime X.

Flow:

  • Account holder sets an allowance of 50 tokens for runtime X by submitting an +allow transaction to the consensus layer.

  • Account holder submits a runtime transaction that performs some action costing +50 tokens.

  • Account holder's runtime transaction is executed in runtime X round R:

    • Runtime X emits a message to transfer 50 tokens from the user's account to +the runtime's own account.

      As an optimization runtime X can verify current consensus layer state and +reject the transaction early to prevent paying for needless consensus layer +message processing.

    • Runtime X updates its state to indicate a pending transfer of 50 tokens from +the user. It uses the index of the emitted message to be able to match the +message execution result once it arrives.

    • Runtime X submits commitments to the consensus layer.

  • When finalizing round R for runtime X, the consensus layer transfers 50 tokens +from the account holder's account to the runtime X account.

  • Corresponding message result event is emitted, indicating success.

  • When runtime X processes round R+1, the runtime receives the set of emitted +message result events.

  • Runtime X processes message result events, using the index field to match the +corresponding pending action and executes whatever action it queued.

    • In case the message result event would indicate failure, the pending action +can be pruned.

Consequences

Positive

  • Consensus layer tokens can be transferred into and out of runtimes, enabling +more use cases.

  • Any tokens must be explicitly made available to the runtime which limits the +damage from badly written or malicious runtimes.

  • Account holders can change the allowance at any time.

Negative

  • A badly written or malicious runtime could steal the tokens explicitly +deposited into the runtime. This includes any actions by the runtime owner +which would modify the runtime's security parameters.

  • A badly written, malicious or forever suspended runtime can lock tokens in +the runtime account forever. This could be mitigated via an unspecified +consensus layer governance mechanism.

  • Account holders may mistakenly transfer tokens directly into a runtime account +which may cause such tokens to be locked forever.

  • Account holders may change the allowance or reduce their account balance right +before the runtime round is finalized, causing the emitted messages to fail +while the runtime still needs to pay for gas to execute the messages.

Neutral

  • The runtime must handle all message results in the next round as otherwise it +cannot easily get past messages.

References

+ + + + \ No newline at end of file diff --git a/adrs/0004-runtime-governance/index.html b/adrs/0004-runtime-governance/index.html new file mode 100644 index 0000000000..047885692d --- /dev/null +++ b/adrs/0004-runtime-governance/index.html @@ -0,0 +1,102 @@ + + + + + +ADR 0004: Runtime Governance | Oasis Documentation + + + + +
+
Skip to main content

ADR 0004: Runtime Governance

Component

Oasis Core

Changelog

  • 2020-10-07: Add per-role max node limits, minimum required election pool size
  • 2020-09-30: Add entity whitelist admission policy max nodes limit
  • 2020-09-17: Initial draft

Status

Accepted

Context

Currently all runtimes can only be governed by a single entity -- the runtime +owner. In this regard governance means being able to update certain fields in +the runtime descriptor stored by the consensus layer registry service. On one +hand the runtime descriptor contains security-critical parameters and on the +other there needs to be a mechanism through which the runtimes can be upgraded +(especially so for TEE-based runtimes where a specific runtime binary is +enforced via remote attestation mechanisms).

This proposal extends runtime governance options and enables a path towards +runtimes that can define their own governance mechanisms. This proposal assumes +that ADR 0003 has been adopted and runtimes can have their own accounts in the +staking module.

Decision

This proposal takes a simplistic but powerful approach which allows each runtime +to choose its governance model upon its first registration. It does so through +a newly introduced field in the runtime descriptor which indicates how the +runtime descriptor can be updated in the future.

Runtime Descriptor

The runtime descriptor version is bumped to 2. Version 1 descriptors are +accepted at genesis and are converted to the new format by assuming the entity +governance model as that is the only option in v1. All new runtime registrations +must use the v2 descriptor.

Governance Model

This proposal updates the runtime descriptor by adding fields as follows:

type Runtime struct {
// GovernanceModel specifies the runtime governance model.
GovernanceModel RuntimeGovernanceModel `json:"governance_model"`

// ... existing fields omitted ...
}

// RuntimeGovernanceModel specifies the runtime governance model.
type RuntimeGovernanceModel uint8

const (
GovernanceEntity RuntimeGovernanceModel = 1
GovernanceRuntime RuntimeGovernanceModel = 2
GovernanceConsensus RuntimeGovernanceModel = 3
)

// ... some text serialization methods omitted ...

The governance_model field can specifiy one of the following governance +models:

  • Entity governance (GovernanceEntity). This causes the runtime to behave +exactly as before, the runtime owner (indicated by entity_id in the runtime +descriptor) is the only one who can update the runtime descriptor via +registry.RegisterRuntime method calls.

    The runtime owner is also the one that needs to provide the required stake +in escrow in order to avoid the runtime from being suspended. As before note +that anyone can delegate the required stake to the runtime owner in order to +enable runtime operation (but the owner can always prevent the runtime from +operating by performing actions which would cause the stake claims to no +longer be satisfied).

  • Runtime-defined governance (GovernanceRuntime). In this case the runtime +itself is the only one who can update the runtime descriptor by emitting a +runtime message. The runtime owner (indicated by entity_id) is not able to +perform any updates after the initial registration and such attempts must +return ErrForbidden.

    The runtime itself is the one that needs to provide the required stake in +escrow in order to avoid the runtime from being suspended. This assumes that +runtimes can have accounts in the staking module as specified by ADR 0003. +Note that anyone can delegate the required stake to a runtime in order to +enable its operation.

  • Consensus layer governance (GovernanceConsensus). In this case only the +consensus layer itself can update the runtime descriptor either through a +network upgrade or via a consensus layer governance mechanism not specified by +this proposal.

    Runtimes using this governance model are never suspended and do not need to +provide stake in escrow.

    Runtimes using this governance model cannot be registered/updated via regular +registry method calls or runtime messages (doing so must return +ErrForbidden). Instead such a runtime can only be registered at genesis, +through a network upgrade or via a consensus layer governance mechanism not +specified by this proposal.

Entity Whitelist Admission Policy

The entity whitelist admission policy configuration structure is changed to +allow specifying the maximum number of nodes that each entity can register under +the given runtime for each role.

type EntityWhitelistConfig struct {
// MaxNodes is the maximum number of nodes that an entity can register under
// the given runtime for a specific role. If the map is empty or absent, the
// number of nodes is unlimited. If the map is present and non-empty, the
// the number of nodes is restricted to the specified maximum (where zero
// means no nodes allowed), any missing roles imply zero nodes.
MaxNodes map[node.RolesMask]uint16 `json:"max_nodes,omitempty"`
}

type EntityWhitelistRuntimeAdmissionPolicy struct {
Entities map[signature.PublicKey]EntityWhitelistConfig `json:"entities"`
}

The new max_nodes field specifies the maximum number of nodes an entity can +register for the given runtime for each role. If the map is empty or absent, the +number of nodes is unlimited. If the map is present and non-empty, the number of +nodes is restricted to the specified number (where zero means no nodes are +allowed). Any missing roles imply zero nodes.

Each key (roles mask) in the max_nodes map must specify a single role, +otherwise the runtime descriptor is rejected with ErrInvalidArgument.

When transforming runtime descriptors from version 1, an entry in the entities +field maps to an EntityWhitelistConfig structure with max_nodes absent, +denoting that an unlimited number of nodes is allowed (as before).

Minimum Required Committee Election Pool Size

The executor and storage runtime parameters are updated to add a new field +defining the minimum required committee election pool size. The committee +scheduler is updated to refuse election for a given runtime committee in case +the number of candidate nodes is less than the configured minimum pool size.

type ExecutorParameters struct {
// MinPoolSize is the minimum required candidate compute node pool size.
MinPoolSize uint64 `json:"min_pool_size"`

// ... existing fields omitted ...
}

type StorageParameters struct {
// MinPoolSize is the minimum required candidate storage node pool size.
MinPoolSize uint64 `json:"min_pool_size"`

// ... existing fields omitted ...
}

The value of min_pool_size must be non-zero and must be equal to or greater +than the corresponding sum of group_size and group_backup_size. Otherwise +the runtime descriptor is rejected with ErrInvalidArgument.

When transforming runtime descriptors from version 1, min_pool_size for the +executor committee is computed as group_size + group_backup_size while the +min_pool_size for the storage committee is equal to group_size.

State

This proposal introduces/updates the following consensus state in the registry +module:

Stored Runtime Descriptors

Since the runtime descriptors can now be updated by actors other than the +initial registering entity, it does not make sense to store signed runtime +descriptors. The value of storage key prefixed with 0x13 which previously +contained signed runtime descriptors is modified to store plain runtime +descriptors.

Genesis Document

This proposal updates the registry part of the genesis document as follows:

  • The type of the runtimes field is changed to a list of runtime descriptors +(was a list of signed runtime descriptors before).

  • The type of the suspended_runtimes field is changed to a list of runtime +descriptors (was a list of signed runtime descriptors before).

Runtime descriptors must be transformed to support the new fields.

Transaction Methods

This proposal updates the following transaction methods in the registry module:

Register Runtime

Runtime registration enables a new runtime to be created or an existing runtime +to be updated (in case the governance model allows it).

Method name:

registry.RegisterRuntime

The body of a register runtime transaction must be a Runtime descriptor. +The signer of the transaction must be the owning entity key.

Registering a runtime may require sufficient stake in either the owning entity's +(when entity governance is used) or the runtime's (when runtime governance is +used) escrow account.

Changing the governance model from GovernanceEntity to GovernanceRuntime is +allowed. Any other governance model changes are not allowed and must fail with +ErrForbidden. Support for other changes is deferred to a consensus layer +governance mechanism not specified by this proposal.

Using the GovernanceRuntime governance model for a runtime of any kind other +than KindCompute must return ErrInvalidArgument.

Messages

This proposal introduces the following runtime messages:

Update Runtime Descriptor

The update runtime descriptor message enables a runtime to update its own +descriptor when the current governance model allows it.

Field name:

update_runtime

Body:

type UpdateRuntimeMessage struct {
registry.Runtime
}

The body of the update runtime descriptor message is a new runtime descriptor +that must be for the runtime emitting this message. Otherwise the message is +considered malformed.

The actions performed when processing the message are the same as those +performed when processing the registry.RegisterRuntime method call, just made +on the runtime's (instead of an entity's) behalf.

Consensus Parameters

Registry

This proposal introduces the following new consensus parameters in the registry +module:

  • enable_runtime_governance_models (set of RuntimeGovernanceModel) specifies +the set of runtime governance models that are allowed to be used when +creating/updating registrations (either via method calls or via runtime +messages). In case a runtime is using a governance model not specified in this +list, an update to such a runtime must fail with ErrForbidden.

Rust Runtime Support Library

The Rust runtime support library (oasis-core-runtime) must be updated to +support the updated and newly needed message structures (the runtime descriptor +and the update runtime message).

Consequences

Positive

  • Runtimes can define their governance model, enabling them to become more +decentralized while still allowing upgrades.

  • Runtimes using the entity whitelist admission policy can limit the number of +nodes that each entity can register.

  • Runtimes can specify the minimum size of the compute/storage node pool from +which committees are elected.

Negative

Neutral

References

  • ADR 0003 - Consensus/Runtime Token Transfer
+ + + + \ No newline at end of file diff --git a/adrs/0005-runtime-compute-slashing/index.html b/adrs/0005-runtime-compute-slashing/index.html new file mode 100644 index 0000000000..6f02839bda --- /dev/null +++ b/adrs/0005-runtime-compute-slashing/index.html @@ -0,0 +1,96 @@ + + + + + +ADR 0005: Runtime Compute Node Slashing | Oasis Documentation + + + + +
+
Skip to main content

ADR 0005: Runtime Compute Node Slashing

Component

Oasis Core

Changelog

  • 2020-10-14: Evidence expiry, duplicate evidence detection
  • 2020-09-28: Initial draft

Status

Accepted

Context

The runtime compute nodes make updates to the runtime state by submitting +commitment messages to the roothash service in the consensus layer where +discrepancy detection and resolution are performed.

Currently, the compute nodes are never slashed even if they commit incorrect +results. While integrity is guarded by discrepancy detection and resolution, +compute nodes should be disincentivized to behave incorrectly.

Decision

This proposal introduces a slashing mechanism for punishing misbehaving compute +nodes as follows:

  • Per-runtime configurable slashing parameters are added to the runtime +descriptor similar to the global slashing configuration that currently exists +in the staking service.

  • New runtime-specific slashing reasons are introduced: (i) submitting +incorrect compute results and (ii) signing two different executor commits or +proposed batches for the same round.

  • Failure-indicating executor commits are introduced in order to give the +compute nodes a possibility to vote for failure when they cannot execute the +given batch (e.g., due to unavailability of storage or key manager) without +getting slashed. Such commits will always trigger a discrepancy during +discrepancy detection and will vote for failing the round in discrepancy +resolution phase.

Runtime Descriptor

This proposal updates the runtime staking parameters (stored under the staking +field of the runtime descriptor) as follows:

type RuntimeStakingParameters struct {
// ... existing fields omitted ...

// Slashing are the per-runtime misbehavior slashing parameters.
Slashing map[staking.SlashReason]staking.Slash `json:"slashing,omitempty"`

// RewardSlashEquvocationRuntimePercent is the percentage of the reward obtained when slashing
// for equivocation that is transferred to the runtime's account.
RewardSlashEquvocationRuntimePercent uint8 `json:"reward_equivocation,omitempty"`

// RewardSlashBadResultsRuntimePercent is the percentage of the reward obtained when slashing
// for incorrect results that is transferred to the runtime's account.
RewardSlashBadResultsRuntimePercent uint8 `json:"reward_bad_results,omitempty"`
}

Slashing Parameters

The slash reason type in the staking module is changed from int to uint8.

The slash reason definitions are updated as follows:

const (
// SlashConsensusEquivocation is slashing due to equivocation in the
// consensus layer.
SlashConsensusEquivocation SlashReason = 0x00

// SlashRuntimeIncorrectResults is slashing due to submission of incorrect
// results in runtime executor commitments.
SlashRuntimeIncorrectResults SlashReason = 0x80
// SlashRuntimeEquivocation is slashing due to signing two different
// executor commits or proposed batches for the same round.
SlashRuntimeEquivocation SlashReason = 0x81
)

Executor Commitments

The executor commitment body structures are updated to make certain fields +optional and to introduce the failure field as follows:

type ExecutorCommitmentFailure uint8

const (
// FailureNone indicates that no failure has occurred.
FailureNone ExecutorCommitmentFailure = 0
// FailureUnknown indicates a generic failure.
FailureUnknown ExecutorCommitmentFailure = 1
// FailureStorageUnavailable indicates that batch processing failed due to
// storage being unavailable.
FailureStorageUnavailable ExecutorCommitmentFailure = 2
// FailureKeyManagerUnavailable indicates that batch processing failed due
// to key manager being unavailable.
FailureKeyManagerUnavailable ExecutorCommitmentFailure = 3
)

type ExecutorCommitmentHeader struct {
// Required fields.

Round uint64 `json:"round"`
PreviousHash hash.Hash `json:"previous_hash"`

// Optional fields (may be absent for failure indication).

IORoot *hash.Hash `json:"io_root,omitempty"`
StateRoot *hash.Hash `json:"state_root,omitempty"`
MessageHash *hash.Hash `json:"messages_hash,omitempty"`
}

type ExecutorCommitmentBody struct {
Header ExecutorCommitmentHeader `json:"header"`
Failure ExecutorCommitmentFailure `json:"failure,omitempty"`

TxnSchedSig signature.Signature `json:"txn_sched_sig"`
InputRoot hash.Hash `json:"input_root"`
InputStorageSigs []signature.Signature `json:"input_storage_sigs"`

// Optional fields (may be absent for failure indication).

StorageSignatures []signature.Signature `json:"storage_signatures,omitempty"`
RakSig *signature.RawSignature `json:"rak_sig,omitempty"`
}

The notion of an failure-indicating executor commitment is introduced as being +an executor commitment with the following field values:

  • The failure field must be present and non-zero. The code can indicate a +reason for the failure but currently the reason is ignored during processing.

  • header.round, header.previous_hash, txn_sched_sig, input_root and +input_storage_sigs are set as for usual commitments (e.g., they must be +valid).

  • All other fields must be omitted or set to nil.

Root Hash Commitment Processing

The processing of executor commitments by the commitment pool is modified as +follows:

  • Adding new commitments (AddExecutorCommitment)

    • If a commitment for a node already exists the existing commitment is +checked for evidence of equivocation. Any evidence of misbehavior is +processed as described in the Evidence subsection below.
  • Discrepancy detection (DetectDiscrepancy)

    • If any executor commitment indicates failure, the discrepancy detection +process signals a discrepancy (which implies that discrepancy resolution is +triggered).
  • Discrepancy resolution (ResolveDiscrepancy)

    • When tallying votes, any executor commitments indicating failure are tallied +into its own bucket. If the failure bucket receives 1/2+ votes, the round +fails.

    • If after discrepancy resolution a non-failure option receives 1/2+ votes, +this is considered the correct result. Executor commitments for any other +result (excluding failure indication) are considered incorrect and are +subject to slashing (based on the configured slashing instructions for the +SlashRuntimeIncorrectResults reason).

A portion of slashed funds is disbursed equally to the compute nodes which +participated in discrepancy resolution for the round. The remainder of slashed +funds is transferred to the runtime account.

Any slashing instructions related to freezing nodes are currently ignored.

State

This proposal introduces/updates the following consensus state in the roothash +module:

  • List of past valid evidence (0x24)

    A hash uniquely identifying the evidence is stored for each successfully +processed evidence that has not yet expired using the following key format:

    0x24 <H(runtime-id) (hash.Hash)> <round (uint64)> <evidence-hash (hash.Hash)>

    The value is empty as we only need to detect duplicate evidence.

Transaction Methods

This proposal updates the following transaction methods in the roothash module:

Evidence

The evidence method allows anyone to submit evidence of runtime node +misbehavior.

Method name:

roothash.Evidence

Body:

type EvidenceKind uint8

const (
// EvidenceKindEquivocation is the evidence kind for equivocation.
EvidenceKindEquivocation = 1
)

type Evidence struct {
ID common.Namespace `json:"id"`

EquivocationExecutor *EquivocationExecutorEvidence `json:"equivocation_executor,omitempty"`
EquivocationBatch *EquivocationBatchEvidence `json:"equivocation_batch,omitempty"`
}

type EquivocationExecutorEvidence struct {
CommitA commitment.ExecutorCommitment `json:"commit_a"`
CommitB commitment.ExecutorCommitment `json:"commit_b"`
}

type EquivocationBatchEvidence struct {
BatchA commitment.SignedProposedBatch `json:"batch_a"`
BatchB commitment.SignedProposedBatch `json:"batch_b"`
}

Fields:

  • id specifies the runtime identifier of a runtime this evidence is for.
  • equivocation_executor (optional) specifies evidence of an executor node +equivocating when signing commitments.
  • equivocation_batch (optional) specifies evidence of an executor node +equivocating when signing proposed batches.

If no evidence is specified (e.g., all evidence fields are nil) the method +call is invalid and must fail with ErrInvalidArgument.

For all kinds of evidence, the following steps are performed to verify evidence +validity:

  • Current state for the runtime identified by id is fetched. If the runtime +does not exist, the evidence is invalid.

  • If no slashing instructions for SlashRuntimeEquivocation are configured for +the given runtime, there is no point in collecting evidence so the method call +must fail with ErrRuntimeDoesNotSlash.

When processing EquivocationExecutor evidence, the following steps are +performed to verify evidence validity:

  • header.round fields of both commitments are compared. If they are not the +same, the evidence is invalid.

  • Both executor commitments are checked for basic validity. If either is +invalid, the evidence is invalid.

  • The header.previous_hash, header.io_root, header.state_root and +header.messages_hash fields of both commitments are compared. If they are +the same, the evidence is invalid.

  • The failure indication fields of both commitments are compared. If they are +the same, the evidence is invalid.

  • header.round field is compared with the runtime's current state. If it is +more than max_evidence_age (consensus parameter) rounds behind, the evidence +is invalid.

  • Public keys of signers of both commitments are compared. If they are not the +same, the evidence is invalid.

  • Signatures of both commitments are verified. If either is invalid, the +evidence is invalid.

  • Otherwise the evidence is valid.

When processing EquivocationBatch evidence, the following steps are +performed to verify evidence validity:

  • The header.round fields of both proposed batches are compared. If they are +not the same, the evidence is invalid.

  • The header fields of both proposed batches are checked for basic validity. +If any is invalid, the evidence is invalid.

  • The io_root fields of both proposed batches are compared. If they are the +same, the evidence is invalid.

  • Public keys of signers of both commitments are compared. If they are not the +same, the evidence is invalid.

  • Signatures of both proposed batches are validated. If either is invalid, the +evidence is invalid.

  • Otherwise the evidence is valid.

For all kinds of valid evidence, the following steps are performed after +validation:

  • The evidence hash is derived by hashing the evidence kind and the public key +of the signer and the evidence is looked up in the list of past valid +evidence. If evidence already exists there, the method fails with +ErrDuplicateEvidence.

  • The valid evidence hash is stored in the list of past valid evidence.

If the evidence is deemed valid by the above procedure, the misbehaving compute +node is slashed based on the runtime slashing parameters for the +SlashRuntimeEquivocation reason.

Any slashing instructions related to freezing nodes are currently ignored.

The node submitting the evidence may be rewarded from part of the slashed +amount to incentivize evidence submission. The remainder of slashed funds is +transferred to the runtime account.

Evidence Expiry

On each epoch transition, for each runtime, expired evidence (as defined by the +max_evidence_age and the current runtime's round) must be pruned from the +list of past valid evidence.

Evidence Collection

Nodes collect commitment messages distributed via the P2P gossip network and +check for any signs of misbehavior. In case valid evidence can be constructed, +it is submitted to the consensus layer. Any evidence parts that have expired +should be discarded.

Consensus Parameters

Roothash

This proposal introduces the following new consensus parameters in the roothash +module:

  • max_evidence_age (uint64) specifies the maximum age of submitted evidence in +the number of rounds.

Consequences

Positive

  • Compute nodes can be disincentivized to submit incorrect results by runtimes +configuring slashing parameters.

Negative

  • Checking for duplicate evidence requires additional state in the consensus +layer to store the evidence hashes (73 bytes per evidence).

  • Expiring old evidence requires additional per-runtime state lookups and +updates that happen on each epoch transition.

  • If a runtime exhibits non-determinism, this can result in a compute node being +slashed. While we specify that runtimes should be deterministic, for non-SGX +runtimes we have no way determining whether a discrepancy is due to runtime +non-determinism or a faulty compute node.

Neutral

  • This proposal does not introduce any kind of slashing for liveness.

  • This proposal does not introduce freezing misbehaving nodes.

References

+ + + + \ No newline at end of file diff --git a/adrs/0006-consensus-governance/index.html b/adrs/0006-consensus-governance/index.html new file mode 100644 index 0000000000..d6c3d37a8b --- /dev/null +++ b/adrs/0006-consensus-governance/index.html @@ -0,0 +1,105 @@ + + + + + +ADR 0006: Consensus Governance | Oasis Documentation + + + + +
+
Skip to main content

ADR 0006: Consensus Governance

Component

Oasis Core

Changelog

  • 2021-03-30: Update name of the CastVote method's body
  • 2021-01-06: Update API to include Proposals() method
  • 2020-12-08: Updates to match the actual implementation
  • 2020-10-27: Voting period in epochs, min upgrade cancellation difference, +failed proposal state
  • 2020-10-16: Initial draft

Status

Accepted

Context

Currently the consensus layer does not contain any on-chain governance +mechanism so any network upgrades need to be carefully coordinated off-chain. +An on-chain governance mechanism would allow upgrades to be handled in a more +controlled (and automatable) manner without introducing the risk of corrupting +state.

Decision

This proposal introduces a minimal on-chain governance mechanism where anyone +can submit governance proposals and the validators can vote where one base unit +of delegated stake counts as one vote.

The high-level overview is as follows:

  • A new governance API is added to the consensus layer and its Tendermint +based implementation. It supports transactions for submitting proposals and +voting on proposals. It supports queries for listing current proposals and +votes for any given proposal.

  • Two governance proposal kinds are supported, a consensus layer upgrade +proposal (where the content is basically the existing upgrade descriptor) and +the cancellation of a pending upgrade.

A proposal is created through a submit proposal transaction and requires a +minimum deposit (which is later refunded in case the proposal passes). Once a +proposal is successfully submitted the voting period starts. Entities that are +part of the validator set may cast votes for the proposal. After the voting +period completes, the votes are tallied and the proposal either passes or is +rejected.

In case the proposal passes, the actions specified in the content of the propsal +are executed. Currently the only actions are scheduling of an upgrade by +publishing an upgrade descriptor or cancelling a previously passed upgrade.

State

Staking

This proposal adds the following consensus layer state in the staking module:

  • Governance deposits account balance (0x59), similar to the common pool.

Governance

This proposal adds the following consensus layer state in the governance module:

  • Next proposal identifier (0x80)

    The next proposal identifier is stored as a CBOR-serialized uint64.

  • List of proposals (0x81)

    Each proposal is stored under a separate storage key with the following key +format:

    0x81 <proposal-id (uint64)>

    And CBOR-serialized value:

    // ProposalState is the state of the proposal.
    type ProposalState uint8

    const (
    StateActive ProposalState = 1
    StatePassed ProposalState = 2
    StateRejected ProposalState = 3
    StateFailed ProposalState = 4
    )

    // Proposal is a consensus upgrade proposal.
    type Proposal struct {
    // ID is the unique identifier of the proposal.
    ID uint64 `json:"id"`
    // Submitter is the address of the proposal submitter.
    Submitter staking.Address `json:"submitter"`
    // State is the state of the proposal.
    State ProposalState `json:"state"`
    // Deposit is the deposit attached to the proposal.
    Deposit quantity.Quantity `json:"deposit"`

    // Content is the content of the proposal.
    Content ProposalContent `json:"content"`

    // CreatedAt is the epoch at which the proposal was created.
    CreatedAt beacon.EpochTime `json:"created_at"`
    // ClosesAt is the epoch at which the proposal will close and votes will
    // be tallied.
    ClosesAt beacon.EpochTime `json:"closes_at"`

    // Results are the final tallied results after the voting period has
    // ended.
    Results map[Vote]quantity.Quantity `json:"results,omitempty"`
    // InvalidVotes is the number of invalid votes after tallying.
    InvalidVotes uint64 `json:"invalid_votes,omitempty"`
    }
  • List of active proposals (0x82)

    Each active proposal (one that has not yet closed) is stored under a separate +storage key with the following key format:

    0x82 <closes-at-epoch (uint64)> <proposal-id (uint64)>

    The value is empty as the proposal ID can be inferred from the key.

  • List of votes (0x83)

    Each vote is stored under a separate storage key with the following key +format:

    0x83 <proposal-id (uint64)> <voter-address (staking.Address)>

    And CBOR-serialized value:

    // Vote is a governance vote.
    type Vote uint8

    const (
    VoteYes Vote = 1
    VoteNo Vote = 2
    VoteAbstain Vote = 3
    )
  • List of pending upgrades (0x84)

    Each pending upgrade is stored under a separate storage key with the following +key format:

    0x84 <upgrade-epoch (uint64)> <proposal-id (uint64)>

    The value is empty as the proposal upgrade descriptor can be obtained via +proposal that can be inferred from the key.

  • Parameters (0x85)

    Governance consensus parameters.

    With CBOR-serialized value:

    // ConsensusParameters are the governance consensus parameters.
    type ConsensusParameters struct {
    // GasCosts are the governance transaction gas costs.
    GasCosts transaction.Costs `json:"gas_costs,omitempty"`

    // MinProposalDeposit is the number of base units that are deposited when
    // creating a new proposal.
    MinProposalDeposit quantity.Quantity `json:"min_proposal_deposit,omitempty"`

    // VotingPeriod is the number of epochs after which the voting for a proposal
    // is closed and the votes are tallied.
    VotingPeriod beacon.EpochTime `json:"voting_period,omitempty"`

    // Quorum is he minimum percentage of voting power that needs to be cast on
    // a proposal for the result to be valid.
    Quorum uint8 `json:"quorum,omitempty"`

    // Threshold is the minimum percentage of VoteYes votes in order for a
    // proposal to be accepted.
    Threshold uint8 `json:"threshold,omitempty"`

    // UpgradeMinEpochDiff is the minimum number of epochs between the current
    // epoch and the proposed upgrade epoch for the upgrade proposal to be valid.
    // This is also the minimum number of epochs between two pending upgrades.
    UpgradeMinEpochDiff beacon.EpochTime `json:"upgrade_min_epoch_diff,omitempty"`

    // UpgradeCancelMinEpochDiff is the minimum number of epochs between the current
    // epoch and the proposed upgrade epoch for the upgrade cancellation proposal to be valid.
    UpgradeCancelMinEpochDiff beacon.EpochTime `json:"upgrade_cancel_min_epoch_diff,omitempty"`
    }

Genesis Document

The genesis document needs to be updated to include a governance field with +any initial state (see State) and consensus parameters (see Consensus +Parameters) for the governance service.

Transaction Methods

This proposal adds the following transaction methods in the governance module:

Submit Proposal

Proposal submission enables a new consensus layer governance proposal to be +created.

Method name:

governance.SubmitProposal

Body:

// ProposalContent is a consensus layer governance proposal content.
type ProposalContent struct {
Upgrade *UpgradeProposal `json:"upgrade,omitempty"`
CancelUpgrade *CancelUpgradeProposal `json:"cancel_upgrade,omitempty"`
}

// UpgradeProposal is an upgrade proposal.
type UpgradeProposal struct {
upgrade.Descriptor
}

// CancelUpgradeProposal is an upgrade cancellation proposal.
type CancelUpgradeProposal struct {
// ProposalID is the identifier of the pending upgrade proposal.
ProposalID uint64 `json:"proposal_id"`
}

Fields:

  • upgrade (optional) specifies an upgrade proposal.
  • cancel_upgrade (optional) specifies an upgrade cancellation proposal.

Exactly one of the proposal kind fields needs to be non-nil, otherwise the +proposal is considered malformed.

Upon processing any proposal the following steps are first performed:

  • The account indicated by the signer is loaded.

  • If the account balance is less than min_proposal_deposit, the method call +fails with ErrInsufficientBalance.

Upon processing an UpgradeProposal the following steps are then performed:

  • The upgrade descriptor is checked for basic internal validity. If the check +fails, the method call fails with ErrInvalidArgument.

  • The upgrade descriptor's epoch field is compared with the current epoch. If +the specified epoch is not at least upgrade_min_epoch_diff epochs ahead of +the current epoch, the method call fails with ErrUpgradeTooSoon.

  • The set of pending upgrades is checked to make sure that no upgrades are +currently pending within upgrade_min_epoch_diff epochs of the upgrade +descriptor's epoch field. If there is such an existing upgrade pending, the +method call fails with ErrUpgradeAlreadyPending.

Upon processing a CancelUpgradeProposal the following steps are then +performed:

  • The set of pending upgrades is checked to make sure that the given upgrade +proposal is currently pending to be executed. If there is no such upgrade, the +method call fails with ErrNoSuchUpgrade.

  • The upgrade descriptor's epoch field is compared with the current epoch. If +the specified epoch is not at least upgrade_cancel_min_epoch_diff epochs +ahead of the current epoch, the method call fails with ErrUpgradeTooSoon.

Upon processing any proposal the following steps are then performed:

  • The min_proposal_deposit base units are transferred from the signer's +account to the governance service's proposal deposit account.

  • The signer's account is saved.

  • A new proposal is created and assigned an identifier.

  • The corresponding ProposalSubmittedEvent is emitted with the following +structure:

    type ProposalSubmittedEvent struct {
    // ID is the unique identifier of a proposal.
    ID uint64 `json:"id"`
    // Submitter is the staking account address of the submitter.
    Submitter staking.Address `json:"submitter"`
    }
  • The corresponding staking.TransferEvent is emitted, indicating transfer from +the submitter's account to the proposal deposit account.

Vote

Voting for submitted consensus layer governance proposals.

Method name:

governance.CastVote

Body:

type ProposalVote struct {
// ID is the unique identifier of a proposal.
ID uint64 `json:"id"`
// Vote is the vote.
Vote Vote `json:"vote"`
}

Upon processing a vote the following steps are performed:

  • The entity descriptor corresponding to the transaction signer is fetched. In +case no such entity exists, the method call fails with ErrNotEligible.

  • It is checked whether any entity's nodes are in the current validator set. In +case they are not, the method call fails with ErrNotEligible.

  • The proposal identified by id is loaded. If the proposal does not exist, +the method call fails with ErrNoSuchProposal.

  • If the proposal's state is not StateActive, the method call fails with +ErrVotingIsClosed.

  • The vote is added to the list of votes. If the vote already exists, it is +overwritten.

  • The corresponding VoteEvent is emitted with the following structure:

    type VoteEvent struct {
    // ID is the unique identifier of a proposal.
    ID uint64 `json:"id"`
    // Submitter is the staking account address of the submitter.
    Submitter staking.Address `json:"submitter"`
    // Vote is the cast vote.
    Vote Vote `json:"vote"`
    }

Queries

This proposal introduces the following query methods in the governance module:

type Backend interface {
// ActiveProposals returns a list of all proposals that have not yet closed.
ActiveProposals(ctx context.Context, height int64) ([]*Proposal, error)

// Proposals returns a list of all proposals.
Proposals(ctx context.Context, height int64) ([]*Proposal, error)

// Proposal looks up a specific proposal.
Proposal(ctx context.Context, query *ProposalQuery) (*Proposal, error)

// Votes looks up votes for a specific proposal.
Votes(ctx context.Context, query *ProposalQuery) ([]*VoteEntry, error)

// PendingUpgrades returns a list of all pending upgrades.
PendingUpgrades(ctx context.Context, height int64) ([]*upgrade.Descriptor, error)

// StateToGenesis returns the genesis state at specified block height.
StateToGenesis(ctx context.Context, height int64) (*Genesis, error)

// ConsensusParameters returns the governance consensus parameters.
ConsensusParameters(ctx context.Context, height int64) (*ConsensusParameters, error)

// GetEvents returns the events at specified block height.
GetEvents(ctx context.Context, height int64) ([]*Event, error)

// WatchEvents returns a channel that produces a stream of Events.
WatchEvents(ctx context.Context) (<-chan *Event, pubsub.ClosableSubscription, error)
}

// ProposalQuery is a proposal query.
type ProposalQuery struct {
Height int64 `json:"height"`
ID uint64 `json:"id"`
}

// VoteEntry contains data about a cast vote.
type VoteEntry struct {
Voter staking.Address `json:"voter"`
Vote Vote `json:"vote"`
}

// Event signifies a governance event, returned via GetEvents.
type Event struct {
Height int64 `json:"height,omitempty"`
TxHash hash.Hash `json:"tx_hash,omitempty"`

ProposalSubmitted *ProposalSubmittedEvent `json:"proposal_submitted,omitempty"`
ProposalExecuted *ProposalExecutedEvent `json:"proposal_executed,omitempty"`
ProposalFinalized *ProposalFinalizedEvent `json:"proposal_finalized,omitempty"`
Vote *VoteEvent `json:"vote,omitempty"`
}

Tallying

In EndBlock the list of active proposals is checked to see if there was an +epoch transition in this block. If there was, the following steps are performed +for each proposal that should be closed at the current epoch:

  • A mapping of current validator entity addresses to their respective active +escrow balances is prepared.

  • A results mapping from Vote to number of votes is initialized in the +proposal's results field.

  • Votes from the list of votes for the given proposal are iterated and the +address of each vote is looked up in the prepared entity address mapping. The +corresponding number of votes (on the principle of 1 base unit equals one +vote) are added to the results mapping based on the voted option. Any votes +that are not from the current validator set are ignored and the +invalid_votes field is incremented for each such vote.

  • In case the percentage of votes relative to the total voting power is less +than quorum, the proposal is rejected.

  • In case the percentage of VoteYes votes relative to all valid votes is less +than threshold, the proposal is rejected.

  • Otherwise the proposal is passed.

  • The proposal's status is changed to either StatePassed or StateRejected +and the proposal is saved.

  • The proposal is removed from the list of active proposals.

  • In case the proposal has been passed, the proposal content is executed. If +proposal execution fails, the proposal's state is changed to StateFailed.

  • The corresponding ProposalFinalizedEvent is emitted with the following +structure:

    type ProposalFinalizedEvent struct {
    // ID is the unique identifier of a proposal.
    ID uint64 `json:"id"`
    // State is the new proposal state.
    State ProposalState `json:"state"`
    }
  • In case the proposal has been passed, the deposit is transferred back to the +proposal submitter and a corresponding staking.TransferEvent is emitted, +indicating transfer from the proposal deposit account to the submitter's +account.

  • In case the proposal has been rejected, the deposit is transferred to the +common pool and a corresponding staking.TransferEvent is emitted, +indicating transfer from the proposal deposit account to the common pool +account.

Proposal Content Execution

After any proposal is successfully executed the corresponding +ProposalExecutedEvent is emitted with the following structure:

type ProposalExecutedEvent struct {
// ID is the unique identifier of a proposal.
ID uint64 `json:"id"`
}

Upgrade Proposal

The set of pending upgrades is checked to make sure that no upgrades are +currently pending within upgrade_min_epoch_diff of the upgrade descriptor's +epoch field. If there is such an existing pending upgrade the upgrade proposal +execution fails.

When an upgrade proposal is executed, a new entry is added to the list of +pending upgrades using epoch as <upgrade-epoch>.

On each epoch transition (as part of BeginBlock) it is checked whether a +pending upgrade is scheduled for that epoch. In case it is and we are not +running the new version, the consensus layer will panic. Otherwise, the pending +upgrade proposal is removed.

Cancel Upgrade Proposal

When a cancel upgrade proposal is executed, the proposal identified by +proposal_id is looked up and removed from the list of pending upgrades. In +case the pending upgrade does not exist anymore, no action is performed.

Consensus Parameters

This proposal introduces the following new consensus parameters in the +governance module:

  • gas_costs (transaction.Costs) are the governance transaction gas costs.

  • min_proposal_deposit (base units) specifies the number of base units that +are deposited when creating a new proposal.

  • voting_period (epochs) specifies the number of epochs after which the voting +for a proposal is closed and the votes are tallied.

  • quorum (uint8: [0,100]) specifies the minimum percentage of voting power +that needs to be cast on a proposal for the result to be valid.

  • threshold (uint8: [0,100]) specifies the minimum percentage of VoteYes +votes in order for a proposal to be accepted.

  • upgrade_min_epoch_diff (epochs) specifies the minimum number of epochs +between the current epoch and the proposed upgrade epoch for the upgrade +proposal to be valid. Additionally specifies the minimum number of epochs +between two consecutive pending upgrades.

  • upgrade_cancel_min_epoch_diff (epochs) specifies the minimum number of +epochs between the current epoch and the proposed upgrade epoch for the +upgrade cancellation proposal to be valid.

The following parameter sanity checks are introduced:

  • Product of quorum and threshold must be 2/3+.

  • voting_period must be less than upgrade_min_epoch_diff and +upgrade_cancel_min_epoch_diff.

Consequences

Positive

  • The consensus layer can coordinate on upgrades.

Negative

Neutral

References

+ + + + \ No newline at end of file diff --git a/adrs/0007-improved-random-beacon/index.html b/adrs/0007-improved-random-beacon/index.html new file mode 100644 index 0000000000..6cd9723609 --- /dev/null +++ b/adrs/0007-improved-random-beacon/index.html @@ -0,0 +1,105 @@ + + + + + +ADR 0007: Improved Random Beacon | Oasis Documentation + + + + +
+
Skip to main content

ADR 0007: Improved Random Beacon

Component

Oasis Core

Changelog

  • 2020-10-22: Initial version

Status

Proposed

Context

Any one who considers arithmetical methods of producing random digits +is, of course, in a state of sin.

--Dr. John von Neumann

The existing random beacon used by Oasis Core, is largely a placeholder +implementation that naively uses the previous block's commit hash as the +entropy input. As such it is clearly insecure as it is subject to +manipulation.

A better random beacon which is harder for an adversary to manipulate +is required to provide entropy for secure committee elections.

Decision

At a high level, this ADR proposes implementing an on-chain random beacon +based on "SCRAPE: Scalabe Randomness Attested by Public Entities" by +Cascudo and David. The new random beacon will use a commit-reveal scheme +backed by a PVSS scheme so that as long as the threshold of participants +is met, and one participant is honest, secure entropy will be generated.

Note: This document assumes the reader understands SCRAPE. Details +regarding the underlying SCRAPE implementation are omitted for brevity.

Node Descriptor

The node descriptor of each node will be extended to include the following +datastructure.

type Node struct {
// ... existing fields omitted ...

// Beacon contains information for this node's participation
// in the random beacon protocol.
//
// TODO: This is optional for now, make mandatory once enough
// nodes provide this field.
Beacon *BeaconInfo `json:"beacon,omitempty"`
}

// BeaconInfo contains information for this node's participation in
// the random beacon protocol.
type BeaconInfo struct {
// Point is the elliptic curve point used for the PVSS algorithm.
Point scrape.Point `json:"point"`
}

Each node will generate and maintain a long term elliptic curve point +and scalar pair (public/private key pair), the point (public key) of +which will be included in the node descriptor.

For the purposes of the initial implementation, the curve will be P-256.

Consensus Parameters

The beacon module will have the following consensus parameters that +control behavior.

type SCRAPEParameters struct {
Participants uint64 `json:"participants"`
Threshold uint64 `json:"threshold"`
PVSSThreshold uint64 `json:"pvss_threshold"`

CommitInterval int64 `json:"commit_interval"`
RevealInterval int64 `json:"reveal_interval"`
TransitionDelay int64 `json:"transition_delay"`
}

Fields:

  • Participants - The number of participants to be selected for each +beacon generation protocol round.

  • Threshold - The minimum number of participants which must +successfully contribute entropy for the final output to be +considered valid.

  • PVSSThreshold - The minimum number of participants that are +required to reconstruct a PVSS secret from the corresponding +decrypted shares (Note: This usually should just be set to +Threshold).

  • CommitInterval - The duration of the Commit phase, in blocks.

  • RevealInterval - The duration of the Reveal phase, in blocks.

  • TransitionDelay - The duration of the post Reveal phase delay, in blocks.

Consensus State and Events

The on-chain beacon will maintain and make available the following consensus +state.

// RoundState is a SCRAPE round state.
type RoundState uint8

const (
StateInvalid RoundState = 0
StateCommit RoundState = 1
StateReveal RoundState = 2
StateComplete RoundState = 3
)

// SCRAPEState is the SCRAPE backend state.
type SCRAPEState struct {
Height int64 `json:"height,omitempty"`

Epoch EpochTime `json:"epoch,omitempty"`
Round uint64 `json:"round,omitempty"`
State RoundState `json:"state,omitempty"`

Instance *scrape.Instance `json:"instance,omitempty"`
Participants []signature.PublicKey `json:"participants,omitempty"`
Entropy []byte `json:"entropy,omitempty"`

BadParticipants map[signature.PublicKey]bool `json:"bad_participants,omitempty"`

CommitDeadline int64 `json:"commit_deadline,omitempty"`
RevealDeadline int64 `json:"reveal_deadline,omitempty"`
TransitionHeight int64 `json:"transition_height,omitempty"`

RuntimeDisableHeight int64 `json:"runtime_disable_height,omitempty"`
}

Fields:

  • Height - The block height at which the last event was emitted.

  • Epoch - The epoch in which this beacon is being generated.

  • Round - The epoch beacon generation round.

  • State - The beacon generation step (commit/reveal/complete).

  • Instance - The SCRAPE protocol state (encrypted/decrypted shares of +all participants).

  • Participants - The node IDs of the nodes selected to participate +in this beacon generation round.

  • Entropy - The final raw entropy, if any.

  • BadParticipants - A map of nodes that were selected, but have failed +to execute the protocol correctly.

  • CommitDeadline - The height in blocks by which participants must +submit their encrypted shares.

  • RevealDeadline - The height in blocks by which participants must +submit their decrypted shares.

  • TransitionHeight - The height at which the epoch will transition +assuming this round completes successfully.

  • RuntimeDisableHeight - The height at which, upon protocol failure, +runtime transactions will be disabled. This height will be set to +the transition height of the 0th round.

Upon transition to a next step of the protocol, the on-chain beacon will +emit the following event.

// SCRAPEEvent is a SCRAPE backend event.
type SCRAPEEvent struct {
Height int64 `json:"height,omitempty"`

Epoch EpochTime `json:"epoch,omitempty"`
Round uint64 `json:"round,omitempty"`
State RoundState `json:"state,omitempty"`

Participants []signature.PublicKey `json:"participants,omitempty"`
}

Field definitions are identical to that of those in the SCRAPEState +datastructure.

Transactions

Participating nodes will submit the following transactions when required, +signed by the node identity key.

var (
// MethodSCRAPECommit is the method name for a SCRAPE commitment.
MethodSCRAPECommit = transaction.NewMethodName(ModuleName, "SCRAPECommit", SCRAPECommit{})

// MethodSCRAPEReveal is the method name for a SCRAPE reveal.
MethodSCRAPEReveal = transaction.NewMethodName(ModuleName, "SCRAPEReveal", SCRAPEReveal{})
)

// SCRAPECommit is a SCRAPE commitment transaction payload.
type SCRAPECommit struct {
Epoch EpochTime `json:"epoch"`
Round uint64 `json:"round"`

Commit *scrape.Commit `json:"commit,omitempty"`
}

// SCRAPEReveal is a SCRAPE reveal transaction payload.
type SCRAPEReveal struct {
Epoch EpochTime `json:"epoch"`
Round uint64 `json:"round"`

Reveal *scrape.Reveal `json:"reveal,omitempty"`
}

Fields:

  • Epoch - The epoch in which the transaction is applicable.

  • Round - The epoch beacon generation round for the transaction.

  • Commit - The SCRAPE commit consisting of PVSS shares encrypted to +every participant.

  • Reveal - The SCRAPE reveal consisting of the decrypted result of +PVSS shares received from every participant.

Beacon Generation

The beacon generation process is split into three sequential stages, +roughly corresponding to the steps in the SCRAPE protocol. Any failures +in the Commit and Reveal phases result in a failed protocol round, and +the generation process will restart after disqualifying participants who +have induced the failure.

Commit Phase

Upon epoch transition or a prior failed round the commit phase is initiated +the consensus application will select Particpants nodes from the current +validator set (in order of decending stake) to serve as entropy contributors.

The SCRAPEState structure is (re)-initialized, and a SCRAPEEvent is +broadcast to signal to the participants that they should generate and +submit their encrypted shares via a SCRAPECommit transaction.

Each commit phase lasts exactly CommitInterval blocks, at the end of which, +the round will be closed to further commits.

At the end of the commit phase, the SCRAPE protocol state is evaluated +to ensure that Threshold/PVSSThreshold nodes have published encrypted +shares, and if an insufficient number of nodes have published in either +case, the round is considered to have failed.

The following behaviors are currently candidates for a node being marked +as malicious/non-particpatory (BadParticipant) and subject to exclusion +from future rounds and slashing.

  • Not submitting a commitment.

  • Malformed commitments (corrupted/fails to validate/etc).

  • Attempting to alter an existing commitment for a given Epoch/Round.

Reveal Phase

When the CommitInterval has passed, assuming that a sufficient number of +commits have been received, the consensus application transitions into the +reveal phase by updating the SCRAPEState structure and broadcasting a +SCRAPEEvent to signal to the participants that they should reveal the +decrypted values of the encrypted shares received from other participants +via a SCRAPEReveal transaction.

Each reveal phase lasts exactly RevealInterval blocks, at the end of which, +the round will be closed to further reveals.

At the end of the reveal phase, the SCRAPE protocol state is evaluated to +ensure that Threshold/PVSSThreshold nodes have published decrypted +shares, and if an insufficient number of nodes have published in either +case, the round is considered to have failed.

The following behaviors are currently candidates for a node being marked +as malicious/non-participatory (BadParticipant) and subject to exclusion +from future rounds and slashing.

  • Not submitting a reveal.

  • Malformed commitments (corrupted/fails to validate/etc).

  • Attempting to alter an existing reveal for a given Epoch/Round.

Note: It is possible for anybody who can observe consensus state to derive +the entropy the moment a threshold number of SCRAPEReveal transactions +have been processed. Therefore the reveal phase should be a small fraction +of the desired epoch as it is possible to derive the results of the +committee elections for the next epoch mid-reveal phase.

Complete (Transition Wait) Phase

When the RevealInterval has passed, assuming that a sufficient number +of reveals have been received, the consensus application recovers the +final entropy output (the hash of the secret shared by each participant) +and transitions into the complete (transition wait) phase by updating the +SCRAPEState structure and broadcasting a SCRAPEEvent to signal to +participants the completion of the round.

No meaningful protocol activity happens one a round has successfully +completed, beyond the scheduling of the next epoch transition.

Misc. Changes/Notes

Nodes MUST not be slashed for non-participation if they have not had +the opportunity to propose any blocks during the relevant interval.

Processing commitments and reveals is currently rather CPU intensive +and thus each block SHOULD only contain one of each to prevent the +consesus from stalling.

To thwart attempts to manipulate committee placement by virute of the +fact that it is possible to observe the entropy used for elections early +nodes that register between the completion of the final commit phase and +the epoch transition in any given epoch MUST be excluded from committee +eligibility.

Consequences

Positive

  • The random beacon output is unbaised, provided that at least one +participant is honest.

  • The amount of consensus state required is relatively small.

  • All protocol messages and steps can be verified on-chain, and misbehavior +can be attributed.

  • The final output can be generated on-chain.

Negative

  • Epoch intervals are theoretically variable under this proposal, as the +beacon generation needs to be re-ran with new participants upon failure.

  • A new failure mode is introduced at the consensus layer, where the +beacon generation protocol exhausts eligible participants.

  • Without using pairing based cryptography, the number of participants +in the beacon generation is limited to a small subset of the anticipated +active validator set.

  • There is a time window where the next beacon can be derived by anyone +with access to the consensus state before the epoch transition actually +happens. This should be mitigated by having a relatively short reveal +period.

  • The commit and reveal steps of the protocol are rather slow, especially +as the number of participants increases.

Neutral

  • Due to performance reasons, the curve used by the PVSS scheme will +be P-256 instead of Ed25519. The point and scalar pairs that each +node generates on this curve are exclusively for use in the random +beacon protocol and are not used anywhere else.

References

+ + + + \ No newline at end of file diff --git a/adrs/0008-standard-account-key-generation/index.html b/adrs/0008-standard-account-key-generation/index.html new file mode 100644 index 0000000000..4ca84dab0a --- /dev/null +++ b/adrs/0008-standard-account-key-generation/index.html @@ -0,0 +1,135 @@ + + + + + +ADR 0008: Standard Account Key Generation | Oasis Documentation + + + + +
+
Skip to main content

ADR 0008: Standard Account Key Generation

Component

Oasis Core

Changelog

  • 2021-05-07: Add test vectors and reference implementation, extend Consequences +section
  • 2021-04-19: Switch from BIP32-Ed25519 to SLIP-0010 for hierarchical key +derivation scheme
  • 2021-01-27: Initial draft

Status

Accepted

Context

Currently, each application interacting with the Oasis Network defines its own +method of generating an account's private/public key pair.

Account's public key is in turn used to derive the account's address of the +form oasis1 ... 40 characters ... which is used to for a variety of operations +(i.e. token transfers, delegations/undelegations, ...) on the network.

The blockchain ecosystem has developed many standards for generating keys which +improve key storage and interoperability between different applications.

Adopting these standards will allow the Oasis ecosystem to:

  • Make key derivation the same across different applications (i.e. wallets).
  • Allow users to hold keys in hardware wallets.
  • Allow users to hold keys in cold storage more reliably (i.e. using the +familiar 24 word mnemonics).
  • Define how users can generate multiple keys from a single seed (i.e. +the 24 or 12 word mnemonic).

Decision

Mnemonic Codes for Master Key Derivation

We use Bitcoin's BIP-0039: Mnemonic code for generating deterministic keys +to derivate a binary seed from a mnemonic code.

The binary seed is in turn used to derive the master key, the root key from +which a hierarchy of deterministic keys is derived, as described in +Hierarchical Key Derivation Scheme.

We strongly recommend using 24 word mnemonics which correspond to 256 bits of +entropy.

Hierarchical Key Derivation Scheme

We use Sathoshi Labs' SLIP-0010: Universal private key derivation from master +private key, which is a superset of +Bitcoin's BIP-0032: Hierarchical Deterministic Wallets derivation algorithm, +extended to work on other curves.

Account keys use the edwards25519 curve from the Ed25519 signature scheme +specified in RFC 8032.

Key Derivation Paths

We adapt BIP-0044: Multi-Account Hierarchy for Deterministic Wallets for +generating deterministic keys where coin_type equals 474, as assigned to the +Oasis Network by SLIP-0044.

The following BIP-0032 path should be used to generate keys:

m/44'/474'/x'

where x represents the key number.

Note that all path levels are hardened, e.g. 44' is 44 | 0x8000000 or +44 + 2^31.

The key corresponding to key number 0 (i.e. m/44'/474'/0') is called the +primary key.

The account corresponding to the primary key is called the primary account. +Applications (i.e. wallets) should use this account as a user's default Oasis +account.

Rationale

BIPs and SLIPs are industry standards used by a majority of blockchain projects +and software/hardware wallets.

SLIP-0010 for Hierarchical Key Derivation Scheme

SLIP-0010 defines a hierarchical key derivation scheme which is a superset of +BIP-0032 derivation algorithm extended to work on other curves.

In particular, we use their adaptation for the edwards25519 curve.

Adoption

It is used by Stellar (SEP-0005).

It is supported by Ledger and Trezor hardware wallets.

It is commonly used by Ledger applications, including:

Difficulties in Adapting BIP-0032 to edwards25519 Curve

Creating a hierarchical key derivation scheme for the edwards25519 curve +proved to be very challenging due to edwards25519's small cofactor and bit +"clamping".

BIP-0032 was designed for the secp256k1 elliptic curve with a prime-order +group. For performance reasons, edwards25519 doesn't provide a prime-order group +and provides a group of order h * l instead, where h is a small co-factor +(8) and l is a 252-bit prime.

While using a co-factor offers better performance, it has proven to be a source +of issues and vulnerabilities in higher-layer protocol implementations as +described by Risretto authors.

Additionally, edwards25519 curve employs bit "clamping". As described by Trevor +Perrin, low bits are "clamped" to deal with +small-subgroup attacks and high bits are "clamped" so that:

  • the scalar is smaller than the subgroup order, and
  • the highest bit set is constant in case the scalar is used with a +non-constant-time scalar multiplication algorithm that leaks based on the +highest set bit.

These issues were discussed on modern crypto's mailing list [[1]][ +moderncrypto-ed25519-hd1], [2].

SLIP-0010 avoids these issues because it doesn't try to support non-hardened +parent public key to child public key derivation and only supports hardened +private parent key to private child key derivation when used with the +edwards25519 curve.

Shorter Key Derivation Paths

Similar to Stellar's SEP-0005, we decided not to use the full BIP-0032 +derivation path specified by BIP-0044 because SLIP-0010's scheme for +edwards25519 curve only supports hardened private parent key to private child +key derivation and additionally, the Oasis Network is account-based rather than +UTXO-based.

Trezor follows the same scheme for account-based blockchain networks as +described in their BIP-44 derivation paths document.

Test Vectors

[
{
"kind": "standard account key generation",
"bip39_mnemonic": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
"bip39_passphrase": "",
"bip39_seed": "5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4",
"oasis_accounts": [
{
"bip32_path": "m/44'/474'/0'",
"private_key": "fb181e94e95cc6bedd2da03e6c4aca9951053f3e9865945dbc8975a6afd217c3ad55bbb7c192b8ecfeb6ad18bbd7681c0923f472d5b0c212fbde33008005ad61",
"public_key": "ad55bbb7c192b8ecfeb6ad18bbd7681c0923f472d5b0c212fbde33008005ad61",
"address": "oasis1qqx0wgxjwlw3jwatuwqj6582hdm9rjs4pcnvzz66"
},
{
"bip32_path": "m/44'/474'/1'",
"private_key": "1792482bcb001f45bc8ab15436e62d60fe3eb8c86e8944bfc12da4dc67a5c89b73fd7c51a0f059ea34d8dca305e0fdb21134ca32216ca1681ae1d12b3d350e16",
"public_key": "73fd7c51a0f059ea34d8dca305e0fdb21134ca32216ca1681ae1d12b3d350e16",
"address": "oasis1qr4xfjmmfx7zuyvskjw9jl3nxcp6a48e8v5e27ty"
},
{
"bip32_path": "m/44'/474'/2'",
"private_key": "765be01f40c1b78dd807e03a5099220c851cfe55870ab082be2345d63ffb9aa40f85ea84b81abded443be6ab3e16434cdddebca6e12ea27560a6ed65ff1998e0",
"public_key": "0f85ea84b81abded443be6ab3e16434cdddebca6e12ea27560a6ed65ff1998e0",
"address": "oasis1qqtdpw7jez243dnvmzfrhvgkm8zpndssvuwm346d"
},
{
"bip32_path": "m/44'/474'/3'",
"private_key": "759b3c2af3d7129072666677b37e9e7b6d22c8bbf634816627e1704f596f60c411ebdac05bfa37b746692733f15a02be9842b29088272354012417a215666b0e",
"public_key": "11ebdac05bfa37b746692733f15a02be9842b29088272354012417a215666b0e",
"address": "oasis1qqs7wl20gfppe2krdy3tm4298yt9gftxpc9j27z2"
},
{
"bip32_path": "m/44'/474'/4'",
"private_key": "db77a8a8508fd77083ba63f31b0a348441d4823e6ba73b65f354a93cf789358d8753c5da6085e6dbf5969773d27b08ee05eddcb3e11d570aaadf0f42036e69b1",
"public_key": "8753c5da6085e6dbf5969773d27b08ee05eddcb3e11d570aaadf0f42036e69b1",
"address": "oasis1qq8neyfkydj874tvs6ksljlmtxgw3plkkgf69j4w"
},
{
"bip32_path": "m/44'/474'/5'",
"private_key": "318e1fba7d83ca3ea57b0f45377e77391479ec38bfb2236a2842fe1b7a624e8800e1a8016629f2882bca2174f29033ec2a57747cd9d3c27f49cc6e11e38ee7bc",
"public_key": "00e1a8016629f2882bca2174f29033ec2a57747cd9d3c27f49cc6e11e38ee7bc",
"address": "oasis1qrdjslqdum7wwehz3uaw6t6xkpth0a9n8clsu6xq"
},
{
"bip32_path": "m/44'/474'/6'",
"private_key": "63a7f716e1994f7a8ab80f8acfae4c28c21af6b2f3084756b09651f4f4ee38606b85d0a8a9747faac85233ad5e4501b2a6862a4c02a46a0b7ea699cf2bd38f98",
"public_key": "6b85d0a8a9747faac85233ad5e4501b2a6862a4c02a46a0b7ea699cf2bd38f98",
"address": "oasis1qzlt62g85303qcrlm7s2wx2z8mxkr5v0yg5me0z3"
},
{
"bip32_path": "m/44'/474'/7'",
"private_key": "34af69924c04d75c79bd120e03d667ff6287ab602f9285bb323667ddf9f25c974f49a7672eeadbf78f910928e3d592d17f1e14964693cfa2afd94b79f0d49f48",
"public_key": "4f49a7672eeadbf78f910928e3d592d17f1e14964693cfa2afd94b79f0d49f48",
"address": "oasis1qzw2gd3qq8nse6648df32zxvsryvljeyyyl3cxma"
},
{
"bip32_path": "m/44'/474'/8'",
"private_key": "aa5242e7efe8dee05c21192766a11c46531f500ff7c0cc29ed59523c5e618792c0a24bf07953520f21c1c25882d9dbf00d24d0499be443fdcf07f2da9601d3e5",
"public_key": "c0a24bf07953520f21c1c25882d9dbf00d24d0499be443fdcf07f2da9601d3e5",
"address": "oasis1qqzjkx9u549r87ctv7x7t0un29vww6k6hckeuvtm"
},
{
"bip32_path": "m/44'/474'/9'",
"private_key": "b661567dcb9b5290889e110b0e9814e72d347c3a3bad2bafe2969637541451e5da8c9830655103c726ff80a4ac2f05a7e0b948a1986734a4f63b3e658da76c66",
"public_key": "da8c9830655103c726ff80a4ac2f05a7e0b948a1986734a4f63b3e658da76c66",
"address": "oasis1qpawhwugutd48zu4rzjdcgarcucxydedgq0uljkj"
},
{
"bip32_path": "m/44'/474'/2147483647'",
"private_key": "cc05cca118f3f26f05a0ff8e2bf5e232eede9978b7736ba10c3265870229efb19e7c2b2d03265ce4ea175e3664a678182548a7fc6db04801513cff7c98c8f151",
"public_key": "9e7c2b2d03265ce4ea175e3664a678182548a7fc6db04801513cff7c98c8f151",
"address": "oasis1qq7895v02vh40yc2dqfxhldww7wxsky0wgfdenrv"
}
]
},
{
"kind": "standard account key generation",
"bip39_mnemonic": "equip will roof matter pink blind book anxiety banner elbow sun young",
"bip39_passphrase": "",
"bip39_seed": "ed2f664e65b5ef0dd907ae15a2788cfc98e41970bc9fcb46f5900f6919862075e721f37212304a56505dab99b001cc8907ef093b7c5016a46b50c01cc3ec1cac",
"oasis_accounts": [
{
"bip32_path": "m/44'/474'/0'",
"private_key": "4e9ca1a4c2ed90c90da93ea181557ef9f465f444c0b7de35daeb218f9390d98545601f761af17dba50243529e629732f1c58d08ffddaa8491238540475729d85",
"public_key": "45601f761af17dba50243529e629732f1c58d08ffddaa8491238540475729d85",
"address": "oasis1qqjkrr643qv7yzem6g4m8rrtceh42n46usfscpcf"
},
{
"bip32_path": "m/44'/474'/1'",
"private_key": "2d0d2e75a13fd9dc423a2db8dfc1db6ebacd53f22c8a7eeb269086ec3b443eb627ed04a3c0dcec6591c001e4ea307d65cbd712cb90d85ab7703c35eee07a77dd",
"public_key": "27ed04a3c0dcec6591c001e4ea307d65cbd712cb90d85ab7703c35eee07a77dd",
"address": "oasis1qp42qp8d5k8pgekvzz0ld47k8ewvppjtmqg7t5kz"
},
{
"bip32_path": "m/44'/474'/2'",
"private_key": "351749392b02c6b7a5053bc678e71009b4fb07c37a67b44558064dc63b2efd9219456a3f0cf3f4cc5e6ce52def57d92bb3c5a651fa9626b246cfec07abc28724",
"public_key": "19456a3f0cf3f4cc5e6ce52def57d92bb3c5a651fa9626b246cfec07abc28724",
"address": "oasis1qqnwwhj4qvtap422ck7qjxf7wm89tgjhwczpu0f3"
},
{
"bip32_path": "m/44'/474'/3'",
"private_key": "ebc13ccb62142ed5b600f398270801f8f80131b225feb278d42982ce314f896292549046214fdb4729bf7a6ee4a3bbd0f463c476acc933b2c7cce084509abee4",
"public_key": "92549046214fdb4729bf7a6ee4a3bbd0f463c476acc933b2c7cce084509abee4",
"address": "oasis1qp36crawwyk0gnfyf0epcsngnpuwrz0mtu8qzu2f"
},
{
"bip32_path": "m/44'/474'/4'",
"private_key": "664b95ad8582831fb787afefd0febdddcf03343cc1ca5aa86057477e0f22c93b331288192d442d3a32e239515b4c019071c57ee89f91942923dd4c1535db096c",
"public_key": "331288192d442d3a32e239515b4c019071c57ee89f91942923dd4c1535db096c",
"address": "oasis1qz8d2zptvf44y049g9dtyqya4g0jcqxmjsf9pqa3"
},
{
"bip32_path": "m/44'/474'/5'",
"private_key": "257600bfccc21e0bc772f4d1dcfb2834805e07959ad7bd586e7deec4a320bfcecbbfef21f0833744b3504a9860b42cb0bb11e2eb042a8b83e3ceb91fe0fca096",
"public_key": "cbbfef21f0833744b3504a9860b42cb0bb11e2eb042a8b83e3ceb91fe0fca096",
"address": "oasis1qz0cxkl3mftumy9l4g663fmwg69vmtc675xh8exw"
},
{
"bip32_path": "m/44'/474'/6'",
"private_key": "10d224fbbac9d6e3084dff75ed1d3ae2ce52bce3345a48bf68d1552ed7d89594defb924439e0c93f3b14f25b3cb4044f9bc9055fa4a14d89f711528e6760133b",
"public_key": "defb924439e0c93f3b14f25b3cb4044f9bc9055fa4a14d89f711528e6760133b",
"address": "oasis1qz3pjvqnkyj42d0mllgcjd66fkavzywu4y4uhak7"
},
{
"bip32_path": "m/44'/474'/7'",
"private_key": "517bcc41be16928d32c462ee2a38981ed15b784028eb0914cfe84acf475be342102ad25ab9e1707c477e39da2184f915669791a3a7b87df8fd433f15c926ede2",
"public_key": "102ad25ab9e1707c477e39da2184f915669791a3a7b87df8fd433f15c926ede2",
"address": "oasis1qr8zs06qtew5gefgs4608a4dzychwkm0ayz36jqg"
},
{
"bip32_path": "m/44'/474'/8'",
"private_key": "ee7577c5cef5714ba6738635c6d9851c43428ff3f1e8db2fe7f45fb8d8be7c55a6ec8903ca9062910cc780c9b209c7767c2e57d646bbe06901d090ad81dabe8b",
"public_key": "a6ec8903ca9062910cc780c9b209c7767c2e57d646bbe06901d090ad81dabe8b",
"address": "oasis1qp7w82tmm6srgxqqzragdt3269334pjtlu44qpeu"
},
{
"bip32_path": "m/44'/474'/9'",
"private_key": "5257b10a5fcfd008824e2216be17be6e47b9db74018f63bb55de4d747cae6d7bba734348f3ec7af939269f62828416091c0d89e14c813ebf5e64e24d6d37e7ab",
"public_key": "ba734348f3ec7af939269f62828416091c0d89e14c813ebf5e64e24d6d37e7ab",
"address": "oasis1qp9t7zerat3lh2f7xzc58ahqzta5kj4u3gupgxfk"
},
{
"bip32_path": "m/44'/474'/2147483647'",
"private_key": "e7152f1b69ad6edfc05dccf67dad5305edb224669025c809d89de7e56b2cabe58c348f412819da57361cdbd7dfbe695a05dba7f24b8e7328ff991ffadab6c4d2",
"public_key": "8c348f412819da57361cdbd7dfbe695a05dba7f24b8e7328ff991ffadab6c4d2",
"address": "oasis1qzajez400yvnzcv8x8gtcxt4z5mkfchuh5ca05hq"
}
]
}
]

To generate these test vectors yourself, run:

make -C go staking/gen_account_vectors

We also provide more extensive test vectors. To generate them, run:

make -C go staking/gen_account_vectors_extended

Implementation

Reference implementation is in Oasis Core's go/common/crypto/sakg package.

Alternatives

BIP32-Ed25519 for Hierarchical Key Derivation

The BIP32-Ed25519 (also sometimes referred to as Ed25519 and BIP32 +based on Khovratovich) is a key derivation scheme that also adapts +BIP-0032's hierarchical derivation scheme for the edwards25519 curve from +the Ed25519 signature scheme specified in RFC 8032.

Adoption

It is used by Cardano (CIP 3) and Tezos (dubbed bip25519 derivation scheme).

It is supported by Ledger and Trezor hardware wallets.

It is commonly used by Ledger applications, including:

Security Concerns

Its advantage is that it supports non-hardened parent public key to child public +key derivation which enables certain use cases described in [BIP-0032][ +BIP-0032-use-cases] (i.e. audits, insecure money receiver, ...).

At the same time, allowing non-hardened parent public key to child public key +derivation presents a serious security concern due to edwards25519's co-factor +issues.

Jeff Burdges (Web3 Foundation) warned about a potential key recovery attack +on the BIP32-Ed25519 scheme which could occur under the +following two assumptions:

  1. The Ed25519 library used in BIP-Ed25519 derivation scheme does clamping +immediately before signing.
  2. Adversary has the power to make numerous small payments in deep hierarchies +of key derivations, observe if the victim can cash out each payment, and +adaptively continue this process.

The first assumption is very reasonable since the BIP32-Ed25519 paper makes +supporting this part of their specification.

The second assumption is a bit more controversial. +The BIP32-Ed25519 paper's specification limits the BIP-0032 path length +(i.e. the number of levels in the tree) to 220. +But in practice, no implementation checks that and the issue is that path length +is not an explicit part of the BIP32-Ed25519 algorithm. That means that one +doesn't know how deep in the tree the current parent/child node is. Hence, it +would be very hard to enforce the 220 path length limit.

Implementation Issues

One practical issue with BIP32-Ed25519 is that its authors didn't provide a +reference implementation and accompanying test vectors.

This has led to a number of incompatible BIP32-Ed25519 implementations.

For example, Vincent Bernardoff's OCaml implementation +and Shude Li's Go implementation follow BIP32-Ed25519's +original master (i.e. root) key derivation specification and use SHA512 and +SHA256 for deriving the private key k and chain code c (respectively) from +the seed (i.e. master secret).

On the other hand, Ledger's [Python implementation in orakolo repository][ +BIP32-Ed25519-orakolo] and [C implementation for their Speculos emulator][ +BIP32-Ed25519-speculos] (variant with curve equal to CX_CURVE_Ed25519 and +mode equal to HDW_NORMAL) use HMAC-SHA512 and HMAC-SHA256 for deriving the +private key k and chain code c (respectively) from the seed.

Furthermore, [Vincent Bernardoff's OCaml implementation][ +BIP32-Ed25519-OCaml-root-discard] follows BIP32-Ed25519 paper's instructions +to discard the seed (i.e. master secret) if the master key's third highest bit +of the last byte of kL is not zero.

On the other hand, Shude Li's Go implementation +just clears the master key's third highest bit +and Ledger's implementations repeatedly set +the seed to the master key and restart the derivation process until a master key +with the desired property is found.

Cardano uses its own variants of BIP32-Ed25519 described in CIP 3. In +particular, they define different variants of master key derivation from the +seed described in SLIP-0023.

Lastly, some implementations, notably Oasis' Ledger app, +don't use use BIP32-Ed25519's private and public key directly but use the +obtained kL (first 32 bytes) of the 64 byte BIP32-Ed25519 derived +private key as Ed25519's seed (i.e. non-extended private key). For more details, +see Zondax/ledger-oasis#84.

Tor's Next Generation Hidden Service Keys for Hierarchical Key Derivation

The Next-Generation Hidden Services in Tor specification defines a +hierarchical key derivation scheme for Tor's keys which employs +multiplicative blinding instead of an additive one use by BIP-0032.

Jeff Burdges (Web3 Foundation)'s post on potential key recovery +attack on the BIP32-Ed25519 scheme mentions there is +nothing wrong with this proposed scheme. +Likewise, Justin Starry (Solana)'s summary of approaches to adopting BIP-0032 +for Ed25519 recommends this scheme as one of the possible +approaches to adapt BIP-0032 for edwards25519 curve.

One practical issue with using this scheme would be the absence of support by +the Ledger and Trezor hardware wallets.

Consequences

Positive

  • Different applications interacting with the Oasis Network will use a +standards-compliant (BIP-0039, SLIP-0010, BIP-0044) and +interoperable account key generation process.

    Hence, there will be no vendor lock-in and users will have the option to +easily switch between standards-compliant applications (e.g. different +wallets).

  • Using SLIP-0010 avoids a spectrum of issues when trying to support +non-hardened public parent key to public child key derivation with the +edwards25519 curve. +Non-hardened key derivation is practically impossible to implement securely +due to edwards25519 curve's co-factor issues.

    This is achieved by SLIP-0010 explicitly disallowing non-hardened public +parent key to public child key derivation with the edwards25519 curve.

  • Using a 3-level BIP-0032 path (i.e. m/44'/474'/x') +allows Oasis' Ledger app to implement automatic switching +between existing (legacy) account key generation and the standard account key +generation proposed in this ADR.

    Since the existing (legacy) account key generation used in +Oasis' Ledger app uses a 5-level BIP-0032 path, the +Oasis' Ledger app will be able to automatically switch between standard and +existing (legacy) account key generation just based on the number of levels of +the given BIP-0032 path.

Negative

  • The account key generation proposed in this ADR is incompatible with two +existing account key generation schemes deployed in the field:

    That means that these two applications will need to support two account key +generations schemes simultaneously to allow existing users to access their +(old) accounts generated via the existing (legacy) account key generation +scheme.

  • SLIP-0010's scheme for edwards25519 curve only supports hardened private +parent key to private child key derivation.

    That means it will not be possible to implement wallet features that require +non-hardened key derivation, e.g. watch-only feature where one is able to +monitor a hierarchical wallet's accounts just by knowing the root public key +and deriving all accounts' public keys from that.

Neutral

References

+ + + + \ No newline at end of file diff --git a/adrs/0009-ed25519-semantics/index.html b/adrs/0009-ed25519-semantics/index.html new file mode 100644 index 0000000000..db238e755b --- /dev/null +++ b/adrs/0009-ed25519-semantics/index.html @@ -0,0 +1,48 @@ + + + + + +ADR 0009: Ed25519 Signature Verification Semantics | Oasis Documentation + + + + +
+
Skip to main content

ADR 0009: Ed25519 Signature Verification Semantics

Component

Oasis Core

Changelog

  • 2021-05-10: Initial version

Status

Informative

Context

In programming, it's often the buts in the specification that kill you.

-- Boris Beizer

For a large host of reasons, mostly historical, there are numerous definitions +of "Ed25519 signature validation" in the wild, which have the potential to +be mutually incompatible. This ADR serves to provide a rough high-level +overview of the issue, and to document the current definition of "Ed25519 +signature verification" as used by Oasis Core.

Decision

The Oasis Core consensus layer (and all of the Go components) currently uses +the following Ed25519 verification semantics.

  • Non-canonical s is rejected (MUST enforce s < L)
  • Small order A/R are rejected
  • Non-canonical A/R are accepted
  • The cofactored verification equation MUST be used ([8][S]B = [8]R + [8][k]A)
  • A/R may have a non-zero torsion component.

Reject Non-canonical s

Ed25519 signatures are trivially malleable unless the scalar component is +constrained to 0 <= s < L, as is possible to create valid signatures +from an existing public key/message/signature tuple by adding L to s.

This check is mandated in all recent formulations of Ed25519 including +but not limited to RFC 8032 and FIPS 186-5, and most modern implementations +will include this check.

Note: Only asserting that s[31] & 224 == 0 as done in older implementations +is insufficient.

Reject Small Order A/R

Rejecting small order A is required to make the signature scheme strongly +binding (resilience to key/message substitution attacks).

Rejecting (or accepting) small order R is not believed to have a security +impact.

Accept Non-canonical A/R

The discrete logarithm of the Ed25519 points that have a valid non-canonical +encoding and are not small order is unknown, and accepting them is not +believed to have a security impact.

Note: RFC 8032 and FIPS 186-5 require rejecting non-canonically encoded +points.

Cofactored Verification Equation

There are two forms of the Ed25519 verification equation commonly in use, +[S]B = R + [k]A (cofactor-less), and [8][S]B = [8]R + [8][k]A +(cofactored), which are mutually incompatible in that it is possible +to produce signatures that pass with one and fail with the other.

The cofactored verification equation is explicitly required by FIPS 186-5, +and is the only equation that is compatible with batch signature verification. +Additionally, the more modern lattice-reduction based technique for fast +signature verification is incompatible with existing implementations unless +cofactored.

Accept A/R With Non-zero Torsion

No other library enforces this, the check is extremely expensive, and +with how Oasis Core currently uses Ed25519 signatures, this has no security +impact. In the event that Oasis Core does exotic things that, for example, +require that the public key is in the prime-order subgroup, this must be +changed.

Consequences

Positive

The verification semantics in use by Oasis Core provides the following +properties:

  • SUF-CMA security
  • Non-repudiation (strong binding)
  • Compatibility with batch and lattice reduction based verification.

Negative

The combination of "reject small order A/R" and "accept non-canonical A/R" +is difficult to test as it is not easily possible to generate valid +signatures that meet both conditions.

Neutral

Future Improvements

WARNING: Any changes to verification semantics are consensus breaking.

  • Consider switching to the "Algorithm 2" definition, for ease of testing +and because it is the default behavior provided by curve25519-voi.
  • Consider switching to ZIP-215 semantics, to be inline with other projects, +more library support (Give up on strong binding).
  • Switching to ristretto255 (sr25519) eliminates these problems entirely.

Recomendations For Future Projects

The definition used in Oasis Core is partly historical. New code should +strongly consider using one of FIPS 186-5, Algorithm 2, or ZIP-215 semantics.

References

+ + + + \ No newline at end of file diff --git a/adrs/0010-vrf-elections/index.html b/adrs/0010-vrf-elections/index.html new file mode 100644 index 0000000000..0d4dd2b98a --- /dev/null +++ b/adrs/0010-vrf-elections/index.html @@ -0,0 +1,83 @@ + + + + + +ADR 0010: VRF-based Committee Elections | Oasis Documentation + + + + +
+
Skip to main content

ADR 0010: VRF-based Committee Elections

Component

Oasis Core

Changelog

  • 2021-05-10: Initial version

Status

Accepted

Context

While functional, the current PVSS-based random beacon is neither all that +performant, nor all that scalable. To address both concerns, this ADR +proposes transitioning the election procedure to one that is based on +cryptographic sortition of Verifiable Random Function (VRF) outputs.

Decision

Cryptographic Primitives

Let the VRF to be used across the system be ECVRF-EDWARDS25519-SHA512-ELL2 +from the Verifiable Random Functions (VRFs) draft (v10), with the +following additions and extra clarifications:

  • All public keys MUST be validated via the "ECVRF Validate Key" procedure +as specified in section 5.6.1 (Small order public keys MUST be +rejected).

  • The string_to_point routine MUST reject non-canonically encoded points +as specified in RFC 8032. Many ed25519 implementations are lax about +enforcing this when decoding.

  • When decoding s in the ECVRF_verify routine, the s scalar MUST fall +within the range 0 <= i < L. This change will make proofs +non-malleable. Note that this check is unneeded for the c scalar +as it is 128-bits, and thus will always lie within the valid range. +This check was not present in the IETF draft prior to version 10.

  • Implementations MAY choose to incorporate additional randomness into +the ECVRF_nonce_generation_RFC8032 function. Note that proofs (pi_string) +are not guaranteed to be unique or deterministic even without this +extension (the signer can use any arbitrary value for the nonce and +produce a valid proof, without altering beta_string).

Let the tuple oriented cryptographic hash function be TupleHash256 from +NIST SP 800-185.

Node Descriptor Changes

The node descriptor of each node will be extended to include the following +datastructure.

type Node struct {
// ... existing fields omitted ...

// VRF is the public key used by the node to generate VRF proofs.
VRF *VRFInfo `json:"vrf,omitempty"`
}

type VRFInfo struct {
// ID is the unique identifier of the node used to generate VRF proofs.
ID signature.PublicKey `json:"id"`
}

The VRF public key shall be a long-term Ed25519 public key, that is distinct +from every other key used by the node. The key MUST not be small order.

The existing Beacon member of the node descriptor is considered deprecated +and will first be ignored by the consensus layer, and then removed in a +subsequent version following a transitionary period.

Consensus Parameters

The scheduler module will have the following additional consensus parameters +that control behavior.

type ConsensusParameters struct {
// ... existing fields omitted ...

// VRFParameters is the paramenters for the VRF-based cryptographic
// sortition based election system.
VRFParameters *VRFParameters `json:"vrf_params"`
}

// VRFParameters are the VRF scheduler parameters.
type VRFParameters struct {
// AlphaHighQualityThreshold is the minimum number of proofs (Pi)
// that must be received for the next input (Alpha) to be considered
// high quality. If the VRF input is not high quality, runtimes will
// be disabled for the next epoch.
AlphaHighQualityThreshold uint64 `json:"alpha_hq_threshold,omitempty"`

// Interval is the epoch interval (in blocks).
Interval int64 `json:"interval,omitempty"`

// ProofSubmissionDelay is the wait peroid in blocks after an epoch
// transition that nodes MUST wait before attempting to submit a
// VRF proof for the next epoch's elections.
ProofSubmissionDelay int64 `json:"proof_delay,omitempty"`

// PrevState is the VRF state from the previous epoch, for the
// current epoch's elections.
PrevState *PrevVRFState `json:"prev_state,omitempty"`
}

// PrevVRFState is the previous epoch's VRF state that is to be used for
// elections.
type PrevVRFState struct {
// Pi is the accumulated pi_string (VRF proof) outputs for the
// previous epoch.
Pi map[signature.PublicKey]*signature.Proof `json:"pi.omitempty"`

// CanElectCommittees is true iff the previous alpha was generated
// from high quality input such that committee elections are possible.
CanElectCommittees bool `json:"can_elect,omitempty"`
}

Consensus State, Events, and Transactions

The scheduler component will maintain and make available the following additonal +consensus state.

// VRFState is the VRF scheduler state.
type VRFState struct {
// Epoch is the epoch for which this alpha is valid.
Epoch EpochTime `json:"epoch"`

// Alpha is the active VRF alpha_string input.
Alpha []byte `json:"alpha"`

// Pi is the accumulated pi_string (VRF proof) outputs.
Pi map[signature.PublicKey]*signature.Proof `json:"pi,omitempty"`

// AlphaIsHighQuality is true iff the alpha was generated from
// high quality input such that elections will be possible.
AlphaIsHighQuality bool `json:"alpha_hq"`

// SubmitAfter is the block height after which nodes may submit
// VRF proofs for the current epoch.
SubmitAfter int64 `json:"submit_after"`
}

Implementations MAY cache the beta_string values that are generated from valid +pi_strings for performance reasons, however as this is trivial to recalculate, +it does not need to be explicitly exposed.

Upon epoch transition, the scheduler will emit the following event.

// VRFEvent is the VRF scheduler event.
type VRFEvent struct {
// Epoch is the epoch that Alpha is valid for.
Epoch EpochTime `json:"epoch,omitempty"`

// Alpha is the active VRF alpha_string input.
Alpha []byte `json:"alpha,omitempty"`

// SubmitAfter is the block height after which nodes may submit
// VRF proofs for the current epoch.
SubmitAfter int64 `json:"submit_after"`
}

type VRFProve struct {
// Epoch is the epoch that this VRF proof is for.
Epoch epochtime.EpochTime `json:"epoch"`

// Pi is the VRF proof for the current epoch.
Pi []byte `json:"pi"`
}

VRF Operation

For the genesis epoch, let the VRF alpha_string input be derived as:

TupleHash256((chain_context, I2OSP(epoch,8)), 256, "oasis-core:vrf/alpha")

For every subsequent epoch, let alpha_string be derived as:

TupleHash256((chain_context, I2OSP(epoch, 8), beta_0, ... beta_n), 256, "oasis-core:vrf/alpha")

where beta_0 through beta_n are the beta_string outputs gathered from +all valid pi_strings submitted during the previous epoch (after the +on-transition culling is complete), in ascending lexographic order by +VRF key. If the number of beta values incorporated into the TupleHash +computation is greater than or equal to AlphaHighQuality threshold, +the alpha is considered "strong", and committee elections are allowed +based on the proofs generated with this alpha. If the alpha value is +weak (insufficient nodes submitted proofs), only validator elections +are allowed.

Upon receiving a VRFEvent, all eligible nodes MUST wait a minimum of +ProofSubmissionDelay blocks, and then submit a VRFProve transaction, +with the Proof field set to the output of +ECVRF_prove(VRFKey_private, alpha_string).

Upon receiving a VRFProve transaction, the scheduler does the following:

  1. Rejects the transaction if less than ProofSubmissionDelay blocks +have elapsed since the transition into the current epoch.

  2. Checks to see if the node tentatively eligible to be included in +the next election according to the following criteria:

    • Not frozen.

    • Has registered the VRF.ID used to generate the proof prior +to the transition into the current epoch (May slash).

    • Has not already submitted a proof for the current epoch +(May slash if proof is different).

  3. Validates the proof, and if valid, stores the VRF.ID + pi_string +in the consensus state.

VRF Committee Elections

The following changes are made to the committee election process.

On epoch transition, as long as the alpha used to generate the proofs +is considered strong re-validate node eligibility for all nodes that +submitted a VRF proof (Not frozen, VRF.ID has not changed), and cull +proofs from nodes that are now ineligible.

If the alpha value is considered weak, no commitee elections are allowed.

For each committee:

  1. Filter the node list based on the current stake/eligibility criteria, +and additionally filter out nodes that have not submitted a valid +VRF proof.

  2. For each eligible (node, commitee kind, committe role) tuple, derive +a sortition string as:

`s_n = TupleHash256((chain_context, I2OSP(epoch, 8), runtime_id, I2OSP(kind, 1), I2OSP(role, 1), beta_n), 256, "oasis-core:vrf/committee")`
  1. Sort s_0 ... s_n in ascending lexographical order.

  2. Select the requisite nodes that produced the sortition strings +starting from the head of the sorted list as the committee.

Committee elections MUST be skipped for the genesis and subsequent epoch, +as the genesis epoch has no VRF proofs, and proofs submitted during the +genesis epoch are based on the bootstrap alpha_string.

VRF Validator Elections

The only place where the beacon is currently used in the validator selection +process is to pick a single node out of multiple eligible nodes controlled by +the same entity to become a validator.

When this situation occurs the validator is selected as follows:

  1. For all validator-eligible nodes controlled by the given entity, +derive a sortition string as:
 `s_n = TupleHash256((chain_context, I2OSP(epoch, 8), beta_n), 256, "oasis-core:vrf/validator")`
  1. Sort s_0 ... s_n, in ascending lexographic order.

  2. Select the node that produced the 0th sortition string in the sorted +list as the validator.

This is safe to do with beta values generated via the bootstrap alpha string +as it is up to the entity running the nodes in question as to which ones +are a validator anyway.

As a concession for the transition process, if the number of validators +that submit proofs is less than the minimum number of validators configured +in the scheduler, validator tie-breaks (and only validator tie-breaks) +will be done by permuting the node list (as in the current PVSS beacon), +using entropy from the block hash.

As nodes are required to submit a VRF public key as part of non-genesis +registrations, and each node will attempt to submit a VRF proof, this +backward compatibility hack should only be triggered on the genesis +epoch, and can be removed on the next major upgrade.

Timekeeping Changes

Timekeeping will go back to a fixed-interval epoch transition mechanism, with +all of the beacon related facilities removed. As this is primarily a module +rename and code removal, the exact details are left unspecified.

Consequences

Positive

  • This is significantly simpler from a design standpoint.

  • This is significantly faster and scales significantly better.

  • It is possible to go back to fixed-length epochs again.

Negative

  • The system loses a way to generate entropy at the consensus layer.

  • The simple design involves an additional 1-epoch period after network +initialization where elections are not available.

Neutral

  • I need to implement TupleHash256.

References

+ + + + \ No newline at end of file diff --git a/adrs/0011-incoming-runtime-messages/index.html b/adrs/0011-incoming-runtime-messages/index.html new file mode 100644 index 0000000000..e1341251bc --- /dev/null +++ b/adrs/0011-incoming-runtime-messages/index.html @@ -0,0 +1,91 @@ + + + + + +ADR 0011: Incoming Runtime Messages | Oasis Documentation + + + + +
+
Skip to main content

ADR 0011: Incoming Runtime Messages

Component

Oasis Core

Changelog

  • 2022-01-07: Update based on insights from implementation
  • 2021-12-09: Introduce an explicit fee field, clarify token transfers
  • 2021-10-26: Initial draft

Status

Accepted

Context

There is currently a single mechanism through which the consensus layer and a +runtime may interact in a consistent and secure manner. This is the mechanism +of runtime messages that can be emitted by runtimes (see ADR 3) and allows +the consensus layer to act on a runtime's behalf. This mechanism is currently +used for pulling tokens from consensus layer accounts that have previously +set proper allowances and for updating the runtime descriptor when the runtime +governance model (see ADR 4) is in effect.

This ADR proposes to implement the reverse mechanism where anyone issuing a +transaction at the consensus layer can queue arbitrary messages for processing +by the runtime in its next round.

Decision

On a high level this proposal affects the following components:

  • A new transaction method roothash.SubmitMsg is added to the roothash +consensus service to queue a new message for the specific runtime.

  • Additional per-runtime state is added to the roothash service containing the +currently queued messages, sorted by arrival time.

  • During processing of a round the proposer may propose to pop any number of +messages and process them by pushing them to the runtime, similar as it does +for transaction batches. This is of course subject to discrepancy detection.

  • The runtime host protocol is updated to allow the host to push arbitrary +incoming messages in addition to the transaction batch.

  • The runtime descriptor is updated to include a field that specifies the +maximum size of the incoming message queue.

Incoming Message

Each incoming message is represented as follows:

type IncomingMessage struct {
// ID is the unique identifier of the message.
ID uint64 `json:"id"`

// Caller is the address of the caller authenticated by the consensus layer.
Caller staking.Address `json:"caller"`

// Tag is an optional tag provided by the caller which is ignored and can be used to match
// processed incoming message events later.
Tag uint64 `json:"tag,omitempty"`

// Fee is the fee sent into the runtime as part of the message being sent.
// The fee is transferred before the message is processed by the runtime.
Fee quantity.Quantity `json:"fee,omitempty"`

// Tokens are any tokens sent into the runtime as part of the message being
// sent. The tokens are transferred before the message is processed by the
// runtime.
Tokens quantity.Quantity `json:"tokens,omitempty"`

// Data is arbitrary runtime-dependent data.
Data []byte `json:"data,omitempty"`
}

Executor Commitments

The compute results header structure is updated to include two fields that +specify the number and hash of incoming messages included in a batch as follows:

type ComputeResultsHeader struct {
// ... existing fields omitted ...

// InMessagesHash is the hash of processed incoming messages.
InMessagesHash *hash.Hash `json:"in_msgs_hash,omitempty"`
// InMessagesCount is the number of processed incoming messages.
InMessagesCount uint32 `json:"in_msgs_count,omitempty"`
}

Where the hash of included incoming messages is computed as follows:

// InMessagesHash returns a hash of provided incoming runtime messages.
func InMessagesHash(msgs []IncomingMessage) (h hash.Hash) {
if len(msgs) == 0 {
// Special case if there are no messages.
h.Empty()
return
}
return hash.NewFrom(msgs)
}

Note that this also requires the enclave RAK signature (for runtimes requiring +the use of TEEs) to be computed over this updated new header.

Runtime Block Header

The runtime block header is updated to include the InMessagesHash field as +follows:

type Header struct {
// ... existing fields omitted ...

// InMessagesHash is the hash of processed incoming messages.
InMessagesHash hash.Hash `json:"in_msgs_hash"`
}

Runtime Descriptor

This proposal updates the runtime transaction scheduler parameters (stored under +the txn_scheduler field of the runtime descriptor) as follows:

type TxnSchedulerParameters struct {
// ... existing fields omitted ...

// MaxInMessages specifies the maximum size of the incoming message queue
// for this runtime.
MaxInMessages uint32 `json:"max_in_messages,omitempty"`
}

It also updates the runtime staking parameters (stored under the staking field +of the runtime descriptor) as follows:

type RuntimeStakingParameters struct {
// ... existing fields omitted ...

// MinInMessageFee specifies the minimum fee that the incoming message must
// include for the message to be queued.
MinInMessageFee quantity.Quantity `json:"min_in_msg_fee,omitempty"`
}

State

This proposal introduces/updates the following consensus state in the roothash +module:

  • Incoming message queue metadata (0x28)

    Metadata for the incoming message queue.

    0x28 <H(runtime-id) (hash.Hash)>

    The value is the following CBOR-serialized structure:

    type IncomingMessageQueue struct {
    // Size contains the current size of the queue.
    Size uint32 `json:"size,omitempty"`

    // NextSequenceNumber contains the sequence number that should be used for
    // the next queued message.
    NextSequenceNumber uint64 `json:"next_sequence_number,omitempty"`
    }
  • Incoming message queue item (0x29)

    A queue of incoming messages pending to be delivered to the runtime in the +next round.

    0x29 <H(runtime-id) (hash.Hash)> <sequence-no (uint64)>

    The value is a CBOR-serialized IncomingMessage structure.

Transaction Methods

This proposal updates the following transaction methods in the roothash module:

Submit Message

The submit message method allows anyone to submit incoming runtime messages to +be queued for delivery to the given runtime.

Method name:

roothash.SubmitMsg

Body:

type SubmitMsg struct {
ID common.Namespace `json:"id"`
Fee quantity.Quantity `json:"fee,omitempty"`
Tokens quantity.Quantity `json:"tokens,omitempty"`
Data []byte `json:"data,omitempty"`
}

Fields:

  • id specifies the destination runtime's identifier.
  • fee specifies the fee that should be sent into the runtime as part of the +message being sent. The fee is transferred before the message is processed by +the runtime.
  • tokens specifies any tokens to be sent into the runtime as part of the +message being sent. The tokens are transferred before the message is processed +by the runtime.
  • data arbitrary data to be sent to the runtime for processing.

The transaction signer implicitly specifies the caller. Upon executing the +submit message method the following actions are performed:

  • Gas is accounted for (new submitmsg gas operation).

  • The runtime descriptor for runtime id is retrieved. If the runtime does not +exist or is currently suspended the method fails with ErrInvalidRuntime.

  • The txn_scheduler.max_in_messages field in the runtime descriptor is +checked. If it is equal to zero the method fails with +ErrIncomingMessageQueueFull.

  • If the value of the fee field is smaller than the value of the +staking.min_in_msg_fee field in the runtime descriptor the method fails with +ErrIncomingMessageInsufficientFee.

  • The number of tokens corresponding to fee + tokens are moved from the +caller's account into the runtime account. If there is insufficient balance to +do so the method fails with ErrInsufficientBalance.

  • The incoming queue metadata structure is fetched. If it doesn't yet exist it +is populated with zero values.

  • If the value of the size field in the metadata structure is equal to or +larger than the value of the txn_scheduler.max_in_messages field in the +runtime descriptor the method fails with ErrIncomingMessageQueueFull.

  • An IncomingMessage structure is generated based on the caller and method +body and the value of the next_sequence_number metadata field is used to +generate a proper key for storing it in the queue. The structure is inserted +into the queue.

  • The size and next_sequence_number fields are incremented and the updated +metadata is saved.

Queries

This proposal adds the following new query methods in the roothash module by +updating the roothash.Backend interface as follows:

type Backend interface {
// ... existing methods omitted ...

// GetIncomingMessageQueueMeta returns the given runtime's incoming message queue metadata.
GetIncomingMessageQueueMeta(ctx context.Context, request *RuntimeRequest) (*message.IncomingMessageQueueMeta, error)

// GetIncomingMessageQueue returns the given runtime's queued incoming messages.
GetIncomingMessageQueue(ctx context.Context, request *InMessageQueueRequest) ([]*message.IncomingMessage, error)
}

// IncomingMessageQueueMeta is the incoming message queue metadata.
type IncomingMessageQueueMeta struct {
// Size contains the current size of the queue.
Size uint32 `json:"size,omitempty"`

// NextSequenceNumber contains the sequence number that should be used for the next queued
// message.
NextSequenceNumber uint64 `json:"next_sequence_number,omitempty"`
}

// InMessageQueueRequest is a request for queued incoming messages.
type InMessageQueueRequest struct {
RuntimeID common.Namespace `json:"runtime_id"`
Height int64 `json:"height"`

Offset uint64 `json:"offset,omitempty"`
Limit uint32 `json:"limit,omitempty"`
}

Runtime Host Protocol

This proposal updates the existing host to runtime requests in the runtime host +protocol as follows:

type RuntimeExecuteTxBatchRequest struct {
// ... existing fields omitted ...

// IncomingMessages are the incoming messages from the consensus layer that
// should be processed by the runtime in this round.
IncomingMessages []*IncomingMessage `json:"in_messages,omitempty"`
}

Rust Runtime Support Library

This proposal updates the transaction::Dispatcher trait as follows:

pub trait Dispatcher: Send + Sync {
// ... existing unchanged methods omitted ...

/// Execute the transactions in the given batch.
fn execute_batch(
&self,
ctx: Context,
batch: &TxnBatch,
in_msgs: Vec<IncomingMessage>, // Added argument.
) -> Result<ExecuteBatchResult, RuntimeError>;
}

Executor Processing

The executor processing pipeline is changed such that pending incoming messages +are queried before the next round starts and are then passed to the runtime via +the runtime host protocol.

The executor may perform checks to estimate resource use early, similarly to how +checks are performed for transactions as they arrive.

Runtime Processing

The proposal requires that messages are processed by the runtime in queue order +(e.g. on each round InMessagesCount messages are poped from the queue). This +simplifies the design but the runtimes need to carefully consider how much +resources to allocate for executing messages (vs. regular transactions) in a +round.

The runtime has full autonomy in choosing how many messages to execute as it +is given the complete message batch. It should first compute how many messages +to process by running them in "check" mode and computing how much gas (or other +resources) they take and then choosing as many as fits.

Specifying these details is left to the runtime implementation although the SDK +is expected to adopt an approach with separate max_inmsg_gas and +max_inmsg_slots parameters which limits how resources are allocated for +incoming message processing in each round. If a single message exceeds either of +these limits it will result in execution failure of that message.

Root Hash Commitment Processing

The processing of executor commitments is modified as follows:

  • No changes are made to the discrepancy detection and resolution protocols +besides the newly added fields being taken into account in discrepancy +determination.

  • After a successful round, the InMessagesCount field of the compute body is +checked and the corresponding number of messages are popped from the queue in +increasing order of their sequence numbers. The queue metadata is updated +accoordingly by decrementing the value of the size field and the +InMessagesHash is added to the newly emitted block header.

Consequences

Positive

  • Consensus layer transactions can trigger actions in the runtime without +additional runtime transactions. This would also allow pushing tokens into +the runtime via a consensus layer transaction or even invoking smart contracts +that result in consensus layer actions to happen (via emitted messages).

  • Each runtime can define the format of incoming messages. The SDK would likely +use something that contains a transaction (either signed to support +non-Ed25519 callers or unsigned for smaller Ed25519-based transactions) so +arbitrary invocations would be possible.

Negative

  • Storing the queue will increase the size of consensus layer state.

  • This could lead to incoming messages being used exclusively to interact with a +runtime leading to the consensus layer getting clogged with incoming message +submission transactions. Posting such messages would be more expensive though +as it would require paying per transaction consensus layer fees in addition to +the runtime fees. If clogging does eventually happen the fees can be adjusted +to encourage transaction submission to runtimes directly.

Neutral

  • Allows rollup-like constructions where all transactions are posted to the +consensus layer first and the runtime is just executing those.

  • Retrieving the result of processing an incoming message is more involved.

+ + + + \ No newline at end of file diff --git a/adrs/0012-runtime-message-results/index.html b/adrs/0012-runtime-message-results/index.html new file mode 100644 index 0000000000..e5123992c3 --- /dev/null +++ b/adrs/0012-runtime-message-results/index.html @@ -0,0 +1,35 @@ + + + + + +ADR 0012: Runtime Message Results | Oasis Documentation + + + + +
+
Skip to main content

ADR 0012: Runtime Message Results

Component

Oasis Core

Changelog

  • 2021-12-04: Initial version
  • 2021-12-10: Extend the implementation section
  • 2022-01-27: Update the concrete result types

Status

Accepted

Context

Currently, the results of emitted runtime messages are MessageEvents, which +only provide information whether the message execution was successful or not. +For various use-cases additional information about message results would be +useful.

One of such is supporting staking by runtimes. Currently, a runtime can emit an +AddEscrow message, but is unaware of the actual amount of shares it obtained +as a result of the added escrow. For some use-cases (e.g. runtime staking user +deposited funds) this information is crucial for accounting.

Similarly, for ReclaimEscrow, the runtime doesn't have the direct information +at which epoch the stake gets debonded.

The only way to currently obtain this data is to subscribe to consensus events, +something which runtime doesn't have access to.

Adding results to MessageEvent solves both of the mentioned use cases:

  • for AddEscrow the result should contain amount of shares obtained with the +escrow

  • for ReclaimEscrow the result should contain the amount of shares and epoch +at which the stake gets debonded

Decision

Implement support for arbitrary result data in MessageEvent runtime message +results.

Implementation

  • Result field is added to roothash.MessageEvent struct:
// MessageEvent is a runtime message processed event.
type MessageEvent struct {
Module string `json:"module,omitempty"`
Code uint32 `json:"code,omitempty"`
Index uint32 `json:"index,omitempty"`

// Result contains message execution results for successfully executed messages.
Result cbor.RawMessage `json:"result,omitempty"
}

The Result field is runtime message specific and is present only when the +message execution was successful (Code is errors.CodeNoError).

  • ExecuteMessage method in MessageSubscriber interface is updated to include +a response:
// MessageSubscriber is a message subscriber interface.
type MessageSubscriber interface {
// ExecuteMessage executes a given message.
ExecuteMessage(ctx *Context, kind, msg interface{}) (interface{}, error)
}
  • Publish method of the MessageDispatcher interface is updated to include +the response:
// MessageDispatcher is a message dispatcher interface.
type MessageDispatcher interface {
// Publish publishes a message of a given kind by dispatching to all subscribers.
// Subscribers can return a result, but at most one subscriber should return a
// non-nil result to any published message. Panics in case more than one subscriber
// returns a non-nil result.
//
// In case there are no subscribers ErrNoSubscribers is returned.
Publish(ctx *Context, kind, msg interface{}) (interface{}, error)
}

In case the Publish error is nil the Roothash backend propagates the +result to the emitted MessageEvent.

With these changes the runtime is able to obtain message execution results via +MessageEvents in RoundResults.

Message Execution Results

  • AddEscrow message execution result is the AddEscrowResult:
type AddEscrowResult struct {
Owner Address `json:"owner"`
Escrow Address `json:"escrow"`
Amount quantity.Quantity `json:"amount"`
NewShares quantity.Quantity `json:"new_shares"`
}
  • ReclaimEscrow message execution result is the +ReclaimEscrowResult:
type ReclaimEscrowResult struct {
Owner Address `json:"owner"`
Escrow Address `json:"escrow"`
Amount quantity.Quantity `json:"amount"`
DebondingShares quantity.Quantity `json:"debonding_shares"`
RemainingShares quantity.Quantity `json:"remaining_shares"`
DebondEndTime beacon.EpochTime `json:"debond_end_time"`
}
  • Transfer message execution result is the TransferResult:
type TransferResult struct {
From Address `json:"from"`
To Address `json:"to"`
Amount quantity.Quantity `json:"amount"`
}
  • Withdraw message execution result is the WithdrawResult:
type WithdrawResult struct {
Owner Address `json:"owner"`
Beneficiary Address `json:"beneficiary"`
Allowance quantity.Quantity `json:"allowance"`
AmountChange quantity.Quantity `json:"amount_change"`
}
  • UpdateRuntime message execution result is the registry Runtime descriptor.

Consequences

Positive

All the functionality for runtimes to support staking is implemented.

Negative

Requires breaking changes.

Neutral

Alternatives considered

Add support to runtimes for subscribing to consensus events. A more heavyweight +solution, that can still be implemented in future if desired. Decided against it +due to simplicity of the message events solution for the present use cases.

+ + + + \ No newline at end of file diff --git a/adrs/0013-runtime-upgrades/index.html b/adrs/0013-runtime-upgrades/index.html new file mode 100644 index 0000000000..4a94b3c10f --- /dev/null +++ b/adrs/0013-runtime-upgrades/index.html @@ -0,0 +1,35 @@ + + + + + +ADR 0013: Runtime Upgrade Improvements | Oasis Documentation + + + + +
+
Skip to main content

ADR 0013: Runtime Upgrade Improvements

Component

Oasis Core

Changelog

  • 2022-01-25: Initial version

Status

Accepted

Context

Currently major runtime updates incur at least one epoch worth of downtime +for the transition period. This is suboptimal, and can be improved to allow +seamless runtime updates, with some changes to the runtime descriptor and +scheduler behavior.

Decision

Implement support for seamless breaking runtime upgrades.

Implementation

Runtime descriptor related changes:

// Runtime represents a runtime.
type Runtime struct { // nolint: maligned
// Deployments specifies the runtime deployments (versions).
Deployments []*VersionInfo `json:"deployments"`

// Version field is relocated to inside the VersionInfo structure.

// Other unchanged fields omitted for brevity.
}

// VersionInfo is the per-runtime version information.
type VersionInfo struct {
// Version of the runtime.
Version version.Version `json:"version"`

// ValidFrom stores the epoch at which, this version is valid.
ValidFrom beacon.EpochTime `json:"valid_from"`

// TEE is the enclave version information, in an enclave provider specific
// format if any.
TEE []byte `json:"tee,omitempty"`
}

The intended workflow here is to:

  • Deploy runtimes with the initial Deployment populated.

  • Update the runtime version via the deployment of a new version +of the descriptor with an additional version info entry. +Sufficient nodes must upgrade their runtime binary and +configuration by the ValidFrom epoch or the runtime will fail +to be scheduled (no special handling is done, this is the existing +"insufficient nodes" condition).

  • Aborting or altering pending updates via the deployment of a new version +of the descriptor with the removed/ammended not-yet-valid Deployments +is possible in this design, but perhaps should be forbidden.

  • Altering exisiting Deployments entries is strictly forbidden, +except the removal of superceded descriptors.

  • Deploying descriptors with Deployments that will never be valid +(as in one that is superceded by a newer version) is strictly +forbidden.

The existing node descriptor is a flat vector of Runtime entries +containing the runtime ID, version, and TEE information, so no changes +are required.

On transition to an epoch where a new version takes effect, the consensus +layer MAY prune the descriptor's Deployments field of superceded versions.

The only scheduler and worker side changes are to incorporate the runtime +version into scheduling, and to pick the correct deployed version of the +runtime to use, both on a once-per-epoch-per-runtime basis.

Consequences

Positive

  • Seamless runtime upgrades will be possible.

  • The code changes required are relatively minimal, and this is likely +the simplest possible solution that will work.

Negative

  • It may be overly simplistic.
+ + + + \ No newline at end of file diff --git a/adrs/0014-runtime-signing-tx-with-hardware-wallet/index.html b/adrs/0014-runtime-signing-tx-with-hardware-wallet/index.html new file mode 100644 index 0000000000..c879416b39 --- /dev/null +++ b/adrs/0014-runtime-signing-tx-with-hardware-wallet/index.html @@ -0,0 +1,120 @@ + + + + + +ADR 0014: Signing Runtime Transactions with Hardware Wallet | Oasis Documentation + + + + +
+
Skip to main content

ADR 0014: Signing Runtime Transactions with Hardware Wallet

Component

Oasis SDK

Changelog

  • 2023-02-24:
    • APDU: Define Oasis native and Ethereum-compatible address length.
  • 2023-02-09:
    • Encode Meta.runtime_id and Meta.orig_to as Base16.
    • Change SIG in SIGN_RT_SECP256K1 to 65-byte encoded R,S,V format.
  • 2023-01-23:
  • 2023-01-03:
    • Add Sapphire runtime ID and consensus address on Mainnet.
  • 2022-12-13:
    • Fix Secp256k1 public key size.
  • 2022-10-12:
    • Add Sapphire runtime ID and consensus address on Testnet,
    • Remove redundant sig_context from Meta,
    • Require tx.call.format to be either 0 or 1.
  • 2022-07-15: Initial public version

Status

Proposed

Context

This document proposes additions to APDU specification, guidelines for parsing +runtime transactions and general UI/UX for signing them on a hardware wallet:

  1. APDUSPEC additions
  2. Changes to Allowance transaction
  3. Signing general runtime transactions,
  4. Signing smart contract runtime transactions,
  5. Signing EVM runtime transactions.
  6. Signing encrypted runtime transactions,

Test vectors

Test vectors for all runtime transactions in this ADR can be generated by +using gen_runtime_vectors tool as part of the Oasis SDK.

Runtime transaction format

The format of the runtime transaction to be signed by the +hardware wallet is the following:

/// Transaction.
#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
pub struct Transaction {
#[cbor(rename = "v")]
pub version: u16,

pub call: Call,

#[cbor(rename = "ai")]
pub auth_info: AuthInfo,
}

The transaction can be signed with Secp256k1 ("Ethereum"), Ed25519 key, +or Sr25519 key! Information on this along with the gas fee is stored inside +ai field.

call is defined as follows:

/// Method call.
#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
pub struct Call {
/// Call format.
#[cbor(optional, default)]
pub format: CallFormat,
/// Method name.
#[cbor(optional, default, skip_serializing_if = "String::is_empty")]
pub method: String,
/// Method body.
pub body: cbor::Value,
/// Read-only flag.
///
/// A read-only call cannot make any changes to runtime state. Any attempt at modifying state
/// will result in the call failing.
#[cbor(optional, default, rename = "ro")]
pub read_only: bool,
}

If format is:

  • 0, the transaction is unencrypted,
  • 1, the transaction is encrypted,
  • any other, the transaction should be rejected with unsupported call format +error unless implemented outside the scope of this ADR.

method contains the name of the runtime module followed by . and the method +name. If format is 1, method is empty.

body contains a CBOR-encoded transaction. If format equals 1, body +contains CBOR-encoded CallEnvelopeX25519DeoxysII +which contains the encrypted transaction body inside its data field.

Decision

APDUSPEC additions

GET_ADDR_SECP256K1

Command
FieldTypeContentExpected
CLAbyte (1)Application Identifier0x05
INSbyte (1)Instruction ID0x04
P1byte (1)Request User confirmationNo = 0
P2byte (1)Parameter 2ignored
Lbyte (1)Bytes in payload(depends)
Path[0]byte (4)Derivation Path Data44
Path[1]byte (4)Derivation Path Data60
Path[2]byte (4)Derivation Path Data?
Path[3]byte (4)Derivation Path Data?
Path[4]byte (4)Derivation Path Data?

The first three items in the derivation path are hardened.

Response
FieldTypeContentNote
PKbyte (33)Public Key
ADDRbyte (40)Lower-case hex addr
SW1-SW2byte (2)Return codesee list of return codes

GET_ADDR_SR25519

Command
FieldTypeContentExpected
CLAbyte (1)Application Identifier0x05
INSbyte (1)Instruction ID0x03
P1byte (1)Request User confirmationNo = 0
P2byte (1)Parameter 2ignored
Lbyte (1)Bytes in payload(depends)
Path[0]byte (4)Derivation Path Data44
Path[1]byte (4)Derivation Path Data474
Path[2]byte (4)Derivation Path Data?
Path[3]byte (4)Derivation Path Data?
Path[4]byte (4)Derivation Path Data?

The first three items in the derivation path are hardened.

Response
FieldTypeContentNote
PKbyte (32)Public Key
ADDRbyte (46)Bech32 addr
SW1-SW2byte (2)Return codesee list of return codes

SIGN_RT_ED25519

Command
FieldTypeContentExpected
CLAbyte (1)Application Identifier0x05
INSbyte (1)Instruction ID0x05
P1byte (1)Payload desc0 = init
1 = add
2 = last
P2byte (1)----not used
Lbyte (1)Bytes in payload(depends)

The first packet/chunk includes only the derivation path.

All other packets/chunks should contain message to sign.

First Packet

FieldTypeContentExpected
Path[0]byte (4)Derivation Path Data44
Path[1]byte (4)Derivation Path Data474
Path[2]byte (4)Derivation Path Data?
Path[3]byte (4)Derivation Path Data?
Path[4]byte (4)Derivation Path Data?

Other Chunks/Packets

FieldTypeContentExpected
Databytes...Meta+Message

Data is defined as:

FieldTypeContentExpected
Metabytes..CBOR metadata
Messagebytes..CBOR data to sign
Response
FieldTypeContentNote
SIGbyte (64)Signature
SW1-SW2byte (2)Return codesee list of return codes

SIGN_RT_SECP256K1

Command
FieldTypeContentExpected
CLAbyte (1)Application Identifier0x05
INSbyte (1)Instruction ID0x07
P1byte (1)Payload desc0 = init
1 = add
2 = last
P2byte (1)----not used
Lbyte (1)Bytes in payload(depends)

The first packet/chunk includes only the derivation path.

All other packets/chunks should contain message to sign.

First Packet

FieldTypeContentExpected
Path[0]byte (4)Derivation Path Data44
Path[1]byte (4)Derivation Path Data60
Path[2]byte (4)Derivation Path Data?
Path[3]byte (4)Derivation Path Data?
Path[4]byte (4)Derivation Path Data?

Other Chunks/Packets

FieldTypeContentExpected
Databytes...Meta+Message

Data is defined as:

FieldTypeContentExpected
Metabytes..CBOR metadata
Messagebytes..CBOR data to sign
Response
FieldTypeContentNote
SIGbyte (65)SignatureR,S,V bigendian integers
SW1-SW2byte (2)Return codesee list of return codes

SIGN_RT_SR25519

Command
FieldTypeContentExpected
CLAbyte (1)Application Identifier0x05
INSbyte (1)Instruction ID0x06
P1byte (1)Payload desc0 = init
1 = add
2 = last
P2byte (1)----not used
Lbyte (1)Bytes in payload(depends)

The first packet/chunk includes only the derivation path.

All other packets/chunks should contain message to sign.

First Packet

FieldTypeContentExpected
Path[0]byte (4)Derivation Path Data44
Path[1]byte (4)Derivation Path Data474
Path[2]byte (4)Derivation Path Data?
Path[3]byte (4)Derivation Path Data?
Path[4]byte (4)Derivation Path Data?

Other Chunks/Packets

FieldTypeContentExpected
Databytes...Meta+Message

Data is defined as:

FieldTypeContentExpected
Metabytes..CBOR metadata
Messagebytes..CBOR data to sign
Response
FieldTypeContentNote
SIGbyte (64)Signature
SW1-SW2byte (2)Return codesee list of return codes

Meta parameter

Meta is a CBOR-encoded string → string map with the following fields:

  • runtime_id: Base16-encoded runtime ID (64-byte string)
  • chain_context: chain ID (64-byte string)
  • orig_to (optional): Base16-encoded ethereum destination address (40-byte +string)

Changes to Allowance transaction

staking.Allow transaction already exists on the consensus layer. We propose +the following improvement to the UI:

|     Type     > | <    To    > | <    Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <             > | <              |
| Allowance | <TO> | ROSE +-<AMOUNT> | ROSE <FEE> | <GAS LIMIT> | <NETWORK> | APPROVE | REJECT |
| | | | | | | | |

IMPROVEMENT: The hardware wallet renders the +following literals in place of TO for specific NETWORK and addresses:

  • Network: Mainnet, To: oasis1qrnu9yhwzap7rqh6tdcdcpz0zf86hwhycchkhvt8Cipher
  • Network: Testnet, To: oasis1qqdn25n5a2jtet2s5amc7gmchsqqgs4j0qcg5k0tCipher
  • Network: Mainnet, To: oasis1qzvlg0grjxwgjj58tx2xvmv26era6t2csqn22pteEmerald
  • Network: Testnet, To: oasis1qr629x0tg9gm5fyhedgs9lw5eh3d8ycdnsxf0runEmerald
  • Network: Mainnet, To: oasis1qrd3mnzhhgst26hsp96uf45yhq6zlax0cuzdgcfcSapphire
  • Network: Testnet, To: oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xdSapphire

For more information on how the addresses above are derived from the runtime ID +check the runtime accounts section.

Signing general runtime transactions

Deposit

We propose the following UI for consensus.Deposit runtime transaction:

|     Type     > | <   To (1/1)  > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Deposit | <MIXED_TO> | <SYM> <AMOUNT> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | |

MIXED_TO can either be oasis1 or the Ethereum's 0x address. If Meta +does not contain orig_to field, render the tx.call.body.to value in +oasis1 format in place of MIXED_TO. If Meta.orig_to is set, +then:

  1. Check that the ethereum address stored in orig_to field maps to the +native address in tx.call.body.to according to the reference +implementation of the mapping.
  2. Render orig_to value in 0x format in place of MIXED_TO.

In addition, if tx.call.body.to is empty, then the deposit is made to the +signer's account inside the runtime. In this case Self literal is rendered in +place of MIXED_TO.

AMOUNT and FEE show the amount of tokens transferred in the transaction and +the transaction fee. The number must be formatted according to the number of +decimal places and showing a corresponding symbol SYM beside. These are +determined by the following mapping hardcoded in the hardware wallet:

(Network, Runtime ID, Denomination) → (Number of decimals, SYM)

Denomination information is stored in tx.part.body.amount[1] or +tx.ai.fee.amount[1] for the tokens transferred in the transaction or the fee +respectively. Empty Denomination is valid and signifies the native token +for the known networks and runtime IDs (see below).

The hardware wallet should have at least the following mappings hardcoded:

  • Network: Mainnet, runtime ID: Cipher, Denomination: "" → 9, ROSE
  • Network: Testnet, runtime ID: Cipher, Denomination: "" → 9, TEST
  • Network: Mainnet, runtime ID: Emerald, Denomination: "" → 18, ROSE
  • Network: Testnet, runtime ID: Emerald, Denomination: "" → 18, TEST
  • Network: Mainnet, runtime ID: Sapphire, Denomination: "" → 18, ROSE
  • Network: Testnet, runtime ID: Sapphire, Denomination: "" → 18, TEST

If the lookup fails, the following policy should be respected:

  1. SYM is rendered as empty string.
  2. The number of decimals is 18, if runtime ID matches any Emerald or Sapphire +runtime on any network.
  3. Otherwise, the number of decimals is 9.

RUNTIME shows the 32-byte hex encoded runtime ID stored in Meta.runtime_id. +If NETWORK matches Mainnet or Testnet, then human-readable version of +RUNTIME is shown:

  • Network: Mainnet, runtime ID: 000000000000000000000000000000000000000000000000e199119c992377cbCipher
  • Network: Testnet, runtime ID: 0000000000000000000000000000000000000000000000000000000000000000Cipher
  • Network: Mainnet, runtime ID: 000000000000000000000000000000000000000000000000e2eaa99fc008f87fEmerald
  • Network: Testnet, runtime ID: 00000000000000000000000000000000000000000000000072c8215e60d5bca7Emerald
  • Network: Mainnet, runtime ID: 000000000000000000000000000000000000000000000000f80306c9858e7279Sapphire
  • Network: Testnet, runtime ID: 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6cSapphire

SIGNATURE CONTEXT COMPUTATION: Chain domain separation context +for runtime transactions beginning with +oasis-runtime-sdk/tx: v0 for chain and followed by the hash derived from +Meta.runtime_id and Meta.chain_context. See golang implementation for the reference implementation.

Withdraw

We propose the following UI for consensus.Withdraw method:

|     Type     > | <   To (1/1)  > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Withdraw | <TO> | <SYM> <AMOUNT> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | |

If tx.call.body.to is empty, then the withdrawal is made to the signer's +consensus account. In this case Self literal is rendered in +place of TO.

Transfer

We propose the following UI for the accounts.Transfer method:

|     Type     > | <   To (1/1)  > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Transfer | <MIXED_TO> | <SYM> <AMOUNT> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | |

Example

The user wants to deposit 100 ROSE to +0xDce075E1C39b1ae0b75D554558b6451A226ffe00 account on Emerald on the Mainnet. +First they sign the deposit allowance transaction for Emerald.

|     Type     > | <    To    > | <   Amount   > | < Gas limit > | <     Fee     > | <  Network  > | <             > | <              |
| Allowance | Emerald | ROSE +100.0 | 1277 | ROSE 0.0 | Mainnet | APPROVE | REJECT |
| | Mainnet | | | | | | |

Next, they sign the runtime deposit transaction.

|     Type     > | <   To (1/2)  > | <    To (2/2)   > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Deposit | 0xDce075E1C39b1 | 451A226ffe00 | ROSE 100.0 | ROSE 0.0 | 11310 | Mainnet | Emerald | APPROVE | REJECT |
| (ParaTime) | ae0b75D554558b6 | | | | | | | | |

Then, they transfer some tokens to another account inside the runtime:

|     Type     > | <    To (1/2)  > | <    To (2/2)   > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Transfer | oasis1qpupfu7e2n | m8anj64ytrayne | ROSE 10.0 | ROSE 0.00015 | 11311 | Mainnet | Emerald | APPROVE | REJECT |
| (ParaTime) | 6pkezeaw0yhj8mce | | | | | | | | |

Finally, the user withdraws the remainder of tokens back to the Mainnet.

|     Type     > | <    To (1/2)  > | <    To (2/2)   > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Withdraw | oasis1qrec770vre | 504k68svq7kzve | ROSE 99.9997 | ROSE 0.00015 | 11311 | Mainnet | Emerald | APPROVE | REJECT |
| (ParaTime) | k0a9a5lcrv0zvt22 | | | | | | | | |

Signing smart contract runtime transactions

Uploading smart contract

contracts.Upload method will not be signed by the hardware wallet +because the size of the Wasm byte code to sign may easily exceed the maximum +size of the available encrypted memory.

Instantiating smart contract

We propose the following UI for the contracts.Instantiate method:

|  Review Contract > | < Code ID > | < Amount (1/1) > | < Data (1/1) > | ... | <    Fee    > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Instantiation | <CODE ID> | <AMOUNT...> | <DATA> | ... | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | ... | | | | | | |

DATA is a JSON-like representation of tx.call.body.data, if the latter +is a CBOR-encoded map. If tx.call.body.data is empty or not present, +then Data screen is hidden. If tx.call.body.data is in some other format, +require blind signing mode and hide Data screen.

Blind signing means that the user does not see all contract information. In some +cases - as is this - not even the amount or the contract address! When +signing blindly, it is crucial that the user trusts the client application that +it generated a non-malicious transaction!

AMOUNT... is the amount of tokens sent. Contract SDK supports sending +multiple tokens at once, each with its own denomination symbol. The hardware +wallet should render all of them, one per page. For rendering rules of each +AMOUNT consult the runtime deposit behavior.

There can be multiple Data screens Data 1, Data 2, ..., Data N for each key in +tx.call.body.data map. DATA can be one of the following types:

  • string
  • number (integer, float)
  • array
  • map
  • boolean
  • null

Strings are rendered as UTF-8 strings and the following characters need to be +escaped: :, ,, }, ], .

Numbers are rendered in standard general base-10 encoding. Floats use decimal +period and should be rendered with at least one decimal.

For strings and numbers that cannot fit a single page, a pagination is +activated.

Boolean and null values are rendered as true, false and null respectively +on a single page.

Array and map is rendered in form VAL1,VAL2,... and KEY1:VAL1,KEY1:VAL1,... +respectively. For security, the items of the map must be sorted +lexicographically by KEY. KEY and VAL can be of any supported type. If it +is a map or array it is rendered as {DATA} or [DATA] respectively +to avoid disambiguation. Otherwise, it is just DATA.

If the content of an array or a map cannot fit a single page, no pagination +is introduced. Instead, the content is trimmed, ellipsis is appended at +the end and the screen becomes confirmable. If the user double-clicks it, a +subscreen for item n of an array or a map is shown. There is one subscreen +for each item of the array or a map of size N titled Data n.1, +Data n.2, ..., Data n.N which renders the item n as +DATA for an array item or DATA:DATA for a map item:

|   Data 1.1 (1/1) > | < Data 1.2 (1/1) | < Data 1.3 (1/1) | ... | <          |
| <DATA> | <DATA> | <DATA> | | BACK |
| | | | | |

The recursive approach described above allows user to browse through a complete +tree of data stracture (typically a request name along with the arguments) by +using ⬅️ and ➡️ buttons, visit a child by double-clicking and returning to a +parent node by confirming the BACK screen.

The maximum string length, the length of the array, the depth of a map must +have reasonable limits on the hardware wallet. If that limit is exceeded, the +hardware wallet displays an error on the initial screen. Then, if the user +still wants to sign such a transaction, they need to enable blind signing.

The following UI is shown when blind-signing a non-encrypted transaction due +to too complex function parameters.

|  Review Contract > | < BLIND > | < Instance ID (1/1) > | <   Amount    > | <     Fee     > | <  Network  > | <  ParaTime > | <            > | <             |
| Instantiation | SIGNING! | <INSTANCE ID> | <SYM> <AMOUNT> | <SYM> <FEE> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | |

Calling smart contract

The hardware wallet should show details of the runtime transaction to the +user, when this is possible. We propose the following UI for the +contracts.Call method:

| Review Contract > | < Instance ID > | < Amount (1/1) > | < Data (1/1) > | ... | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <              |
| Call | <INSTANCE ID> | <AMOUNT...> | <DATA> | ... | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | ... | | | | | | |

The Data screen behavior is the same as for +contracts.Instantiate transaction.

Upgrading smart contracts

We propose the following UI for the contracts.Upgrade method:

|  Review Contract > | < Instance ID (1/1) > | < Amount (1/1) > | < New Code ID (1/1) > | < Data (1/1) > | ... | < ParaTime > | <     Fee     > | < Gas limit > | < Network > | < ParaTime > | <             > | <               |
| Upgrade | <INSTANCE ID> | <AMOUNT...> | <CODE_ID> | <DATA> | | <RUNTIME> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | | | | | |

The Data screen behavior is the same as for the +contract instantiate transaction.

Example

To upload, instantiate and call the hello world example running on Testnet +Cipher the user first signs the contract upload transaction with a file-based +ed25519 keypair. The user obtains the Code ID 3 for the uploaded contract.

Next, the user instantiates the contract and obtains the Instance ID 2.

|  Review Contract > | < Code ID > | <  Amount  > | <      Data      > | <    Fee    > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <               |
| Instantiation | 3 | ROSE 0.0 | {instantiate:{init | ROSE 0.0 | 1348 | Mainnet | Cipher | APPROVE | REJECT |
| (ParaTime) | | | ial_counter:42}} | | | | | | | |

Finally, they perform a call to say_hello function on a smart contract +passing the {"who":"me"} object as a function argument.

| Review Contract > | < Instance ID > | <  Amount  > | <      Data      > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <             > | <              |
| Call | 2 | ROSE 0.0 | {say_hello:{who:me | ROSE 0.0 | 1283 | Mainnet | Cipher | APPROVE | REJECT |
| (ParaTime) | | | }} | | | | | | |

For a complete example, the user can provide a more complex object:

{
"who": {
"username": "alice",
"client_secret": "e5868ebb4445fc2ad9f949956c1cb9ddefa0d421",
"last_logins": [1646835046, 1615299046, 1583763046, 1552140646],
"redirect": null
}
}

In this case the hardware wallet renders the following UI.

| Review Contract > | <  Instance ID  > | <   Amount  > | <      Data      > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime  > | <            > | <              |
| Call | 2 | ROSE 0.0 | {say_hello:{who:{u | ROSE 0.15 | 1283 | Mainnet | Cipher | APPROVE | REJECT |
| (ParaTime) | | | sername:alice,cli… | | | | | | |

V V

| Data 1 > | < |
| say_hello:{who:{us | BACK |
| ername:alice,clie… | |

V V

| Data 1.1 > | < |
| who:{username:alic | BACK |
| e,client_secret:[… | |

V V

| Data 1.1.1 > | < Data 1.1.2 (1/2) > | < Data 1.1.2 (2/2) > | < Data 1.1.3 > | < Data 1.1.4 > | < |
| username:alice | client_secret:e5868e | 1cb9ddefa0d421 | last_logins:[1646835 | redirect:null | BACK |
| | bb4445fc2ad9f949956c | | 046,1615299046,1583… | | |

V V

| Data 1.1.3.1 > | < Data 1.1.3.2 > | < Data 1.1.3.3 > | < Data 1.1.3.4 | < |
| 1646835046 | 1615299046 | 1583763046 | 1552140646 | BACK |
| | | | | |

Signing EVM runtime transactions

Creating smart contract

evm.Create method will not be managed by the hardware wallet because the +size of the EVM byte code may easily exceed the wallet's encrypted memory size.

Calling smart contract

In contrast to contracts.Call, evm.Call method requires contract ABI and +support for RLP decoding in order to extract argument names from +tx.call.body.data. This is outside of the scope of this ADR and the blind +signing, explicitly allowed by the user, is performed.

We propose the following UI:

| Review Contract > | < BLIND > | < Tx hash (1/1) > | < Address (1/1) > | <   Amount    > | <     Fee     > | < Gas limit > | <  Network  > | <  ParaTime > | <            > | <             |
| Call | SIGNING! | <TX_HASH> | <ADDRESS> | <SYM> <AMOUNT> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | | | |

TX_HASH is a hex representation of sha256 checksum of tx.call.body.data +field.

ADDRESS is a hex-encoded address of the smart contract.

Signing encrypted runtime transactions

Encrypted transactions (tx.call.format == 1) contain call data inside the +envelope's data field encrypted with Deoxys-II +ephemeral key and X25519 key derivation.

The hardware wallet is not expected to implement any of these decryption +schemes, neither it is safe to share the ephemeral key with anyone. Instead, +the user should enable blind signing and the hardware wallet should +show the hash of the encrypted call data, the public key and the nonce:

| Review Encrypted > | < BLIND > | < Tx hash (1/1) > | < Public key (1/1) > | <  Nonce (1/1) > | <    Fee    > | < Gas limit > | <  Network  > | <  ParaTime > | <             > | <             |
| Transaction | SIGNING! | <TX_HASH> | <PUBLIC_KEY> | <NONCE> | <SYM> <FEE> | <GAS LIMIT> | <NETWORK> | <RUNTIME> | APPROVE | REJECT |
| (ParaTime) | | | | | | | | | | |

TX_HASH is a hex representation of sha256 checksum of tx.call.body.data +field.

PUBLIC_KEY is a hex representation of the 32-byte tx.call.body.pk field.

NONCE is a hex representation of the 15-byte tx.call.body.nonce field.

Since the transaction stored inside the tx.call.body.data field is encrypted, +there is also no way to discriminate between the transactions, for example +contracts.Call, contracts.Upgrade or evm.Call.

Consequences

Positive

Users will have a similar experience for signing runtime transactions on any +wallet implementing this ADR.

Negative

For some transactions, user will need to trust the client application and use +blind signing.

Neutral

Consideration of roothash.SubmitMsg transactions

This ADR does not propose a UI for generic runtime calls +(roothash.SubmitMsg, see ADR 11). The proposed design in this ADR assumes a +new release of the hardware wallet app each time a new runtime transaction type +is introduced.

Signing contract uploads on hardware wallets

In the future perhaps, if only the merkle root hash of the Wasm contract would +be contained in the transaction, signing such a contract could be feasible. See +how Ethereum 2.x contract deployment is done using this approach.

Consideration of adding From screen

None of the proposed UIs and the existing implementation of signing the +consensus transactions on Ledger show who is a signer of the transaction. +The signer's from address can be extracted from +tx.ai.si[0].address_spec.signature.<SIGNATURE TYPE> +for oasis native address and if the signer wants to show the Ethereum address, +Meta.orig_from should be populated and the hardware wallet should +verify it before showing the tx.

References

+ + + + \ No newline at end of file diff --git a/adrs/0015-vrf-per-block-entropy/index.html b/adrs/0015-vrf-per-block-entropy/index.html new file mode 100644 index 0000000000..b6b64d1787 --- /dev/null +++ b/adrs/0015-vrf-per-block-entropy/index.html @@ -0,0 +1,39 @@ + + + + + +ADR 0015: Randomized Paratime Proposer Selection | Oasis Documentation + + + + +
+
Skip to main content

ADR 0015: Randomized Paratime Proposer Selection

Component

Oasis Core

Changelog

  • 2022-09-14: Initial import

Status

Proposed

Context

The paratime block proposer currently is selected via a round-robin algorithm, +and it is trivial to determine the block proposer well in advance. This ADR +proposes having a mechanism for generating per-consensus block entropy via +ECVRF1, and randomizing the Paratime block proposer.

Decision

Prerequisites

Let each node have a distinct long-term VRF keypair, that is published as +part of the node's descriptor (as per ADR 0010).

Let Tendermint actually implement ExtendVote/VerifyVoteExtension as +per certain versions of the ABCI++ spec2. Note that it appears that this +will NOT be in Tendermint 0.37.x, but instead is scheduled for a later +release.

Vote extension

ABCI++ introduces a notion of an application defined vote_extension blob +that is set by the tendermint block proposer, and verified by all of the +voters. Oasis will use the following datastructure, serialized to canonical +CBOR, and signed with the node's consensus signing key.

type OasisVoteExtension struct {
// Pi is the proposer's VRF proof for the current block height.
Pi []byte `json:"pi"`
}

For the genesis block +1 (No previous beta), let the VRF alpha_string input +be derived as:

TupleHash256((chain_context, I2OSP(height,8)), 256, "oasis-core:tm-vrf/alpha")

For subsequent blocks, let the VRF alpha_string input be derived as:

TupleHash256((chain_context, I2OSP(height,8), prev_beta), 256, "oasis-core:tm-vrf/alpha") +where prev_beta is the beta_string output from the previous height's ECVRF +proof.

Blocks must have a valid OasisVoteExtension blob to be considered valid, +and nodes MUST use the same ECVRF key for the entire epoch (key changes +mid-epoch are ignored till the epoch transition) to prevent the proposer +from regenerating the ECVRF key repeatedly to fish for entropy output.

Proposer selection

Instead of round-robin through the per-epoch list of primary (non-backup) +workers, the index for the node can be selected as thus:

seed = TupleHash256((chain_context, I2OSP(height,8), runtime_id, pi), 256, "oasis-core:tm-vrf/paratime")
drbg = drbg.New(crypto.SHA512, seed, nil, "BlockProposer")
rng = rand.New(mathrand.New(drbg))

l := len(primary_nodes)
primary_index = int(rng.Int63n(l))

Consequences

Positive

The paratime block proposer(s) will be randomized.

This can be done without having to patch tendermint.

In theory, the system will have a way to generate entropy at the consensus +layer again.

Negative

The tendermint block proposer still will be selected via a round robin +algorithm. Note that Oasis does not have smart contracts at that level so +the impact of being able to predict the block proposer there is less +significant than other systems.

People may be tempted to abuse this entropy for other things (eg: inside +paratimes), which would be incorrect (block proposer can cheat).

This relies on interfaces exposed by ABCI++, which appear to no longer +be part of 0.37.x, so it is unknown when this will be possible to implement.

Neutral

References

+ + + + \ No newline at end of file diff --git a/adrs/0016-consensus-parameters-change-proposal/index.html b/adrs/0016-consensus-parameters-change-proposal/index.html new file mode 100644 index 0000000000..06068ce608 --- /dev/null +++ b/adrs/0016-consensus-parameters-change-proposal/index.html @@ -0,0 +1,62 @@ + + + + + +ADR 0016: Consensus Parameters Change Proposal | Oasis Documentation + + + + +
+
Skip to main content

ADR 0016: Consensus Parameters Change Proposal

Component

Oasis Core

Changelog

  • 2022-09-15: Initial version

Status

Proposed

Context

Currently consensus parameters can only be changed with an upgrade governance +proposal which is effective but not very efficient. Upgrades require downtime +during which binaries need to be updated, nodes restarted and synced, consensus +network version has to be increased etc. We would like to avoid this cumbersome +procedure and change the parameters of a consensus module as fast and as simple +as possible without affecting the performance of the consensus layer.

Decision

Implement governance proposal which changes consensus parameters only.

Implementation

New proposal

A new type of governance proposal named ChangeParametersProposal should be +added to the consensus layer. The proposal should contain two non-empty fields:

  • the name of the consensus Module the changes should be applied to, and,

  • a CBOR-encoded document Changes describing parameter changes.

// ChangeParametersProposal is a consensus parameters change proposal.
type ChangeParametersProposal struct {
// Module identifies the consensus backend module to which changes should be
// applied.
Module string `json:"module"`
// Changes are consensus parameter changes that should be applied to
// the module.
Changes cbor.RawMessage `json:"changes"`
}

Both fields should be validated before proposal submission to avoid having +invalid proposals with empty fields. A more in-depth validation should be done +by consensus modules during submission to ensure that the encoded Changes are +complete and well-formed and that there is exactly one module to which changes +will be applied.

// ValidateBasic performs a basic validation on the change parameters proposal.
func (p *ChangeParametersProposal) ValidateBasic() error {
// Validate that both fields are set.
}

The new proposal should be added to the ProposalContent. The extension should +still allow only one proposal at a time, so we must not forget to update +the code responsible for validation.

type ProposalContent struct {
...
ChangeParameters *ChangeParametersProposal `json:"change_parameters,omitempty"`
}

Parameter changes

Each consensus module should carefully scope which parameters are allowed to +be changed. For example, a governance module could allow changing only the gas +costs and the voting period, while the staking module would allow changing +all parameters.

// ConsensusParameterChanges define allowed governance consensus parameter
// changes.
type ConsensusParameterChanges struct {
// GasCosts are the new gas costs.
GasCosts *transaction.Costs `json:"gas_costs,omitempty"`
// VotingPeriod is the new voting period.
VotingPeriod *beacon.EpochTime `json:"voting_period,omitempty"`
}

To prevent invalid proposals being submitted, ConsensusParameterChanges +should expose validation method which can be used to check if changes are +valid (e.g. changes are not empty, parameters have the right ranges).

// SanityCheck performs a sanity check on the consensus parameters changes.
func (c *ConsensusParameterChanges) SanityCheck() error {
// Validate changes.
}

How changes are executed is up to the module implementation.

// Apply applies changes to the given consensus parameters.
func (c *ConsensusParameterChanges) Apply(params *ConsensusParameters) error {
// Apply changes.
}

Submission

When a new ChangeParametersProposal is submitted a basic validation is +performed first which checks whether the Module name and Changes are set +correctly. Afterwards, a validation message is broadcasted to all modules +requesting them to validate the proposal. Only the module for which Changes +are intended should act and reply to the message, other modules should silently +ignore it. In case no module replies, the proposal is immediately rejected +as not being supported.

The module should carefully examine the proposal, check whether the proposal +is well-formed, Changes are not empty and deserialize correctly to the +expected format, deserialized parameter changes are valid etc. If all checks +succeed, the module should respond with a confirmation message. Otherwise, +an error describing why proposal is invalid should be returned as a response.

Note: Validation at this stage cannot always be complete as valid parameter +values are not necessary independent of each other. If multiple proposals are +being executed at the same time, the resulting parameters can be invalid even +though validation of each proposal passed. Therefore, another validation +is required when the proposal is about to be executed.

Execution

If ChangeParametersProposal closes as accepted (vote passed), the governance +module will execute the proposal by broadcasting a message containing +the proposal to all modules. Notification can be done using the same message +dispatch mechanism as in the submission phase. Once messages are delivered, +only one module will act and try to apply Changes.

That module should first fetch current consensus parameters, then apply +proposed Changes and finally validate the result. Validation of parameters +is necessary as mentioned in the submission phase. If validation succeeds, +the consensus parameters are updated and proposal is marked as passed. +Otherwise, the proposal is marked as failed and the proposed parameter +changes are discarded.

// SanityCheck performs a sanity check on the consensus parameters.
func (p *ConsensusParameters) SanityCheck() error {
// Validate parameters.
}

How to enable the new proposal

Adding a new proposal type is a consensus breaking change. To make it +non-breaking we introduce a new governance consensus parameter which disables +the new type by default and can be enabled via governance. When disabled, +the governance module will treat the new proposal type as invalid, thus not +violating the consensus.

type ConsensusParameters struct {
...
// EnableChangeParametersProposal is true iff change parameters proposals are
// allowed.
EnableChangeParametersProposal bool `json:"enable_change_parameters_proposal,omitempty"`
}

Consequences

Positive

  • Agile and zero-downtime consensus parameter changes.

  • Separation of consensus parameter changes and consensus upgrades.

Negative

  • Introduction of a new governance consensus parameter which enables new +proposals in the upgrade handler. New parameters can always be considered +as a minor disadvantage as they usually increase the complexity of the code.

Neutral

References

No references.

+ + + + \ No newline at end of file diff --git a/adrs/0017-app-standards/index.html b/adrs/0017-app-standards/index.html new file mode 100644 index 0000000000..8ba918085e --- /dev/null +++ b/adrs/0017-app-standards/index.html @@ -0,0 +1,50 @@ + + + + + +ADR 0017: ParaTime Application Standard Proposal Process | Oasis Documentation + + + + +
+
Skip to main content

ADR 0017: ParaTime Application Standard Proposal Process

Component

ADRs

Changelog

  • 2022-10-05: Initial version
  • 2022-10-12: Accepted

Status

Accepted

Context

Applications running within a ParaTime having a novel runtime environment +(e.g., Sapphire, Cipher) benefit from interoperability standards. For example, +ERCs in Ethereum. ADRs are already present in the Oasis ecosystem and so are a +starting point, but these are intended for lightweight recording of decisions, +not gathering consensus around community contributions. This ADR proposes a +template and process amendment for ADRs introducing ParaTime-specific +application standards.

Decision

ADRs will be used for application standards because they are already well +supported within the Oasis ecosystem, and have most of the structure needed +for application standards. Although adapting another project's process would be +easy, having multiple proposal repositories could lead to confusion.

For use with application standards, ADRs shall have more structure to make +contributions fair and straightforward. Specifically, additional required +sections and concrete requirements for acceptance.

Although community standards are only proposals, the Decision section will +keep its name for compatibility with the existing template. The decision in this +context will be to accept the standard for distribution to a wider audience.

Naming Conventions

App standard ADRs shall be referred to as ADR-<number> regardless of the +targeted ParaTime.

Changes to the ADR template

  • add a new Apps component, which has the ParaTime as its sub-component

New Section Requirements

Decision: Specification & Reference Implementation

The Decision section gets two new sub-sections:

Specification: A complete description of the interface of the standard, +including the threat/trust model, rationale for design decisions, alternative +approaches, and references to related work. This section will generally be +mostly prose with sprinkles of code for illustration.

Reference Implementation: A basic implementation of the proposed standard +written in a common language that targets the ParaTime runtime environment. +The reference implementation in the ADR should be executable.

Security Considerations

This new section details any weak points of the proposal or common security +flaws that a re-implementation of the specification may run into, as well as +suggestions for avoiding security issues.

Acceptance Requirements

Like all ADRs, an Apps component ADR will start as Proposed and end up merged +once Accepted. An application standard ADR following the above format will be +accepted once:

  • there is consensus within the ParaTime's own community that the standard meets +its design goals
  • there are no outstanding compatibility or security issues
  • an ADR repo committer has signed off on the structure and format of the ADR

Alternatives

One alternative is to fit the ParaTime-specific application standard proposals +into the existing ADR template, but this would cause the Decision section to +become overloaded with the necessary information in an ad-hoc way.

Another alternative is to encourage ParaTimes to do whatever they think most +effective. That's always allowed, of course, and it may sometimes be useful to +wholesale copy the best practices of another community. However, if we make the +ADR process convenient enough, the community can focus its collective effort on +the single ADR repo.

Within the chosen decision, there were many choices of structure from the now +several EIP-like repos. The ones chosen were the minimum we need to get going, +in the spirit of the lightweight ADR process. If more structure is needed in +the future, we can amend this process or switch to a new system entirely, at +which point this ADR shall be marked as Superseded.

Consequences

Positive

  • The community has a rallying point for standard development.
  • We can reuse existing process.

Negative

  • The app standard process might still not be ideal even after this proposal.
  • ADR-NNN naming convention is not forwards compatible.

Neutral

  • We will need to maintain additional ADR process going forward.

References

+ + + + \ No newline at end of file diff --git a/adrs/0020-governance-delegator-votes/index.html b/adrs/0020-governance-delegator-votes/index.html new file mode 100644 index 0000000000..7fb69957ed --- /dev/null +++ b/adrs/0020-governance-delegator-votes/index.html @@ -0,0 +1,72 @@ + + + + + +ADR 0020: Governance Support for Delegator Votes | Oasis Documentation + + + + +
+
Skip to main content

ADR 0020: Governance Support for Delegator Votes

Component

Oasis Core

Changelog

  • 2022-11-07: Minor updates. Added Cosmos-SDK implementation note.
  • 2022-11-03: Added benchmarks, minor updates.
  • 2022-11-02: Initial draft.

Status

Accepted

Context

With the current governance voting mechanism (ADR 04), only the active +validator set is participating in voting. This means that the validators are +voting on behalf of all their delegators. This ADR proposes a change so that +each delegator is able to vote with its own stake. The delegators vote acts as +an override of the validator vote.

Decision

Casting Votes

In the current implementation the submitter of a vote needs to be a part of the +active validator committee at the time the vote is cast. This requirement is +relaxed so that additionally anyone with a delegation to an active validator +committee entity can vote.

This change requires an efficient staking.DelegationsFor query to obtain a +list of accounts the submitter is delegating to. Staking state is updated with:

// delegationKeyReverseFmt is the key format used for reverse mapping of
// delegations (delegator address, escrow address).
//
// Value is CBOR-serialized delegation.
delegationKeyReverseFmt = keyformat.New(0x5A, &staking.Address{}, &staking.Address{})

state.SetDelegation function is updated to store both delegationKeyFmt and +the reverse delegationKeyReverseFmt. DelegationsFor query function is +updated to use the added reverse mapping.

For completeness the same can be done for debonding delegations, although not +necessary for the governance changes proposed in this ADR.

Alternative solutions

Possible alternatives that would avoid adding the reverse mapping are:

  • Querying DelegationsTo for each validator. This results in num_validators +queries per cast vote transaction which is still too much.
  • Allowing anyone to cast votes. Potentially a viable solution, but this could +result in the number of voters growing uncontrollably large. This might be ok, +if the vote tallying procedure would ignore those votes. However the votes +state could still grow problematically big.

Vote tallying

When a proposal closes, the vote tallying procedure changes to:

# Two-pass over votes approach.
1 Tally up the validator votes (as it is already implemented) # First pass.
2 For each of the voters do: # Second pass.
3 For each of the entities voter delegates to:
4 Skip non validator entities
5 Skip if voter's vote matches the delegation entity vote
6 Compute stake from the delegation shares
4 If delegation entity voted, subtract the stake from the delegation entity vote tally
5 Add computed stake to the voter's vote tally
  • Possbile variant: instead of using DelegationsFor query in step 3), a map of +all validator delegators could be prebuild, by using DelegationTo for each +of the validators. Even with the efficient DelegationsFor query, this can be +beneficial IF the number of voters is large.

This procedure iterates over all voters and can be beneficial if the number of +voters is relatively low compared to the number of all validator delegators.

Alternative Vote Tallying procedures

A possible alternative would be to iterate over the delegators-validator sets:

# Delegators-validator pass approach.
1 Precompute stakes for all delegators to validators from shares.
2 For each validator
3 For each delegator to the validator
4 IF validator and delegators votes match (or delegator didn't vote)
5 Add delegator stake to the validator's vote (or nothing if validator didn't vote)
6 IF validator and delegator vote don't match
7 Add delegator stake to the delegator's vote (or nothing if delegator didn't vote)

The voting procedure now iterates over all delegators of the active validator +set. The amount of work is somewhat predictable as it doesn't depend on the +number of voters but on the delegators-to-validator sets. However the number of +votes is bound by the size of the delegators-to-validator set and in realistic +scenario likely much smaller.

Implementations in other chains

Cosmos-SDK uses a similar approach to the proposed solution in the ADR. The +tallying iterates over voters, their delegations and validators. For detailed +implementation see: Cosmos-SDK Vote Tallying Code. The voting itself is +limited to delegators (similar as proposed in this document).

Benchmarks

The Vote Tallying procedure variants were benchmarked on mainnet data.

Some basic stats from mainnet:

  • 120 validators
  • ~49500 eligible voters (unique delegators to validators)
  • average number of delegations-to per account is 1

The variants were benchmarked in scenarios with different number of voters. In +all scenarios the mainnet consensus state was used, only the number of +(simulated) voters varied. All votes were eligible (had at least one delegation +to an active validator) and all of the delegator votes did override the +validator votes.

The three tested variants were:

  • "Two pass over voters (optimized DelegationsFor)" - as described in the +proposed Vote tallying solution. Reverse mapping key is used for the +DelegationsFor queries (described in Casting Votes section).
  • "Two pass over voters (pre-build validator escrow)" - as described in the +proposed Vote tallying solution with modification of prebuilding a map of all +validator delegators (mentioned in the "Possible variant" section).
  • "Validator-delegators" - as described in the alternatives section.

Two pass over voters (optimized DelegationsFor) +Two pass over voters (pre-build validators escrow) +Validator-delegators

The above results show that:

  • Two-pass approach (querying DelegationsFor for every voter) is fastest up to +about 25000 voters for a proposal. In the worst case (every eligible voter +voted) it is about twice as slow as the alternatives. In that case the +tallying took about 3 seconds.
  • The two-pass approach using pre-built map of all validator delegators is +comparable to the "Validator-delegators" procedure. This makes sense as in +both cases the main work is done in querying the delegators of validators.

In reality, the number of voters will likely be small compared to the eligible +set of all delegators, so the two-pass approach (with querying DelegationsFor +for every voter) seems to make the most sense.

If number of voters ever becomes problematic, the method could also implement a +heuristic to use the prebuilt validator-delegators map when the number of voters +is large (e.g. number of voters > 1/2 eligible delegators), but at the moment +there is no efficient way to query the number of all delegators.

Pruning

With the possibility of increased number of votes per proposal a pruning of +votes can be implemented. Votes for a proposal can be pruned as soon as the +first block after the proposal is closed. Because proposal is closed in the +EndBlock state (which includes votes received in this last block), the pruning +should not be done before the block after, so that the exact state at the time +of the closing can be queried.

Voting via messages

Delegator can also be a runtime. For enabling runtimes to vote, casting votes +should also be supported via runtime messages.

Roothash message type is updated to include governance message field:

type Message struct {
Staking *StakingMessage `json:"staking,omitempty"`
Registry *RegistryMessage `json:"registry,omitempty"`
Governance *GovernanceMessage `json:"governance,omitempty"`
}

// GovernanceMessage is a governance message that allows a runtime to perform governance operations.
type GovernanceMessage struct {
cbor.Versioned

CastVote *governance.ProposalVote `json:"cast_vote,omitempty"`
}

Governance backend is updated to handle the cast vote message.

For completeness, support for submitting proposals via runtime messages can also +be implemented.

Consequences

Positive

  • Delegators are able to override validators vote. In the case of unresponsive +validators this increases the voting participation.
  • Delegators are able to vote with their own stake.
  • (if implemented) Staking DelegationsFor queries are now efficient and don't +require scanning the full delegations state.

Negative

  • This increases the complexity of the vote tallying procedure.
  • This increases the size of the governance votes state.
  • This increases the complexity and size of the consensus staking state if the +DelegationsFor reverse mapping is implemented.

Neutral

+ + + + \ No newline at end of file diff --git a/adrs/0021-keymanager-ephemeral-secrets/index.html b/adrs/0021-keymanager-ephemeral-secrets/index.html new file mode 100644 index 0000000000..c2b62bb5df --- /dev/null +++ b/adrs/0021-keymanager-ephemeral-secrets/index.html @@ -0,0 +1,40 @@ + + + + + +ADR 0021: Forward-Secret Ephemeral Secrets | Oasis Documentation + + + + +
+
Skip to main content

ADR 0021: Forward-Secret Ephemeral Secrets

Component

Oasis Core

Changelog

  • 2023-02-17:
    • Rename ephemeral entropy to ephemeral secret
    • Update types and methods, add method for loading a secret
    • Define publish ephemeral secret transaction
    • Split instructions for generation and replication in two sections
  • 2022-12-01: Initial proposal

Status

Accepted

Context

The network needs forward-secret ephemeral secrets that are distributed +amongst enclave executors. Because of the forward-secrecy requirements, +using the current key manager master secret is not workable.

Decision

Runtime encryption key (REK)

Let the per-enclave node.CapabilityTEE structure and related helpers be +ammeded as follows, to faciliate the addition of a X25519 public key held +by the enclave, so that encrypted data can be published on-chain to an +enclave instance.

// Note: This could also be done via the keymanager InitResponse, but
// it is the author's opinion that having a general mechanism for this
// may be useful in other contexts.

// CapabilityTEE represents the node's TEE capability.
type CapabilityTEE struct {
...

// Runtime encryption key.
REK *x25519.PublicKey `json:"rek,omitempty"`
}

Ephemeral secrets

The key manger enclave will gain the following additional RPC methods:

const (
// Local RPC methods (plaintext).
GenerateEphemeralSecret = "generate_ephemeral_secret"
LoadEphemeralSecret = "load_ephemeral_secret"

// Remote RPC method (Noise session).
ReplicateEphemeralSecret = "replicate_ephemeral_secret"
)

type GenerateEphemeralSecretRequest struct {
Epoch beacon.EpochTime `json:"epoch"`
}

type ReplicateEphemeralSecretRequest struct {
Epoch beacon.EpochTime `json:"epoch"`
}

type LoadEphemeralSecretRequest struct {
SignedSecret SignedEncryptedEphemeralSecret `json:"signed_secret"`
}

type GenerateEphemeralSecretResponse struct {
SignedSecret SignedEncryptedEphemeralSecret `json:"signed_secret"`
}

type ReplicateEphemeralSecretResponse struct {
// The request and this response are considered confidential,
// so the channel handles authentication and confidentiality.
EphemeralSecret [32]byte `json:"ephemeral_secret"`
}

Ephemeral secret generation will return a signed and encrypted ephemeral secret +for the requested epoch.

type EncryptedSecret struct {
// Checksum is the secret verification checksum.
Checksum []byte `json:"checksum"`

// PubKey is the public key used to derive the symmetric key for decryption.
PubKey x25519.PublicKey `json:"pub_key"`

// Nonce is the nonce used to decrypt the secret.
Nonce []byte `json:"nonce"`

// Ciphertexts is the map of REK encrypted ephemeral secrets for all known key manager enclaves.
Ciphertexts map[x25519.PublicKey][]byte `json:"ciphertexts"`
}

type EncryptedEncryptedSecret struct {
// ID is the runtime ID of the key manager.
ID common.Namespace `json:"runtime_id"`

// Epoch is the epoch to which the secret belongs.
Epoch beacon.EpochTime `json:"epoch"`

// Secret is the encrypted secret.
Secret EncryptedSecret `json:"secret"`
}

type SignedEncryptedEphemeralSecret struct {
// Secret is the encrypted ephemeral secret.
Secret EncryptedEphemeralSecret `json:"secret"`

// Signature is a signature of the ephemeral secret.
Signature signature.RawSignature `json:"signature"`
}

Ephemeral secret transaction

Key manager application will be augmented with a PublishEphemeralSecret +transaction that will accept the first published secret for an epoch and +discard the others.

MethodPublishEphemeralSecret = transaction.NewMethodName(
ModuleName, "PublishEphemeralSecret", SignedEncryptedEphemeralSecret{}
)

Generation

Each keymanager will, at a random time in a given epoch:

  1. Check to see if another instance has published the next epoch's ephemeral +secret. If yes, go to step 4.

  2. Execute a local generate_ephemeral_secret RPC call. The enclave will, +in-order, use the light client to query the members of the committee, +generate secret, and return a GenerateEphemeralSecretResponse. +On failure, go to step 1.

  3. Publish SignedEncryptedEphemeralSecret to consensus via +a PublishEphemeralSecret transaction.

  4. This key manager instance is DONE.

Replication

Each key manager will:

  1. Listen to the publications of new ephemeral secrets and forward them to +the enclave.

  2. Enclave will validate the secret and verify that it was published in the +consensus. Iff verification succeeds and there is a corresponding REK entry +in the Ciphertexts map, decrypt the secret and go to step 4.

  3. Until a successful response is obtained, iterate through the enclaves +in the ephemeral secret Ciphertexts map, issuing +replicate_ephemeral_secret RPC calls. On failure, repeat step 3.

  4. This key manager instance is DONE.

Consequences

Positive

  • It will be possible to publish ephemeral encrypted data to enclave +instances on-chain.

  • There will be ephemeral secret per key manager committee.

  • Enclave compromise can not go back to previous epochs to compromise +the ephemeral secrets.

  • Ephemeral secrets are never encrypted with SGX sealing key nor stored in +cold storage.

Negative

  • If enough key manager workers restart at the wrong time, the epoch's +ephemeral secret will be lost, and it will take until the next epoch +to recover.

  • Forward-secrecy is imperfect due to the epoch granular nature of the +ephemeral secret.

+ + + + \ No newline at end of file diff --git a/adrs/0022-keymanager-master-secrets/index.html b/adrs/0022-keymanager-master-secrets/index.html new file mode 100644 index 0000000000..7437e6db9d --- /dev/null +++ b/adrs/0022-keymanager-master-secrets/index.html @@ -0,0 +1,69 @@ + + + + + +ADR 0022: Forward-Secret Master Secrets | Oasis Documentation + + + + +
+
Skip to main content

ADR 0022: Forward-Secret Master Secrets

Component

Oasis Core

Changelog

  • 2023-04-17: Initial proposal

Status

Proposed

Context

The network needs forward-secret master secrets that are generated periodically +and distributed amongst enclave executors.

Decision

Key manager status

Key manager status will be extended with the following fields:

type Status struct {
...

// Generation is the generation of the latest master secret.
Generation uint64 `json:"generation,omitempty"`

// RotationEpoch is the epoch of the last master secret rotation.
RotationEpoch beacon.EpochTime `json:"rotation_epoch,omitempty"`
}

Enclave init response

Key manager enclave init response will be extended with the following fields:

type InitResponse struct {
...

NextChecksum []byte `json:"next_checksum,omitempty"`
NextRSK *signature.PublicKey `json:"next_rsk,omitempty"`
}

Master secrets

The key manager enclave will gain the following additional local RPC methods:

const (
GenerateMasterSecret = "generate_master_secret"
LoadMasterSecret = "load_master_secret"
)

type GenerateMasterSecretRequest struct {
Generation uint64 `json:"generation"`
Epoch beacon.EpochTime `json:"epoch"`
}

type GenerateMasterSecretResponse struct {
SignedSecret SignedEncryptedMasterSecret `json:"signed_secret"`
}

type LoadMasterSecretRequest struct {
SignedSecret SignedEncryptedMasterSecret `json:"signed_secret"`
}

Remote RPC method for replicating master secret will be extended to support +replication of generations and to return a Merkle proof for secret verification.

pub struct ReplicateMasterSecretRequest {
...

/// Generation.
#[cbor(optional)]
pub generation: u64,
}

pub struct ReplicateMasterSecretResponse {
...

/// Checksum of the preceding master secret.
#[cbor(optional)]
pub checksum: Vec<u8>,
}

Master secret generation will return a signed and encrypted master secret +for the requested generation and epoch.

type EncryptedMasterSecret struct {
// ID is the runtime ID of the key manager.
ID common.Namespace `json:"runtime_id"`

// Generation is the generation of the secret.
Generation uint64 `json:"generation"`

// Epoch is the epoch in which the secret was created.
Epoch beacon.EpochTime `json:"epoch"`

// Secret is the encrypted secret.
Secret EncryptedSecret `json:"secret"`
}

type SignedEncryptedMasterSecret struct {
// Secret is the encrypted master secret.
Secret EncryptedMasterSecret `json:"secret"`

// Signature is a signature of the master secret.
Signature signature.RawSignature `json:"signature"`
}

Checksums

Checksum computation will be extended with hash chains:

  • checksum_0 = KMAC(generation_0, runtime_id)
  • checksum_N = KMAC(generation_N, checksum_(N-1)) for N > 0

Hash chains allow us to use the previous checksum as a Merkle proof. +Given a verified checksum and a proof, a master secret can be verified +using the following formula:

  • next_checksum = KMAC(secret, prev_checksum)

Master secret transaction

Key manager application will be augmented with a PublishMasterSecret +transaction which will accept the proposal for the next generation of the master +secret if the following conditions are met:

  • The proposal's master secret generation number is one greater than the last +accepted generation, or 0 if no secrets have been accepted so far.

  • The proposal is intended to be accepted in the upcoming epoch.

  • Master secret hasn't been proposed in the current epoch.

  • The rotation period will either expire in the upcoming epoch or has already +expired.

    • The first master secret (generation 0) can be proposed immediately and even +if the rotation interval is set to 0.

    • If the rotation interval is set to 0, rotations are disabled and secrets +cannot be proposed anymore. To enable them again, update the rotation +interval in the policy.

  • The master secret is encrypted to the majority of the enclaves that form +the committee.

  • The node proposing the secret is a member of the key manager committee.

If accepted, the next secret can be proposed after the rotation interval +expires. Otherwise, the next secret can be proposed in the next epoch.

MethodPublishMasterSecret = transaction.NewMethodName(
ModuleName, "PublishMasterSecret", SignedEncryptedMasterSecret{}
)

Setup

The key manager is initialized with an empty checksum and no nodes. +Every node needs to register with an empty checksum to be included +in the key manager committee. Only members of the committee are +allowed to generate master secrets and will be able to decrypt +the proposals.

Generation

Each keymanager will, at a random time in a given epoch:

  1. Check to see if rotation period has expired. If not, go to step 5.

  2. Check to see if another instance has published a proposal for the upcoming +epoch. If yes, go to step 5.

  3. Execute a local generate_master_secret RPC call. The enclave will, +in-order:

    • Verify the master secret generation number.

    • Randomly select a secret.

    • Use the light client to query the members of the committee.

    • Encrypt and checksum the selected secret.

    • Return GenerateMasterSecretResponse.

    On failure, go to step 1.

  4. Read SignedEncryptedMasterSecret from the response and publish it +in the consensus layer using PublishMasterSecret transaction.

  5. This key manager instance is DONE.

Replication

Each key manager will listen for the publication of new master secret proposals +and will, when a new secret is proposed:

  1. Cancel master secret generation scheduled for the current epoch.

  2. Forward the proposal to the enclave.

  3. The enclave will verify that:

    • The proposal was published in the consensus layer.

    • The secret can be decrypted with the enclave's REK key.

    • The master secret generation number is one greater than the last known +generation.

    • The checksum computed from the decrypted secret and the last known +checksum matches the one in the proposal.

    If all verifications pass, the enclave will:

    • Decrypt the secret, encrypt it with SGX sealing key and store +the ciphertext locally.

    • Derive the RSK key for the proposed secret and store it in the memory +together with the computed checksum.

    Otherwise, go to step 5.

  4. Request enclave to initialize again and use the response to register +with the forthcoming checksum and RSK key derived from the proposal.

  5. This key manager instance is DONE.

Rotation

Key manager application will try to rotate the master secret every epoch +as part of the key manager status generation as follows:

  1. Fetch the latest master secret proposal. +On failure, go to step 6.

  2. Verify the master secret generation number and epoch of the proposal. +On failure, go to step 6.

    • The rotation period is not verified here as it is already checked when +the secret is proposed. Optionally, we can add this check to cover +the case when the policy changes after the secret is proposed.
  3. Count how many nodes have stored the proposal locally.

    • Compare the checksum of the proposal to the next_checksum field in +the init response.
  4. Accept the proposal if the majority of the nodes have replicated +the proposed secret and announced next_checksum in their init status.

    • Increment the master secret generation number by 1.

    • Update the last rotation epoch.

    • Update the checksum.

  5. Broadcast the new status.

    • If the master secret generation number has advanced, the enclaves will +try to apply the proposal they stored locally.
  6. Key manager application is DONE.

Confirmation

Each key manager will listen for the key manager status updates and will, +when the master secret generation number advances:

  1. Send the key manager status to the enclave.

  2. The enclave will:

    • Check that the master secret generation number is one greater than +the last known generation.

    • Load locally stored proposal for the next master secret or replicate it +from another enclave.

    • Use the proposal to compute the next checksum.

    • Verify the computed checksum against the latest key manager status.

    If checksum matches, the enclave will:

    • Encrypt the secret with SGX sealing key using master secret generation +number as additional data and store the ciphertext locally.

    • Update the last known generation number.

    • Update the latest checksum and RSK key.

    Otherwise, go to step 1.

  3. Request enclave to initialize again and use the response to register +with the latest checksum and RSK key while leaving the forthcoming +checksum and RSK key empty.

  4. This key manager instance is DONE.

Consequences

Positive

  • Runtimes can periodically or on demand re-encrypt their state using +the latest generation of the master secret.

  • Compromise of an enclave cannot reveal master secrets generated after its +upgrade or obsolescence.

  • If enclave initialization is interrupted or aborted, the subsequent +initialization will resume from where the previous one left off. +This means that any secrets that have already been replicated and +verified will not be fetched again.

  • When compared to Merkle trees, hash chains provide a straightforward way +to transition from the current checksum implementation and also enable +the use of simpler proofs that can be validated in constant time.

Negative

  • Initialization takes time as all master secrets need to be replicated.

    Number of secretsReplication time
    1045 sec
    10052 sec
    10002 min 45 sec
    1000021 min 17 sec

    Table 1: Local machine benchmarks (without any network overhead)

  • Master secret replication response must contain a Merkle proof for secret +verification.

  • Newly accepted master secrets cannot be used immediately to derive runtime +keys because key manager enclaves need to confirm them first. When using +Tendermint as a backend, this delay is even greater as the verifier is one +block behind.

Neutral

  • Master secrets need to be replicated in reverse order to ensure all +secrets are verified against checksum published in the consensus layer.
+ + + + \ No newline at end of file diff --git a/adrs/index.html b/adrs/index.html new file mode 100644 index 0000000000..bdaeb93027 --- /dev/null +++ b/adrs/index.html @@ -0,0 +1,16 @@ + + + + + +Architectural Decision Records | Oasis Documentation + + + + +
+
Skip to main content
+ + + + \ No newline at end of file diff --git a/adrs/template/index.html b/adrs/template/index.html new file mode 100644 index 0000000000..67e3df4558 --- /dev/null +++ b/adrs/template/index.html @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/assets/css/styles.57405ff0.css b/assets/css/styles.57405ff0.css new file mode 100644 index 0000000000..8005573a18 --- /dev/null +++ b/assets/css/styles.57405ff0.css @@ -0,0 +1 @@ +.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}*,.loadingRing_RJI3 div{box-sizing:border-box}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#3884ff;--ifm-color-primary-dark:#3884ff;--ifm-color-primary-darker:#3884ff;--ifm-color-primary-darkest:#3884ff;--ifm-color-primary-light:#3884ff;--ifm-color-primary-lighter:#3884ff;--ifm-color-primary-lightest:#3884ff;--ifm-code-font-size:95%;--docusaurus-announcement-bar-height:auto;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.list_eTzJ article:last-child,.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after,.searchBarContainer_NW3z.searchIndexLoading_EJ1f .searchBarLoadingRing_YnHq{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.content_knG7 a,.hitFooter_E9YW a,.suggestion_fB_2.cursor_eG29 mark{text-decoration:underline}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;pointer-events:none;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.cardContainer_fWXF :last-child,.collapsibleContent_i85q>:last-child,.footer__items,.searchResultItem_U687>h2,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter);content:""}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.header-github-link:before,.header-link:before,.header-www-link:before{height:24px;width:24px;display:flex}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}#nprogress,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--ifm-color-primary:#3884ff;--ifm-color-primary-dark:#3884ff;--ifm-color-primary-darker:#3884ff;--ifm-color-primary-darkest:#3884ff;--ifm-color-primary-light:#3884ff;--ifm-color-primary-lighter:#3884ff;--ifm-color-primary-lightest:#3884ff}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}.docusaurus-highlight-code-line{background-color:#0000001a;display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}html[data-theme=dark] .docusaurus-highlight-code-line{background-color:#0000004d}.header-link:before{content:""}.header-github-link:hover,.header-www-link:hover{opacity:.6}.header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;content:""}.header-www-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='M12 23c6.075 0 11-4.925 11-11S18.075 1 12 1 1 5.925 1 12s4.925 11 11 11zm0 0c3 0 4-5 4-11S15 1 12 1 8 6 8 12s1 11 4 11zM2 16h20M2 8h20'/%3E%3C/svg%3E") no-repeat;content:""}[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}[data-theme=dark] .header-www-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' d='M12 23c6.075 0 11-4.925 11-11S18.075 1 12 1 1 5.925 1 12s4.925 11 11 11zm0 0c3 0 4-5 4-11S15 1 12 1 8 6 8 12s1 11 4 11zM2 16h20M2 8h20'/%3E%3C/svg%3E") no-repeat}.markdown>a.card{margin-bottom:32px}.theme-doc-sidebar-menu{font-size:14px}html[data-theme=dark] main img{background-color:#fff}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_b6E3,.hideAction_vcyE>svg,.sidebarLogo_isFc,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.searchBar_RVTs .dropdownMenu_qbY6{background:var(--search-local-modal-background,#f5f6f7);border-radius:6px;box-shadow:var(--search-local-modal-shadow,inset 1px 1px 0 0 #ffffff80,0 3px 8px 0 #555a64);left:auto!important;margin-top:8px;padding:var(--search-local-spacing,12px);position:relative;right:0!important;width:var(--search-local-modal-width,560px)}html[data-theme=dark] .searchBar_RVTs .dropdownMenu_qbY6{background:var(--search-local-modal-background,var(--ifm-background-color));box-shadow:var(--search-local-modal-shadow,inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309)}.searchBar_RVTs .dropdownMenu_qbY6 .suggestion_fB_2{align-items:center;background:var(--search-local-hit-background,#fff);border-radius:4px;box-shadow:var(--search-local-hit-shadow,0 1px 3px 0 #d4d9e1);color:var(--search-local-hit-color,#444950);cursor:pointer;display:flex;flex-direction:row;height:var(--search-local-hit-height,56px);padding:0 var(--search-local-spacing,12px);width:100%}.hitTree_kk6K,.noResults_l6Q3{align-items:center;display:flex}html[data-theme=dark] .dropdownMenu_qbY6 .suggestion_fB_2{background:var(--search-local-hit-background,var(--ifm-color-emphasis-100));box-shadow:var(--search-local-hit-shadow,none);color:var(--search-local-hit-color,var(--ifm-font-color-base))}.searchBar_RVTs .dropdownMenu_qbY6 .suggestion_fB_2:not(:last-child){margin-bottom:4px}.searchBar_RVTs .dropdownMenu_qbY6 .suggestion_fB_2.cursor_eG29{background-color:var(--search-local-highlight-color,var(--ifm-color-primary))}.hitFooter_E9YW a,.hitIcon_a7Zy,.hitPath_ieM4,.hitTree_kk6K,.noResultsIcon_EBY5{color:var(--search-local-muted-color,#969faf)}html[data-theme=dark] .hitIcon_a7Zy,html[data-theme=dark] .hitPath_ieM4,html[data-theme=dark] .hitTree_kk6K,html[data-theme=dark] .noResultsIcon_EBY5{color:var(--search-local-muted-color,var(--ifm-color-secondary-darkest))}.hitTree_kk6K>svg{height:var(--search-local-hit-height,56px);opacity:.5;width:24px}.hitIcon_a7Zy,.hitTree_kk6K>svg{stroke-width:var(--search-local-icon-stroke-width,1.4)}.hitAction_NqkB,.hitIcon_a7Zy{height:20px;width:20px}.hitWrapper_sAK8{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;margin:0 8px;overflow-x:hidden;width:80%}.hitWrapper_sAK8 mark{background:none;color:var(--search-local-highlight-color,var(--ifm-color-primary))}.hitTitle_vyVt{font-size:.9em}.hitPath_ieM4{font-size:.75em}.hitPath_ieM4,.hitTitle_vyVt{overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.noResults_l6Q3{flex-direction:column;justify-content:center;padding:var(--search-local-spacing,12px) 0}.noResultsIcon_EBY5{margin-bottom:var(--search-local-spacing,12px)}.hitFooter_E9YW{font-size:.85em;margin-top:var(--search-local-spacing,12px);text-align:center}.cursor_eG29 .hideAction_vcyE>svg,.tocCollapsibleContent_vkbj a{display:block}.suggestion_fB_2.cursor_eG29,.suggestion_fB_2.cursor_eG29 .hitIcon_a7Zy,.suggestion_fB_2.cursor_eG29 .hitPath_ieM4,.suggestion_fB_2.cursor_eG29 .hitTree_kk6K,.suggestion_fB_2.cursor_eG29 mark{color:var(--search-local-hit-active-color,var(--ifm-color-white))!important}.searchBarContainer_NW3z{margin-left:16px}.searchBarContainer_NW3z .searchBarLoadingRing_YnHq{display:none;left:10px;position:absolute;top:6px}.searchBarContainer_NW3z .searchClearButton_qk4g{background:none;border:none;line-height:1rem;padding:0;position:absolute;right:.8rem;top:50%;transform:translateY(-50%)}.navbar__search{position:relative}.searchIndexLoading_EJ1f .navbar__search-input{background-image:none}.searchHintContainer_Pkmr{align-items:center;display:flex;gap:4px;height:100%;justify-content:center;pointer-events:none;position:absolute;right:10px;top:0}.searchHint_iIMx{background-color:var(--ifm-navbar-search-input-background-color);border:1px solid var(--ifm-color-emphasis-500);box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-500);color:var(--ifm-navbar-search-input-placeholder-color)}.loadingRing_RJI3{display:inline-block;height:20px;opacity:var(--search-local-loading-icon-opacity,.5);position:relative;width:20px}.loadingRing_RJI3 div{animation:1.2s cubic-bezier(.5,0,.5,1) infinite a;border:2px solid var(--search-load-loading-icon-color,var(--ifm-navbar-search-input-color));border-color:var(--search-load-loading-icon-color,var(--ifm-navbar-search-input-color)) #0000 #0000 #0000;border-radius:50%;display:block;height:16px;margin:2px;position:absolute;width:16px}.loadingRing_RJI3 div:first-child{animation-delay:-.45s}.loadingRing_RJI3 div:nth-child(2){animation-delay:-.3s}.loadingRing_RJI3 div:nth-child(3){animation-delay:-.15s}@keyframes a{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.cardContainer_fWXF{--ifm-link-color:var(--ifm-color-emphasis-800);--ifm-link-hover-color:var(--ifm-color-emphasis-700);--ifm-link-hover-decoration:none;border:1px solid var(--ifm-color-emphasis-200);box-shadow:0 1.5px 3px 0 #00000026;transition:all var(--ifm-transition-fast) ease;transition-property:border,box-shadow}.cardContainer_fWXF:hover{border-color:var(--ifm-color-primary);box-shadow:0 3px 6px 0 #0003}.cardTitle_rnsV{font-size:1.2rem}.cardDescription_PWke{font-size:.8rem}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.searchQueryInput_CFBF,.searchVersionInput_t5lH{background:var(--ifm-background-color);border:var(--ifm-global-border-width) solid var(--ifm-color-content-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-font-color-base);font-size:var(--ifm-font-size-base);margin-bottom:1rem;padding:.5rem;width:100%}.searchResultItem_U687{border-bottom:1px solid #dfe3e8;padding:1rem 0}.searchResultItemPath_uIbk{color:var(--ifm-color-content-secondary);font-size:.8rem;margin:.5rem 0 0}.searchResultItemSummary_oZHr{font-style:italic;margin:.5rem 0 0}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.docPage__5DB{flex:1 0}.docsWrapper_BCFX{display:flex;flex:1 0 auto}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.title_kItE{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-leading)*1.25)}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_Xe31{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.docItemCol_VOVn,.generatedIndexPage_vN6x{max-width:75%!important}.list_eTzJ article:nth-last-child(-n+2){margin-bottom:0!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media not (max-width:996px){.searchBar_RVTs.searchBarLeft_MXDe .dropdownMenu_qbY6{left:0!important;right:auto!important}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.navbar__search-input:not(:focus){width:2rem}.searchBar_RVTs .dropdownMenu_qbY6{max-width:calc(100vw - var(--ifm-navbar-padding-horizontal)*2);width:var(--search-local-modal-width-sm,340px)}.searchBarContainer_NW3z:not(.focused_OWtg) .searchClearButton_qk4g,.searchHintContainer_Pkmr{display:none}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/assets/files/data-3564fe57c5907977ab1cd7c274a1b895.csv b/assets/files/data-3564fe57c5907977ab1cd7c274a1b895.csv new file mode 100644 index 0000000000..22b539185e --- /dev/null +++ b/assets/files/data-3564fe57c5907977ab1cd7c274a1b895.csv @@ -0,0 +1,42 @@ +T [months],Strategic Partners & Reserve,Community & Ecosystem,Foundation,Core Contributors,Backers +0,12500000,370000000,250000000,0,759000000 +3,0,0,0,0,0 +6,12500000,0,0,0,0 +9,12500000,0,0,0,0 +12,12500000,407000000,0,300000000,759000000 +15,12500000,0,0,150000000,0 +18,12500000,370000000,0,150000000,782000000 +21,12500000,37000000,0,150000000,0 +24,12500000,37000000,100000000,150000000,0 +27,12500000,37000000,0,150000000,0 +30,12500000,37000000,0,150000000,0 +33,12500000,18500000,0,140000000,0 +36,12500000,18500000,25000000,140000000,0 +39,12500000,18500000,0,140000000,0 +42,12500000,18500000,0,140000000,0 +45,12500000,18500000,0,120000000,0 +48,12500000,18500000,25000000,120000000,0 +51,12500000,18500000,25000000,0,0 +54,12500000,18500000,25000000,0,0 +57,12500000,18500000,25000000,0,0 +60,12500000,18500000,25000000,0,0 +63,12500000,18500000,25000000,0,0 +66,12500000,18500000,25000000,0,0 +69,12500000,18500000,25000000,0,0 +72,12500000,18500000,25000000,0,0 +75,12500000,18500000,25000000,0,0 +78,12500000,18500000,25000000,0,0 +81,12500000,18500000,25000000,0,0 +84,12500000,18500000,25000000,0,0 +87,12500000,18500000,25000000,0,0 +90,12500000,18500000,25000000,0,0 +93,12500000,18500000,25000000,0,0 +96,12500000,18500000,25000000,0,0 +99,12500000,18500000,25000000,0,0 +102,12500000,18500000,25000000,0,0 +105,12500000,18500000,25000000,0,0 +108,12500000,18500000,25000000,0,0 +111,12500000,18500000,25000000,0,0 +114,12500000,18500000,25000000,0,0 +117,12500000,18500000,25000000,0,0 +120,12500000,18500000,25000000,0,0 diff --git a/assets/files/data-e5c85038908548ce84bf7db10d5899b9.csv b/assets/files/data-e5c85038908548ce84bf7db10d5899b9.csv new file mode 100644 index 0000000000..302e241a7d --- /dev/null +++ b/assets/files/data-e5c85038908548ce84bf7db10d5899b9.csv @@ -0,0 +1,446 @@ +Until epoch,Estimated date,Reward per epoch %,Estimated annualized rewards % +1170,2020-11-18T16:00:00.000Z,0.002081,20.0697 +4842,2021-04-20T03:46:38.848Z,0.002081,20.0697 +4866,2021-04-21T03:41:51.259Z,0.002080,20.0592 +4890,2021-04-22T03:37:03.669Z,0.002079,20.0486 +4914,2021-04-23T03:32:16.080Z,0.002078,20.0381 +4938,2021-04-24T03:27:28.491Z,0.002076,20.0170 +4962,2021-04-25T03:22:40.902Z,0.002075,20.0064 +4986,2021-04-26T03:17:53.313Z,0.002073,19.9853 +5010,2021-04-27T03:13:05.723Z,0.002071,19.9643 +5034,2021-04-28T03:08:18.134Z,0.002069,19.9432 +5058,2021-04-29T03:03:30.545Z,0.002067,19.9221 +5082,2021-04-30T02:58:42.956Z,0.002065,19.9010 +5106,2021-05-01T02:53:55.366Z,0.002063,19.8799 +5130,2021-05-02T02:49:07.777Z,0.002060,19.8483 +5154,2021-05-03T02:44:20.188Z,0.002057,19.8167 +5178,2021-05-04T02:39:32.599Z,0.002054,19.7851 +5202,2021-05-05T02:34:45.010Z,0.002050,19.7430 +5226,2021-05-06T02:29:57.420Z,0.002046,19.7009 +5250,2021-05-07T02:25:09.831Z,0.002041,19.6484 +5274,2021-05-08T02:20:22.242Z,0.002036,19.5958 +5298,2021-05-09T02:15:34.653Z,0.002030,19.5327 +5322,2021-05-10T02:10:47.063Z,0.002024,19.4697 +5346,2021-05-11T02:05:59.474Z,0.002017,19.3962 +5370,2021-05-12T02:01:11.885Z,0.002008,19.3018 +5394,2021-05-13T01:56:24.296Z,0.001999,19.2075 +5418,2021-05-14T01:51:36.706Z,0.001988,19.0923 +5442,2021-05-15T01:46:49.117Z,0.001975,18.9563 +5466,2021-05-16T01:42:01.528Z,0.001961,18.8100 +5490,2021-05-17T01:37:13.939Z,0.001945,18.6431 +5514,2021-05-18T01:32:26.350Z,0.001927,18.4555 +5538,2021-05-19T01:27:38.760Z,0.001909,18.2683 +5562,2021-05-20T01:22:51.171Z,0.001889,18.0606 +5586,2021-05-21T01:18:03.582Z,0.001870,17.8636 +5610,2021-05-22T01:13:15.993Z,0.001851,17.6669 +5634,2021-05-23T01:08:28.403Z,0.001834,17.4912 +5658,2021-05-24T01:03:40.814Z,0.001818,17.3261 +5682,2021-05-25T00:58:53.225Z,0.001803,17.1715 +5706,2021-05-26T00:54:05.636Z,0.001791,17.0480 +5730,2021-05-27T00:49:18.047Z,0.001779,16.9246 +5754,2021-05-28T00:44:30.457Z,0.001769,16.8219 +5778,2021-05-29T00:39:42.868Z,0.001761,16.7398 +5802,2021-05-30T00:34:55.279Z,0.001753,16.6578 +5826,2021-05-31T00:30:07.690Z,0.001747,16.5963 +5850,2021-06-01T00:25:20.100Z,0.001741,16.5348 +5874,2021-06-02T00:20:32.511Z,0.001736,16.4836 +5898,2021-06-03T00:15:44.922Z,0.001731,16.4324 +5922,2021-06-04T00:10:57.333Z,0.001727,16.3915 +5946,2021-06-05T00:06:09.744Z,0.001723,16.3506 +5970,2021-06-06T00:01:22.154Z,0.001720,16.3199 +5994,2021-06-06T23:56:34.565Z,0.001717,16.2892 +6018,2021-06-07T23:51:46.976Z,0.001714,16.2586 +6042,2021-06-08T23:46:59.387Z,0.001711,16.2279 +6066,2021-06-09T23:42:11.797Z,0.001709,16.2075 +6090,2021-06-10T23:37:24.208Z,0.001707,16.1871 +6114,2021-06-11T23:32:36.619Z,0.001705,16.1666 +6138,2021-06-12T23:27:49.030Z,0.001703,16.1462 +6162,2021-06-13T23:23:01.440Z,0.001701,16.1258 +6186,2021-06-14T23:18:13.851Z,0.001700,16.1156 +6210,2021-06-15T23:13:26.262Z,0.001698,16.0952 +6234,2021-06-16T23:08:38.673Z,0.001697,16.0850 +6258,2021-06-17T23:03:51.084Z,0.001696,16.0748 +9234,2021-10-19T13:09:30.020Z,0.001694,16.0544 +9258,2021-10-20T13:04:42.430Z,0.001693,16.0442 +9282,2021-10-21T12:59:54.841Z,0.001692,16.0340 +9306,2021-10-22T12:55:07.252Z,0.001690,16.0136 +9330,2021-10-23T12:50:19.663Z,0.001689,16.0034 +9354,2021-10-24T12:45:32.073Z,0.001687,15.9830 +9378,2021-10-25T12:40:44.484Z,0.001686,15.9728 +9402,2021-10-26T12:35:56.895Z,0.001684,15.9524 +9426,2021-10-27T12:31:09.306Z,0.001682,15.9320 +9450,2021-10-28T12:26:21.717Z,0.001680,15.9117 +9474,2021-10-29T12:21:34.127Z,0.001677,15.8811 +9498,2021-10-30T12:16:46.538Z,0.001675,15.8607 +9522,2021-10-31T12:11:58.949Z,0.001672,15.8302 +9546,2021-11-01T12:07:11.360Z,0.001669,15.7997 +9570,2021-11-02T12:02:23.770Z,0.001666,15.7691 +9594,2021-11-03T11:57:36.181Z,0.001662,15.7284 +9618,2021-11-04T11:52:48.592Z,0.001658,15.6878 +9642,2021-11-05T11:48:01.003Z,0.001653,15.6369 +9666,2021-11-06T11:43:13.413Z,0.001648,15.5861 +9690,2021-11-07T11:38:25.824Z,0.001642,15.5252 +9714,2021-11-08T11:33:38.235Z,0.001635,15.4541 +9738,2021-11-09T11:28:50.646Z,0.001627,15.3730 +9762,2021-11-10T11:24:03.057Z,0.001619,15.2919 +9786,2021-11-11T11:19:15.467Z,0.001609,15.1906 +9810,2021-11-12T11:14:27.878Z,0.001597,15.0692 +9834,2021-11-13T11:09:40.289Z,0.001584,14.9378 +9858,2021-11-14T11:04:52.700Z,0.001570,14.7964 +9882,2021-11-15T11:00:05.110Z,0.001553,14.6250 +9906,2021-11-16T10:55:17.521Z,0.001535,14.4438 +9930,2021-11-17T10:50:29.932Z,0.001516,14.2529 +9954,2021-11-18T10:45:42.343Z,0.001496,14.0522 +9978,2021-11-19T10:40:54.754Z,0.001476,13.8519 +10002,2021-11-20T10:36:07.164Z,0.001456,13.6520 +10026,2021-11-21T10:31:19.575Z,0.001438,13.4723 +10050,2021-11-22T10:26:31.986Z,0.001422,13.3128 +10074,2021-11-23T10:21:44.397Z,0.001407,13.1636 +10098,2021-11-24T10:16:56.807Z,0.001393,13.0244 +10122,2021-11-25T10:12:09.218Z,0.001382,12.9152 +10146,2021-11-26T10:07:21.629Z,0.001372,12.8160 +10170,2021-11-27T10:02:34.040Z,0.001363,12.7268 +10194,2021-11-28T09:57:46.451Z,0.001355,12.6475 +10218,2021-11-29T09:52:58.861Z,0.001348,12.5783 +10242,2021-11-30T09:48:11.272Z,0.001342,12.5189 +10266,2021-12-01T09:43:23.683Z,0.001336,12.4596 +10290,2021-12-02T09:38:36.094Z,0.001332,12.4200 +10314,2021-12-03T09:33:48.504Z,0.001327,12.3707 +10338,2021-12-04T09:29:00.915Z,0.001323,12.3312 +10362,2021-12-05T09:24:13.326Z,0.001320,12.3015 +10386,2021-12-06T09:19:25.737Z,0.001317,12.2719 +10410,2021-12-07T09:14:38.147Z,0.001314,12.2423 +10434,2021-12-08T09:09:50.558Z,0.001311,12.2127 +10458,2021-12-09T09:05:02.969Z,0.001309,12.1930 +10482,2021-12-10T09:00:15.380Z,0.001307,12.1733 +10506,2021-12-11T08:55:27.791Z,0.001305,12.1536 +10530,2021-12-12T08:50:40.201Z,0.001303,12.1339 +10554,2021-12-13T08:45:52.612Z,0.001301,12.1142 +10578,2021-12-14T08:41:05.023Z,0.001299,12.0945 +10602,2021-12-15T08:36:17.434Z,0.001298,12.0846 +10626,2021-12-16T08:31:29.844Z,0.001296,12.0649 +10650,2021-12-17T08:26:42.255Z,0.001295,12.0551 +13602,2022-04-18T22:37:08.780Z,0.001294,12.0452 +13626,2022-04-19T22:32:21.191Z,0.001293,12.0354 +13674,2022-04-21T22:22:46.013Z,0.001292,12.0255 +13698,2022-04-22T22:17:58.424Z,0.001291,12.0157 +13722,2022-04-23T22:13:10.834Z,0.001290,12.0058 +13746,2022-04-24T22:08:23.245Z,0.001289,11.9960 +13770,2022-04-25T22:03:35.656Z,0.001288,11.9861 +13794,2022-04-26T21:58:48.067Z,0.001287,11.9763 +13818,2022-04-27T21:54:00.477Z,0.001286,11.9665 +13842,2022-04-28T21:49:12.888Z,0.001285,11.9566 +13866,2022-04-29T21:44:25.299Z,0.001284,11.9468 +13890,2022-04-30T21:39:37.710Z,0.001282,11.9271 +13914,2022-05-01T21:34:50.120Z,0.001281,11.9173 +13938,2022-05-02T21:30:02.531Z,0.001279,11.8976 +13962,2022-05-03T21:25:14.942Z,0.001277,11.8779 +13986,2022-05-04T21:20:27.353Z,0.001275,11.8583 +14010,2022-05-05T21:15:39.764Z,0.001272,11.8288 +14034,2022-05-06T21:10:52.174Z,0.001270,11.8091 +14058,2022-05-07T21:06:04.585Z,0.001267,11.7796 +14082,2022-05-08T21:01:16.996Z,0.001263,11.7403 +14106,2022-05-09T20:56:29.407Z,0.001259,11.7011 +14130,2022-05-10T20:51:41.817Z,0.001255,11.6618 +14154,2022-05-11T20:46:54.228Z,0.001249,11.6029 +14178,2022-05-12T20:42:06.639Z,0.001244,11.5539 +14202,2022-05-13T20:37:19.050Z,0.001237,11.4853 +14226,2022-05-14T20:32:31.461Z,0.001229,11.4069 +14250,2022-05-15T20:27:43.871Z,0.001221,11.3286 +14274,2022-05-16T20:22:56.282Z,0.001212,11.2406 +14298,2022-05-17T20:18:08.693Z,0.001202,11.1429 +14322,2022-05-18T20:13:21.104Z,0.001191,11.0355 +14346,2022-05-19T20:08:33.514Z,0.001181,10.9379 +14370,2022-05-20T20:03:45.925Z,0.001171,10.8404 +14394,2022-05-21T19:58:58.336Z,0.001162,10.7528 +14418,2022-05-22T19:54:10.747Z,0.001153,10.6652 +14442,2022-05-23T19:49:23.157Z,0.001146,10.5972 +14466,2022-05-24T19:44:35.568Z,0.001139,10.5291 +14490,2022-05-25T19:39:47.979Z,0.001133,10.4709 +14514,2022-05-26T19:35:00.390Z,0.001128,10.4223 +14538,2022-05-27T19:30:12.801Z,0.001123,10.3738 +14562,2022-05-28T19:25:25.211Z,0.001119,10.3350 +14586,2022-05-29T19:20:37.622Z,0.001116,10.3059 +14610,2022-05-30T19:15:50.033Z,0.001113,10.2769 +14634,2022-05-31T19:11:02.444Z,0.001110,10.2478 +14658,2022-06-01T19:06:14.854Z,0.001107,10.2187 +14682,2022-06-02T19:01:27.265Z,0.001105,10.1993 +14706,2022-06-03T18:56:39.676Z,0.001103,10.1800 +14730,2022-06-04T18:51:52.087Z,0.001101,10.1606 +14754,2022-06-05T18:47:04.498Z,0.001100,10.1509 +14778,2022-06-06T18:42:16.908Z,0.001098,10.1316 +14802,2022-06-07T18:37:29.319Z,0.001097,10.1219 +14826,2022-06-08T18:32:41.730Z,0.001096,10.1122 +14850,2022-06-09T18:27:54.141Z,0.001095,10.1025 +14874,2022-06-10T18:23:06.551Z,0.001094,10.0929 +14898,2022-06-11T18:18:18.962Z,0.001093,10.0832 +14922,2022-06-12T18:13:31.373Z,0.001092,10.0735 +14946,2022-06-13T18:08:43.784Z,0.001091,10.0638 +14970,2022-06-14T18:03:56.195Z,0.001090,10.0542 +15018,2022-06-16T17:54:21.016Z,0.001089,10.0445 +17994,2022-10-18T07:59:59.952Z,0.001088,10.0348 +18018,2022-10-19T07:55:12.363Z,0.001087,10.0251 +18042,2022-10-20T07:50:24.774Z,0.001085,10.0058 +18066,2022-10-21T07:45:37.184Z,0.001084,9.9961 +18090,2022-10-22T07:40:49.595Z,0.001082,9.9768 +18114,2022-10-23T07:36:02.006Z,0.001081,9.9671 +18138,2022-10-24T07:31:14.417Z,0.001079,9.9478 +18162,2022-10-25T07:26:26.827Z,0.001077,9.9285 +18186,2022-10-26T07:21:39.238Z,0.001075,9.9092 +18210,2022-10-27T07:16:51.649Z,0.001073,9.8898 +18234,2022-10-28T07:12:04.060Z,0.001070,9.8609 +18258,2022-10-29T07:07:16.471Z,0.001067,9.8319 +18282,2022-10-30T07:02:28.881Z,0.001065,9.8126 +18306,2022-10-31T06:57:41.292Z,0.001061,9.7740 +18330,2022-11-01T06:52:53.703Z,0.001058,9.7451 +18354,2022-11-02T06:48:06.114Z,0.001054,9.7065 +18378,2022-11-03T06:43:18.524Z,0.001049,9.6583 +18402,2022-11-04T06:38:30.935Z,0.001044,9.6101 +18426,2022-11-05T06:33:43.346Z,0.001039,9.5619 +18450,2022-11-06T06:28:55.757Z,0.001033,9.5042 +18474,2022-11-07T06:24:08.168Z,0.001025,9.4272 +18498,2022-11-08T06:19:20.578Z,0.001017,9.3503 +18522,2022-11-09T06:14:32.989Z,0.001008,9.2638 +18546,2022-11-10T06:09:45.400Z,0.000998,9.1678 +18570,2022-11-11T06:04:57.811Z,0.000986,9.0528 +18594,2022-11-12T06:00:10.221Z,0.000972,8.9187 +18618,2022-11-13T05:55:22.632Z,0.000956,8.7656 +18642,2022-11-14T05:50:35.043Z,0.000939,8.6032 +18666,2022-11-15T05:45:47.454Z,0.000920,8.4220 +18690,2022-11-16T05:40:59.864Z,0.000900,8.2316 +18714,2022-11-17T05:36:12.275Z,0.000879,8.0320 +18738,2022-11-18T05:31:24.686Z,0.000857,7.8233 +18762,2022-11-19T05:26:37.097Z,0.000837,7.6339 +18786,2022-11-20T05:21:49.508Z,0.000818,7.4543 +18810,2022-11-21T05:17:01.918Z,0.000800,7.2845 +18834,2022-11-22T05:12:14.329Z,0.000784,7.1337 +18858,2022-11-23T05:07:26.740Z,0.000770,7.0020 +18882,2022-11-24T05:02:39.151Z,0.000758,6.8892 +18906,2022-11-25T04:57:51.561Z,0.000747,6.7859 +18930,2022-11-26T04:53:03.972Z,0.000738,6.7014 +18954,2022-11-27T04:48:16.383Z,0.000730,6.6264 +18978,2022-11-28T04:43:28.794Z,0.000722,6.5515 +19002,2022-11-29T04:38:41.205Z,0.000716,6.4953 +19026,2022-11-30T04:33:53.615Z,0.000710,6.4392 +19050,2022-12-01T04:29:06.026Z,0.000705,6.3924 +19074,2022-12-02T04:24:18.437Z,0.000701,6.3550 +19098,2022-12-03T04:19:30.848Z,0.000697,6.3176 +19122,2022-12-04T04:14:43.258Z,0.000693,6.2803 +19146,2022-12-05T04:09:55.669Z,0.000689,6.2429 +19170,2022-12-06T04:05:08.080Z,0.000686,6.2149 +19194,2022-12-07T04:00:20.491Z,0.000684,6.1962 +19218,2022-12-08T03:55:32.902Z,0.000681,6.1682 +19242,2022-12-09T03:50:45.312Z,0.000679,6.1496 +19266,2022-12-10T03:45:57.723Z,0.000677,6.1309 +19290,2022-12-11T03:41:10.134Z,0.000675,6.1122 +19314,2022-12-12T03:36:22.545Z,0.000673,6.0936 +19338,2022-12-13T03:31:34.955Z,0.000671,6.0749 +19362,2022-12-14T03:26:47.366Z,0.000669,6.0563 +19386,2022-12-15T03:21:59.777Z,0.000668,6.0470 +19410,2022-12-16T03:17:12.188Z,0.000666,6.0283 +22386,2023-04-18T17:22:51.124Z,0.000665,6.0190 +22410,2023-04-19T17:18:03.534Z,0.000664,6.0097 +22434,2023-04-20T17:13:15.945Z,0.000663,6.0004 +22458,2023-04-21T17:08:28.356Z,0.000662,5.9911 +22482,2023-04-22T17:03:40.767Z,0.000661,5.9818 +22506,2023-04-23T16:58:53.178Z,0.000660,5.9724 +22530,2023-04-24T16:54:05.588Z,0.000659,5.9631 +22554,2023-04-25T16:49:17.999Z,0.000658,5.9538 +22578,2023-04-26T16:44:30.410Z,0.000657,5.9445 +22602,2023-04-27T16:39:42.821Z,0.000656,5.9352 +22626,2023-04-28T16:34:55.231Z,0.000655,5.9259 +22650,2023-04-29T16:30:07.642Z,0.000653,5.9073 +22674,2023-04-30T16:25:20.053Z,0.000651,5.8886 +22698,2023-05-01T16:20:32.464Z,0.000649,5.8700 +22722,2023-05-02T16:15:44.875Z,0.000647,5.8514 +22746,2023-05-03T16:10:57.285Z,0.000645,5.8328 +22770,2023-05-04T16:06:09.696Z,0.000643,5.8142 +22794,2023-05-05T16:01:22.107Z,0.000640,5.7863 +22818,2023-05-06T15:56:34.518Z,0.000636,5.7491 +22842,2023-05-07T15:51:46.928Z,0.000633,5.7213 +22866,2023-05-08T15:46:59.339Z,0.000629,5.6841 +22890,2023-05-09T15:42:11.750Z,0.000624,5.6377 +22914,2023-05-10T15:37:24.161Z,0.000618,5.5820 +22938,2023-05-11T15:32:36.571Z,0.000612,5.5263 +22962,2023-05-12T15:27:48.982Z,0.000605,5.4614 +22986,2023-05-13T15:23:01.393Z,0.000597,5.3873 +23010,2023-05-14T15:18:13.804Z,0.000588,5.3039 +23034,2023-05-15T15:13:26.215Z,0.000578,5.2114 +23058,2023-05-16T15:08:38.625Z,0.000568,5.1190 +23082,2023-05-17T15:03:51.036Z,0.000557,5.0174 +23106,2023-05-18T14:59:03.447Z,0.000546,4.9159 +23130,2023-05-19T14:54:15.858Z,0.000536,4.8238 +23154,2023-05-20T14:49:28.268Z,0.000526,4.7317 +23178,2023-05-21T14:44:40.679Z,0.000517,4.6489 +23202,2023-05-22T14:39:53.090Z,0.000509,4.5753 +23226,2023-05-23T14:35:05.501Z,0.000502,4.5110 +23250,2023-05-24T14:30:17.912Z,0.000495,4.4467 +23274,2023-05-25T14:25:30.322Z,0.000490,4.4008 +23298,2023-05-26T14:20:42.733Z,0.000485,4.3549 +23322,2023-05-27T14:15:55.144Z,0.000481,4.3183 +23346,2023-05-28T14:11:07.555Z,0.000477,4.2816 +23370,2023-05-29T14:06:19.965Z,0.000474,4.2541 +23394,2023-05-30T14:01:32.376Z,0.000471,4.2266 +23418,2023-05-31T13:56:44.787Z,0.000468,4.1991 +23442,2023-06-01T13:51:57.198Z,0.000466,4.1808 +23466,2023-06-02T13:47:09.609Z,0.000464,4.1625 +23490,2023-06-03T13:42:22.019Z,0.000462,4.1442 +23514,2023-06-04T13:37:34.430Z,0.000460,4.1259 +23538,2023-06-05T13:32:46.841Z,0.000459,4.1167 +23562,2023-06-06T13:27:59.252Z,0.000457,4.0984 +23586,2023-06-07T13:23:11.662Z,0.000456,4.0893 +23610,2023-06-08T13:18:24.073Z,0.000455,4.0801 +23634,2023-06-09T13:13:36.484Z,0.000454,4.0710 +23658,2023-06-10T13:08:48.895Z,0.000453,4.0618 +23682,2023-06-11T13:04:01.305Z,0.000452,4.0527 +23706,2023-06-12T12:59:13.716Z,0.000451,4.0436 +23730,2023-06-13T12:54:26.127Z,0.000450,4.0344 +23754,2023-06-14T12:49:38.538Z,0.000449,4.0253 +26754,2023-10-17T02:50:29.885Z,0.000448,4.0161 +26802,2023-10-19T02:40:54.706Z,0.000447,4.0070 +26826,2023-10-20T02:36:07.117Z,0.000446,3.9978 +26874,2023-10-22T02:26:31.938Z,0.000445,3.9887 +26898,2023-10-23T02:21:44.349Z,0.000444,3.9796 +26946,2023-10-25T02:12:09.171Z,0.000443,3.9704 +26970,2023-10-26T02:07:21.581Z,0.000442,3.9613 +26994,2023-10-27T02:02:33.992Z,0.000441,3.9522 +27018,2023-10-28T01:57:46.403Z,0.000440,3.9430 +27042,2023-10-29T01:52:58.814Z,0.000438,3.9247 +27066,2023-10-30T01:48:11.225Z,0.000437,3.9156 +27090,2023-10-31T01:43:23.635Z,0.000436,3.9065 +27114,2023-11-01T01:38:36.046Z,0.000434,3.8882 +27138,2023-11-02T01:33:48.457Z,0.000432,3.8700 +27162,2023-11-03T01:29:00.868Z,0.000430,3.8517 +27186,2023-11-04T01:24:13.278Z,0.000428,3.8334 +27210,2023-11-05T01:19:25.689Z,0.000426,3.8152 +27234,2023-11-06T01:14:38.100Z,0.000423,3.7878 +27258,2023-11-07T01:09:50.511Z,0.000420,3.7605 +27282,2023-11-08T01:05:02.922Z,0.000416,3.7240 +27306,2023-11-09T01:00:15.332Z,0.000412,3.6875 +27330,2023-11-10T00:55:27.743Z,0.000407,3.6420 +27354,2023-11-11T00:50:40.154Z,0.000402,3.5964 +27378,2023-11-12T00:45:52.565Z,0.000396,3.5418 +27402,2023-11-13T00:41:04.975Z,0.000389,3.4781 +27426,2023-11-14T00:36:17.386Z,0.000381,3.4054 +27450,2023-11-15T00:31:29.797Z,0.000373,3.3327 +27474,2023-11-16T00:26:42.208Z,0.000365,3.2601 +27498,2023-11-17T00:21:54.619Z,0.000357,3.1875 +27522,2023-11-18T00:17:07.029Z,0.000349,3.1150 +27546,2023-11-19T00:12:19.440Z,0.000341,3.0425 +27570,2023-11-20T00:07:31.851Z,0.000334,2.9791 +27594,2023-11-21T00:02:44.262Z,0.000328,2.9248 +27618,2023-11-21T23:57:56.672Z,0.000323,2.8796 +27642,2023-11-22T23:53:09.083Z,0.000318,2.8344 +27666,2023-11-23T23:48:21.494Z,0.000314,2.7983 +27690,2023-11-24T23:43:33.905Z,0.000310,2.7621 +27714,2023-11-25T23:38:46.315Z,0.000307,2.7350 +27738,2023-11-26T23:33:58.726Z,0.000304,2.7079 +27762,2023-11-27T23:29:11.137Z,0.000302,2.6899 +27786,2023-11-28T23:24:23.548Z,0.000299,2.6628 +27810,2023-11-29T23:19:35.959Z,0.000297,2.6448 +27834,2023-11-30T23:14:48.369Z,0.000296,2.6358 +27858,2023-12-01T23:10:00.780Z,0.000294,2.6177 +27882,2023-12-02T23:05:13.191Z,0.000293,2.6087 +27906,2023-12-03T23:00:25.602Z,0.000291,2.5907 +27930,2023-12-04T22:55:38.012Z,0.000290,2.5816 +27954,2023-12-05T22:50:50.423Z,0.000289,2.5726 +27978,2023-12-06T22:46:02.834Z,0.000288,2.5636 +28002,2023-12-07T22:41:15.245Z,0.000287,2.5546 +28050,2023-12-09T22:31:40.066Z,0.000286,2.5456 +28074,2023-12-10T22:26:52.477Z,0.000285,2.5366 +28122,2023-12-12T22:17:17.299Z,0.000284,2.5276 +28146,2023-12-13T22:12:29.709Z,0.000283,2.5185 +31170,2024-04-17T12:08:33.467Z,0.000282,2.5095 +31266,2024-04-21T11:49:23.110Z,0.000281,2.5005 +31338,2024-04-24T11:35:00.342Z,0.000280,2.4915 +31410,2024-04-27T11:20:37.575Z,0.000279,2.4825 +31458,2024-04-29T11:11:02.396Z,0.000278,2.4735 +31506,2024-05-01T11:01:27.218Z,0.000277,2.4645 +31530,2024-05-02T10:56:39.629Z,0.000276,2.4555 +31554,2024-05-03T10:51:52.039Z,0.000275,2.4465 +31602,2024-05-05T10:42:16.861Z,0.000274,2.4375 +31626,2024-05-06T10:37:29.272Z,0.000272,2.4195 +31650,2024-05-07T10:32:41.682Z,0.000271,2.4105 +31674,2024-05-08T10:27:54.093Z,0.000270,2.4015 +31698,2024-05-09T10:23:06.504Z,0.000268,2.3835 +31722,2024-05-10T10:18:18.915Z,0.000266,2.3655 +31746,2024-05-11T10:13:31.326Z,0.000264,2.3475 +31770,2024-05-12T10:08:43.736Z,0.000262,2.3295 +31794,2024-05-13T10:03:56.147Z,0.000259,2.3025 +31818,2024-05-14T09:59:08.558Z,0.000257,2.2845 +31842,2024-05-15T09:54:20.969Z,0.000254,2.2576 +31866,2024-05-16T09:49:33.379Z,0.000251,2.2306 +31890,2024-05-17T09:44:45.790Z,0.000249,2.2126 +31914,2024-05-18T09:39:58.201Z,0.000246,2.1857 +31938,2024-05-19T09:35:10.612Z,0.000244,2.1677 +31962,2024-05-20T09:30:23.022Z,0.000242,2.1498 +31986,2024-05-21T09:25:35.433Z,0.000240,2.1318 +32010,2024-05-22T09:20:47.844Z,0.000238,2.1139 +32034,2024-05-23T09:16:00.255Z,0.000237,2.1049 +32058,2024-05-24T09:11:12.666Z,0.000236,2.0959 +32106,2024-05-26T09:01:37.487Z,0.000234,2.0780 +32130,2024-05-27T08:56:49.898Z,0.000233,2.0690 +32154,2024-05-28T08:52:02.309Z,0.000232,2.0600 +32202,2024-05-30T08:42:27.130Z,0.000231,2.0511 +32250,2024-06-01T08:32:51.952Z,0.000230,2.0421 +32298,2024-06-03T08:23:16.773Z,0.000229,2.0331 +32394,2024-06-07T08:04:06.416Z,0.000228,2.0242 +32490,2024-06-11T07:44:56.060Z,0.000227,2.0152 +35514,2024-10-14T21:40:59.817Z,0.000226,2.0062 +35562,2024-10-16T21:31:24.639Z,0.000225,1.9973 +35586,2024-10-17T21:26:37.049Z,0.000224,1.9883 +35610,2024-10-18T21:21:49.460Z,0.000223,1.9793 +35634,2024-10-19T21:17:01.871Z,0.000222,1.9704 +35658,2024-10-20T21:12:14.282Z,0.000221,1.9614 +35682,2024-10-21T21:07:26.692Z,0.000220,1.9524 +35706,2024-10-22T21:02:39.103Z,0.000219,1.9435 +35730,2024-10-23T20:57:51.514Z,0.000218,1.9345 +35754,2024-10-24T20:53:03.925Z,0.000216,1.9166 +35778,2024-10-25T20:48:16.336Z,0.000215,1.9077 +35802,2024-10-26T20:43:28.746Z,0.000213,1.8897 +35826,2024-10-27T20:38:41.157Z,0.000212,1.8808 +35850,2024-10-28T20:33:53.568Z,0.000210,1.8629 +35874,2024-10-29T20:29:05.979Z,0.000208,1.8450 +35898,2024-10-30T20:24:18.389Z,0.000205,1.8181 +35922,2024-10-31T20:19:30.800Z,0.000203,1.8002 +35946,2024-11-01T20:14:43.211Z,0.000200,1.7734 +35970,2024-11-02T20:09:55.622Z,0.000196,1.7376 +35994,2024-11-03T20:05:08.033Z,0.000192,1.7019 +36018,2024-11-04T20:00:20.443Z,0.000188,1.6661 +36042,2024-11-05T19:55:32.854Z,0.000183,1.6214 +36066,2024-11-06T19:50:45.265Z,0.000177,1.5679 +36090,2024-11-07T19:45:57.676Z,0.000171,1.5143 +36114,2024-11-08T19:41:10.086Z,0.000164,1.4519 +36138,2024-11-09T19:36:22.497Z,0.000155,1.3717 +36162,2024-11-10T19:31:34.908Z,0.000146,1.2915 +36186,2024-11-11T19:26:47.319Z,0.000136,1.2025 +36210,2024-11-12T19:21:59.729Z,0.000125,1.1047 +36234,2024-11-13T19:17:12.140Z,0.000114,1.0070 +36258,2024-11-14T19:12:24.551Z,0.000102,0.9005 +36282,2024-11-15T19:07:36.962Z,0.000091,0.8030 +36306,2024-11-16T19:02:49.373Z,0.000081,0.7145 +36330,2024-11-17T18:58:01.783Z,0.000072,0.6348 +36354,2024-11-18T18:53:14.194Z,0.000063,0.5553 +36378,2024-11-19T18:48:26.605Z,0.000056,0.4934 +36402,2024-11-20T18:43:39.016Z,0.000049,0.4316 +36426,2024-11-21T18:38:51.426Z,0.000044,0.3875 +36450,2024-11-22T18:34:03.837Z,0.000039,0.3434 +36474,2024-11-23T18:29:16.248Z,0.000034,0.2993 +36498,2024-11-24T18:24:28.659Z,0.000030,0.2640 +36522,2024-11-25T18:19:41.070Z,0.000027,0.2376 +36546,2024-11-26T18:14:53.480Z,0.000024,0.2112 +36570,2024-11-27T18:10:05.891Z,0.000021,0.1847 +36594,2024-11-28T18:05:18.302Z,0.000019,0.1671 +36618,2024-11-29T18:00:30.713Z,0.000017,0.1495 +36642,2024-11-30T17:55:43.123Z,0.000015,0.1319 +36666,2024-12-01T17:50:55.534Z,0.000013,0.1143 +36690,2024-12-02T17:46:07.945Z,0.000011,0.0967 +36714,2024-12-03T17:41:20.356Z,0.000010,0.0879 +36738,2024-12-04T17:36:32.766Z,0.000008,0.0703 +36762,2024-12-05T17:31:45.177Z,0.000007,0.0615 +36786,2024-12-06T17:26:57.588Z,0.000006,0.0527 +36810,2024-12-07T17:22:09.999Z,0.000005,0.0440 +36834,2024-12-08T17:17:22.410Z,0.000004,0.0352 +36858,2024-12-09T17:12:34.820Z,0.000003,0.0264 +36882,2024-12-10T17:07:47.231Z,0.000002,0.0176 +36930,2024-12-12T16:58:12.053Z,0.000001,0.0088 diff --git a/assets/images/0020-bench1-b406915bd71a67020495939d2c89075b.png b/assets/images/0020-bench1-b406915bd71a67020495939d2c89075b.png new file mode 100644 index 0000000000..0728f99cb0 Binary files /dev/null and b/assets/images/0020-bench1-b406915bd71a67020495939d2c89075b.png differ diff --git a/assets/images/0020-bench2-1cc7812d2c015e4a03288cc6f165bb4e.png b/assets/images/0020-bench2-1cc7812d2c015e4a03288cc6f165bb4e.png new file mode 100644 index 0000000000..c69432f247 Binary files /dev/null and b/assets/images/0020-bench2-1cc7812d2c015e4a03288cc6f165bb4e.png differ diff --git a/assets/images/0020-bench3-8741906103d267c9119ac66826d39bd1.png b/assets/images/0020-bench3-8741906103d267c9119ac66826d39bd1.png new file mode 100644 index 0000000000..cb6e48a79c Binary files /dev/null and b/assets/images/0020-bench3-8741906103d267c9119ac66826d39bd1.png differ diff --git a/assets/images/01_home-273aa8dd19d696a15d80a7ddb4775b03.png b/assets/images/01_home-273aa8dd19d696a15d80a7ddb4775b03.png new file mode 100644 index 0000000000..9eea791958 Binary files /dev/null and b/assets/images/01_home-273aa8dd19d696a15d80a7ddb4775b03.png differ diff --git a/assets/images/02_this_is_your_mnemonic-f6b21a57650cd2882d4198b965225990.png b/assets/images/02_this_is_your_mnemonic-f6b21a57650cd2882d4198b965225990.png new file mode 100644 index 0000000000..a22085e5c8 Binary files /dev/null and b/assets/images/02_this_is_your_mnemonic-f6b21a57650cd2882d4198b965225990.png differ diff --git a/assets/images/03_confirm_your_mnemonic-d8c76dc27f0eaabb82a0df2bcaadef60.png b/assets/images/03_confirm_your_mnemonic-d8c76dc27f0eaabb82a0df2bcaadef60.png new file mode 100644 index 0000000000..ba843366b4 Binary files /dev/null and b/assets/images/03_confirm_your_mnemonic-d8c76dc27f0eaabb82a0df2bcaadef60.png differ diff --git a/assets/images/04_how_to_open_your_wallet-207f16708a2033f2934b448cd6c7098f.png b/assets/images/04_how_to_open_your_wallet-207f16708a2033f2934b448cd6c7098f.png new file mode 100644 index 0000000000..a6019979d5 Binary files /dev/null and b/assets/images/04_how_to_open_your_wallet-207f16708a2033f2934b448cd6c7098f.png differ diff --git a/assets/images/05.1_open_with_mnemonics-5da80b206b09bfba004c0627b6a1ddf8.png b/assets/images/05.1_open_with_mnemonics-5da80b206b09bfba004c0627b6a1ddf8.png new file mode 100644 index 0000000000..442f25ac4f Binary files /dev/null and b/assets/images/05.1_open_with_mnemonics-5da80b206b09bfba004c0627b6a1ddf8.png differ diff --git a/assets/images/05.2_open_with_private_key-b8eb93b498f4e11035bc37a3d131b654.png b/assets/images/05.2_open_with_private_key-b8eb93b498f4e11035bc37a3d131b654.png new file mode 100644 index 0000000000..556c3daa3c Binary files /dev/null and b/assets/images/05.2_open_with_private_key-b8eb93b498f4e11035bc37a3d131b654.png differ diff --git a/assets/images/06_toogle_between_light_and_dark_mode-57dcfb63b072831a2665fc7326bba0f9.png b/assets/images/06_toogle_between_light_and_dark_mode-57dcfb63b072831a2665fc7326bba0f9.png new file mode 100644 index 0000000000..2d4a746cae Binary files /dev/null and b/assets/images/06_toogle_between_light_and_dark_mode-57dcfb63b072831a2665fc7326bba0f9.png differ diff --git a/assets/images/07_light_mode-6e042f5b062b159a9e6de55ca3f2fbee.png b/assets/images/07_light_mode-6e042f5b062b159a9e6de55ca3f2fbee.png new file mode 100644 index 0000000000..05285647a3 Binary files /dev/null and b/assets/images/07_light_mode-6e042f5b062b159a9e6de55ca3f2fbee.png differ diff --git a/assets/images/08_select_language-36d406acc14d2ccb72103b323b774826.png b/assets/images/08_select_language-36d406acc14d2ccb72103b323b774826.png new file mode 100644 index 0000000000..6b15485b28 Binary files /dev/null and b/assets/images/08_select_language-36d406acc14d2ccb72103b323b774826.png differ diff --git a/assets/images/accounts1-67bdeddfaab1b76f424c1d413cee99e3.png b/assets/images/accounts1-67bdeddfaab1b76f424c1d413cee99e3.png new file mode 100644 index 0000000000..e663a1b103 Binary files /dev/null and b/assets/images/accounts1-67bdeddfaab1b76f424c1d413cee99e3.png differ diff --git a/assets/images/accounts2-68f87ae6b9aa0a6f39b9c04c47df05ab.png b/assets/images/accounts2-68f87ae6b9aa0a6f39b9c04c47df05ab.png new file mode 100644 index 0000000000..f188c2394b Binary files /dev/null and b/assets/images/accounts2-68f87ae6b9aa0a6f39b9c04c47df05ab.png differ diff --git a/assets/images/active_delegations-35fdecb7b195c877bca7fd010b9e3926.png b/assets/images/active_delegations-35fdecb7b195c877bca7fd010b9e3926.png new file mode 100644 index 0000000000..f5a1514669 Binary files /dev/null and b/assets/images/active_delegations-35fdecb7b195c877bca7fd010b9e3926.png differ diff --git a/assets/images/backers-68a28b448e9f1757941ef06bb6dd90e2.png b/assets/images/backers-68a28b448e9f1757941ef06bb6dd90e2.png new file mode 100644 index 0000000000..d471013a09 Binary files /dev/null and b/assets/images/backers-68a28b448e9f1757941ef06bb6dd90e2.png differ diff --git a/assets/images/band_demooracle_smartcontract-33de5c1550770b2f65357831fc13c6e1.png b/assets/images/band_demooracle_smartcontract-33de5c1550770b2f65357831fc13c6e1.png new file mode 100644 index 0000000000..f423e973bf Binary files /dev/null and b/assets/images/band_demooracle_smartcontract-33de5c1550770b2f65357831fc13c6e1.png differ diff --git a/assets/images/band_deploy_demooracle_smartcontact-bcfd8510f590412a0eb3af8025b8a9dc.png b/assets/images/band_deploy_demooracle_smartcontact-bcfd8510f590412a0eb3af8025b8a9dc.png new file mode 100644 index 0000000000..221d637dbc Binary files /dev/null and b/assets/images/band_deploy_demooracle_smartcontact-bcfd8510f590412a0eb3af8025b8a9dc.png differ diff --git a/assets/images/band_get_rates-1172d264b2dcff4f0841da0e3f8a9d53.png b/assets/images/band_get_rates-1172d264b2dcff4f0841da0e3f8a9d53.png new file mode 100644 index 0000000000..de6a863635 Binary files /dev/null and b/assets/images/band_get_rates-1172d264b2dcff4f0841da0e3f8a9d53.png differ diff --git a/assets/images/block_explorer1-300ad8505c206bca6ecb6416836e6770.png b/assets/images/block_explorer1-300ad8505c206bca6ecb6416836e6770.png new file mode 100644 index 0000000000..87b7e7059c Binary files /dev/null and b/assets/images/block_explorer1-300ad8505c206bca6ecb6416836e6770.png differ diff --git a/assets/images/block_explorer2-c07d43edbfeb9e90e1b38710179e9062.png b/assets/images/block_explorer2-c07d43edbfeb9e90e1b38710179e9062.png new file mode 100644 index 0000000000..064a53c5fb Binary files /dev/null and b/assets/images/block_explorer2-c07d43edbfeb9e90e1b38710179e9062.png differ diff --git a/assets/images/brave-d5324693f54e8be95d23c517033a1f6c.png b/assets/images/brave-d5324693f54e8be95d23c517033a1f6c.png new file mode 100644 index 0000000000..6a2a26a209 Binary files /dev/null and b/assets/images/brave-d5324693f54e8be95d23c517033a1f6c.png differ diff --git a/assets/images/chrome_web_store-2ac7085f1a5c5a70358a46177a37f69a.png b/assets/images/chrome_web_store-2ac7085f1a5c5a70358a46177a37f69a.png new file mode 100644 index 0000000000..8341811662 Binary files /dev/null and b/assets/images/chrome_web_store-2ac7085f1a5c5a70358a46177a37f69a.png differ diff --git a/assets/images/client-km-compute-8776815a499e44e00cfdd8953fdc9fb3.svg b/assets/images/client-km-compute-8776815a499e44e00cfdd8953fdc9fb3.svg new file mode 100644 index 0000000000..45199b42be --- /dev/null +++ b/assets/images/client-km-compute-8776815a499e44e00cfdd8953fdc9fb3.svg @@ -0,0 +1,4 @@ + + + +
2.
Get Ephemeral
ParaTime Public Key
2....
3.
Encrypt & Submit
Transaction
3....
Client
(Node.js, MetaMask,
Oasis CLI)
Client...
Oasis Node
Key Manager
🔒
Oasis Node...
4.
Get Ephemeral
ParaTime Secret and
Contract State Keypair
4....
6.
Encrypted Transaction
Result
6....
Oasis Node
ParaTime Compute
🔒
Oasis Node...
🔒 Trusted Execution Environment
🔒 Trusted Execution Environment
1.
Generate Client
Keypair
1....
5.
Confidentially Execute Contract
and Write to Blockchain
5....
Text is not SVG - cannot display
\ No newline at end of file diff --git a/assets/images/compare_networks-9630fe031fad10dc47c0c56aa1f00d33.png b/assets/images/compare_networks-9630fe031fad10dc47c0c56aa1f00d33.png new file mode 100644 index 0000000000..513af14929 Binary files /dev/null and b/assets/images/compare_networks-9630fe031fad10dc47c0c56aa1f00d33.png differ diff --git a/assets/images/confirm-new-poll-44de684bfe667f9b7c51358f6e374bc9.png b/assets/images/confirm-new-poll-44de684bfe667f9b7c51358f6e374bc9.png new file mode 100644 index 0000000000..9301a99211 Binary files /dev/null and b/assets/images/confirm-new-poll-44de684bfe667f9b7c51358f6e374bc9.png differ diff --git a/assets/images/confirm_transaction_ETH_WETH-9fb853c57c97ac65fe40ca29178ad684.png b/assets/images/confirm_transaction_ETH_WETH-9fb853c57c97ac65fe40ca29178ad684.png new file mode 100644 index 0000000000..9e4bc64baf Binary files /dev/null and b/assets/images/confirm_transaction_ETH_WETH-9fb853c57c97ac65fe40ca29178ad684.png differ diff --git a/assets/images/connect_wallet-6c13918efbcc33da6004a1306f8a1b0e.png b/assets/images/connect_wallet-6c13918efbcc33da6004a1306f8a1b0e.png new file mode 100644 index 0000000000..862b5b2045 Binary files /dev/null and b/assets/images/connect_wallet-6c13918efbcc33da6004a1306f8a1b0e.png differ diff --git a/assets/images/consensus_paratime_communication-9e496f13908c8e30ad6e63e6da9f5fa3.png b/assets/images/consensus_paratime_communication-9e496f13908c8e30ad6e63e6da9f5fa3.png new file mode 100644 index 0000000000..c86218febf Binary files /dev/null and b/assets/images/consensus_paratime_communication-9e496f13908c8e30ad6e63e6da9f5fa3.png differ diff --git a/assets/images/create-poll-07bde4932eab22772d5d7e193cbc0255.png b/assets/images/create-poll-07bde4932eab22772d5d7e193cbc0255.png new file mode 100644 index 0000000000..2245d6f6fa Binary files /dev/null and b/assets/images/create-poll-07bde4932eab22772d5d7e193cbc0255.png differ diff --git a/assets/images/data_tokenization-3931e375a8cea5a5756f82573ea95223.png b/assets/images/data_tokenization-3931e375a8cea5a5756f82573ea95223.png new file mode 100644 index 0000000000..37dc1cc7be Binary files /dev/null and b/assets/images/data_tokenization-3931e375a8cea5a5756f82573ea95223.png differ diff --git a/assets/images/deposit-9a48e6aeeededfa9dd09784795f2f2e8.png b/assets/images/deposit-9a48e6aeeededfa9dd09784795f2f2e8.png new file mode 100644 index 0000000000..47f596e3f8 Binary files /dev/null and b/assets/images/deposit-9a48e6aeeededfa9dd09784795f2f2e8.png differ diff --git a/assets/images/ecosystem-9c15f2d71858df610097d36faa5e0f71.jpg b/assets/images/ecosystem-9c15f2d71858df610097d36faa5e0f71.jpg new file mode 100644 index 0000000000..c0c52a3479 Binary files /dev/null and b/assets/images/ecosystem-9c15f2d71858df610097d36faa5e0f71.jpg differ diff --git a/assets/images/ecosystem-defi-52ce0ac1743d0d251120d3ac98519906.jpg b/assets/images/ecosystem-defi-52ce0ac1743d0d251120d3ac98519906.jpg new file mode 100644 index 0000000000..b250460cd2 Binary files /dev/null and b/assets/images/ecosystem-defi-52ce0ac1743d0d251120d3ac98519906.jpg differ diff --git a/assets/images/features-69565025aa30dbd10c01eed76e58b212.png b/assets/images/features-69565025aa30dbd10c01eed76e58b212.png new file mode 100644 index 0000000000..c19e6dd32e Binary files /dev/null and b/assets/images/features-69565025aa30dbd10c01eed76e58b212.png differ diff --git a/assets/images/gasless-gsn-flow-ce9d704c33063bf100cc9d483f696a95.jpg b/assets/images/gasless-gsn-flow-ce9d704c33063bf100cc9d483f696a95.jpg new file mode 100644 index 0000000000..4a3683560e Binary files /dev/null and b/assets/images/gasless-gsn-flow-ce9d704c33063bf100cc9d483f696a95.jpg differ diff --git a/assets/images/gasless-on-chain-signer-3f3b75e0b9fddb83e45c51d52ee5a8bd.svg b/assets/images/gasless-on-chain-signer-3f3b75e0b9fddb83e45c51d52ee5a8bd.svg new file mode 100644 index 0000000000..6ca4a197c6 --- /dev/null +++ b/assets/images/gasless-on-chain-signer-3f3b75e0b9fddb83e45c51d52ee5a8bd.svg @@ -0,0 +1,4 @@ + + + +
1.
🔒 call
makeProxyTransaction
(nonce, gasPrice, request, rsv)
1....
3.
 🔒eth.sendTransaction(tx)
3....
Gasless Client
(Node.js, Metamask, Oasis CLI)
Gasless Client...
5.
addr.call(tx)
5....
On-Chain Proxy
contract
On-Chain Proxy...
DAOv1
DAOv1
4.
decrypt tx
4....
Trust
Trust
2.
verify tx
2....
Text is not SVG - cannot display
\ No newline at end of file diff --git a/assets/images/hardhat-boilerplate-frontend2-6d2fe4701649136e7c90270f572a86be.png b/assets/images/hardhat-boilerplate-frontend2-6d2fe4701649136e7c90270f572a86be.png new file mode 100644 index 0000000000..49a293bba2 Binary files /dev/null and b/assets/images/hardhat-boilerplate-frontend2-6d2fe4701649136e7c90270f572a86be.png differ diff --git a/assets/images/hardhat-boilerplate-frontend3-727893cadf6a2874b868f655cb84d059.png b/assets/images/hardhat-boilerplate-frontend3-727893cadf6a2874b868f655cb84d059.png new file mode 100644 index 0000000000..16c4f944fb Binary files /dev/null and b/assets/images/hardhat-boilerplate-frontend3-727893cadf6a2874b868f655cb84d059.png differ diff --git a/assets/images/import-c480eafa2580a6ab0da6fae21a218a8b.png b/assets/images/import-c480eafa2580a6ab0da6fae21a218a8b.png new file mode 100644 index 0000000000..29e57cfec3 Binary files /dev/null and b/assets/images/import-c480eafa2580a6ab0da6fae21a218a8b.png differ diff --git a/assets/images/import2-31417b4705500f1bcf47eb54fc24d1f9.png b/assets/images/import2-31417b4705500f1bcf47eb54fc24d1f9.png new file mode 100644 index 0000000000..ad2bec2549 Binary files /dev/null and b/assets/images/import2-31417b4705500f1bcf47eb54fc24d1f9.png differ diff --git a/assets/images/index-45df31c8f3f67661a8d6c4944be35956.png b/assets/images/index-45df31c8f3f67661a8d6c4944be35956.png new file mode 100644 index 0000000000..63ebe4c46c Binary files /dev/null and b/assets/images/index-45df31c8f3f67661a8d6c4944be35956.png differ diff --git a/assets/images/ledger-live-manager-oasis-c2e03e9ceb8fe81107faa3b8a175f837.png b/assets/images/ledger-live-manager-oasis-c2e03e9ceb8fe81107faa3b8a175f837.png new file mode 100644 index 0000000000..6e907d2184 Binary files /dev/null and b/assets/images/ledger-live-manager-oasis-c2e03e9ceb8fe81107faa3b8a175f837.png differ diff --git a/assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg b/assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg new file mode 100644 index 0000000000..d69c8856bd Binary files /dev/null and b/assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg differ diff --git a/assets/images/lending_market-89baec95cc4d9c2a312f884a6c1c9a78.png b/assets/images/lending_market-89baec95cc4d9c2a312f884a6c1c9a78.png new file mode 100644 index 0000000000..e5a21fbf3c Binary files /dev/null and b/assets/images/lending_market-89baec95cc4d9c2a312f884a6c1c9a78.png differ diff --git a/assets/images/live_allow_ledger_manager-30797e705e2068c9c7ee2b6eed02c6a9.png b/assets/images/live_allow_ledger_manager-30797e705e2068c9c7ee2b6eed02c6a9.png new file mode 100644 index 0000000000..163c42123d Binary files /dev/null and b/assets/images/live_allow_ledger_manager-30797e705e2068c9c7ee2b6eed02c6a9.png differ diff --git a/assets/images/live_search_apps-d344482547f64a390b308f2e1272af31.png b/assets/images/live_search_apps-d344482547f64a390b308f2e1272af31.png new file mode 100644 index 0000000000..58b9adb92a Binary files /dev/null and b/assets/images/live_search_apps-d344482547f64a390b308f2e1272af31.png differ diff --git a/assets/images/live_search_results_oasis_install-b346253511375cf2643b524e3c0291ab.png b/assets/images/live_search_results_oasis_install-b346253511375cf2643b524e3c0291ab.png new file mode 100644 index 0000000000..f81efd55aa Binary files /dev/null and b/assets/images/live_search_results_oasis_install-b346253511375cf2643b524e3c0291ab.png differ diff --git a/assets/images/live_unlock_ledger-502e6c5d1ae4698f027cae7e166c59cd.png b/assets/images/live_unlock_ledger-502e6c5d1ae4698f027cae7e166c59cd.png new file mode 100644 index 0000000000..6a9eb65957 Binary files /dev/null and b/assets/images/live_unlock_ledger-502e6c5d1ae4698f027cae7e166c59cd.png differ diff --git a/assets/images/mainscreen-444c4a14f5bcc45a74a9697a0a1e9b80.png b/assets/images/mainscreen-444c4a14f5bcc45a74a9697a0a1e9b80.png new file mode 100644 index 0000000000..209b5dc7e9 Binary files /dev/null and b/assets/images/mainscreen-444c4a14f5bcc45a74a9697a0a1e9b80.png differ diff --git a/assets/images/metrics-background-17ff1b79c8113d871e481b777779d2ae.png b/assets/images/metrics-background-17ff1b79c8113d871e481b777779d2ae.png new file mode 100644 index 0000000000..fba9a4d7ae Binary files /dev/null and b/assets/images/metrics-background-17ff1b79c8113d871e481b777779d2ae.png differ diff --git a/assets/images/oasis-core-consensus-tendermint-d5ec48977d94f45cfa764d6585f6b21b.svg b/assets/images/oasis-core-consensus-tendermint-d5ec48977d94f45cfa764d6585f6b21b.svg new file mode 100644 index 0000000000..9f56a3ee16 --- /dev/null +++ b/assets/images/oasis-core-consensus-tendermint-d5ec48977d94f45cfa764d6585f6b21b.svg @@ -0,0 +1,3 @@ + + +
Tendermint Core
Tendermint Core
ABCI
Application Multiplexer
ABCI...
Queries
Queries
Transaction
Submission
Transaction...
Epoch Time
Epoch Time
Random Beacon
Random Beacon
Staking
Staking
Registry
Registry
Cmte. Scheduler
Cmte. Scheduler
Root Hash
Root Hash
Key Manager
Key Manager
Oasis Core Consensus API
Oasis Core Consensus API
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/images/oasis-core-high-level-4dd19f00411531fadd7a32ea1d596e6f.svg b/assets/images/oasis-core-high-level-4dd19f00411531fadd7a32ea1d596e6f.svg new file mode 100644 index 0000000000..e7434c957e --- /dev/null +++ b/assets/images/oasis-core-high-level-4dd19f00411531fadd7a32ea1d596e6f.svg @@ -0,0 +1,3 @@ + + +
Epoch
Time
Epoch...
Random
Beacon
Random...
Staking
Staking
Registry
Registry
Cmte.
Scheduler
Cmte....
Root
Hash
Root...
Key
Manager
Key...
Consensus
Layer
Consensus...
Runtime
Layer
Runtime...
Runtime C
Runtime C
Executor
Executor
Storage
Storage
Executor
Executor
Storage
Storage
Runtime A
Runtime A
Runtime B
Runtime B
Executor
Executor
Storage
Storage
Runtime D
Runtime D
Executor
Executor
Storage
Storage
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/images/oasis-core-runtime-details-4fefa00801807028812dc6d3900d2a38.svg b/assets/images/oasis-core-runtime-details-4fefa00801807028812dc6d3900d2a38.svg new file mode 100644 index 0000000000..c67b00f642 --- /dev/null +++ b/assets/images/oasis-core-runtime-details-4fefa00801807028812dc6d3900d2a38.svg @@ -0,0 +1,3 @@ + + +
Epoch
Time
Epoch...
Random
Beacon
Random...
Staking
Staking
Registry
Registry
Elects Committees
Elects Committees
Cmte.
Scheduler
Cmte....
Canonical
State
Canonical...
Canonical State
Canonical State
RootHash
RootHash
Key
Manager
Key...
Runtime Layer
Runtime...
Consensus Layer
Consensu...
Executor
Executor
Executor
Executor
Storage
Storage
Storage
Storage
Commit
Summaries
Commit...
Transactions
Transactions
Runtime
Client
Runtime...
Runtime A
Runtime A
Executor
Executor
Key
Manager
Key...
Distributes
Policy
Distributes...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/assets/images/oasisscan1-024c1033c1ceeff4ca4f4294f544ce9c.png b/assets/images/oasisscan1-024c1033c1ceeff4ca4f4294f544ce9c.png new file mode 100644 index 0000000000..fd8ce29ce5 Binary files /dev/null and b/assets/images/oasisscan1-024c1033c1ceeff4ca4f4294f544ce9c.png differ diff --git a/assets/images/oasisscan1-32c1face6545fbbf9d21fc4f1e4ddc2f.png b/assets/images/oasisscan1-32c1face6545fbbf9d21fc4f1e4ddc2f.png new file mode 100644 index 0000000000..8f83b7f7e1 Binary files /dev/null and b/assets/images/oasisscan1-32c1face6545fbbf9d21fc4f1e4ddc2f.png differ diff --git a/assets/images/oasisscan2-00e68913dfa621eb7c5f170e3b2f6378.png b/assets/images/oasisscan2-00e68913dfa621eb7c5f170e3b2f6378.png new file mode 100644 index 0000000000..fda89ac7c9 Binary files /dev/null and b/assets/images/oasisscan2-00e68913dfa621eb7c5f170e3b2f6378.png differ diff --git a/assets/images/oasisscan2-85c233753dbb01035bc36849c7b5c6ca.png b/assets/images/oasisscan2-85c233753dbb01035bc36849c7b5c6ca.png new file mode 100644 index 0000000000..6c66702b8f Binary files /dev/null and b/assets/images/oasisscan2-85c233753dbb01035bc36849c7b5c6ca.png differ diff --git a/assets/images/oasisscan_account_details-3fd09f8a59be210c67bbbaadf716f1c5.png b/assets/images/oasisscan_account_details-3fd09f8a59be210c67bbbaadf716f1c5.png new file mode 100644 index 0000000000..6886853eee Binary files /dev/null and b/assets/images/oasisscan_account_details-3fd09f8a59be210c67bbbaadf716f1c5.png differ diff --git a/assets/images/opl-contract-flow.mmd-57ad04dbec00703789880a36eea87e94.svg b/assets/images/opl-contract-flow.mmd-57ad04dbec00703789880a36eea87e94.svg new file mode 100644 index 0000000000..f18c9dbac2 --- /dev/null +++ b/assets/images/opl-contract-flow.mmd-57ad04dbec00703789880a36eea87e94.svg @@ -0,0 +1 @@ +UserHome ContractSGNExecutorSapphire ContractTransactionSGN Watches EventsWaits for SGN ApprovalSubmit Proof TxUserHome ContractSGNExecutorSapphire Contract \ No newline at end of file diff --git a/assets/images/paratimes-1e42fa05f5490ec7eeebc5608a8c0000.png b/assets/images/paratimes-1e42fa05f5490ec7eeebc5608a8c0000.png new file mode 100644 index 0000000000..ba5a57fc86 Binary files /dev/null and b/assets/images/paratimes-1e42fa05f5490ec7eeebc5608a8c0000.png differ diff --git a/assets/images/paratimes2-0695739c8ea5c7ae9bb51d144ed3a083.png b/assets/images/paratimes2-0695739c8ea5c7ae9bb51d144ed3a083.png new file mode 100644 index 0000000000..1a464fb872 Binary files /dev/null and b/assets/images/paratimes2-0695739c8ea5c7ae9bb51d144ed3a083.png differ diff --git a/assets/images/partners-98bce621edbe8c16b650cf27984f15e1.png b/assets/images/partners-98bce621edbe8c16b650cf27984f15e1.png new file mode 100644 index 0000000000..1d312a1f72 Binary files /dev/null and b/assets/images/partners-98bce621edbe8c16b650cf27984f15e1.png differ diff --git a/assets/images/past-dao-proposals-fd0f3f96be29751307e0850e034593c3.png b/assets/images/past-dao-proposals-fd0f3f96be29751307e0850e034593c3.png new file mode 100644 index 0000000000..4387ca7142 Binary files /dev/null and b/assets/images/past-dao-proposals-fd0f3f96be29751307e0850e034593c3.png differ diff --git a/assets/images/press_logos-c37908c3371f7230bc2f71ef5729788f.png b/assets/images/press_logos-c37908c3371f7230bc2f71ef5729788f.png new file mode 100644 index 0000000000..2656bedde2 Binary files /dev/null and b/assets/images/press_logos-c37908c3371f7230bc2f71ef5729788f.png differ diff --git a/assets/images/privacy-layer-diagram-5b87a6dff417d5a4074bd6fdee9dce7e.png b/assets/images/privacy-layer-diagram-5b87a6dff417d5a4074bd6fdee9dce7e.png new file mode 100644 index 0000000000..391e3f85bf Binary files /dev/null and b/assets/images/privacy-layer-diagram-5b87a6dff417d5a4074bd6fdee9dce7e.png differ diff --git a/assets/images/redeem_tokens-f1082c546b479f813a98c3969e4257ba.png b/assets/images/redeem_tokens-f1082c546b479f813a98c3969e4257ba.png new file mode 100644 index 0000000000..07f0ddc510 Binary files /dev/null and b/assets/images/redeem_tokens-f1082c546b479f813a98c3969e4257ba.png differ diff --git a/assets/images/redeem_tokens2-738d656761667f29cfbd85388866ea49.png b/assets/images/redeem_tokens2-738d656761667f29cfbd85388866ea49.png new file mode 100644 index 0000000000..dd836a176d Binary files /dev/null and b/assets/images/redeem_tokens2-738d656761667f29cfbd85388866ea49.png differ diff --git a/assets/images/remix1-400bc72123a178beea4c86d2ba9857cd.png b/assets/images/remix1-400bc72123a178beea4c86d2ba9857cd.png new file mode 100644 index 0000000000..a4ce650491 Binary files /dev/null and b/assets/images/remix1-400bc72123a178beea4c86d2ba9857cd.png differ diff --git a/assets/images/remix2-66fd8dbfe9f2a299501f5f9c75bdd08d.png b/assets/images/remix2-66fd8dbfe9f2a299501f5f9c75bdd08d.png new file mode 100644 index 0000000000..af79cde92f Binary files /dev/null and b/assets/images/remix2-66fd8dbfe9f2a299501f5f9c75bdd08d.png differ diff --git a/assets/images/remix3-e2db0ab19df6a1aff70c68018b93e897.png b/assets/images/remix3-e2db0ab19df6a1aff70c68018b93e897.png new file mode 100644 index 0000000000..ec8d79efc5 Binary files /dev/null and b/assets/images/remix3-e2db0ab19df6a1aff70c68018b93e897.png differ diff --git a/assets/images/remix4-41183efd0966503c866863efba485d1c.png b/assets/images/remix4-41183efd0966503c866863efba485d1c.png new file mode 100644 index 0000000000..359b162105 Binary files /dev/null and b/assets/images/remix4-41183efd0966503c866863efba485d1c.png differ diff --git a/assets/images/secure_enclave-685f409cf66aabca221edfab5292e1dc.png b/assets/images/secure_enclave-685f409cf66aabca221edfab5292e1dc.png new file mode 100644 index 0000000000..654fdc43ea Binary files /dev/null and b/assets/images/secure_enclave-685f409cf66aabca221edfab5292e1dc.png differ diff --git a/assets/images/select_source_dest_amount-6be16ab5449bce3d7d1fe651cef4876f.png b/assets/images/select_source_dest_amount-6be16ab5449bce3d7d1fe651cef4876f.png new file mode 100644 index 0000000000..5f2f5acf1a Binary files /dev/null and b/assets/images/select_source_dest_amount-6be16ab5449bce3d7d1fe651cef4876f.png differ diff --git a/assets/images/send_tokens-0e219f5c38fda30ea6ec094e6dabec62.png b/assets/images/send_tokens-0e219f5c38fda30ea6ec094e6dabec62.png new file mode 100644 index 0000000000..6c151b6ab6 Binary files /dev/null and b/assets/images/send_tokens-0e219f5c38fda30ea6ec094e6dabec62.png differ diff --git a/assets/images/send_tokens_to_wormhole-a7154abd51883a7b0b9b10659830e7a1.png b/assets/images/send_tokens_to_wormhole-a7154abd51883a7b0b9b10659830e7a1.png new file mode 100644 index 0000000000..8975112018 Binary files /dev/null and b/assets/images/send_tokens_to_wormhole-a7154abd51883a7b0b9b10659830e7a1.png differ diff --git a/assets/images/settings-ffbfad31202135351449d6d411667969.png b/assets/images/settings-ffbfad31202135351449d6d411667969.png new file mode 100644 index 0000000000..6bc4872298 Binary files /dev/null and b/assets/images/settings-ffbfad31202135351449d6d411667969.png differ diff --git a/assets/images/show_private_key-bf6f89e80fb50ffa6728980e19d7d96b.png b/assets/images/show_private_key-bf6f89e80fb50ffa6728980e19d7d96b.png new file mode 100644 index 0000000000..20b13d5d6f Binary files /dev/null and b/assets/images/show_private_key-bf6f89e80fb50ffa6728980e19d7d96b.png differ diff --git a/assets/images/sourcify1-898a49b3519501962fe80f3ba09314b1.png b/assets/images/sourcify1-898a49b3519501962fe80f3ba09314b1.png new file mode 100644 index 0000000000..b6dba793af Binary files /dev/null and b/assets/images/sourcify1-898a49b3519501962fe80f3ba09314b1.png differ diff --git a/assets/images/sourcify2-d95710724b0373068c2ac0f857e07928.png b/assets/images/sourcify2-d95710724b0373068c2ac0f857e07928.png new file mode 100644 index 0000000000..42b201dfe2 Binary files /dev/null and b/assets/images/sourcify2-d95710724b0373068c2ac0f857e07928.png differ diff --git a/assets/images/sourcify3-8be00790df0e04f4720273e6cde8a867.png b/assets/images/sourcify3-8be00790df0e04f4720273e6cde8a867.png new file mode 100644 index 0000000000..ac32713f68 Binary files /dev/null and b/assets/images/sourcify3-8be00790df0e04f4720273e6cde8a867.png differ diff --git a/assets/images/switch_to_emerald-64787a9ffef61c7bc90fe1437e97d21d.png b/assets/images/switch_to_emerald-64787a9ffef61c7bc90fe1437e97d21d.png new file mode 100644 index 0000000000..3463c67714 Binary files /dev/null and b/assets/images/switch_to_emerald-64787a9ffef61c7bc90fe1437e97d21d.png differ diff --git a/assets/images/team_logos-343a69f4e7c6b3d857f51f910752efb6.png b/assets/images/team_logos-343a69f4e7c6b3d857f51f910752efb6.png new file mode 100644 index 0000000000..284953bc6b Binary files /dev/null and b/assets/images/team_logos-343a69f4e7c6b3d857f51f910752efb6.png differ diff --git a/assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg b/assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg new file mode 100644 index 0000000000..8c7d7d2f36 --- /dev/null +++ b/assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg @@ -0,0 +1,1474 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/timeline-fcb8cf7365a3b7742c563223e08cd070.png b/assets/images/timeline-fcb8cf7365a3b7742c563223e08cd070.png new file mode 100644 index 0000000000..5481170dcd Binary files /dev/null and b/assets/images/timeline-fcb8cf7365a3b7742c563223e08cd070.png differ diff --git a/assets/images/uni_map-342c7d3df7a918f68531615dfb33b3ee.png b/assets/images/uni_map-342c7d3df7a918f68531615dfb33b3ee.png new file mode 100644 index 0000000000..4791376ce5 Binary files /dev/null and b/assets/images/uni_map-342c7d3df7a918f68531615dfb33b3ee.png differ diff --git a/assets/images/vote-on-ballot-1a35d67b60f5531fd4b91a1633030ee2.png b/assets/images/vote-on-ballot-1a35d67b60f5531fd4b91a1633030ee2.png new file mode 100644 index 0000000000..7bf2d6a362 Binary files /dev/null and b/assets/images/vote-on-ballot-1a35d67b60f5531fd4b91a1633030ee2.png differ diff --git a/assets/images/wallet_ext_accounts_ledger-00e350e8cc5168c58d3dbd56d72f0357.png b/assets/images/wallet_ext_accounts_ledger-00e350e8cc5168c58d3dbd56d72f0357.png new file mode 100644 index 0000000000..59a1deba85 Binary files /dev/null and b/assets/images/wallet_ext_accounts_ledger-00e350e8cc5168c58d3dbd56d72f0357.png differ diff --git a/assets/images/wallet_ext_import1-695dd9713fb10621f4447840cdbbe9fd.png b/assets/images/wallet_ext_import1-695dd9713fb10621f4447840cdbbe9fd.png new file mode 100644 index 0000000000..bced5ca076 Binary files /dev/null and b/assets/images/wallet_ext_import1-695dd9713fb10621f4447840cdbbe9fd.png differ diff --git a/assets/images/wallet_ext_import2-ace8c17920abf877d4c68f40c1854eb3.png b/assets/images/wallet_ext_import2-ace8c17920abf877d4c68f40c1854eb3.png new file mode 100644 index 0000000000..5cdb569153 Binary files /dev/null and b/assets/images/wallet_ext_import2-ace8c17920abf877d4c68f40c1854eb3.png differ diff --git a/assets/images/wallet_ext_import3-bd9f503231d12dec0764340d7695cb5a.png b/assets/images/wallet_ext_import3-bd9f503231d12dec0764340d7695cb5a.png new file mode 100644 index 0000000000..53d105bef3 Binary files /dev/null and b/assets/images/wallet_ext_import3-bd9f503231d12dec0764340d7695cb5a.png differ diff --git a/assets/images/wallet_web_account_address-0dd7d76aebb5f4ed5c078086328ccd9e.png b/assets/images/wallet_web_account_address-0dd7d76aebb5f4ed5c078086328ccd9e.png new file mode 100644 index 0000000000..400029a873 Binary files /dev/null and b/assets/images/wallet_web_account_address-0dd7d76aebb5f4ed5c078086328ccd9e.png differ diff --git a/assets/images/wallet_web_open_ledger-e51cb72a003a6182977c88ab17640e10.png b/assets/images/wallet_web_open_ledger-e51cb72a003a6182977c88ab17640e10.png new file mode 100644 index 0000000000..872fee18a9 Binary files /dev/null and b/assets/images/wallet_web_open_ledger-e51cb72a003a6182977c88ab17640e10.png differ diff --git a/assets/images/wallet_web_open_ledger_account-ed82b4ff6218c9048f1de817c86c59f5.png b/assets/images/wallet_web_open_ledger_account-ed82b4ff6218c9048f1de817c86c59f5.png new file mode 100644 index 0000000000..dea778bb7f Binary files /dev/null and b/assets/images/wallet_web_open_ledger_account-ed82b4ff6218c9048f1de817c86c59f5.png differ diff --git a/assets/images/wallet_web_received_rose_on_ledger_account-c4c156f34823a0295cb15ed58ba96c80.png b/assets/images/wallet_web_received_rose_on_ledger_account-c4c156f34823a0295cb15ed58ba96c80.png new file mode 100644 index 0000000000..f6ebfb1006 Binary files /dev/null and b/assets/images/wallet_web_received_rose_on_ledger_account-c4c156f34823a0295cb15ed58ba96c80.png differ diff --git a/assets/images/wallet_web_select_accounts_to_open-969db3be1effeaa820032d37798cb59a.png b/assets/images/wallet_web_select_accounts_to_open-969db3be1effeaa820032d37798cb59a.png new file mode 100644 index 0000000000..4e830c061c Binary files /dev/null and b/assets/images/wallet_web_select_accounts_to_open-969db3be1effeaa820032d37798cb59a.png differ diff --git a/assets/images/wallet_web_select_ledger_device_connect-80a3396eca59a50b4df51f7b002604dd.png b/assets/images/wallet_web_select_ledger_device_connect-80a3396eca59a50b4df51f7b002604dd.png new file mode 100644 index 0000000000..83f125397e Binary files /dev/null and b/assets/images/wallet_web_select_ledger_device_connect-80a3396eca59a50b4df51f7b002604dd.png differ diff --git a/assets/images/wallet_web_send_confirm_tx-22c8e7574fb5cbc9edbfdfffae1c57de.png b/assets/images/wallet_web_send_confirm_tx-22c8e7574fb5cbc9edbfdfffae1c57de.png new file mode 100644 index 0000000000..437cb0e48d Binary files /dev/null and b/assets/images/wallet_web_send_confirm_tx-22c8e7574fb5cbc9edbfdfffae1c57de.png differ diff --git a/assets/images/wallet_web_send_confirm_tx_ledger-107bae9057a413cc91850ab7cceb910e.jpg b/assets/images/wallet_web_send_confirm_tx_ledger-107bae9057a413cc91850ab7cceb910e.jpg new file mode 100644 index 0000000000..2aa8d707dd Binary files /dev/null and b/assets/images/wallet_web_send_confirm_tx_ledger-107bae9057a413cc91850ab7cceb910e.jpg differ diff --git a/assets/images/wallet_web_send_rose-be33ca81a26cbf7d896fa5fd60a883f8.png b/assets/images/wallet_web_send_rose-be33ca81a26cbf7d896fa5fd60a883f8.png new file mode 100644 index 0000000000..3ea42dc668 Binary files /dev/null and b/assets/images/wallet_web_send_rose-be33ca81a26cbf7d896fa5fd60a883f8.png differ diff --git a/assets/images/wallet_web_send_verify_balance-49fdd9aa7169c2a34eb84bfdeee1e337.png b/assets/images/wallet_web_send_verify_balance-49fdd9aa7169c2a34eb84bfdeee1e337.png new file mode 100644 index 0000000000..d68bbd94be Binary files /dev/null and b/assets/images/wallet_web_send_verify_balance-49fdd9aa7169c2a34eb84bfdeee1e337.png differ diff --git a/assets/images/yuzuswap-ea0c9c9a22e563c5b43b9ea538b5faac.png b/assets/images/yuzuswap-ea0c9c9a22e563c5b43b9ea538b5faac.png new file mode 100644 index 0000000000..ed29e7c053 Binary files /dev/null and b/assets/images/yuzuswap-ea0c9c9a22e563c5b43b9ea538b5faac.png differ diff --git a/assets/js/00eda7cc.68affd87.js b/assets/js/00eda7cc.68affd87.js new file mode 100644 index 0000000000..80a601ef1d --- /dev/null +++ b/assets/js/00eda7cc.68affd87.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[194],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>g});var i=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=i.createContext({}),d=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},u=function(e){var n=d(e.components);return i.createElement(l.Provider,{value:n},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},c=i.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),p=d(t),c=r,g=p["".concat(l,".").concat(c)]||p[c]||m[c]||o;return t?i.createElement(g,a(a({ref:n},u),{},{components:t})):i.createElement(g,a({ref:n},u))}));function g(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,a=new Array(o);a[0]=c;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[p]="string"==typeof e?e:r,a[1]=s;for(var d=2;d{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>d});var i=t(7462),r=(t(7294),t(3905));const o={},a="Deploying a Runtime",s={unversionedId:"core/development-setup/deploying-a-runtime",id:"core/development-setup/deploying-a-runtime",title:"Deploying a Runtime",description:"Before proceeding, make sure to look at the [prerequisites] required for running",source:"@site/docs/core/development-setup/deploying-a-runtime.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/deploying-a-runtime",permalink:"/core/development-setup/deploying-a-runtime",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/deploying-a-runtime.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Single Validator Node Network",permalink:"/core/development-setup/single-validator-node-network"},next:{title:"High-Level Components",permalink:"/core/high-level-components"}},l={},d=[{value:"Provision a Single Validator Node Network",id:"provision-a-single-validator-node-network",level:2},{value:"Initializing a Runtime",id:"initializing-a-runtime",level:2},{value:"Submitting the Runtime Register Transaction",id:"submitting-the-runtime-register-transaction",level:2},{value:"Confirm Runtime is Registered",id:"confirm-runtime-is-registered",level:2},{value:"Running a Runtime Node",id:"running-a-runtime-node",level:2},{value:"Updating Entity Nodes",id:"updating-entity-nodes",level:2}],u={toc:d},p="wrapper";function m(e){let{components:n,...t}=e;return(0,r.kt)(p,(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"deploying-a-runtime"},"Deploying a Runtime"),(0,r.kt)("p",null,"Before proceeding, make sure to look at the ",(0,r.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites"},"prerequisites")," required for running\nan Oasis Core environment followed by ",(0,r.kt)("a",{parentName:"p",href:"/core/development-setup/building"},"build instructions")," for the respective\nenvironment (non-SGX or SGX), using the ",(0,r.kt)("a",{parentName:"p",href:"/core/development-setup/oasis-net-runner"},(0,r.kt)("inlineCode",{parentName:"a"},"oasis-net-runner"))," and see ",(0,r.kt)("a",{parentName:"p",href:"/core/runtime/"},"runtime\ndocumentation")," for a general documentation on runtimes."),(0,r.kt)("p",null,"These instructions will show how to register and deploy a runtime node on a\nlocal development network."),(0,r.kt)("h2",{id:"provision-a-single-validator-node-network"},"Provision a Single Validator Node Network"),(0,r.kt)("p",null,"Use the ",(0,r.kt)("a",{parentName:"p",href:"/core/development-setup/oasis-net-runner"},(0,r.kt)("inlineCode",{parentName:"a"},"oasis-net-runner"))," to provision a validator node network without any\nregistered runtimes."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"mkdir /tmp/runtime-example\n\noasis-net-runner \\\n --basedir.no_temp_dir \\\n --basedir /tmp/runtime-example \\\n --fixture.default.node.binary go/oasis-node/oasis-node \\\n --fixture.default.setup_runtimes=false \\\n --fixture.default.deterministic_entities \\\n --fixture.default.fund_entities \\\n --fixture.default.num_entities 2\n")),(0,r.kt)("p",null,"The following steps should be run in a separate terminal window. To simplify the\ninstructions set up an ",(0,r.kt)("inlineCode",{parentName:"p"},"ADDR")," environment variable pointing to the UNIX socket\nexposed by the started node:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"export ADDR=unix:/tmp/runtime-example/net-runner/network/validator-0/internal.sock\n")),(0,r.kt)("p",null,"Confirm the network is running by listing all registered entities:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis-node registry entity list -a $ADDR -v\n")),(0,r.kt)("p",null,"Should give output similar to:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'{"v":2,"id":"JTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrk=","nodes":["LQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH0="]}\n{"v":2,"id":"+MJpnSTzc11dNI5emMa+asCJH5cxBiBCcpbYE4XBdso="}\n{"v":2,"id":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU="}\n')),(0,r.kt)("p",null,"In following steps we will register and run the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue"},"simple-keyvalue")," runtime on the\nnetwork."),(0,r.kt)("h2",{id:"initializing-a-runtime"},"Initializing a Runtime"),(0,r.kt)("p",null,"To generate and sign a runtime registration transaction that will initialize and\nregister the runtime we will use the ",(0,r.kt)("inlineCode",{parentName:"p"},"registry runtime gen_register")," command.\nWhen initializing a runtime we need to provide the runtime descriptor."),(0,r.kt)("p",null,"For additional information about runtimes and parameters see the ",(0,r.kt)("a",{parentName:"p",href:"/core/runtime/"},"runtime\ndocumentation")," and ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime"},"code reference"),"."),(0,r.kt)("p",null,"Before generating the registration transaction, gather the following data and\nset up environment variables to simplify instructions."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ENTITY_DIR")," - Path to the entity directory created when starting the\ndevelopment network. This entity will be the runtime owner. The genesis used\nin the provisioning initial network step funds the all entities in entities.\nIn the following instructions we will be using the ",(0,r.kt)("inlineCode",{parentName:"li"},"entity-2")," entity (located\nin ",(0,r.kt)("inlineCode",{parentName:"li"},"/tmp/runtime-example/net-runner/network/entity-2/")," directory)."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ENTITY_ID")," - ID of the entity that will be the owner of the runtime. You can\nget the entity ID from ",(0,r.kt)("inlineCode",{parentName:"li"},"$ENTITY_DIR/entity.json")," file."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"GENESIS_JSON")," - Path to the genesis.json file used in the development\nnetwork. (defaults to:\n",(0,r.kt)("inlineCode",{parentName:"li"},"/tmp/runtime-example/net-runner/network/genesis.json"),")."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RUNTIME_ID")," - See ",(0,r.kt)("a",{parentName:"li",href:"/core/runtime/identifiers"},"runtime identifiers")," on how to choose a runtime\nidentifier. In this example we use\n",(0,r.kt)("inlineCode",{parentName:"li"},"8000000000000000000000000000000000000000000000000000000001234567")," which is a\ntest identifier that will not work outside local tests."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RUNTIME_GENESIS_JSON")," - Path to the runtime genesis state file. The runtime\nused in this example does not use a genesis file."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"NONCE")," - Entity account nonce. If you followed the guide, nonce ",(0,r.kt)("inlineCode",{parentName:"li"},"0")," would be\nthe initial nonce to use for the entity. Note: make sure to keep updating the\nnonce when generating new transactions. To query for current account nonce\nvalue use ",(0,r.kt)("a",{parentName:"li",href:"/core/oasis-node/cli#info"},"stake account info")," CLI.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"export ENTITY_DIR=/tmp/runtime-example/net-runner/network/entity-2/\nexport ENTITY_ID=+MJpnSTzc11dNI5emMa+asCJH5cxBiBCcpbYE4XBdso=\nexport GENESIS_JSON=/tmp/runtime-example/net-runner/network/genesis.json\nexport RUNTIME_ID=8000000000000000000000000000000000000000000000000000000001234567\nexport RUNTIME_DESCRIPTOR=/tmp/runtime-example/runtime_descriptor.json\nexport NONCE=0\n")),(0,r.kt)("p",null,"Prepare a runtime descriptor:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'cat << EOF > "${RUNTIME_DESCRIPTOR}"\n{\n "v": 2,\n "id": "${RUNTIME_ID}",\n "entity_id": "${ENTITY_ID}",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "state": null,\n "storage_receipts": null,\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 0,\n "versions": {\n "version": {}\n },\n "executor": {\n "group_size": 1,\n "group_backup_size": 0,\n "allowed_stragglers": 0,\n "round_timeout": 5,\n "max_messages": 32\n },\n "txn_scheduler": {\n "algorithm": "simple",\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 16777216,\n "propose_batch_timeout": 5\n },\n "storage": {\n "group_size": 1,\n "min_write_replication": 1,\n "max_apply_write_log_entries": 100000,\n "max_apply_ops": 2,\n "checkpoint_interval": 10000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "entity_whitelist": {\n "entities": {\n "${ENTITY_ID}": {}\n }\n }\n },\n "staking": {},\n "governance_model": "entity"\n}\nEOF\n')),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis-node registry runtime gen_register \\\n --transaction.fee.gas 1000 \\\n --transaction.fee.amount 0 \\\n --transaction.file /tmp/runtime-example/register_runtime.tx \\\n --transaction.nonce $NONCE \\\n --genesis.file $GENESIS_JSON \\\n --signer.backend file \\\n --signer.dir $ENTITY_DIR \\\n --runtime.descriptor /tmp/runtime-example/runtime-descriptor.json\n --debug.dont_blame_oasis \\\n --debug.allow_test_keys\n")),(0,r.kt)("p",null,"After confirmation, this command outputs a signed transaction in the\n",(0,r.kt)("inlineCode",{parentName:"p"},"/tmp/runtime-example/register_runtime.tx")," file. In the next step we will submit\nthe transaction to complete the runtime registration."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"When registering a runtime on a ",(0,r.kt)("em",{parentName:"p"},"non-development")," network you will likely want\nto modify default parameters. Additionally, since we are running this on a debug\nnetwork, we had to enable the ",(0,r.kt)("inlineCode",{parentName:"p"},"debug.dont_blame_oasis")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"debug.allow_test_keys")," flags.")),(0,r.kt)("h2",{id:"submitting-the-runtime-register-transaction"},"Submitting the Runtime Register Transaction"),(0,r.kt)("p",null,"To register the runtime, submit the generated transaction."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis-node consensus submit_tx \\\n --transaction.file /tmp/runtime-example/register_runtime.tx \\\n --address $ADDR\n")),(0,r.kt)("h2",{id:"confirm-runtime-is-registered"},"Confirm Runtime is Registered"),(0,r.kt)("p",null,"To confirm the runtime is registered use the ",(0,r.kt)("inlineCode",{parentName:"p"},"registry runtime list")," command."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis-node registry runtime list \\\n --verbose \\\n --include_suspended \\\n --address $ADDR\n")),(0,r.kt)("p",null,"Should give output similar to"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'{\n "v": 2,\n "id": "8000000000000000000000000000000000000000000000000000000001234567",\n "entity_id": "+MJpnSTzc11dNI5emMa+asCJH5cxBiBCcpbYE4XBdso=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "state": null,\n "storage_receipts": null,\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 0,\n "versions": {\n "version": {}\n },\n "executor": {\n "group_size": 1,\n "group_backup_size": 0,\n "allowed_stragglers": 0,\n "round_timeout": 5,\n "max_messages": 32\n },\n "txn_scheduler": {\n "algorithm": "simple",\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 16777216,\n "propose_batch_timeout": 5\n },\n "storage": {\n "group_size": 1,\n "min_write_replication": 1,\n "max_apply_write_log_entries": 100000,\n "max_apply_ops": 2,\n "checkpoint_interval": 10000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "entity_whitelist": {\n "entities": {\n "+MJpnSTzc11dNI5emMa+asCJH5cxBiBCcpbYE4XBdso=": {}\n }\n }\n },\n "staking": {},\n "governance_model": "entity"\n}\n')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Since we did not setup any runtime nodes, the runtime\nwill get ",(0,r.kt)("a",{parentName:"p",href:"/core/runtime/#suspending-runtimes"},"suspended")," until nodes for the runtime register.")),(0,r.kt)("p",null,"In the next step we will setup and run a runtime node."),(0,r.kt)("h2",{id:"running-a-runtime-node"},"Running a Runtime Node"),(0,r.kt)("p",null,"We will now run a node that will act as a compute, storage and client node for\nthe runtime."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"In a real word scenario there would be multiple nodes\nrunning the runtime, each likely serving as a single type only.")),(0,r.kt)("p",null,"Before running the node, gather the following data parameters and set up\nenvironment variables to simplify instructions."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RUNTIME_BINARY")," - Path to the runtime binary that will be run on the node. We\nwill use the ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue"},"simple-keyvalue")," runtime. If you followed the ",(0,r.kt)("a",{parentName:"li",href:"/core/development-setup/building"},"build\ninstructions")," the built binary is available at\n",(0,r.kt)("inlineCode",{parentName:"li"},"./target/default/debug/simple-keyvalue"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"SEED_NODE_ADDRESS")," - Address of the seed node in the development network.\nSeed node address can be seen in the ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-net-runner")," logs, when the network\nis initially provisioned.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"export RUNTIME_BINARY=/workdir/target/default/debug/simple-keyvalue\nexport SEED_NODE_ADDRESS=@127.0.0.1:20000\n\n# Runtime node data dir.\nmkdir -m 0700 /tmp/runtime-example/runtime-node\n\n# Start runtime node.\noasis-node \\\n --datadir /tmp/runtime-example/runtime-node \\\n --log.level debug \\\n --log.format json \\\n --log.file /tmp/runtime-example/runtime-node/node.log \\\n --grpc.log.debug \\\n --worker.registration.entity $ENTITY_DIR/entity.json \\\n --genesis.file $GENESIS_JSON \\\n --worker.storage.enabled \\\n --worker.compute.enabled \\\n --runtime.provisioner unconfined \\\n --runtime.supported $RUNTIME_ID \\\n --runtime.paths $RUNTIME_ID=$RUNTIME_BINARY \\\n --consensus.tendermint.debug.addr_book_lenient \\\n --consensus.tendermint.debug.allow_duplicate_ip \\\n --consensus.tendermint.p2p.seed $SEED_NODE_ADDRESS \\\n --debug.dont_blame_oasis \\\n --debug.allow_test_keys\n")),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"This also enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"When running a runtime node in a production setting, the\n",(0,r.kt)("inlineCode",{parentName:"p"},"worker.p2p.addresses")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.client.addresses")," flags need to be configured\nas well.")),(0,r.kt)("p",null,"Following steps should be run in a new terminal window."),(0,r.kt)("h2",{id:"updating-entity-nodes"},"Updating Entity Nodes"),(0,r.kt)("p",null,"Before the newly started runtime node can register itself as a runtime node, we\nneed to update the entity information in registry, to include the started node."),(0,r.kt)("p",null,"Before proceeding, gather the runtime node id and store it in a variable. If you\nfollowed above instructions, the node id can be seen in\n",(0,r.kt)("inlineCode",{parentName:"p"},"/tmp/runtime-example/runtime-node/identity_pub.pem")," (or using the ",(0,r.kt)("a",{parentName:"p",href:"/core/oasis-node/cli#status"},"node control\nstatus command"),")."),(0,r.kt)("p",null,"Update the entity and generate a transaction that will update the registry\nstate."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"# NOTE: this ID is not generated deterministically make sure to change the ID\n# with your node id.\nexport NODE_ID=NOPhD7UlMZBO8fNyo2xLFanlmvl+EmZ5s4mM2z9nEBg=\n\noasis-node registry entity update \\\n --signer.dir $ENTITY_DIR \\\n --entity.node.id $NODE_ID\n\noasis-node registry entity gen_register \\\n --genesis.file $GENESIS_JSON \\\n --signer.backend file \\\n --signer.dir $ENTITY_DIR \\\n --transaction.file /tmp/runtime-example/update_entity.tx \\\n --transaction.fee.gas 2000 \\\n --transaction.fee.amount 0 \\\n --transaction.nonce $NONCE \\\n --debug.dont_blame_oasis \\\n --debug.allow_test_keys\n")),(0,r.kt)("p",null,"Submit the generated transaction:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis-node consensus submit_tx \\\n --transaction.file /tmp/runtime-example/update_entity.tx \\\n --address $ADDR\n")),(0,r.kt)("p",null,"Confirm the entity in the registry has been updated by querying the registry\nstate:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'oasis-node registry entity list -a $ADDR -v\n\n{"v":1,"id":"JTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrk=","nodes":["LQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH0="]}\n{"v":1,"id":"+MJpnSTzc11dNI5emMa+asCJH5cxBiBCcpbYE4XBdso=","nodes":["vWUfSmjrHSlN5tSSO3/Qynzx+R/UlwPV9u+lnodQ00c="]}\n{"v":1,"id":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","allow_entity_signed_nodes":true}\n')),(0,r.kt)("p",null,"Node is now able to register and the runtime should get resumed, make sure this\nhappens by querying the registry for runtimes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'# Ensure node is registered\noasis-node registry node list -a $ADDR -v | grep "$NODE_ID"\n\n# Ensure runtime is resumed.\noasis-node registry runtime list -a $ADDR -v\n')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"You might need to wait few seconds for an epoch\ntransition so that the node is registered and runtime gets resumed.")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/03741c42.21967c4b.js b/assets/js/03741c42.21967c4b.js new file mode 100644 index 0000000000..14d20f33ac --- /dev/null +++ b/assets/js/03741c42.21967c4b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6525],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>k});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),d=a,k=u["".concat(s,".").concat(d)]||u[d]||m[d]||o;return n?r.createElement(k,i(i({ref:t},c),{},{components:n})):r.createElement(k,i({ref:t},c))}));function k(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,i[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=n(7462),a=(n(7294),n(3905));const o={},i="Oasis Core Developer Documentation",l={unversionedId:"core/README",id:"core/README",title:"Oasis Core Developer Documentation",description:"Architecture",source:"@site/docs/core/README.md",sourceDirName:"core",slug:"/core/",permalink:"/core/",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/README.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",next:{title:"Development Setup",permalink:"/core/development-setup"}},s={},p=[{value:"Development Setup",id:"development-setup",level:2},{value:"High-Level Components",id:"high-level-components",level:2},{value:"Common Functionality",id:"common-functionality",level:2},{value:"Processes",id:"processes",level:2}],c={toc:p},u="wrapper";function m(e){let{components:t,...o}=e;return(0,a.kt)(u,(0,r.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"oasis-core-developer-documentation"},"Oasis Core Developer Documentation"),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Architecture",src:n(4434).Z,width:"581",height:"181"})),(0,a.kt)("h2",{id:"development-setup"},"Development Setup"),(0,a.kt)("p",null,"Here are instructions on how to set up the local build environment, run the\ntests and some examples on how to prepare test networks for local development of\nOasis Core components."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Build Environment Setup and Building",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/prerequisites"},"Prerequisites")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/building"},"Building")))),(0,a.kt)("li",{parentName:"ul"},"Running Tests and Development Networks",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/running-tests"},"Running Tests")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/oasis-net-runner"},"Local Network Runner With a Simple Runtime")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/single-validator-node-network"},"Single Validator Node Network")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/development-setup/deploying-a-runtime"},"Deploying a Runtime"))))),(0,a.kt)("h2",{id:"high-level-components"},"High-Level Components"),(0,a.kt)("p",null,"At the highest level, Oasis Core is divided into two major layers: the\n",(0,a.kt)("em",{parentName:"p"},"consensus layer")," and the ",(0,a.kt)("em",{parentName:"p"},"runtime layer")," as shown on the figure above."),(0,a.kt)("p",null,"The idea behind the consensus layer is to provide a minimal set of features\nrequired to securely operate independent runtimes running in the runtime layer.\nIt provides the following services:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Epoch-based time keeping and a random beacon."),(0,a.kt)("li",{parentName:"ul"},"Basic staking operations required to operate a PoS blockchain."),(0,a.kt)("li",{parentName:"ul"},"An entity, node and runtime registry that distributes public keys and\nmetadata."),(0,a.kt)("li",{parentName:"ul"},"Runtime committee scheduling, commitment processing and minimal state keeping.")),(0,a.kt)("p",null,"On the other side, each runtime defines its own state and state transitions\nindependent from the consensus layer, submitting only short proofs that\ncomputations were performed and results were stored. This means that runtime\nstate and logic are completely decoupled from the consensus layer, and the\nconsensus layer only provides information on what state (summarized by a\ncryptographic hash of a Merklized data structure) is considered canonical at any\ngiven point in time."),(0,a.kt)("p",null,"See the following sections for more details on specific components and their\nimplementations."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/"},"Consensus Layer"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/transactions"},"Transactions")),(0,a.kt)("li",{parentName:"ul"},"Services",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/epochtime"},"Epoch Time")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/beacon"},"Random Beacon")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/staking"},"Staking")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/registry"},"Registry")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/scheduler"},"Committee Scheduler")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/governance"},"Governance")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/roothash"},"Root Hash")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/keymanager"},"Key Manager")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/genesis"},"Genesis Document")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/test-vectors"},"Transaction Test Vectors")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/runtime/"},"Runtime Layer"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/runtime/#operation-model"},"Operation Model")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/runtime/runtime-host-protocol"},"Runtime Host Protocol")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/runtime/identifiers"},"Identifiers")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/runtime/messages"},"Messages")))),(0,a.kt)("li",{parentName:"ul"},"Oasis Node (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-node"),")",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/oasis-node/rpc"},"RPC")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/oasis-node/metrics"},"Metrics")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/oasis-node/cli"},"CLI"))))),(0,a.kt)("h2",{id:"common-functionality"},"Common Functionality"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/encoding"},"Serialization")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/crypto"},"Cryptography")),(0,a.kt)("li",{parentName:"ul"},"Protocols",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/authenticated-grpc"},"Authenticated gRPC")))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/mkvs"},"Merklized Key-Value Store (MKVS)"))),(0,a.kt)("h2",{id:"processes"},"Processes"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/adrs"},"Architectural Decision Records")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/release-process"},"Release Process")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/versioning"},"Versioning")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/SECURITY"},"Security"))))}m.isMDXComponent=!0},4434:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/oasis-core-high-level-4dd19f00411531fadd7a32ea1d596e6f.svg"}}]); \ No newline at end of file diff --git a/assets/js/041ef302.d048cf33.js b/assets/js/041ef302.d048cf33.js new file mode 100644 index 0000000000..84709b66e0 --- /dev/null +++ b/assets/js/041ef302.d048cf33.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[196],{3905:(e,t,r)=>{r.d(t,{Zo:()=>m,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},m=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,c=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),d=l(r),u=i,f=d["".concat(c,".").concat(u)]||d[u]||p[u]||a;return r?n.createElement(f,o(o({ref:t},m),{},{components:r})):n.createElement(f,o({ref:t},m))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[d]="string"==typeof e?e:i,o[1]=s;for(var l=2;l{r.d(t,{Z:()=>f});var n=r(7294),i=r(6010),a=r(9960),o=r(3438),s=r(3919),c=r(5999);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function m(e){let{href:t,children:r}=e;return n.createElement(a.Z,{href:t,className:(0,i.Z)("card padding--lg",l.cardContainer)},r)}function d(e){let{href:t,icon:r,title:a,description:o}=e;return n.createElement(m,{href:t},n.createElement("h2",{className:(0,i.Z)("text--truncate",l.cardTitle),title:a},r," ",a),o&&n.createElement("p",{className:(0,i.Z)("text--truncate",l.cardDescription),title:o},o))}function p(e){let{item:t}=e;const r=(0,o.Wl)(t);return r?n.createElement(d,{href:r,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,c.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const r=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",i=(0,o.xz)(t.docId??void 0);return n.createElement(d,{href:t.href,icon:r,title:t.label,description:t.description??i?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(p,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,r)=>{r.d(t,{Z:()=>c});var n=r(7294),i=r(6010),a=r(3438),o=r(1564);function s(e){let{className:t}=e;const r=(0,a.jA)();return n.createElement(c,{items:r.items,className:t})}function c(e){const{items:t,className:r}=e;if(!t)return n.createElement(s,e);const c=(0,a.MN)(t);return n.createElement("section",{className:(0,i.Z)("row",r)},c.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(o.Z,{item:e})))))}},7525:(e,t,r)=>{r.d(t,{n:()=>a});var n=r(4477);function i(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&i(t.items)}}function a(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)i(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},2636:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>m,contentTitle:()=>c,default:()=>f,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var n=r(7462),i=(r(7294),r(3905)),a=r(9268),o=r(7525);const s={description:"Build your own ParaTime using Oasis Runtime SDK"},c="Build ParaTime",l={unversionedId:"paratime/README",id:"paratime/README",title:"Build ParaTime",description:"Build your own ParaTime using Oasis Runtime SDK",source:"@site/docs/paratime/README.mdx",sourceDirName:"paratime",slug:"/paratime/",permalink:"/paratime/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/paratime/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Build your own ParaTime using Oasis Runtime SDK"},sidebar:"paratime",next:{title:"Prerequisites",permalink:"/paratime/prerequisites"}},m={},d=[],p={toc:d},u="wrapper";function f(e){let{components:t,...r}=e;return(0,i.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"build-paratime"},"Build ParaTime"),(0,i.kt)("p",null,"This chapter will teach you how to build your own ParaTime with ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk"},"Oasis Runtime\nSDK"),"."),(0,i.kt)(a.Z,{items:[(0,o.n)("/paratime/prerequisites"),(0,o.n)("/paratime/minimal-runtime"),(0,o.n)("/paratime/modules"),(0,o.n)("/paratime/reproducibility"),(0,o.n)("https://api.docs.oasis.io/oasis-sdk/oasis_runtime_sdk")],mdxType:"DocCardList"}))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/047b4156.84da1871.js b/assets/js/047b4156.84da1871.js new file mode 100644 index 0000000000..b6b59fa7d0 --- /dev/null +++ b/assets/js/047b4156.84da1871.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5844],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>y});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var d=o.createContext({}),p=function(e){var t=o.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return o.createElement(d.Provider,{value:t},e.children)},l="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,d=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),l=p(n),m=r,y=l["".concat(d,".").concat(m)]||l[m]||u[m]||a;return n?o.createElement(y,i(i({ref:t},c),{},{components:n})):o.createElement(y,i({ref:t},c))}));function y(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var d in t)hasOwnProperty.call(t,d)&&(s[d]=t[d]);s.originalType=e,s[l]="string"==typeof e?e:r,i[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var o=n(7462),r=(n(7294),n(3905));const a={},i="Copy State from One Node to the Other",s={unversionedId:"node/run-your-node/advanced/copy-state-from-one-node-to-the-other",id:"node/run-your-node/advanced/copy-state-from-one-node-to-the-other",title:"Copy State from One Node to the Other",description:"A network that's been running for some time can accrue significant amount of state. This means bootstraping a new Oasis Node would take quite some time and resources (bandwidth, CPU) since it would need to fetch (download) and validate (replay) all the blocks from the genesis height onwards.",source:"@site/docs/node/run-your-node/advanced/copy-state-from-one-node-to-the-other.md",sourceDirName:"node/run-your-node/advanced",slug:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",permalink:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/advanced/copy-state-from-one-node-to-the-other.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Using State Sync for Quick Bootstraping",permalink:"/node/run-your-node/advanced/sync-node-using-state-sync"},next:{title:"Install Oasis Remote Signer Binary",permalink:"/node/run-your-node/advanced/install-oasis-remote-signer-binary"}},d={},p=[],c={toc:p},l="wrapper";function u(e){let{components:t,...n}=e;return(0,r.kt)(l,(0,o.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"copy-state-from-one-node-to-the-other"},"Copy State from One Node to the Other"),(0,r.kt)("p",null,"A network that's been running for some time can accrue significant amount of state. This means bootstraping a new Oasis Node would take quite some time and resources (bandwidth, CPU) since it would need to fetch (download) and validate (replay) all the blocks from the genesis height onwards."),(0,r.kt)("p",null,"If one has access to an Oasis Node that is synced with the latest height, he could just copy Oasis Node's state from the synced node to an unsynced node."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Another way to speed up bootstraping an Oasis Node is to sync the node using ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/sync-node-using-state-sync"},"State Sync"),".")),(0,r.kt)("p",null,"To bootstrap a new Oasis Node by copying state from a synced Oasis Node, first set up your new Oasis Node as a ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"Validator Node"),", a ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"Non-validator Node")," or a ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"ParaTime Node"),"."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Make sure you use the ",(0,r.kt)("strong",{parentName:"p"},"exact same version of Oasis Core")," on both the synced Oasis Node and your new Oasis Node to prevent ",(0,r.kt)("strong",{parentName:"p"},"issues or state corruption")," if an Oasis Node's state is opened ",(0,r.kt)("strong",{parentName:"p"},"with")," an ",(0,r.kt)("strong",{parentName:"p"},"incompatible version")," of Oasis Core.")),(0,r.kt)("p",null,"Before starting your new Oasis Node, do the following:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Stop the synced Oasis Node.")),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"If an Oasis Node is ",(0,r.kt)("strong",{parentName:"p"},"not stopped")," before its state is copied, its on-disk state might not be consistent and up-to-date. This can lead to ",(0,r.kt)("strong",{parentName:"p"},"state corruption")," and inability to use the state with your new Oasis Node.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Copy the following directories from your synced Oasis Node's working directory (e.g. ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"/srv/oasis/node"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"/serverdir/node"),") to your new Oasis Node's working directory:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"tendermint/abci-state")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"tendermint/data"))))),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"You could also copy the whole ",(0,r.kt)("inlineCode",{parentName:"p"},"tendermint")," directory from your synced Oasis Node's working directory. In that case, you must ",(0,r.kt)("strong",{parentName:"p"},"omit")," the ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"oasis_priv_validator.json")," file"),", otherwise starting your new Oasis Node with fail with something like:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre"},'{"caller":"node.go:696","err":"tendermint/crypto: public key mismatch, state corruption?: %!w()","level":"error","module":"oasis-node","msg":"failed to initialize tendermint service","ts":"2021-09-25T14:13:17.919296668Z"}\n'))),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"If you are copying data from a node that is running ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"},"TEE-enabled ParaTimes"),", you\nmust make sure to ",(0,r.kt)("strong",{parentName:"p"},"remove")," the ",(0,r.kt)("inlineCode",{parentName:"p"},"runtimes/*/worker-local-storage.badger.db")," as\notherwise the ParaTime binary may fail to start on a different node since it\ncontains data sealed to the source CPU.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Start back the synced Oasis Node.")),(0,r.kt)("p",null,"Finally, start your new Oasis Node for the first time."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/049d1767.c5f03788.js b/assets/js/049d1767.c5f03788.js new file mode 100644 index 0000000000..854b09ef0f --- /dev/null +++ b/assets/js/049d1767.c5f03788.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4073],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>h});var r=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function n(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function s(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=r.createContext({}),p=function(e){var t=r.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},c=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var a=e.components,o=e.mdxType,n=e.originalType,l=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=p(a),u=o,h=d["".concat(l,".").concat(u)]||d[u]||m[u]||n;return a?r.createElement(h,s(s({ref:t},c),{},{components:a})):r.createElement(h,s({ref:t},c))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var n=a.length,s=new Array(n);s[0]=u;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[d]="string"==typeof e?e:o,s[1]=i;for(var p=2;p{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>m,frontMatter:()=>n,metadata:()=>i,toc:()=>p});var r=a(7462),o=(a(7294),a(3905));const n={},s="How to Transfer ETH/ERC20 to Emerald ParaTime",i={unversionedId:"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",id:"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",title:"How to Transfer ETH/ERC20 to Emerald ParaTime",description:"This guide will walk you through bringing your assets, i.e. ETH, USDC, USDT,",source:"@site/docs/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime.md",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",permalink:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"How to Transfer ROSE into a ParaTime",permalink:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},next:{title:"Oasis CLI",permalink:"/general/manage-tokens/cli/"}},l={},p=[{value:"About",id:"about",level:2},{value:"Using Wormhole Bridge",id:"using-wormhole-bridge",level:2},{value:"Open Wormhole Bridge and Connect your Account",id:"open-wormhole-bridge-and-connect-your-account",level:3},{value:"Transfer Assets to Oasis",id:"transfer-assets-to-oasis",level:3},{value:"Using Wrapped Assets on Oasis",id:"using-wrapped-assets-on-oasis",level:2}],c={toc:p},d="wrapper";function m(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"how-to-transfer-etherc20-to-emerald-paratime"},"How to Transfer ETH/ERC20 to Emerald ParaTime"),(0,o.kt)("p",null,"This guide will walk you through bringing your assets, i.e. ETH, USDC, USDT,\nfrom Ethereum, BSC, Polygon or Avalanche networks to the Emerald ParaTime using\nthe Wormhole token bridge."),(0,o.kt)("h2",{id:"about"},"About"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/dapp/emerald/"},"Emerald")," is an Oasis ParaTime providing an Ethereum-compatible blockchain for the Oasis Network. If you want to use any dApp for DEX, NFT and similar built on Emerald, you will have to transfer your assets into the Emerald ParaTime."),(0,o.kt)("p",null,"To transfer your ROSE tokens into Emerald, follow ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},"How to Transfer ROSE into a ParaTime"),"."),(0,o.kt)("p",null,"To transfer (i.e. bridge and wrap) your ETH and ERC20 tokens, follow this guide. It will show you how to use ",(0,o.kt)("a",{parentName:"p",href:"https://wormholebridge.com"},"Wormhole Bridge")," to seamlessly transfer your tokens from Ethereum, Solana, Avalanche, BSC, Terra or Polygon to the Oasis Network."),(0,o.kt)("h2",{id:"using-wormhole-bridge"},"Using Wormhole Bridge"),(0,o.kt)("h3",{id:"open-wormhole-bridge-and-connect-your-account"},"Open Wormhole Bridge and Connect your Account"),(0,o.kt)("p",null,"First, get your assets ready in your MetaMask to be transferred over to Oasis. Then navigate to the ",(0,o.kt)("a",{parentName:"p",href:"https://wormholebridge.com"},"Wormhole Bridge"),"'s website and click on ",(0,o.kt)("em",{parentName:"p"},"Transfer Tokens")," to open the ",(0,o.kt)("a",{parentName:"p",href:"https://wormholebridge.com/#/transfer"},"Wormhole Bridge Transfer")," application."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Wormhole Bridge",src:a(1385).Z,width:"2616",height:"2612"})),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Step 1 (Source)")," is to point ",(0,o.kt)("em",{parentName:"p"},"Source")," to the network from where you want to transfer your tokens to ",(0,o.kt)("strong",{parentName:"p"},"Ethereum")," and set the ",(0,o.kt)("em",{parentName:"p"},"Target")," to ",(0,o.kt)("strong",{parentName:"p"},"Oasis"),". Then click ",(0,o.kt)("em",{parentName:"p"},"Connect")," to connect your wallet with the Wormhole Bridge."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Connect your wallet",src:a(2186).Z,width:"3004",height:"1732"})),(0,o.kt)("h3",{id:"transfer-assets-to-oasis"},"Transfer Assets to Oasis"),(0,o.kt)("p",null,"Now you can select an asset from all available assets in your wallet, e.g. ETH, to be transferred to Oasis."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Select the asset to be transferred",src:a(5169).Z,width:"3008",height:"1516"})),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Make sure, that you always have enough ETH (or other assets) for paying gas fees, not only to transfer (i.e. bridge) the assets to Oasis, but also to redeem any assets back to Ethereum.")),(0,o.kt)("p",null,"Choose the ",(0,o.kt)("em",{parentName:"p"},"Amount")," of tokens you want to transfer and click ",(0,o.kt)("em",{parentName:"p"},"Next"),". If your MetaMask wallet is switched to some other network, the Wormhole bridge will ask you to switch to the correct network (e.g. Ethereum Mainnet)."),(0,o.kt)("p",null,"You will then proceed to ",(0,o.kt)("strong",{parentName:"p"},"Step 2 (Target)"),". Your MetaMask wallet will show up again and ask you to switch to the Emerald Mainnet network because that is where your ETH will be wrapped to wETH."),(0,o.kt)("p",null,"The recipient address defaults to the source address on the Ethereum network. You can transfer your ETH into a different destination Ethereum account, by switching the currently opened account in MetaMask. The Wormhole Bridge web app will automatically switch the recipient address accordingly."),(0,o.kt)("p",null,"Next, confirm the recipient address and the amount of WETH tokens to be transferred (i.e. bridged) and click ",(0,o.kt)("em",{parentName:"p"},"Next"),"."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Confirm your recipient address",src:a(5726).Z,width:"3004",height:"1728"})),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Step 3 (Send tokens)")," is to transfer the tokens to the Wormhole Bridge. MetaMask will ask you to switch back to the Ethereum Mainnet so you will be able to confirm your transaction and commence the transfer. Click ",(0,o.kt)("em",{parentName:"p"},"Transfer"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"If you chose to transfer your ETH into a different destination Ethereum account, you will need to switch the currently opened account in MetaMask back to the same account as used in Step 1.")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Send tokens to Wormhole",src:a(5828).Z,width:"3004",height:"1730"})),(0,o.kt)("p",null,"Confirm the Transfer of ETH from Ethereum to wETH on Oasis Emerald by clicking ",(0,o.kt)("em",{parentName:"p"},"Confirm"),"."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Confirm the transfer ETH->WETH",src:a(9049).Z,width:"3010",height:"1728"})),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},'If you use a Ledger hardware wallet backed Ethereum account, you will need to enable "Blind signing" or "Contract data" in the Ethereum Ledger app\'s settings to be able to sign the transaction.')),(0,o.kt)("p",null,"You will have to wait for the confirmations on Ethereum before redeeming your new wETH tokens in Oasis Emerald."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Wait for Ethereum confirmations",src:a(1861).Z,width:"3006",height:"1732"})),(0,o.kt)("p",null,"Now you are ready to redeem your tokens on the Oasis Emerald. Confirm the wallet approval in your MetaMask."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Confirm Redeeming your wETH",src:a(3832).Z,width:"3006",height:"1730"})),(0,o.kt)("p",null,"Congratulations! You just bridged your first ETH (your chosen asset) to wETH on Oasis Emerald."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"ETH to wETH bridging completed",src:a(178).Z,width:"3006",height:"1734"})),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We suggest that you add the new contract address for wETH (your newly wrapped asset) immediately after the transaction is confirmed, so you will see them available in your wallet.")),(0,o.kt)("h2",{id:"using-wrapped-assets-on-oasis"},"Using Wrapped Assets on Oasis"),(0,o.kt)("p",null,"Now you can start using that wrapped assets across new Oasis dApps like the first DEX build on Emerald - ",(0,o.kt)("a",{parentName:"p",href:"https://yuzu-swap.com"},"YuzuSwap"),", where you can swap, provide liquidity and farm YUZU rewards."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Start using wrapped assets on Oasis",src:a(4742).Z,width:"2990",height:"1732"})),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Make sure that your MetaMask is connected to the Emerald Mainnet network. You can find network parameters ",(0,o.kt)("a",{parentName:"p",href:"/dapp/emerald#web3-gateway"},"here"),".")))}m.isMDXComponent=!0},9049:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/confirm_transaction_ETH_WETH-9fb853c57c97ac65fe40ca29178ad684.png"},2186:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/connect_wallet-6c13918efbcc33da6004a1306f8a1b0e.png"},1385:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/index-45df31c8f3f67661a8d6c4944be35956.png"},3832:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/redeem_tokens-f1082c546b479f813a98c3969e4257ba.png"},178:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/redeem_tokens2-738d656761667f29cfbd85388866ea49.png"},5169:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/select_source_dest_amount-6be16ab5449bce3d7d1fe651cef4876f.png"},1861:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/send_tokens-0e219f5c38fda30ea6ec094e6dabec62.png"},5828:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/send_tokens_to_wormhole-a7154abd51883a7b0b9b10659830e7a1.png"},5726:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/switch_to_emerald-64787a9ffef61c7bc90fe1437e97d21d.png"},4742:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/yuzuswap-ea0c9c9a22e563c5b43b9ea538b5faac.png"}}]); \ No newline at end of file diff --git a/assets/js/04a64f04.44092f2d.js b/assets/js/04a64f04.44092f2d.js new file mode 100644 index 0000000000..e8025dd0c5 --- /dev/null +++ b/assets/js/04a64f04.44092f2d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5921],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>m});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=a.createContext({}),i=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},d=function(e){var t=i(e.components);return a.createElement(p.Provider,{value:t},e.children)},c="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,p=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),c=i(n),u=o,m=c["".concat(p,".").concat(u)]||c[u]||h[u]||r;return n?a.createElement(m,l(l({ref:t},d),{},{components:n})):a.createElement(m,l({ref:t},d))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,l=new Array(r);l[0]=u;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[c]="string"==typeof e?e:o,l[1]=s;for(var i=2;i{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={},l="Build",s={unversionedId:"dapp/opl/build",id:"dapp/opl/build",title:"Build",description:"Now that we have written our two smart contracts, let's compile and deploy them!",source:"@site/docs/dapp/opl/build.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/build",permalink:"/dapp/opl/build",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/build.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Ballot Contract",permalink:"/dapp/opl/enclave"},next:{title:"Frontend Application",permalink:"/dapp/opl/frontend"}},p={},i=[{value:"Compiling",id:"compiling",level:3},{value:"Deploying",id:"deploying",level:3},{value:"Localhost",id:"localhost",level:4},{value:"Testnet",id:"testnet",level:4}],d={toc:i},c="wrapper";function h(e){let{components:t,...n}=e;return(0,o.kt)(c,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"build"},"Build"),(0,o.kt)("p",null,"Now that we have written our two smart contracts, let's compile and deploy them!"),(0,o.kt)("h3",{id:"compiling"},"Compiling"),(0,o.kt)("p",null,"Compile both the host and enclave smart contracts by invoking:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"npx hardhat compile\n")),(0,o.kt)("h3",{id:"deploying"},"Deploying"),(0,o.kt)("p",null,"We can make deployments easier by using ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/wighawag/hardhat-deploy"},"Hardhat deploy"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm install -D hardhat-deploy\n")),(0,o.kt)("p",null,"Add the following configuration changes to your ",(0,o.kt)("inlineCode",{parentName:"p"},"hardhat.config.ts"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-diff"},"diff --git a/backend/hardhat.config.ts b/backend/hardhat.config.ts\nindex cd8df42..0875e8e 100644\n--- a/backend/hardhat.config.ts\n+++ b/backend/hardhat.config.ts\n@@ -1,8 +1,70 @@\n-import { HardhatUserConfig } from \"hardhat/config\";\n+import '@oasisprotocol/sapphire-hardhat';\n import \"@nomicfoundation/hardhat-toolbox\";\n+import { HardhatUserConfig, task } from 'hardhat/config';\n+\n+const accounts = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [];\n+\n+task('deploy-ballot-box')\n+ .addParam('hostNetwork')\n+ .setAction(async (args, hre) => {\n+ await hre.run('compile');\n+ const ethers = hre.ethers;\n+ const BallotBoxV1 = await ethers.getContractFactory('BallotBoxV1');\n+ const signer = ethers.provider.getSigner();\n+ const signerAddr = await signer.getAddress();\n+\n+ // Start by predicting the address of the DAO contract.\n+ const hostConfig = hre.config.networks[args.hostNetwork];\n+ if (!('url' in hostConfig)) throw new Error(`${args.hostNetwork} not configured`);\n+ const provider = new ethers.providers.JsonRpcProvider(hostConfig.url);\n+ let nonce = await provider.getTransactionCount(signerAddr);\n+ if (args.hostNetwork === 'local') nonce++;\n+ const daoAddr = ethers.utils.getContractAddress({ from: signerAddr, nonce });\n+\n+ const ballotBox = await BallotBoxV1.deploy(daoAddr);\n+ await ballotBox.deployed();\n+ console.log('expected DAO', daoAddr);\n+ console.log('BallotBox', ballotBox.address);\n+ return ballotBox.address;\n+ });\n+\n+task('deploy-dao')\n+ .addParam('ballotBoxAddr')\n+ .setAction(async (args, hre) => {\n+ await hre.run('compile');\n+ const DAOV1 = await hre.ethers.getContractFactory('DAOV1');\n+ const dao = await DAOV1.deploy(args.ballotBoxAddr);\n+ await dao.deployed();\n+ console.log('DAO', dao.address);\n+ return dao;\n+ });\n+\n+task('deploy-local').setAction(async (_args, hre) => {\n+ await hre.run('compile');\n+ const ballotBox = await hre.run('deploy-ballot-box', { hostNetwork: 'local' });\n+ await hre.run('deploy-dao', { ballotBoxAddr: ballotBox });\n+ });\n \n const config: HardhatUserConfig = {\n solidity: \"0.8.18\",\n+ networks: {\n+ hardhat: {\n+ chainId: 1337, // @see https://hardhat.org/metamask-issue.html\n+ },\n+ local: {\n+ url: 'http://127.0.0.1:8545',\n+ },\n+ bsc_testnet: {\n+ url: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n+ chainId: 97,\n+ accounts,\n+ },\n+ sapphire_testnet: {\n+ url: 'https://testnet.sapphire.oasis.dev',\n+ chainId: 0x5aff,\n+ accounts,\n+ },\n+ }\n };\n \n export default config;\n")),(0,o.kt)("h4",{id:"localhost"},"Localhost"),(0,o.kt)("p",null,"We can start local Hardhat node again:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"npx hardhat node\n")),(0,o.kt)("p",null,"Our deploy should succeed locally."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"npx hardhat deploy-local --network localhost\nNothing to compile\nNo need to generate any newer typings.\nNothing to compile\nNo need to generate any newer typings.\nexpected DAO 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853\nBallotBox 0x0165878A594ca255338adfa4d48449f69242Eb8F\nNothing to compile\nNo need to generate any newer typings.\nDAO 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853\n")),(0,o.kt)("p",null,"We will use these addresses in our frontend application."),(0,o.kt)("h4",{id:"testnet"},"Testnet"),(0,o.kt)("p",null,"We can likewise deploy to ",(0,o.kt)("a",{parentName:"p",href:"../../dapp/sapphire/guide#testnet-and-mainnet"},"Testnet"),"\nwith Sapphire."),(0,o.kt)("p",null,"In this case, we should prepare a wallet with Testnet tokens on both BNB Smart\nChain ",(0,o.kt)("a",{parentName:"p",href:"https://testnet.bnbchain.org/faucet-smart"},"Faucet")," and Sapphire ",(0,o.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev"},"faucet"),"."),(0,o.kt)("p",null,"We will use a common private key for both the host and enclave smart contracts."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"export PRIVATE_KEY=\n")),(0,o.kt)("p",null,"Deploy the enclave smart contract using Testnet parameters."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"npx hardhat deploy-ballot-box --network sapphire_testnet --host-network bsc_testnet\nNothing to compile\nNo need to generate any newer typings.\nexpected DAO 0xFBcb580DD6D64fbF7caF57FB0439502412324179\nBallotBox 0xFb40591a8df155da291A4B52E4Df9901a95b7C06\n")),(0,o.kt)("p",null,"Next, use the obtained ",(0,o.kt)("inlineCode",{parentName:"p"},"BallotBox")," address below to deploy the host smart\ncontract:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"npx hardhat deploy-dao --network bsc_testnet --ballot-box-addr {BALLOT_BOX_ADDR}\nNothing to compile\nNo need to generate any newer typings.\nDAO 0xFBcb580DD6D64fbF7caF57FB0439502412324179\n")),(0,o.kt)("admonition",{title:"Example",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You can try out and download a complete backend example with both host and\nenclave smart contracts from the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/playground/tree/main/opl-secret-ballot/backend"},"Oasis Playground repository"),".")))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/05c525ec.cee7f43a.js b/assets/js/05c525ec.cee7f43a.js new file mode 100644 index 0000000000..4e53d335ce --- /dev/null +++ b/assets/js/05c525ec.cee7f43a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9392],{3905:(e,t,o)=>{o.d(t,{Zo:()=>l,kt:()=>h});var r=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function s(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function a(e){for(var t=1;t=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var c=r.createContext({}),m=function(e){var t=r.useContext(c),o=t;return e&&(o="function"==typeof e?e(t):a(a({},t),e)),o},l=function(e){var t=m(e.components);return r.createElement(c.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var o=e.components,n=e.mdxType,s=e.originalType,c=e.parentName,l=i(e,["components","mdxType","originalType","parentName"]),u=m(o),d=n,h=u["".concat(c,".").concat(d)]||u[d]||p[d]||s;return o?r.createElement(h,a(a({ref:t},l),{},{components:o})):r.createElement(h,a({ref:t},l))}));function h(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var s=o.length,a=new Array(s);a[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:n,a[1]=i;for(var m=2;m{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>s,metadata:()=>i,toc:()=>m});var r=o(7462),n=(o(7294),o(3905));const s={},a="Root Hash",i={unversionedId:"core/consensus/services/roothash",id:"core/consensus/services/roothash",title:"Root Hash",description:"The roothash service is responsible for runtime commitment processing and",source:"@site/docs/core/consensus/services/roothash.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/roothash",permalink:"/core/consensus/services/roothash",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/roothash.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Governance",permalink:"/core/consensus/services/governance"},next:{title:"Key Manager",permalink:"/core/consensus/services/keymanager"}},c={},m=[{value:"Methods",id:"methods",level:2},{value:"Executor Commit",id:"executor-commit",level:3},{value:"Events",id:"events",level:2},{value:"Consensus Parameters",id:"consensus-parameters",level:2}],l={toc:m},u="wrapper";function p(e){let{components:t,...o}=e;return(0,n.kt)(u,(0,r.Z)({},l,o,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"root-hash"},"Root Hash"),(0,n.kt)("p",null,"The roothash service is responsible for runtime commitment processing and\nminimal runtime state keeping."),(0,n.kt)("p",null,"The service interface definition lives in ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/api/api.go"},(0,n.kt)("inlineCode",{parentName:"a"},"go/roothash/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc"},"consensus service API documentation"),"."),(0,n.kt)("h2",{id:"methods"},"Methods"),(0,n.kt)("h3",{id:"executor-commit"},"Executor Commit"),(0,n.kt)("p",null,"The executor commit method allows an executor node to submit commitments of an\nexecuted computation. A new executor commit transaction can be generated using\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc#NewExecutorCommitTx"},(0,n.kt)("inlineCode",{parentName:"a"},"NewExecutorCommitTx")),"."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Method name:")),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre"},"roothash.ExecutorCommit\n")),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Body:")),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-golang"},'type ExecutorCommit struct {\n ID common.Namespace `json:"id"`\n Commits []commitment.ExecutorCommitment `json:"commits"`\n}\n')),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Fields:")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"id")," specifies the ",(0,n.kt)("a",{parentName:"li",href:"/core/runtime/identifiers"},"runtime identifier")," of a runtime this commit is for."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"commits")," are the ",(0,n.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api/commitment?tab=doc#ExecutorCommitment"},"executor commitments"),".")),(0,n.kt)("h2",{id:"events"},"Events"),(0,n.kt)("h2",{id:"consensus-parameters"},"Consensus Parameters"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"max_runtime_messages")," (uint32) specifies the global limit on the number of\n",(0,n.kt)("a",{parentName:"li",href:"/core/runtime/messages"},"messages")," that can be emitted in each round by the runtime. The default value\nof ",(0,n.kt)("inlineCode",{parentName:"li"},"0")," disables the use of runtime messages.")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/06c96f46.fe2d6664.js b/assets/js/06c96f46.fe2d6664.js new file mode 100644 index 0000000000..47dadc0d14 --- /dev/null +++ b/assets/js/06c96f46.fe2d6664.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9899],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>g});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function r(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(t),m=o,g=d["".concat(l,".").concat(m)]||d[m]||u[m]||i;return t?a.createElement(g,r(r({ref:n},c),{},{components:t})):a.createElement(g,r({ref:n},c))}));function g(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,r=new Array(i);r[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[d]="string"==typeof e?e:o,r[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var a=t(7462),o=(t(7294),t(3905));const i={},r="Generating and Signing Transactions",s={unversionedId:"oasis-core-ledger/usage/transactions",id:"oasis-core-ledger/usage/transactions",title:"Generating and Signing Transactions",description:"Before following the instructions below, make sure your Ledger wallet is",source:"@site/docs/oasis-core-ledger/usage/transactions.md",sourceDirName:"oasis-core-ledger/usage",slug:"/oasis-core-ledger/usage/transactions",permalink:"/oasis-core-ledger/usage/transactions",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/usage/transactions.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Exporting Public Key to Entity",permalink:"/oasis-core-ledger/usage/entity"},next:{title:"Identifying Wallets",permalink:"/oasis-core-ledger/usage/wallets"}},l={},p=[],c={toc:p},d="wrapper";function u(e){let{components:n,...t}=e;return(0,o.kt)(d,(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"generating-and-signing-transactions"},"Generating and Signing Transactions"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Before following the instructions below, make sure your Ledger wallet is\nunlocked and the Oasis App is open.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"While the Oasis App is available in ",(0,o.kt)("em",{parentName:"p"},"Developer mode"),', opening the App brings\nup the "Pending Ledger review" screen.\nYou need to press both buttons at once to close that screen and transition to\nthe ',(0,o.kt)("em",{parentName:"p"},"ordinary"),' "Oasis Ready" screen where the Oasis App is ready to be used.')),(0,o.kt)("p",null,"As described in the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/advanced/oasis-cli-tools/"},"Use Your Tokens' Setup")," document of the general\n",(0,o.kt)("a",{parentName:"p",href:"/general/"},"Oasis Docs"),", you need to set the appropriate ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/advanced/oasis-cli-tools/setup#common-cli-flags"},"Base and Signer CLI flags")," for\neach transaction you want to generate."),(0,o.kt)("p",null,"Make sure you set the following environment variables:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"GENESIS_FILE"),": Location of the genesis file."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"LEDGER_SIGNER_PATH"),": Location of the ",(0,o.kt)("inlineCode",{parentName:"li"},"ledger-signer")," binary.\nSee ",(0,o.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/setup#remembering-path-to-ledger-signer-plugin"},"Setup")," for more details.")),(0,o.kt)("p",null,"For convenience, you can set the ",(0,o.kt)("inlineCode",{parentName:"p"},"TX_FLAGS")," environment variable like below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'TX_FLAGS=(--genesis.file "$GENESIS_FILE"\n --signer.dir entity\n --signer.backend plugin\n --signer.plugin.name ledger\n --signer.plugin.path "$LEDGER_SIGNER_PATH"\n)\n')),(0,o.kt)("p",null,"Make sure you replace ",(0,o.kt)("inlineCode",{parentName:"p"},"entity")," with the name of the directory that contains the\n",(0,o.kt)("inlineCode",{parentName:"p"},"entity.json")," file for you Ledger wallet's account.\nSee ",(0,o.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/entity"},"Exporting Public Key to Entity")," for more details."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"In case you will have more than one Ledger wallet connected, you will need to\nspecify which wallet to use by setting the ",(0,o.kt)("inlineCode",{parentName:"p"},"wallet_id")," configuration key in\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, i.e."),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},'--signer.plugin.config "wallet_id:"\n')),(0,o.kt)("p",{parentName:"admonition"},"where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is replaced with the ID of your Ledger wallet.\nSee ",(0,o.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/wallets"},"Identifying Wallets")," for more details.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"If you want to use different account index for the same Ledger wallet, you\nwill need to specify it by setting the ",(0,o.kt)("inlineCode",{parentName:"p"},"index")," configuration key in the\n",(0,o.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, i.e."),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},'--signer.plugin.config "index:"\n')),(0,o.kt)("p",{parentName:"admonition"},"where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is replaced with the account index you want to\nuse."),(0,o.kt)("p",{parentName:"admonition"},"If you need to specify multiple configuration keys in the\n",(0,o.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, you can separate them with a comma (",(0,o.kt)("inlineCode",{parentName:"p"},","),"), e.g."),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},'--signer.plugin.config "wallet_id:1fc3be,index:5"\n'))),(0,o.kt)("p",null,"Then, you can generate and sign a transaction by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'oasis-node stake account gen_ \\\n "${TX_FLAGS[@]}" \\\n --transaction.file tx.json \\\n --transaction.nonce \\\n --transaction.fee.gas \\\n --transaction.fee.amount \n')),(0,o.kt)("p",null,"where:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},""),": type of transaction, e.g. ",(0,o.kt)("inlineCode",{parentName:"li"},"transfer"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"escrow"),", ",(0,o.kt)("inlineCode",{parentName:"li"},"reclaim_escrow"),",\n..."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},""),": your account's current nonce,"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},""),": maximum amount of gas this transaction can spend,"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},""),": amount of tokens you will pay as a fee for this transaction.")),(0,o.kt)("p",null,"Besides these common transaction flags, you will need to specify additional\ntransaction flags specific to the chosen transaction type. Run\n",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node stake account gen_ --help")," for more details."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For a more detailed explanation of the common transaction flags, see\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/advanced/oasis-cli-tools/setup#common-transaction-flags"},"Common Transaction Flags")," section of the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/advanced/oasis-cli-tools/"},"Use Your Tokens' Setup")," doc.")),(0,o.kt)("p",null,"For example, to generate and sign a transfer transaction of 100 tokens to an\naccount with address ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis1qpcgnf84hnvvfvzup542rhc8kjyvqf4aqqlj5kqh"),", run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'oasis-node stake account gen_transfer \\\n "${TX_FLAGS[@]}" \\\n --stake.amount 100000000000 \\\n --stake.transfer.destination oasis1qpcgnf84hnvvfvzup542rhc8kjyvqf4aqqlj5kqh \\\n --transaction.file tx.json \\\n --transaction.nonce 1 \\\n --transaction.fee.gas 2000 \\\n --transaction.fee.amount 2000\n')),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The amounts passed via the ",(0,o.kt)("inlineCode",{parentName:"p"},"--stake.amount")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"--transaction.fee.amount")," flags\nare specified in nROSE units, i.e. 1 ROSE equals 1,000,000,000 nROSE.")),(0,o.kt)("p",null,"This will output a preview of the generated transaction:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\n Nonce: 1\n Fee:\n Amount: ROSE 0.000002\n Gas limit: 2000\n (gas price: ROSE 0.000000001 per gas unit)\n Method: staking.Transfer\n Body:\n To: oasis1qpcgnf84hnvvfvzup542rhc8kjyvqf4aqqlj5kqh\n Amount: ROSE 100.0\nOther info:\n Genesis document's hash: a245619497e580dd3bc1aa3256c07f68b8dcc13f92da115eadc3b231b083d3c4\n")),(0,o.kt)("p",null,"and ask you to verify the transaction's fields on your Ledger wallet's screen."),(0,o.kt)("p",null,"After you've confirmed the transaction's fields are correct, sign the\ntransaction on your Ledger wallet by double-pressing the ",(0,o.kt)("em",{parentName:"p"},"Sign transaction"),"\nscreen."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The next step after signing a transaction is to submit it to the network via\nan online Oasis node by running:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node consensus submit_tx \\\n -a $ADDR \\\n --transaction.file tx_transfer.json\n")),(0,o.kt)("p",{parentName:"admonition"},"For more details, see the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/advanced/oasis-cli-tools/transfer-tokens"},"Transfer Tokens")," document of the general\n",(0,o.kt)("a",{parentName:"p",href:"/general/"},"Oasis Docs"),".")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/086b3520.d62e61f2.js b/assets/js/086b3520.d62e61f2.js new file mode 100644 index 0000000000..fd3bf57868 --- /dev/null +++ b/assets/js/086b3520.d62e61f2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2930],{3905:(e,t,a)=>{a.d(t,{Zo:()=>h,kt:()=>u});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),d=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},h=function(e){var t=d(e.components);return n.createElement(l.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),c=d(a),m=o,u=c["".concat(l,".").concat(m)]||c[m]||p[m]||r;return a?n.createElement(u,i(i({ref:t},h),{},{components:a})):n.createElement(u,i({ref:t},h))}));function u(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:o,i[1]=s;for(var d=2;d{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var n=a(7462),o=(a(7294),a(3905));const r={},i="Frequently Asked Questions",s={unversionedId:"general/manage-tokens/faq",id:"general/manage-tokens/faq",title:"Frequently Asked Questions",description:"This documents answers frequently asked questions about Oasis Wallets and 3rd",source:"@site/docs/general/manage-tokens/faq.md",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/faq",permalink:"/general/manage-tokens/faq",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/faq.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Address book",permalink:"/general/manage-tokens/cli/addressbook"}},l={},d=[{value:"How can I transfer ROSE tokens from my BitPie wallet to my Oasis Wallet?",id:"how-can-i-transfer-rose-tokens-from-my-bitpie-wallet-to-my-oasis-wallet",level:3},{value:"How can I export Oasis private key from a working BitPie wallet?",id:"how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet",level:3},{value:"How can I export Oasis private key, if BitPie doesn't show my ROSE account anymore?",id:"how-can-i-export-oasis-private-key-if-bitpie-doesnt-show-my-rose-account-anymore",level:3},{value:"Chromium under Ubuntu does not recognize my Ledger device. What is the problem?",id:"chromium-under-ubuntu-does-not-recognize-my-ledger-device-what-is-the-problem",level:3},{value:"Are Ethereum and Oasis wallets that different? I can use the same mnemonics with both, right?",id:"are-ethereum-and-oasis-wallets-that-different-i-can-use-the-same-mnemonics-with-both-right",level:3},{value:"Which derivation path should I use on Ledger? ADR 0008 or Legacy?",id:"ledger-derivation-paths",level:3},{value:"The wallet gives me Invalid keyphrase error when importing my wallet from mnemonics. How do I solve it?",id:"the-wallet-gives-me-invalid-keyphrase-error-when-importing-my-wallet-from-mnemonics-how-do-i-solve-it",level:3},{value:"I imported my wallet with mnemonics. The wallet should contain funds, but the balance is empty. What can I do?",id:"i-imported-my-wallet-with-mnemonics-the-wallet-should-contain-funds-but-the-balance-is-empty-what-can-i-do",level:3},{value:"I sent my ROSE to BinanceStaking address. Are they staked? Are they lost? What can I do?",id:"i-sent-my-rose-to-binancestaking-address--are-they-staked-are-they-lost-what-can-i-do",level:3},{value:"I withdrew ROSE from Emerald to an exchange (Binance, KuCoin), but my deposit is not there. What should I do?",id:"i-withdrew-rose-from-emerald-to-an-exchange-binance-kucoin-but-my-deposit-is-not-there-what-should-i-do",level:3}],h={toc:d},c="wrapper";function p(e){let{components:t,...r}=e;return(0,o.kt)(c,(0,n.Z)({},h,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"frequently-asked-questions"},"Frequently Asked Questions"),(0,o.kt)("p",null,"This documents answers frequently asked questions about Oasis Wallets and 3rd\nparty wallets & custody providers supporting ROSE tokens."),(0,o.kt)("h3",{id:"how-can-i-transfer-rose-tokens-from-my-bitpie-wallet-to-my-oasis-wallet"},"How can I transfer ROSE tokens from my BitPie wallet to my Oasis Wallet?"),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"BitPie wallet doesn't use the ",(0,o.kt)("a",{parentName:"p",href:"/adrs/0008-standard-account-key-generation"},"standardized Oasis mnemonic derivation"),".\nConsequently, your ",(0,o.kt)("strong",{parentName:"p"},"Bitpie wallet's mnemonic phrase will not open the same\naccount in the Oasis Wallet"),".")),(0,o.kt)("p",null,"As of May 2023, the newer versions of BitPie wallet ",(0,o.kt)("a",{parentName:"p",href:"https://medium.com/bitpie/announcement-on-suspension-of-support-for-algo-and-rose-fc35cb322617"},"do not support transferring\ntokens on the Oasis network anymore"),". Previously, sending\ntokens from the BitPie wallet to the address generated by the Oasis wallet was\nthe preferred migration procedure."),(0,o.kt)("p",null,"Thus, the only way to access your tokens stored on your BitPie wallet is to\nobtain the private key of your BitPie's wallet in one of the two ways:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"#how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet"},"Export private key from a working BitPie wallet")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"#how-can-i-export-oasis-private-key-if-bitpie-doesnt-show-my-rose-account-anymore"},"Convert BitPie mnemonic to Oasis private key offline"))),(0,o.kt)("p",null,"Once you obtained the private key, you can\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/web#open-wallet-via-private-key"},"import it to the Oasis wallet")," and access\nyour assets."),(0,o.kt)("h3",{id:"how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet"},"How can I export Oasis private key from a working BitPie wallet?"),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Chinese users can follow the ",(0,o.kt)("a",{parentName:"p",href:"https://bitpie.zendesk.com/hc/zh-cn/articles/6796209839503"},"official BitPie support article")," on how to export\nthe Oasis private key from your BitPie wallet.")),(0,o.kt)("p",null,"If you have an existing ROSE account in your BitPie wallet, you can obtain the\nwallet's private key by following the steps below."),(0,o.kt)("p",null,'On the main BitPie wallet screen, click on the "Receive" button.'),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"BitPie main screen",src:a(7018).Z,width:"720",height:"1520"})),(0,o.kt)("p",null,'The QR code with your ROSE address will appear. Then, in the top right corner, tap on the kebab menu "\u22ee" and select "Display Private Key"',(0,o.kt)("em",{parentName:"p"},".")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"BitPie show private key",src:a(2260).Z,width:"720",height:"1520"})),(0,o.kt)("p",null,"BitPie wallet will now ask you to enter your PIN to access the private key."),(0,o.kt)("p",null,"Finally, your account's private key will be shown to you encoded in Base64\nformat (e.g.\n",(0,o.kt)("inlineCode",{parentName:"p"},"YgwGOfrHG1TVWSZBs8WM4w0BUjLmsbk7Gqgd7IGeHfSqdbeQokEhFEJxtc3kVQ4KqkdZTuD0bY7LOlhdEKevaQ=="),")\nwhich you can\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/web#open-wallet-via-private-key"},"import into Oasis Wallet"),"."),(0,o.kt)("h3",{id:"how-can-i-export-oasis-private-key-if-bitpie-doesnt-show-my-rose-account-anymore"},"How can I export Oasis private key, if BitPie doesn't show my ROSE account anymore?"),(0,o.kt)("p",null,"If you reinstalled BitPie or restored it with a mnemonic on a new device, you\nmay not have your ROSE account present anymore. In this case, you will have\nto convert your BitPie mnemonic to the Oasis private key using the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/tools/tree/main/unmnemonic"},"Oasis\nunmnemonic CLI tool"),"."),(0,o.kt)("p",null,"You will have to pick Bitpie algorithm, then enter the number of mnemonics\n(typically 12), the private key index (start with 0 and gradually increase it by\n1, if the resulting account does not contain any tokens) and the output\ndirectory where the file containing the Oasis private key should be stored into.\nFor example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"$ ./unmnemonic\n\n unmnemonic - Recover Oasis Network signing keys from mnemonics\n\n? Which algorithm does your wallet use Bitpie\n? How many words is your mnemonic 12\n? Enter word 1 *****\n? Enter word 2 ******\n? Enter word 3 ******\n? Enter word 4 *******\n? Enter word 5 *****\n? Enter word 6 *******\n? Enter word 7 *******\n? Enter word 8 ****\n? Enter word 9 *****\n? Enter word 10 ******\n? Enter word 11 *****\n? Enter word 12 ******\n? Wallet index(es) (comma separated) 0\n Index[0]: oasis1qp8d9kuduq0zutuatjsgltpugxvl38cuaq3gzkmn\n? Write the keys to disk Yes\n? Output directory /home/user/unmnemonic/wallet-export-2023-05-01\n Index[0]: oasis1qp8d9kuduq0zutuatjsgltpugxvl38cuaq3gzkmn.private.pem - done\nDone writing wallet keys to disk, goodbye.\n")),(0,o.kt)("p",null,"Open the generated file, copy the Base64-encoded key wrapped with\n",(0,o.kt)("inlineCode",{parentName:"p"},"-----BEGIN ED25519 PRIVATE KEY-----")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"-----END ED25519 PRIVATE KEY-----"),",\nand ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/web#open-wallet-via-private-key"},"import it to the Oasis wallet"),"."),(0,o.kt)("h3",{id:"chromium-under-ubuntu-does-not-recognize-my-ledger-device-what-is-the-problem"},"Chromium under Ubuntu does not recognize my Ledger device. What is the problem?"),(0,o.kt)("p",null,"First check that you added the Ledger udev device descriptors as mentioned in the ",(0,o.kt)("a",{parentName:"p",href:"https://support.ledger.com/hc/en-us/articles/4404389606417-Download-and-install-Ledger-Live"},"Linux installation guide"),". Next, check that your Ledger wallet is recognized by the ",(0,o.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/address"},"Oasis Core Ledger tool"),". You should see something like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"$ oasis-core-ledger show_address\noasis1qp8d9kuduq0zutuatjsgltpugxvl38cuaq3gzkmn\nEnsure account address shown on device's screen matches the outputted address.\n")),(0,o.kt)("p",null,"If all of the above works, then the issue is most likely that Chromium does not have the permission to access your Ledger device. Starting with Ubuntu 20.04 the Chromium browser is installed via snap package by default. Snap is more convenient for upstream developers to deploy their software and it also adds additional layer of security by using apparmor. In our case however, it prevents Chromium to access arbitrary USB devices with WebUSB API including your Ledger device. A workaround for this issue is to install Chromium natively using the official ",(0,o.kt)("a",{parentName:"p",href:"https://launchpad.net/~saiarcot895/+archive/ubuntu/chromium-beta"},"Chormium beta PPA")," or the official ",(0,o.kt)("a",{parentName:"p",href:"https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"},"Google Chrome .deb package"),"."),(0,o.kt)("h3",{id:"are-ethereum-and-oasis-wallets-that-different-i-can-use-the-same-mnemonics-with-both-right"},"Are Ethereum and Oasis wallets that different? I can use the same mnemonics with both, right?"),(0,o.kt)("p",null,"Yes, both Oasis and Ethereum wallets make use of the mnemonics as defined in ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki"},"BIP39")," and they even use the same wordlist to derive the keypairs for your wallet. However, they use a different ",(0,o.kt)("strong",{parentName:"p"},"signature scheme and a derivation path"),", so the addresses and the private keys are incompatible."),(0,o.kt)("p",null,"Here's a task for you:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"Visit ",(0,o.kt)("a",{parentName:"li",href:"https://iancoleman.io/bip39/"},"https://iancoleman.io/bip39/")," to generate a BIP39 mnemonic."),(0,o.kt)("li",{parentName:"ol"},"Select ETH token and copy the hex-encoded private key of the first derived account, for example ",(0,o.kt)("inlineCode",{parentName:"li"},"0xab2c4f3bc70d40f12f6030750fe452448b5464114cbfc46704edeef2cd06da74"),"."),(0,o.kt)("li",{parentName:"ol"},"Import the Ethereum-compatible account with the private key obtained above to your Oasis Wallet Browser Extension."),(0,o.kt)("li",{parentName:"ol"},"Notice the Ethereum address of the account, for example ",(0,o.kt)("inlineCode",{parentName:"li"},"0x58c72Eb040Dd0DF10882aA87a39851c21Ae5F331"),"."),(0,o.kt)("li",{parentName:"ol"},'Now in the Account management screen, select this account and click on the "Export private key" button. Confirm the risk warning.'),(0,o.kt)("li",{parentName:"ol"},"You will notice the private key of the Ethereum-compatible account, the hex-encoded address and the very same address encoded in the Oasis Bech32 format, in our case ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qpaj6hznytpvyvalmsdg8vw5fzlpftpw7g7ku0h0"),"."),(0,o.kt)("li",{parentName:"ol"},"Now let's use the private key from step 2 to import the Oasis wallet with. First, convert the hex-encoded key to base64 format, for example by using ",(0,o.kt)("a",{parentName:"li",href:"https://base64.guru/converter/encode/hex"},"this service"),". In our example, that would be ",(0,o.kt)("inlineCode",{parentName:"li"},"qyxPO8cNQPEvYDB1D+RSRItUZBFMv8RnBO3u8s0G2nQ="),"."),(0,o.kt)("li",{parentName:"ol"},"Next, import this base64-encoded private key to the Oasis Wallet Browser Extension."),(0,o.kt)("li",{parentName:"ol"},"You should see your newly imported account and the Oasis address. In our case ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qzaf9zd8rlmchywmkkqmy00wrczstugfxu9q09ng"),"."),(0,o.kt)("li",{parentName:"ol"},"Observe that this account address is different than the Bech32-encoded version of the Ethereum-compatible address despite using the same private key to import the wallet with, because of a different ",(0,o.kt)("em",{parentName:"li"},"signature scheme"),".")),(0,o.kt)("p",null,"As an additional exercise, you can also create an Oasis wallet using the BIP39 mnemonic from the step 1 above. You will notice that the imported account's base64-encoded private key in the account details screen is different from the one in step 7 above. That's because Oasis uses a different ",(0,o.kt)("em",{parentName:"p"},"derivation path")," than Ethereum."),(0,o.kt)("h3",{id:"ledger-derivation-paths"},"Which derivation path should I use on Ledger? ADR 0008 or Legacy?"),(0,o.kt)("p",null,"To convert your mnemonic phrase into a private key for signing trasactions,\neach wallet (hardware or software) performs a ",(0,o.kt)("em",{parentName:"p"},"key derivation"),". The Oasis\nProtocol Foundation standardized the key derivation for official Oasis wallets\nin a document called ",(0,o.kt)("a",{parentName:"p",href:"/adrs/0008-standard-account-key-generation"},"ADR 0008")," back in January 2021. However, the Ledger\nhardware wallet already supported signing transactions at that time using a\ncustom (we now call it ",(0,o.kt)("em",{parentName:"p"},"legacy"),") derivation path which is incompatible with\nthe one defined in ADR 0008. Later, in Oasis app for Ledger v2.3.1 support for\nADR 0008 was added so the wallet can request either derivation from the Ledger\ndevice."),(0,o.kt)("p",null,"The key derivation path defined in ADR 0008 has the following advantages\ncompared to the legacy one:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Derivation path is shorter which results in approximately twice as fast\nkey derivation (and transaction signing) without compromising security."),(0,o.kt)("li",{parentName:"ul"},"In case your Ledger device is broken or lost and you are unable to retrieve\na new one, you will be able to import your Ledger mnemonic and restore your\nprivate key in any Oasis wallet which implements ADR 0008.")),(0,o.kt)("p",null,"For reasons above, we recommend the usage of ADR 0008. However, since there are\nno security considerations at stake, Oasis wallets will support legacy\nderivation on Ledger for the foreseeable future."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"If you happen to import your Ledger mnemonic to a software wallet, consider\nthat mnemonic ",(0,o.kt)("em",{parentName:"p"},"potentially exposed/compromised"),", i.e. not appropriate for a\nhardware wallet mnemonic anymore. If you use a new hardware wallet in the\nfuture, ",(0,o.kt)("strong",{parentName:"p"},"never restore it from the mnemonic that was previously used by any\nsoftware wallet!"))),(0,o.kt)("h3",{id:"the-wallet-gives-me-invalid-keyphrase-error-when-importing-my-wallet-from-mnemonics-how-do-i-solve-it"},"The wallet gives me ",(0,o.kt)("em",{parentName:"h3"},"Invalid keyphrase")," error when importing my wallet from mnemonics. How do I solve it?"),(0,o.kt)("p",null,"Please check that:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"All mnemonics were spelled correctly. Oasis Wallets use English mnemonic phrase words as defined in BIP39. You can find a complete list of valid phrase words ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt"},"here"),"."),(0,o.kt)("li",{parentName:"ul"},"The mnemonics were input in correct order."),(0,o.kt)("li",{parentName:"ul"},"All mnemonics were provided. The keyphrase should be either 12, 15, 18, 21, or 24 words long.")),(0,o.kt)("p",null,"If you checked all of the above and the keyphrase still cannot be imported, please contact Oasis support."),(0,o.kt)("h3",{id:"i-imported-my-wallet-with-mnemonics-the-wallet-should-contain-funds-but-the-balance-is-empty-what-can-i-do"},"I imported my wallet with mnemonics. The wallet should contain funds, but the balance is empty. What can I do?"),(0,o.kt)("p",null,"First, check your wallet address. If the address equals the one that you\nexpected your funds on, then the key derivation from mnemonics worked correctly.\nMake sure you have a working internet connection so that the wallet can fetch\nthe latest balance. Then check that the correct network (Mainnet or Testnet) is\nselected. These are completely separated networks and although the wallet\naddress can be the same, the transactions and consequently the balances may\ndiffer. Finally, there might be a temporary problem with the\n",(0,o.kt)("a",{parentName:"p",href:"https://oasisscan.com"},"Oasis Monitor service")," itself which observes the network\nand indexes transactions. Oasis Wallets rely on that service and once it is back\nup and running, you should be able to see the correct balance."),(0,o.kt)("p",null,"If your wallet address is different than the one you used to transfer your funds\nto, then you used one of the wallets that don't implement the ","[standardized key\nderivation path][adr-8]",". If you were using the BitPie wallet see\n",(0,o.kt)("a",{parentName:"p",href:"#how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet"},"this question"),".\nLedger hardware wallet users should refer to\n",(0,o.kt)("a",{parentName:"p",href:"#ledger-derivation-paths"},"this question"),"."),(0,o.kt)("p",null,"If you still cannot access your funds, please contact Oasis support on ",(0,o.kt)("a",{parentName:"p",href:"https://oasis.io/discord"},"#wallets\nDiscord channel"),"."),(0,o.kt)("h3",{id:"i-sent-my-rose-to-binancestaking-address--are-they-staked-are-they-lost-what-can-i-do"},"I sent my ROSE to BinanceStaking address. Are they staked? Are they lost? What can I do?"),(0,o.kt)("p",null,"If you just make a ",(0,o.kt)("strong",{parentName:"p"},"Send")," transaction to BinanceStaking address ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis1qqekv2ymgzmd8j2s2u7g0hhc7e77e654kvwqtjwm")," then your ROSE coins are not staked. They are now owned by BinanceStaking, which means they are not lost but only owned and managed by them. In this case, you should contact Binance via their ",(0,o.kt)("a",{parentName:"p",href:"https://www.binance.com/en/support"},"Support Center")," or ",(0,o.kt)("a",{parentName:"p",href:"https://www.binance.com/en/chat"},"Submit a request"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Sending ROSE is different than staking it! With the staking transaction you ",(0,o.kt)("strong",{parentName:"p"},"lend")," your ROSE to the chosen validator and you are rewarded for that. ",(0,o.kt)("strong",{parentName:"p"},"Sending")," your ROSE to the receiving address you enter means that only the person who owns the private key (e.g. mnemonics) of that receiving address can manage these tokens and no one else. To learn more, read the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/staking-and-delegating"},"Staking and Delegating chapter"),".")),(0,o.kt)("h3",{id:"i-withdrew-rose-from-emerald-to-an-exchange-binance-kucoin-but-my-deposit-is-not-there-what-should-i-do"},"I withdrew ROSE from Emerald to an exchange (Binance, KuCoin), but my deposit is not there. What should I do?"),(0,o.kt)("p",null,"Withdrawals from Emerald are slightly different from regular ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.Transfer")," transactions used to send ROSE on the consensus layer. If you withdrew your ROSE directly to an exchange and you were not funded there, contact the exchange support and provide them the link to your account on the ",(0,o.kt)("a",{parentName:"p",href:"https://www.oasisscan.com"},"Oasis Scan")," where they can verify all transactions. To learn more about this issue, read the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},"How to Transfer ROSE to ParaTime section"),"."))}p.isMDXComponent=!0},7018:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/mainscreen-444c4a14f5bcc45a74a9697a0a1e9b80.png"},2260:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/show_private_key-bf6f89e80fb50ffa6728980e19d7d96b.png"}}]); \ No newline at end of file diff --git a/assets/js/0e099be9.93acec0f.js b/assets/js/0e099be9.93acec0f.js new file mode 100644 index 0000000000..2457481987 --- /dev/null +++ b/assets/js/0e099be9.93acec0f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7861],{3905:(e,t,o)=>{o.d(t,{Zo:()=>c,kt:()=>m});var n=o(7294);function a(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function s(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function r(e){for(var t=1;t=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var l=n.createContext({}),i=function(e){var t=n.useContext(l),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},c=function(e){var t=i(e.components);return n.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var o=e.components,a=e.mdxType,s=e.originalType,l=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=i(o),h=a,m=d["".concat(l,".").concat(h)]||d[h]||u[h]||s;return o?n.createElement(m,r(r({ref:t},c),{},{components:o})):n.createElement(m,r({ref:t},c))}));function m(e,t){var o=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var s=o.length,r=new Array(s);r[0]=h;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p[d]="string"==typeof e?e:a,r[1]=p;for(var i=2;i{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>s,metadata:()=>p,toc:()=>i});var n=o(7462),a=(o(7294),o(3905));const s={},r="DAO Contract",p={unversionedId:"dapp/opl/host",id:"dapp/opl/host",title:"DAO Contract",description:"Let's start with a smart contract that describes a basic DAO, DAOV1.sol, with a",source:"@site/docs/dapp/opl/host.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/host",permalink:"/dapp/opl/host",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/host.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Setup",permalink:"/dapp/opl/setup"},next:{title:"Ballot Contract",permalink:"/dapp/opl/enclave"}},l={},i=[{value:"Base Contract",id:"base-contract",level:2},{value:"What is different with OPL?",id:"what-is-different-with-opl",level:2},{value:"How does OPL do this?",id:"how-does-opl-do-this",level:3},{value:"Endpoints? Why not Solidity events?",id:"endpoints-why-not-solidity-events",level:3},{value:"Let's see the code",id:"lets-see-the-code",level:3},{value:"Host",id:"host",level:4},{value:"Constructor",id:"constructor",level:4}],c={toc:i},d="wrapper";function u(e){let{components:t,...o}=e;return(0,a.kt)(d,(0,n.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"dao-contract"},"DAO Contract"),(0,a.kt)("p",null,"Let's start with a smart contract that describes a basic DAO, ",(0,a.kt)("inlineCode",{parentName:"p"},"DAOV1.sol"),", with a\nmapping of proposals before we consider the OPL differences."),(0,a.kt)("h2",{id:"base-contract"},"Base Contract"),(0,a.kt)("p",null,"Inside your ",(0,a.kt)("inlineCode",{parentName:"p"},"contracts/")," directory, create a ",(0,a.kt)("inlineCode",{parentName:"p"},"DAOV1.sol")," file. You may have\nalready deployed a similar contract to your home network such as BNB or\nPolygon."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},'// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";\n\ntype ProposalId is bytes32;\n\nstruct ProposalParams {\n string ipfsHash;\n uint16 numChoices;\n bool publishVotes;\n}\n\ncontract DAOV1 {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n error AlreadyExists();\n error NoChoices();\n error TooManyChoices();\n\n event ProposalClosed(ProposalId id, uint256 topChoice);\n\n struct Proposal {\n bool active;\n uint16 topChoice;\n ProposalParams params;\n }\n\n struct ProposalWithId {\n ProposalId id;\n Proposal proposal;\n }\n\n mapping(ProposalId => Proposal) public proposals;\n EnumerableSet.Bytes32Set private activeProposals;\n ProposalId[] private pastProposals;\n\n constructor() {}\n\n function createProposal(ProposalParams calldata _params) external payable returns (ProposalId) {\n bytes32 proposalHash = keccak256(abi.encode(msg.sender, _params));\n ProposalId proposalId = ProposalId.wrap(proposalHash);\n if (_params.numChoices == 0) revert NoChoices();\n if (_params.numChoices > type(uint16).max) revert TooManyChoices();\n if (proposals[proposalId].active) revert AlreadyExists();\n Proposal storage proposal = proposals[proposalId];\n proposal.params = _params;\n proposal.active = true;\n activeProposals.add(proposalHash);\n return proposalId;\n }\n\n function getActiveProposals(\n uint256 _offset,\n uint256 _count\n ) external view returns (ProposalWithId[] memory _proposals) {\n if (_offset + _count > activeProposals.length()) {\n _count = activeProposals.length() - _offset;\n }\n _proposals = new ProposalWithId[](_count);\n for (uint256 i; i < _count; ++i) {\n ProposalId id = ProposalId.wrap(activeProposals.at(_offset + i));\n _proposals[i] = ProposalWithId({id: id, proposal: proposals[id]});\n }\n }\n\n function getPastProposals(\n uint256 _offset,\n uint256 _count\n ) external view returns (ProposalWithId[] memory _proposals) {\n if (_offset + _count > pastProposals.length) {\n _count = pastProposals.length - _offset;\n }\n _proposals = new ProposalWithId[](_count);\n for (uint256 i; i < _count; ++i) {\n ProposalId id = pastProposals[_offset + i];\n _proposals[i] = ProposalWithId({id: id, proposal: proposals[id]});\n }\n }\n}\n')),(0,a.kt)("p",null,"Instead of storing complete ballot proposals on the network, we will use\n",(0,a.kt)("a",{parentName:"p",href:"https://ipfs.tech"},"IPFS"),". Our smart contract will refer to a pinned\n",(0,a.kt)("a",{parentName:"p",href:"https://docs.ipfs.tech/concepts/lifecycle/#_1-content-addressable-representation"},"IPFS file")," by its ",(0,a.kt)("a",{parentName:"p",href:"https://docs.ipfs.tech/concepts/hashing/"},"hash"),"."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},"struct ProposalParams {\n string ipfsHash;\n uint16 numChoices;\n bool publishVotes;\n}\n")),(0,a.kt)("p",null,"Our very simple DAO contract creates proposals and manages them, allowing\nboth active and past proposals to be queried externally through methods\n",(0,a.kt)("inlineCode",{parentName:"p"},"getActiveProposals")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"getPastProposals"),". This would be sufficient on a\nsingle chain, and it is possible to develop confidential applications without\nbridges, relying solely on ",(0,a.kt)("a",{parentName:"p",href:"/dapp/sapphire/"},"Sapphire"),". However, we will proceed\nto demonstrate the cross-chain capabilities of OPL."),(0,a.kt)("h2",{id:"what-is-different-with-opl"},"What is different with OPL?"),(0,a.kt)("p",null,"OPL leverages ",(0,a.kt)("a",{parentName:"p",href:"https://celer.network"},"Celer"),"'s inter-chain ",(0,a.kt)("a",{parentName:"p",href:"https://im-docs.celer.network/developer/celer-im-overview"},"messaging"),"\ncapabilities in order to connect smart contracts deployed on a home network\nsuch as Polygon, or BNB, with the privacy preserving smart contracts deployed\non Sapphire."),(0,a.kt)("p",null,"You will not need to learn how Celer Inter-chain Message (IM) works in order to\nuse OPL, but if you would like to learn more, you can see that OPL realizes\nthe Celer IM interface through the abstraction of an ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L35-L45"},"Endpoint"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},"interface ICelerMessageBus {\n function feeBase() external view returns (uint256);\n\n function feePerByte() external view returns (uint256);\n\n function sendMessage(\n address _host,\n uint256 _hostChainId,\n bytes calldata _message\n ) external payable;\n}\n")),(0,a.kt)("p",null,"which allows us to use this bridge ",(0,a.kt)("a",{parentName:"p",href:"https://im-docs.celer.network/developer/development-guide/contract-framework#send-message"},"function"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},"function sendMessage(\n address _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n uint256 _fee\n) internal\n")),(0,a.kt)("p",null,"In production, you can see the deployed ",(0,a.kt)("a",{parentName:"p",href:"https://explorer.sapphire.oasis.io/address/0x9B36f165baB9ebe611d491180418d8De4b8f3a1f/transactions"},"cBridge contract")," and\n",(0,a.kt)("a",{parentName:"p",href:"https://explorer.sapphire.oasis.io/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D/transactions"},"MessageBus contract"),"."),(0,a.kt)("h3",{id:"how-does-opl-do-this"},"How does OPL do this?"),(0,a.kt)("p",null,"We can ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L76-L84"},"register")," functions with endpoints in order to simplify our code.\nEndpoints are effectively callbacks which listen to messages from the enclaved\nsmart contract."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},"function registerEndpoint(\n bytes memory _method,\n function(bytes calldata) returns (Result) _cb\n) internal {\n // This is a waste of an SLOAD, but the alternative before immutable arrays\n // (https://github.com/ethereum/solidity/issues/12587) land is terribly verbose.\n // This can be fixed once gas usage becomes a problem.\n endpoints[bytes4(keccak256(_method))] = _cb;\n}\n")),(0,a.kt)("p",null,"Under the hood, a ",(0,a.kt)("inlineCode",{parentName:"p"},"postMessage")," function ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L91-L119"},"sends")," the message using the Celer\nMessage Bus. If you would prefer using a different bridging partner, this\npattern will provide you a place to start that integration."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"}," ICelerMessageBus(messageBus).sendMessage{value: fee}(\n remote,\n remoteChainId,\n envelope\n );\n")),(0,a.kt)("h3",{id:"endpoints-why-not-solidity-events"},"Endpoints? Why not Solidity events?"),(0,a.kt)("p",null,"Events in Solidity are non-confidential and do not allow cross-chain\ncommunication. For this reason, OPL uses ",(0,a.kt)("em",{parentName:"p"},"endpoints")," for passing messages\ncross-chain. For example, this function below will listen to such a message and\nclose the proposal."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"}," function _oplBallotClosed(bytes calldata _args) internal returns (Result) {\n (ProposalId proposalId, uint16 topChoice) = abi.decode(_args, (ProposalId, uint16));\n proposals[proposalId].topChoice = topChoice;\n proposals[proposalId].active = false;\n activeProposals.remove(ProposalId.unwrap(proposalId));\n pastProposals.push(proposalId);\n emit ProposalClosed(proposalId, topChoice);\n return Result.Success;\n }\n")),(0,a.kt)("h3",{id:"lets-see-the-code"},"Let's see the code"),(0,a.kt)("p",null,"Let's see OPL at work. We can add our own implementation of event handling to\nprocess cross-chain messages. Let's make the following changes to ",(0,a.kt)("inlineCode",{parentName:"p"},"DAOV1.sol"),"."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-diff"},'diff --git a/backend/contracts/DAOV1.sol b/backend/contracts/DAOV1.sol\nindex 21ea93e..827d80a 100644\n--- a/backend/contracts/DAOV1.sol\n+++ b/backend/contracts/DAOV1.sol\n@@ -1,6 +1,7 @@\n // SPDX-License-Identifier: MIT\n pragma solidity ^0.8.0;\n \n+import {Host, Result} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol";\n import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";\n \n type ProposalId is bytes32;\n@@ -11,7 +12,7 @@ struct ProposalParams {\n bool publishVotes;\n }\n\n-contract DAOV1 {\n+contract DAOV1 is Host {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n \n error AlreadyExists();\n@@ -35,7 +36,9 @@ contract DAOV1 {\n EnumerableSet.Bytes32Set private activeProposals;\n ProposalId[] private pastProposals;\n \n- constructor() {}\n+ constructor(address _ballotBox) Host(_ballotBox) {\n+ registerEndpoint("ballotClosed", _oplBallotClosed);\n+ }\n \n function createProposal(ProposalParams calldata _params) external payable returns (ProposalId) {\n bytes32 proposalHash = keccak256(abi.encode(msg.sender, _params));\n@@ -47,6 +50,7 @@ contract DAOV1 {\n proposal.params = _params;\n proposal.active = true;\n activeProposals.add(proposalHash);\n+ postMessage("createBallot", abi.encode(proposalId, _params));\n return proposalId;\n }\n \n@@ -77,4 +81,14 @@ contract DAOV1 {\n _proposals[i] = ProposalWithId({id: id, proposal: proposals[id]});\n }\n }\n+\n+ function _oplBallotClosed(bytes calldata _args) internal returns (Result) {\n+ (ProposalId proposalId, uint16 topChoice) = abi.decode(_args, (ProposalId, uint16));\n+ proposals[proposalId].topChoice = topChoice;\n+ proposals[proposalId].active = false;\n+ activeProposals.remove(ProposalId.unwrap(proposalId));\n+ pastProposals.push(proposalId);\n+ emit ProposalClosed(proposalId, topChoice);\n+ return Result.Success;\n+ }\n }\n')),(0,a.kt)("h4",{id:"host"},"Host"),(0,a.kt)("p",null,"A ",(0,a.kt)("em",{parentName:"p"},"host")," contract in our terminology is just a smart contract that extends the\n",(0,a.kt)("inlineCode",{parentName:"p"},"Host")," contract ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/opl/Host.sol"},"provided")," and deployed on a home network such as BNB or\nPolygon with a reference to the Sapphire network where our ",(0,a.kt)("em",{parentName:"p"},"enclave"),"\n(privacy-preserving) smart contract will reside."),(0,a.kt)("h4",{id:"constructor"},"Constructor"),(0,a.kt)("p",null,"We provide the address of the confidential (also known as ",(0,a.kt)("em",{parentName:"p"},"enclave"),") smart\ncontract deployed on the Oasis Sapphire as a constructor parameter to the\n",(0,a.kt)("em",{parentName:"p"},"host")," smart contract."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},' constructor(address _ballotBox) Host(_ballotBox) {\n registerEndpoint("ballotClosed", _oplBallotClosed);\n }\n')))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0e9cd926.4684cb82.js b/assets/js/0e9cd926.4684cb82.js new file mode 100644 index 0000000000..dc649be1b4 --- /dev/null +++ b/assets/js/0e9cd926.4684cb82.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2072],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>g});var o=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,o)}return a}function i(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var l=o.createContext({}),d=function(e){var t=o.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},p=function(e){var t=d(e.components);return o.createElement(l.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},v=o.forwardRef((function(e,t){var a=e.components,n=e.mdxType,r=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=d(a),v=n,g=c["".concat(l,".").concat(v)]||c[v]||u[v]||r;return a?o.createElement(g,i(i({ref:t},p),{},{components:a})):o.createElement(g,i({ref:t},p))}));function g(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=a.length,i=new Array(r);i[0]=v;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:n,i[1]=s;for(var d=2;d{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var o=a(7462),n=(a(7294),a(3905));const r={},i="ADR 0020: Governance Support for Delegator Votes",s={unversionedId:"adrs/0020-governance-delegator-votes",id:"adrs/0020-governance-delegator-votes",title:"ADR 0020: Governance Support for Delegator Votes",description:"Component",source:"@site/docs/adrs/0020-governance-delegator-votes.md",sourceDirName:"adrs",slug:"/adrs/0020-governance-delegator-votes",permalink:"/adrs/0020-governance-delegator-votes",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0020-governance-delegator-votes.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0017: ParaTime Application Standard Proposal Process",permalink:"/adrs/0017-app-standards"},next:{title:"ADR 0021: Forward-Secret Ephemeral Secrets",permalink:"/adrs/0021-keymanager-ephemeral-secrets"}},l={},d=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Casting Votes",id:"casting-votes",level:3},{value:"Alternative solutions",id:"alternative-solutions",level:4},{value:"Vote tallying",id:"vote-tallying",level:3},{value:"Alternative Vote Tallying procedures",id:"alternative-vote-tallying-procedures",level:4},{value:"Implementations in other chains",id:"implementations-in-other-chains",level:4},{value:"Benchmarks",id:"benchmarks",level:4},{value:"Pruning",id:"pruning",level:3},{value:"Voting via messages",id:"voting-via-messages",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3}],p={toc:d},c="wrapper";function u(e){let{components:t,...r}=e;return(0,n.kt)(c,(0,o.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"adr-0020-governance-support-for-delegator-votes"},"ADR 0020: Governance Support for Delegator Votes"),(0,n.kt)("h2",{id:"component"},"Component"),(0,n.kt)("p",null,"Oasis Core"),(0,n.kt)("h2",{id:"changelog"},"Changelog"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"2022-11-07: Minor updates. Added Cosmos-SDK implementation note."),(0,n.kt)("li",{parentName:"ul"},"2022-11-03: Added benchmarks, minor updates."),(0,n.kt)("li",{parentName:"ul"},"2022-11-02: Initial draft.")),(0,n.kt)("h2",{id:"status"},"Status"),(0,n.kt)("p",null,"Accepted"),(0,n.kt)("h2",{id:"context"},"Context"),(0,n.kt)("p",null,"With the current governance voting mechanism (",(0,n.kt)("a",{parentName:"p",href:"/adrs/0004-runtime-governance"},"ADR 04"),"), only the active\nvalidator set is participating in voting. This means that the validators are\nvoting on behalf of all their delegators. This ADR proposes a change so that\neach delegator is able to vote with its own stake. The delegators vote acts as\nan override of the validator vote."),(0,n.kt)("h2",{id:"decision"},"Decision"),(0,n.kt)("h3",{id:"casting-votes"},"Casting Votes"),(0,n.kt)("p",null,"In the current implementation the submitter of a vote needs to be a part of the\nactive validator committee at the time the vote is cast. This requirement is\nrelaxed so that additionally anyone with a delegation to an active validator\ncommittee entity can vote."),(0,n.kt)("p",null,"This change requires an efficient ",(0,n.kt)("inlineCode",{parentName:"p"},"staking.DelegationsFor")," query to obtain a\nlist of accounts the submitter is delegating to. Staking state is updated with:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-go"},"// delegationKeyReverseFmt is the key format used for reverse mapping of\n// delegations (delegator address, escrow address).\n//\n// Value is CBOR-serialized delegation.\ndelegationKeyReverseFmt = keyformat.New(0x5A, &staking.Address{}, &staking.Address{})\n")),(0,n.kt)("p",null,(0,n.kt)("inlineCode",{parentName:"p"},"state.SetDelegation")," function is updated to store both ",(0,n.kt)("inlineCode",{parentName:"p"},"delegationKeyFmt")," and\nthe reverse ",(0,n.kt)("inlineCode",{parentName:"p"},"delegationKeyReverseFmt"),". ",(0,n.kt)("inlineCode",{parentName:"p"},"DelegationsFor")," query function is\nupdated to use the added reverse mapping."),(0,n.kt)("p",null,"For completeness the same can be done for debonding delegations, although not\nnecessary for the governance changes proposed in this ADR."),(0,n.kt)("h4",{id:"alternative-solutions"},"Alternative solutions"),(0,n.kt)("p",null,"Possible alternatives that would avoid adding the reverse mapping are:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Querying ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsTo")," for each validator. This results in ",(0,n.kt)("inlineCode",{parentName:"li"},"num_validators"),"\nqueries per cast vote transaction which is still too much."),(0,n.kt)("li",{parentName:"ul"},"Allowing anyone to cast votes. Potentially a viable solution, but this could\nresult in the number of voters growing uncontrollably large. This might be ok,\nif the vote tallying procedure would ignore those votes. However the votes\nstate could still grow problematically big.")),(0,n.kt)("h3",{id:"vote-tallying"},"Vote tallying"),(0,n.kt)("p",null,"When a proposal closes, the vote tallying procedure changes to:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre"},"# Two-pass over votes approach.\n1 Tally up the validator votes (as it is already implemented) # First pass.\n2 For each of the voters do: # Second pass.\n3 For each of the entities voter delegates to:\n4 Skip non validator entities\n5 Skip if voter's vote matches the delegation entity vote\n6 Compute stake from the delegation shares\n4 If delegation entity voted, subtract the stake from the delegation entity vote tally\n5 Add computed stake to the voter's vote tally\n")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Possbile variant: instead of using ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," query in step 3), a map of\nall validator delegators could be prebuild, by using ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationTo")," for each\nof the validators. Even with the efficient ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," query, this can be\nbeneficial IF the number of voters is large.")),(0,n.kt)("p",null,"This procedure iterates over all voters and can be beneficial if the number of\nvoters is relatively low compared to the number of all validator delegators."),(0,n.kt)("h4",{id:"alternative-vote-tallying-procedures"},"Alternative Vote Tallying procedures"),(0,n.kt)("p",null,"A possible alternative would be to iterate over the delegators-validator sets:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre"},"# Delegators-validator pass approach.\n1 Precompute stakes for all delegators to validators from shares.\n2 For each validator\n3 For each delegator to the validator\n4 IF validator and delegators votes match (or delegator didn't vote)\n5 Add delegator stake to the validator's vote (or nothing if validator didn't vote)\n6 IF validator and delegator vote don't match\n7 Add delegator stake to the delegator's vote (or nothing if delegator didn't vote)\n")),(0,n.kt)("p",null,"The voting procedure now iterates over all delegators of the active validator\nset. The amount of work is somewhat predictable as it doesn't depend on the\nnumber of voters but on the delegators-to-validator sets. However the number of\nvotes is bound by the size of the delegators-to-validator set and in realistic\nscenario likely much smaller."),(0,n.kt)("h4",{id:"implementations-in-other-chains"},"Implementations in other chains"),(0,n.kt)("p",null,"Cosmos-SDK uses a similar approach to the proposed solution in the ADR. The\ntallying iterates over voters, their delegations and validators. For detailed\nimplementation see: ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/cosmos/cosmos-sdk/blob/dc004c85f2e8b8fb4f66caac2703228c5bf544cf/x/gov/keeper/tally.go#L37-L90"},"Cosmos-SDK Vote Tallying Code"),". The voting itself is\nlimited to delegators (similar as proposed in this document)."),(0,n.kt)("h4",{id:"benchmarks"},"Benchmarks"),(0,n.kt)("p",null,"The Vote Tallying procedure variants were benchmarked on mainnet data."),(0,n.kt)("p",null,"Some basic stats from mainnet:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"120 validators"),(0,n.kt)("li",{parentName:"ul"},"~49500 eligible voters (unique delegators to validators)"),(0,n.kt)("li",{parentName:"ul"},"average number of delegations-to per account is 1")),(0,n.kt)("p",null,"The variants were benchmarked in scenarios with different number of voters. In\nall scenarios the mainnet consensus state was used, only the number of\n(simulated) voters varied. All votes were eligible (had at least one delegation\nto an active validator) and all of the delegator votes did override the\nvalidator votes."),(0,n.kt)("p",null,"The three tested variants were:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},'"Two pass over voters (optimized DelegationsFor)" - as described in the\nproposed Vote tallying solution. Reverse mapping key is used for the\n',(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," queries (described in Casting Votes section)."),(0,n.kt)("li",{parentName:"ul"},'"Two pass over voters (pre-build validator escrow)" - as described in the\nproposed Vote tallying solution with modification of prebuilding a map of all\nvalidator delegators (mentioned in the "Possible variant" section).'),(0,n.kt)("li",{parentName:"ul"},'"Validator-delegators" - as described in the alternatives section.')),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Two pass over voters (optimized DelegationsFor)",src:a(9605).Z,width:"720",height:"576"}),"\n",(0,n.kt)("img",{alt:"Two pass over voters (pre-build validators escrow)",src:a(8054).Z,width:"720",height:"576"}),"\n",(0,n.kt)("img",{alt:"Validator-delegators",src:a(9581).Z,width:"720",height:"576"})),(0,n.kt)("p",null,"The above results show that:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Two-pass approach (querying ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," for every voter) is fastest up to\nabout 25000 voters for a proposal. In the worst case (every eligible voter\nvoted) it is about twice as slow as the alternatives. In that case the\ntallying took about 3 seconds."),(0,n.kt)("li",{parentName:"ul"},'The two-pass approach using pre-built map of all validator delegators is\ncomparable to the "Validator-delegators" procedure. This makes sense as in\nboth cases the main work is done in querying the delegators of validators.')),(0,n.kt)("p",null,"In reality, the number of voters will likely be small compared to the eligible\nset of all delegators, so the two-pass approach (with querying ",(0,n.kt)("inlineCode",{parentName:"p"},"DelegationsFor"),"\nfor every voter) seems to make the most sense."),(0,n.kt)("p",null,"If number of voters ever becomes problematic, the method could also implement a\nheuristic to use the prebuilt validator-delegators map when the number of voters\nis large (e.g. number of voters > 1/2 eligible delegators), but at the moment\nthere is no efficient way to query the number of all delegators."),(0,n.kt)("h3",{id:"pruning"},"Pruning"),(0,n.kt)("p",null,"With the possibility of increased number of votes per proposal a pruning of\nvotes can be implemented. Votes for a proposal can be pruned as soon as the\nfirst block after the proposal is closed. Because proposal is closed in the\n",(0,n.kt)("inlineCode",{parentName:"p"},"EndBlock")," state (which includes votes received in this last block), the pruning\nshould not be done before the block after, so that the exact state at the time\nof the closing can be queried."),(0,n.kt)("h3",{id:"voting-via-messages"},"Voting via messages"),(0,n.kt)("p",null,"Delegator can also be a runtime. For enabling runtimes to vote, casting votes\nshould also be supported via runtime messages."),(0,n.kt)("p",null,"Roothash message type is updated to include governance message field:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-go"},'type Message struct {\n Staking *StakingMessage `json:"staking,omitempty"`\n Registry *RegistryMessage `json:"registry,omitempty"`\n Governance *GovernanceMessage `json:"governance,omitempty"`\n}\n\n// GovernanceMessage is a governance message that allows a runtime to perform governance operations.\ntype GovernanceMessage struct {\n cbor.Versioned\n\n CastVote *governance.ProposalVote `json:"cast_vote,omitempty"`\n}\n')),(0,n.kt)("p",null,"Governance backend is updated to handle the cast vote message."),(0,n.kt)("p",null,"For completeness, support for submitting proposals via runtime messages can also\nbe implemented."),(0,n.kt)("h2",{id:"consequences"},"Consequences"),(0,n.kt)("h3",{id:"positive"},"Positive"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Delegators are able to override validators vote. In the case of unresponsive\nvalidators this increases the voting participation."),(0,n.kt)("li",{parentName:"ul"},"Delegators are able to vote with their own stake."),(0,n.kt)("li",{parentName:"ul"},"(if implemented) Staking ",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," queries are now efficient and don't\nrequire scanning the full delegations state.")),(0,n.kt)("h3",{id:"negative"},"Negative"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"This increases the complexity of the vote tallying procedure."),(0,n.kt)("li",{parentName:"ul"},"This increases the size of the governance votes state."),(0,n.kt)("li",{parentName:"ul"},"This increases the complexity and size of the consensus staking state if the\n",(0,n.kt)("inlineCode",{parentName:"li"},"DelegationsFor")," reverse mapping is implemented.")),(0,n.kt)("h3",{id:"neutral"},"Neutral"))}u.isMDXComponent=!0},9605:(e,t,a)=>{a.d(t,{Z:()=>o});const o=a.p+"assets/images/0020-bench1-b406915bd71a67020495939d2c89075b.png"},8054:(e,t,a)=>{a.d(t,{Z:()=>o});const o=a.p+"assets/images/0020-bench2-1cc7812d2c015e4a03288cc6f165bb4e.png"},9581:(e,t,a)=>{a.d(t,{Z:()=>o});const o=a.p+"assets/images/0020-bench3-8741906103d267c9119ac66826d39bd1.png"}}]); \ No newline at end of file diff --git a/assets/js/0f0ebacb.f432a5a9.js b/assets/js/0f0ebacb.f432a5a9.js new file mode 100644 index 0000000000..b7d0d4fa5b --- /dev/null +++ b/assets/js/0f0ebacb.f432a5a9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5776],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=a.createContext({}),u=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=u(e.components);return a.createElement(s.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},g=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=u(n),g=i,m=d["".concat(s,".").concat(g)]||d[g]||c[g]||r;return n?a.createElement(m,o(o({ref:t},p),{},{components:n})):a.createElement(m,o({ref:t},p))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,o=new Array(r);o[0]=g;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:i,o[1]=l;for(var u=2;u{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>l,toc:()=>u});var a=n(7462),i=(n(7294),n(3905));const r={},o="Reproducibility",l={unversionedId:"paratime/reproducibility",id:"paratime/reproducibility",title:"Reproducibility",description:"If you wish to build paratime binaries yourself, you can use the",source:"@site/docs/paratime/reproducibility.md",sourceDirName:"paratime",slug:"/paratime/reproducibility",permalink:"/paratime/reproducibility",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/reproducibility.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"paratime",previous:{title:"Modules",permalink:"/paratime/modules"}},s={},u=[{value:"Environment Setup",id:"environment-setup",level:2},{value:"Running the Image",id:"running-the-image",level:2},{value:"Building",id:"building",level:2},{value:"ELF",id:"elf",level:3},{value:"Intel SGX",id:"intel-sgx",level:3},{value:"Generating Bundles",id:"generating-bundles",level:2},{value:"Multi-step SGX Signing Example",id:"multi-step-sgx-signing-example",level:3},{value:"Generate a key",id:"generate-a-key",level:4},{value:"Generate signing data for your enclave",id:"generate-signing-data-for-your-enclave",level:4},{value:"Sign the SIGSTRUCT hash",id:"sign-the-sigstruct-hash",level:5},{value:"Attach the singed SIGSTRUCT to the bundle",id:"attach-the-singed-sigstruct-to-the-bundle",level:5}],p={toc:u},d="wrapper";function c(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"reproducibility"},"Reproducibility"),(0,i.kt)("p",null,"If you wish to build paratime binaries yourself, you can use the\nenvironment provided as part of the SDK. This way you can also verify\nthat the binaries match the ones running on the network."),(0,i.kt)("p",null,"The steps below show how to build the test runtimes provided in the\n",(0,i.kt)("inlineCode",{parentName:"p"},"oasis-sdk")," sources; steps for other paratimes should be similar."),(0,i.kt)("h2",{id:"environment-setup"},"Environment Setup"),(0,i.kt)("p",null,"The build environment is provided as a Docker image containing all the\nnecessary tools. Refer to your system's documentation for pointers on\ninstalling software."),(0,i.kt)("p",null,"The runtime sources need to be mounted into the container so prepare a\ndirectory first, such as:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"git clone https://github.com/oasisprotocol/oasis-sdk.git\n")),(0,i.kt)("h2",{id:"running-the-image"},"Running the Image"),(0,i.kt)("p",null,"The images are available in the ",(0,i.kt)("inlineCode",{parentName:"p"},"oasisprotocol/runtime-builder"),"\nrepository on Docker Hub and are tagged with the same version numbers as\nreleases of the SDK. To pull the image and run a container with it, run\nthe following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"docker run -t -i -v /home/user/oasis-sdk:/src oasisprotocol/runtime-builder:main /bin/bash\n")),(0,i.kt)("p",null,"where:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"/home/user/oasis-sdk")," is the absolute path to the directory\ncontaining the SDK sources (or other paratimes - you likely do not need\nto download the SDK separately if you're building other paratimes), and"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"main")," is a release of the SDK - the documentation of the paratime\nyou're trying to build should mention the version required.")),(0,i.kt)("p",null,"This gives you a root shell in the container. Rust and Cargo are\ninstalled in ",(0,i.kt)("inlineCode",{parentName:"p"},"/cargo"),", Go in ",(0,i.kt)("inlineCode",{parentName:"p"},"/go"),", and the sources to your paratime are\navailable in ",(0,i.kt)("inlineCode",{parentName:"p"},"/src"),"."),(0,i.kt)("h2",{id:"building"},"Building"),(0,i.kt)("h3",{id:"elf"},"ELF"),(0,i.kt)("p",null,"Simply build the paratime in release mode using:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"cargo build --release\n")),(0,i.kt)("p",null,"The resulting binaries will be in ",(0,i.kt)("inlineCode",{parentName:"p"},"/src/target/release/"),"."),(0,i.kt)("h3",{id:"intel-sgx"},"Intel SGX"),(0,i.kt)("p",null,"Follow the normal build procedure for your paratime. For the testing\nruntimes in the SDK, e.g.:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"cd /src\ncargo build --release --target x86_64-fortanix-unknown-sgx\n")),(0,i.kt)("p",null,"After this step is complete, the binaries will be in\n",(0,i.kt)("inlineCode",{parentName:"p"},"/src/target/x86_64-fortanix-unknown-sgx/release/"),"."),(0,i.kt)("p",null,"To produce the sgxs format needed on the Oasis network, change directory\nto where a particular runtime's ",(0,i.kt)("inlineCode",{parentName:"p"},"Cargo.toml")," file is and run the\nfollowing command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"cargo elf2sgxs --release\n")),(0,i.kt)("p",null,"It is necessary to change directories first because the tool does not\ncurrently support cargo workspaces."),(0,i.kt)("p",null,"The resulting binaries will have the ",(0,i.kt)("inlineCode",{parentName:"p"},".sgxs")," extension."),(0,i.kt)("h2",{id:"generating-bundles"},"Generating Bundles"),(0,i.kt)("p",null,"Oasis Core since version 22.0 distributes bundles in the Oasis Runtime Container\nformat which is basically a zip archive with some metadata attached. This makes\nit easier for node operators to configure paratimes. To ease creation of such\nbundles from built binaries and metadata, you can use the ",(0,i.kt)("inlineCode",{parentName:"p"},"orc")," tool provided by\nthe SDK."),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"You can install the ",(0,i.kt)("inlineCode",{parentName:"p"},"orc")," utility by running:"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"go install github.com/oasisprotocol/oasis-sdk/tools/orc@latest\n"))),(0,i.kt)("p",null,"The same bundle can contain both ELF and Intel SGX artifacts. To create a bundle\nuse the following command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc init path/to/elf-binary\n")),(0,i.kt)("p",null,"When including Intel SGX artifacts you may additionally specify:"),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"All bundles, even Intel SGX ones, are required to include an ELF binary of the\nparatime. This binary is used for client nodes that don't have SGX support.")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc init path/to/elf-binary --sgx-executable path/to/binary.sgxs --sgx-signature path/to/binary.sig\n")),(0,i.kt)("p",null,"You can omit the signature initially and add it later by using:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc sgx-set-sig bundle.orc path/to/binary.sig\n")),(0,i.kt)("h3",{id:"multi-step-sgx-signing-example"},"Multi-step SGX Signing Example"),(0,i.kt)("p",null,"Multi-step signing allows enclave signing keys to be kept offline, preferrably\nin some HSM. The following example uses ",(0,i.kt)("inlineCode",{parentName:"p"},"openssl")," and a locally generated key as\nan example, however, it is suggested that the key be stored in a more secure\nlocation than in plaintext on disk."),(0,i.kt)("h4",{id:"generate-a-key"},"Generate a key"),(0,i.kt)("p",null,"We will generate a valid key for enclave signing. This must be a\n3072-bit RSA key with a public exponent of 3. Do this like so:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"openssl genrsa -3 3072 > private.pem\n")),(0,i.kt)("p",null,"We will also need the public key in a later step so let's also generate this\nnow."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"openssl rsa -in private.pem -pubout > public.pem\n")),(0,i.kt)("h4",{id:"generate-signing-data-for-your-enclave"},"Generate signing data for your enclave"),(0,i.kt)("p",null,"Generating signing data is done with the ",(0,i.kt)("inlineCode",{parentName:"p"},"orc sgx-gen-sign-data")," subcommand,\nlike so:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc sgx-gen-sign-data [options] bundle.orc\n")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"See ",(0,i.kt)("inlineCode",{parentName:"p"},"orc sgx-gen-sign-data --help")," for details on available options.")),(0,i.kt)("p",null,"For purposes of this example, let's assume your bundle is named ",(0,i.kt)("inlineCode",{parentName:"p"},"bundle.orc"),".\nYou would generate data to sign like so:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc sgx-gen-sign-data bundle.orc > sigstruct.sha256.bin\n")),(0,i.kt)("p",null,"The output file ",(0,i.kt)("inlineCode",{parentName:"p"},"sigstruct.sha256.bin")," contains the sha256 hash of the\nSIGSTRUCT fields to be signed."),(0,i.kt)("h5",{id:"sign-the-sigstruct-hash"},"Sign the SIGSTRUCT hash"),(0,i.kt)("p",null,"To sign the SIGSTRUCT you must create a signature using the ",(0,i.kt)("inlineCode",{parentName:"p"},"RSASSA-PKCS1-v1_5"),"\nscheme. The following command will do so with ",(0,i.kt)("inlineCode",{parentName:"p"},"openssl"),". If you're using an HSM,\nyour device may have a different process for generating a signature of this\ntype."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"openssl pkeyutl -sign \\\n -in sigstruct.sha256.bin \\\n -inkey private.pem \\\n -out sigstruct.sha256.sig \\\n -pkeyopt digest:sha256\n")),(0,i.kt)("h5",{id:"attach-the-singed-sigstruct-to-the-bundle"},"Attach the singed SIGSTRUCT to the bundle"),(0,i.kt)("p",null,"With the signature in ",(0,i.kt)("inlineCode",{parentName:"p"},"sigstruct.sha256.sig")," we can now generate a valid\nSIGSTRUCT and attach it into the bundle."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc sgx-set-sig bundle.orc sigstruct.sha256.sig public.pem\n")),(0,i.kt)("p",null,"If there are no errors, ",(0,i.kt)("inlineCode",{parentName:"p"},"bundle.orc")," will now contain a valid SGX SIGSTRUCT\nthat was signed by ",(0,i.kt)("inlineCode",{parentName:"p"},"private.pem"),". To verify you can use ",(0,i.kt)("inlineCode",{parentName:"p"},"orc show")," as follows."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"orc show bundle.orc\n")),(0,i.kt)("p",null,"It should return something like the following, showing the bundle content\nincluding the signed SGX SIGSTRUCT (the signature is also verified):"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"Bundle: /path/to/bundle.orc\nName: my-paratime\nRuntime ID: 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\nVersion: 0.1.1\nExecutable: runtime.elf\nSGXS: runtime.sgx\nSGXS MRENCLAVE: a68535bda1574a5e15dfb155c26e39bd404e9991a4d98010581a35d053011340\nSGXS signature: runtime.sgx.sig\nSGXS SIGSTRUCT:\n Build date: 2022-07-14 00:00:00 +0000 UTC\n MiscSelect: 00000000\n MiscSelect mask: FFFFFFFF\n Attributes flags: 0000000000000004\n - 64-bit mode\n Attributes XFRM: 0000000000000003\n Attributes mask: FFFFFFFFFFFFFFFD FFFFFFFFFFFFFFFC\n MRENCLAVE: a68535bda1574a5e15dfb155c26e39bd404e9991a4d98010581a35d053011340\n ISV product ID: 0\n ISV SVN: 0\nDigests:\n runtime.sgx.sig => 3c0daea89dfdb3d0381147dec3e041a596617f686afa9b28436ca17980dafee4\n runtime.elf => a96397fc309bc2116802315c0341a2a9f6f21935d79a3f56d71b3e4d6f6d9302\n runtime.sgx => b96ff3ae9c73646459b7e8dc1d096838720a7c62707affc1800967cbee99b28b\n")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0f921af1.4846e101.js b/assets/js/0f921af1.4846e101.js new file mode 100644 index 0000000000..ef1a8b365e --- /dev/null +++ b/assets/js/0f921af1.4846e101.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2874],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function s(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=a.createContext({}),c=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(l.Provider,{value:n},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=c(t),m=o,h=u["".concat(l,".").concat(m)]||u[m]||d[m]||r;return t?a.createElement(h,s(s({ref:n},p),{},{components:t})):a.createElement(h,s({ref:n},p))}));function h(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var r=t.length,s=new Array(r);s[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i[u]="string"==typeof e?e:o,s[1]=i;for(var c=2;c{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var a=t(7462),o=(t(7294),t(3905));const r={title:"Account",description:"Using CLI for performing account-related tasks"},s="Account-related Tasks",i={unversionedId:"general/manage-tokens/cli/account",id:"general/manage-tokens/cli/account",title:"Account",description:"Using CLI for performing account-related tasks",source:"@site/docs/general/manage-tokens/cli/account.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/account",permalink:"/general/manage-tokens/cli/account",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/account.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Account",description:"Using CLI for performing account-related tasks"},sidebar:"general",previous:{title:"Wallet",permalink:"/general/manage-tokens/cli/wallet"},next:{title:"Transaction",permalink:"/general/manage-tokens/cli/transaction"}},l={},c=[{value:"Network, ParaTime and Account Selectors",id:"npa",level:2},{value:"Network",id:"network",level:3},{value:"ParaTime",id:"paratime",level:3},{value:"Account",id:"account",level:3},{value:"Show the Balance of an Account",id:"show",level:2},{value:"Transfer",id:"transfer",level:2},{value:"Allowance",id:"allow",level:2},{value:"Deposit Tokens to a ParaTime",id:"deposit",level:2},{value:"Withdraw Tokens from the ParaTime",id:"withdraw",level:2},{value:"Delegate Tokens to a Validator",id:"delegate",level:2},{value:"Undelegate Tokens from the Validator",id:"undelegate",level:2},{value:"Advanced",id:"advanced",level:2},{value:"Public Key to Address",id:"from-public-key",level:3},{value:"Non-Interactive Mode",id:"y",level:3},{value:"Output Transaction to File",id:"output-file",level:3},{value:"Do Not Sign the Transaction",id:"unsigned",level:3},{value:"Offline Mode",id:"offline",level:3},{value:"Account's Nonce",id:"nonce",level:3},{value:"Gas Price",id:"gas-price",level:3},{value:"Gas Limit",id:"gas-limit",level:3},{value:"Entity Management",id:"entity",level:3},{value:"Register your Entity",id:"entity-register",level:4},{value:"Deregister Your Entity",id:"entity-deregister",level:4},{value:"Change Your Commission Schedule",id:"amend-commission-schedule",level:3},{value:"Unfreeze Your Node",id:"node-unfreeze",level:3},{value:"Burn Tokens",id:"burn",level:3}],p={toc:c},u="wrapper";function d(e){let{components:n,...t}=e;return(0,o.kt)(u,(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"account-related-tasks"},"Account-related Tasks"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"account")," command is the home for most consensus and ParaTime-layer\non-chain transactions that are signed with one of your accounts such as:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"getting the account balance including delegated assets,"),(0,o.kt)("li",{parentName:"ul"},"sending tokens,"),(0,o.kt)("li",{parentName:"ul"},"delegating or undelegating tokens to or from validators (",(0,o.kt)("em",{parentName:"li"},"staking"),"),"),(0,o.kt)("li",{parentName:"ul"},"depositing and withdrawing tokens to or from a ParaTime,"),(0,o.kt)("li",{parentName:"ul"},"managing withdrawal beneficiaries of your accounts,"),(0,o.kt)("li",{parentName:"ul"},"validator utils such as entity registration, setting the commission schedule,\nunfreezing your node and similar.")),(0,o.kt)("h2",{id:"npa"},"Network, ParaTime and Account Selectors"),(0,o.kt)("p",null,"Before we dig into ",(0,o.kt)("inlineCode",{parentName:"p"},"account")," subcommands, let's look at the three most common\nselectors."),(0,o.kt)("h3",{id:"network"},"Network"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--network ")," parameter specifies the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network"},"network")," which the\nOasis CLI should connect to."),(0,o.kt)("p",null,"For example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000 --network testnet\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\nNonce: 0\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 1.0 TEST\n Available: 1.0 TEST\n\n\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000 --network mainnet\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\nNonce: 0\n\n=== CONSENSUS LAYER (mainnet) ===\n Total: 0.0 ROSE\n Available: 0.0 ROSE\n\n\n")),(0,o.kt)("h3",{id:"paratime"},"ParaTime"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--paratime ")," sets which ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/paratime"},"ParaTime")," Oasis CLI should use.\nIf you do not want to use any ParaTime, for example to perform a consensus\nlayer operation, pass the ",(0,o.kt)("inlineCode",{parentName:"p"},"--no-paratime")," flag explicitly."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show eric --no-paratime\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qzplmfaeywvtc2qnylyhk0uzcxr4y5s3euhaug7q\nNonce: 0\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n\n")),(0,o.kt)("h3",{id:"account"},"Account"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--account ")," specifies which account in your wallet the\nOasis CLI should use to sign the transaction with."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account transfer 1.5 0xDce075E1C39b1ae0b75D554558b6451A226ffe00 --account orlando\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: accounts.Transfer\nBody:\n To: test:dave (oasis1qrk58a6j2qn065m6p06jgjyt032f7qucy5wqeqpt)\n Amount: 1.5 TEST\nAuthorized signer(s):\n 1. cb+NHKt7JT4fumy0wQdkiBwO3P+DUh8ylozMpsu1xH4= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.000231 TEST\n Gas limit: 2310\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: orlando\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account transfer 1.5 0xDce075E1C39b1ae0b75D554558b6451A226ffe00 --account eric\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: accounts.Transfer\nBody:\n To: test:dave (oasis1qrk58a6j2qn065m6p06jgjyt032f7qucy5wqeqpt)\n Amount: 1.5 TEST\nAuthorized signer(s):\n 1. A1ik9X/7X/eGSoSYOKSIJqM7pZ5It/gHbF+wraxi33u3 (secp256k1eth)\n Nonce: 0\nFee:\n Amount: 0.0002316 TEST\n Gas limit: 2316\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: eric\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"You can also set ",(0,o.kt)("strong",{parentName:"p"},"the default ",(0,o.kt)("a",{parentName:"strong",href:"/general/manage-tokens/cli/network#set-default"},"network"),",\n",(0,o.kt)("a",{parentName:"strong",href:"/general/manage-tokens/cli/paratime#set-default"},"ParaTime")," or ",(0,o.kt)("a",{parentName:"strong",href:"/general/manage-tokens/cli/wallet#set-default"},"account")," to use"),", if\nno network, ParaTime or account selectors are provided.")),(0,o.kt)("h2",{id:"show"},"Show the Balance of an Account"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"account show [address]")," command prints the balance, delegated assets\nand other validator information corresponding to:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"a given address,"),(0,o.kt)("li",{parentName:"ul"},"the name of the ",(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/addressbook"},"address book entry")," or"),(0,o.kt)("li",{parentName:"ul"},"the name of one of the accounts in your wallet.")),(0,o.kt)("p",null,"The address is looked up both on the consensus layer and the ParaTime, if\nselected."),(0,o.kt)("p",null,"Running the command without arguments will show you the balance\nof your default account on the default network and ParaTime:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\nNonce: 1\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n\n")),(0,o.kt)("p",null,"You can also pass the name of the account in your wallet or the name stored in\nyour address book:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show orlando\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qq84sc4q0shp5c5klwklqu59evz2mg59hveg7dqx\nNonce: 0\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 10.0 TEST\n Available: 10.0 TEST\n\n\n")),(0,o.kt)("p",null,"Or, you can check the balance of an arbitrary account address by passing the\nnative or Ethereum-compatible addresses."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\nNonce: 0\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 1.0 TEST\n Available: 1.0 TEST\n\n\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show 0xA3243B310CfA8D4b008780BC87E0bb9f6d4FDA06\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qzplmfaeywvtc2qnylyhk0uzcxr4y5s3euhaug7q\nNonce: 0\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n\n\n=== sapphire PARATIME ===\nBalances for all denominations:\n 10.0 TEST\n")),(0,o.kt)("p",null,"To also include any staked assets in the balance, pass the ",(0,o.kt)("inlineCode",{parentName:"p"},"--show-delegations"),"\nflag. For example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve --show-delegations\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve\nNonce: 33\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 972.898210067 TEST\n Available: 951.169098086 TEST\n\n Active Delegations from this Account:\n Total: 16.296833986 TEST\n\n Delegations:\n - To: oasis1qz2tg4hsatlxfaf8yut9gxgv8990ujaz4sldgmzx\n Amount: 16.296833986 TEST (15000000000 shares)\n Debonding Delegations from this Account:\n Total: 5.432277995 TEST\n\n Delegations:\n - To: oasis1qz2tg4hsatlxfaf8yut9gxgv8990ujaz4sldgmzx\n Amount: 5.432277995 TEST (5432277995 shares)\n End Time: epoch 26558\n\n Allowances for this Account:\n Total: 269.5000002 TEST\n Allowances:\n - Beneficiary: oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd\n Amount: 269.5 TEST\n - Beneficiary: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 0.0000002 TEST\n\n=== sapphire PARATIME ===\nBalances for all denominations:\n 6.9995378 TEST\n")),(0,o.kt)("p",null,"Let's look more closely at the figures above. The account's ",(0,o.kt)("strong",{parentName:"p"},"nonce")," is the\nincremental number starting from 0 that must be unique for each account's\ntransaction. In our case, the nonce is 32. This means there have been that many\ntransactions made with this account as the source. The next transaction should\nhave nonce equal to 32."),(0,o.kt)("p",null,"We can see that the total account's ",(0,o.kt)("strong",{parentName:"p"},"balance")," on the consensus layer is ","~","973\ntokens:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"~","951 tokens can immediately be transferred."),(0,o.kt)("li",{parentName:"ul"},"~","16.3 tokens (15,000,000,0000 shares) are staked (delegated)."),(0,o.kt)("li",{parentName:"ul"},"~","5.4 tokens are debonding and will be available for spending in the epoch\n26558."),(0,o.kt)("li",{parentName:"ul"},"up to ","~","270 tokens are ",(0,o.kt)("a",{parentName:"li",href:"#allow"},"allowed")," to be transferred to accounts\n",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd")," and\n",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx")," without the signature of the\naccount above.")),(0,o.kt)("p",null,"Separately, you can notice there are ","~","7 tokens currently ",(0,o.kt)("a",{parentName:"p",href:"#deposit"},"deposited"),"\nin Sapphire."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--show-delegations")," flag is not enabled by default, because account\ndelegations are not indexed on-chain. This means that the endpoint needs\nto scan block by block to retrieve this information and takes some time\noften leading to the timeout on public endpoints due to denial-of-service\nprotection.")),(0,o.kt)("p",null,"Next, let's look at how the account of a validator typically looks like. For\nexample:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account show oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4 --show-delegations\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Address: oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4\nNonce: 17\n\n=== CONSENSUS LAYER (testnet) ===\n Total: 1300.598418401 TEST\n Available: 52.73923316 TEST\n\n Active Delegations from this Account:\n Total: 1247.859185241 TEST\n\n Delegations:\n - To: oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4 (self)\n Amount: 1247.859185241 TEST (1167021437369 shares)\n\n Active Delegations to this Account:\n Total: 1833.451690691 TEST\n (1714678589317 shares)\n\n Delegations:\n - From: oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4 (self)\n Amount: 1247.859185241 TEST (1167021437369 shares)\n - From: oasis1qztnau4t75cf8wh3truwtl7awvnkwe4st5l25yfn\n Amount: 148.289115949 TEST (138682777102 shares)\n - From: oasis1qrvguq055xh42yjl84yn2h5dhm59fkzg9st0mu90\n Amount: 116.290596782 TEST (108757158672 shares)\n - From: oasis1qzhulmesqkcu23r0h5hfslwelud46mkm25zh7uqq\n Amount: 111.30081746 TEST (104090622972 shares)\n - From: oasis1qq05qnywdzz3m45dzqxuek0p4a5dxr86rgxlxc58\n Amount: 104.855987628 TEST (98063296601 shares)\n - From: oasis1qzpvsgt56jxz324dxjv5272mz4j6kfadd5ur7f98\n Amount: 104.855987628 TEST (98063296601 shares)\n\n Commission Schedule:\n Rates:\n (1) start: epoch 15883\n rate: 7.0%\n (2) start: epoch 15994\n rate: 11.0%\n (3) start: epoch 16000\n rate: 14.0%\n (4) start: epoch 16134\n rate: 18.0%\n Rate Bounds:\n (1) start: epoch 15883\n minimum rate: 0.0%\n maximum rate: 10.0%\n (2) start: epoch 15993\n minimum rate: 0.0%\n maximum rate: 20.0%\n\n Stake Accumulator:\n Claims:\n - Name: registry.RegisterEntity\n Staking Thresholds:\n - Global: entity\n - Name: registry.RegisterNode.LAdHWnCkjFR5NUkFHVpfGuKFfZW1Cqjzu6wTFY6v2JI=\n Staking Thresholds:\n - Global: node-validator\n - Name: registry.RegisterNode.xk58fx5ys6CSO33ngMQkgOL5UUHSgOSt0QbqWGGuEF8=\n Staking Thresholds:\n - Global: node-compute\n Staking Thresholds:\n - Global: node-compute\n Staking Thresholds:\n - Global: node-compute\n")),(0,o.kt)("p",null,"We can see there is a total of ","~","1833 tokens delegated to this validator. One\ndelegation was done by the account itself and then there are five more\ndelegators. Sometimes, we also refer to accounts with delegated assets to it as\n",(0,o.kt)("em",{parentName:"p"},"escrow accounts"),"."),(0,o.kt)("p",null,"Next, we can see a ",(0,o.kt)("em",{parentName:"p"},"commission schedule"),". A validator can charge commission for\ntokens that are delegated to it in form of the commission schedule ",(0,o.kt)("strong",{parentName:"p"},"rate\nsteps")," (7%, 11%, 14% and 18% activated on epochs 15883, 15994, 16000 and 16134\nrespectively) and the commission schedule ",(0,o.kt)("strong",{parentName:"p"},"rate bound steps")," (0-10% on\nepoch 15883 and then 0-20% activated on epoch 15993). For more details, see the\n",(0,o.kt)("a",{parentName:"p",href:"./account#amend-commission-schedule"},"account amend-commission-schedule"),"\ncommand."),(0,o.kt)("p",null,"An escrow account may also accumulate one or more ",(0,o.kt)("strong",{parentName:"p"},"stake claims")," as seen\nabove. The network ensures that all claims are satisfied at any given point.\nAdding a new claim is only possible if ",(0,o.kt)("strong",{parentName:"p"},"all of the existing claims plus the\nnew claim can be satisfied"),"."),(0,o.kt)("p",null,"We can observe that the stake accumulator currently has the following claims:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"registry.RegisterEntity")," claim is for registering an entity. It needs to\nsatisfy the global threshold for\n",(0,o.kt)("a",{parentName:"p",href:"./network#show-native-token"},"registering the ",(0,o.kt)("inlineCode",{parentName:"a"},"entity")),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"registry.RegisterNode.LAdHWnCkjFR5NUkFHVpfGuKFfZW1Cqjzu6wTFY6v2JI="),"\nclaim is for registering the validator node with the public key\n",(0,o.kt)("inlineCode",{parentName:"p"},"LAdHWnCkjFR5NUkFHVpfGuKFfZW1Cqjzu6wTFY6v2JI="),". The claim needs to satisfy the\n",(0,o.kt)("a",{parentName:"p",href:"./network#show-native-token"},(0,o.kt)("inlineCode",{parentName:"a"},"node-validator"))," global staking threshold parameter.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"registry.RegisterNode.xk58fx5ys6CSO33ngMQkgOL5UUHSgOSt0QbqWGGuEF8="),"\nclaim is for registering the three compute nodes with the public key\n",(0,o.kt)("inlineCode",{parentName:"p"},"xk58fx5ys6CSO33ngMQkgOL5UUHSgOSt0QbqWGGuEF8=="),". The claim needs to satisfy\nthree ",(0,o.kt)("a",{parentName:"p",href:"./network#show-native-token"},(0,o.kt)("inlineCode",{parentName:"a"},"node-compute"))," global staking threshold parameters."))),(0,o.kt)("p",null,"For more details on registering entities, nodes and ParaTimes, see the\n",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#entities-and-nodes"},"Oasis Core Registry service"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and ParaTime")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account show")," command.")),(0,o.kt)("h2",{id:"transfer"},"Transfer"),(0,o.kt)("p",null,"Use ",(0,o.kt)("inlineCode",{parentName:"p"},"account transfer ")," command to transfer funds between two\naccounts on the consensus layer or between two accounts inside the same\nParaTime."),(0,o.kt)("p",null,"The following command will perform a token transfer inside default ParaTime:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account transfer 2.5 oscar --account orlando\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: accounts.Transfer\nBody:\n To: oscar (oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e)\n Amount: 2.5 TEST\nAuthorized signer(s):\n 1. cb+NHKt7JT4fumy0wQdkiBwO3P+DUh8ylozMpsu1xH4= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.000231 TEST\n Gas limit: 2310\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: orlando\n")),(0,o.kt)("p",null,"Consensus layer token transfers:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account transfer 2.5 oscar --account orlando --no-paratime\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Transfer\nBody:\n To: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n Amount: 2.5 TEST\nNonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 1264\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: orlando\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network, ParaTime and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account transfer")," command.")),(0,o.kt)("h2",{id:"allow"},"Allowance"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"account allow ")," command makes your funds withdrawable by\na 3rd party beneficiary at consensus layer. For example, instead of paying your\npartner for a service directly, you can ask for their address and enable\n",(0,o.kt)("strong",{parentName:"p"},"them")," to withdraw the amount which you agreed on from your account. This is a\nsimilar mechanism to how payment checks were used in the past."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account allow logan 10\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Allow\nBody:\n Beneficiary: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\n Amount change: +10.0 TEST\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1278\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("p",null,"The allowance command uses relative amount. For example, if your run the\nabove command 3 times, Logan will be allowed to withdraw 30 ROSE."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"To reduce the allowed amount or completely ",(0,o.kt)("strong",{parentName:"p"},"disallow")," the withdrawal, use the\nnegative amount. To avoid flag ambiguity in the shell, you will first need to\npass all desired flags and parameters except the negative amount, then append\n",(0,o.kt)("inlineCode",{parentName:"p"},"--")," to mark the end of options, and finally append the negative amount."),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account allow logan -- -10\n")),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Allow\nBody:\n Beneficiary: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\n Amount change: -10.0 TEST\nNonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 1288\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n"))),(0,o.kt)("p",null,"The allowance transaction is also required if you want to deposit funds from\nyour consensus account to a ParaTime. The ParaTime will ",(0,o.kt)("strong",{parentName:"p"},"withdraw")," the amount\nfrom your consensus account and fund your ParaTime account with the same\namount deducted by the deposit fee. Oasis CLI can derive the address of the\nParaTime beneficiary, if you use ",(0,o.kt)("inlineCode",{parentName:"p"},"paratime:")," as the beneficiary\naddress."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account allow paratime:sapphire 10\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Allow\nBody:\n Beneficiary: oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd\n Amount change: +10.0 TEST\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1278\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the ",(0,o.kt)("inlineCode",{parentName:"p"},"account allow"),"\ncommand.")),(0,o.kt)("h2",{id:"deposit"},"Deposit Tokens to a ParaTime"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"account deposit [address]")," will deposit funds from your consensus\naccount to the target address inside the selected ParaTime."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis accounts deposit 10 eugene --gas-price 0\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Deposit\nBody:\n To: eugene (oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz)\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 11310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("p",null,"If no address is provided, the deposit will be made to the address\ncorresponding to your consensus account inside the ParaTime."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis accounts deposit 10 --gas-price 0\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Deposit\nBody:\n To: Self\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 11285\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("p",null,"Currently, deposit transactions are free of charge, hence the ",(0,o.kt)("inlineCode",{parentName:"p"},"--gas-price 0"),"\nparameter to avoid spending unnecessary gas fees. Also, keep in\nmind that ",(0,o.kt)("strong",{parentName:"p"},"deposit and withdrawal fees are always paid by your ParaTime\naccount.")," If it doesn't contain any ROSE, you will not able to cover the fees."),(0,o.kt)("p",null,"You can also make a deposit to an account with arbitrary address inside a\nParaTime. For example, let's deposit to some native address inside the\nParaTime:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account deposit 10 oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6 --gas-price 0\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Deposit\nBody:\n To: oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 11310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("p",null,"Or to some address in the Ethereum format:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis accounts deposit 10 0x90adE3B7065fa715c7a150313877dF1d33e777D5 --gas-price 0\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Deposit\nBody:\n To: oasis1qpupfu7e2n6pkezeaw0yhj8mcem8anj64ytrayne\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0 TEST\n Gas limit: 11310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network, ParaTime and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account deposit")," command.")),(0,o.kt)("h2",{id:"withdraw"},"Withdraw Tokens from the ParaTime"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"account withdraw [to]")," will withdraw funds from your ParaTime account\nto a consensus address:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account withdraw 10 orlando\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Withdraw\nBody:\n To: orlando (oasis1qq84sc4q0shp5c5klwklqu59evz2mg59hveg7dqx)\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0011311 TEST\n Gas limit: 11311\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("p",null,"If the address is not provided, the address of the account inside ParaTime will\nbe used as a consensus address:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account withdraw 10\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Withdraw\nBody:\n To: Self\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0011286 TEST\n Gas limit: 11286\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Withdrawal transactions are not free of charge and the fee will be deducted\n",(0,o.kt)("strong",{parentName:"p"},"from your ParaTime balance"),".")),(0,o.kt)("p",null,"Similar to the ",(0,o.kt)("a",{parentName:"p",href:"#deposit"},(0,o.kt)("inlineCode",{parentName:"a"},"account deposit"))," command, you can also specify an\narbitrary Oasis address which you want to withdraw your tokens to."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis accounts withdraw 10 oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Withdraw\nBody:\n To: oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6\n Amount: 10.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0011311 TEST\n Gas limit: 11311\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"You cannot use the destination address of your ",(0,o.kt)("inlineCode",{parentName:"p"},"secp256k1")," account or any other\nEthereum-formatted address for the withdrawal, because this signature scheme is\nnot supported on the consensus layer!")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network, ParaTime and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account withdraw")," command.")),(0,o.kt)("h2",{id:"delegate"},"Delegate Tokens to a Validator"),(0,o.kt)("p",null,"To stake your tokens on the consensus layer, run\n",(0,o.kt)("inlineCode",{parentName:"p"},"account delegate "),". This will delegate the specified amount of\ntokens to a validator."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account delegate 20 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk --no-paratime\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.AddEscrow\nBody:\n To: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Amount: 20.0 TEST\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1271\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("p",null,"Once your tokens are staked, they are converted into ",(0,o.kt)("em",{parentName:"p"},"shares")," since the number\nof tokens may change over time based on the\n",(0,o.kt)("a",{parentName:"p",href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives"},"staking reward schedule")," or if your validator is subject to\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/terminology#slashing"},"slashing"),". The number of shares on the other hand will remain constant. Also,\nshares are always interpreted as a whole number, whereas the amount of tokens is\nusually a rational number and may lead to rounding errors when managing your\ndelegations."),(0,o.kt)("p",null,"To find out how many shares did you delegate, run ",(0,o.kt)("a",{parentName:"p",href:"#show"},(0,o.kt)("inlineCode",{parentName:"a"},"account show"))," and\nlook for the ",(0,o.kt)("inlineCode",{parentName:"p"},"shares")," under the active delegations section:"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network, ParaTime and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account delegate")," command.")),(0,o.kt)("h2",{id:"undelegate"},"Undelegate Tokens from the Validator"),(0,o.kt)("p",null,"To reclaim your delegated assets, use ",(0,o.kt)("inlineCode",{parentName:"p"},"account undelegate "),". You\nwill need to specify the ",(0,o.kt)("strong",{parentName:"p"},"number of shares instead of tokens")," and the\nvalidator address you want to reclaim your assets from."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account undelegate 20000000000 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk --no-paratime\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.ReclaimEscrow\nBody:\n From: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Shares: 20000000000\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1275\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("p",null,"After submitting the transaction, a ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#show"},"debonding period")," will\ncommence. After the period has passed, the network will automatically move your\nassets back to your account. Note that during the debonding period, your\nassets may still be ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/terminology#slashing"},"slashed"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network, ParaTime and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account undelegate")," command.")),(0,o.kt)("h2",{id:"advanced"},"Advanced"),(0,o.kt)("h3",{id:"from-public-key"},"Public Key to Address"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"account from-public-key ")," converts the Base64-encoded public key\nto the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/terminology#address"},"Oasis native address"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account from-public-key NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve\n")),(0,o.kt)("p",null,"This command is most often used by the network validators for converting the\npublic key of their entity to a corresponding address. You can find your\nentity's ID in the ",(0,o.kt)("inlineCode",{parentName:"p"},"id")," field of the ",(0,o.kt)("inlineCode",{parentName:"p"},"entity.json")," file."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Oasis consensus transactions hold the public key of the signer instead of their\n",(0,o.kt)("em",{parentName:"p"},"from")," address. This command can be used for debugging to determine the\nsigner's staking address on the network.")),(0,o.kt)("h3",{id:"y"},"Non-Interactive Mode"),(0,o.kt)("p",null,"Add ",(0,o.kt)("inlineCode",{parentName:"p"},"-y"),' flag to any operation, if you want to use Oasis CLI in\nnon-interactive mode. This will answer "yes to all" for yes/no questions\nand for all other prompts it will keep the proposed default values.'),(0,o.kt)("h3",{id:"output-file"},"Output Transaction to File"),(0,o.kt)("p",null,"You can use ",(0,o.kt)("inlineCode",{parentName:"p"},"--output-file ")," parameter to save a transaction to\na JSON file instead of immediately broadcasting it to the network. Afterwards,\nuse the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/transaction"},(0,o.kt)("inlineCode",{parentName:"a"},"transaction"))," command to verify and submit the transaction."),(0,o.kt)("h3",{id:"unsigned"},"Do Not Sign the Transaction"),(0,o.kt)("p",null,"If you wish to ",(0,o.kt)("em",{parentName:"p"},"prepare")," a transaction to be signed by a specific account in\nthe future, use the ",(0,o.kt)("inlineCode",{parentName:"p"},"--unsigned")," flag. This will cause Oasis CLI to skip the\nsigning and broadcasting steps. The transaction will be printed to the\nstandard output instead."),(0,o.kt)("p",null,"You can also use ",(0,o.kt)("a",{parentName:"p",href:"#output-file"},(0,o.kt)("inlineCode",{parentName:"a"},"--output-file"))," to store the transaction to a file. This\nsetup is ideal when you want to sign a transaction with the\n",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Air_gap_(networking)"},"offline/air-gapped machine")," machine:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"First, generate an unsigned transaction on a networked machine,"),(0,o.kt)("li",{parentName:"ol"},"copy it over to an air-gapped machine,"),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/transaction#sign"},"sign it")," on the air-gapped machine,"),(0,o.kt)("li",{parentName:"ol"},"copy it over to the networked machine,"),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/transaction#submit"},"broadcast the transaction")," on the networked machine.")),(0,o.kt)("h3",{id:"offline"},"Offline Mode"),(0,o.kt)("p",null,"To generate a transaction without accessing the network and also without\nbroadcasting it, add ",(0,o.kt)("inlineCode",{parentName:"p"},"--offline")," flag. In this case Oasis CLI will require that\nyou provide all necessary transaction details (e.g. ",(0,o.kt)("a",{parentName:"p",href:"#nonce"},"account nonce"),",\n",(0,o.kt)("a",{parentName:"p",href:"#gas-limit"},"gas limit"),", ",(0,o.kt)("a",{parentName:"p",href:"#gas-price"},"gas price"),") which would otherwise be\nautomatically obtained from the network. Oasis CLI will print the transaction to\nthe standard output for you to examine. Use ",(0,o.kt)("a",{parentName:"p",href:"#output-file"},(0,o.kt)("inlineCode",{parentName:"a"},"--output-file")),", if\nyou wish to save the transaction to the file and submit it to the network\nafterwards by using the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/transaction#submit"},(0,o.kt)("inlineCode",{parentName:"a"},"transaction submit"))," command."),(0,o.kt)("h3",{id:"nonce"},"Account's Nonce"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"--nonce ")," will override the detection of the account's nonce used\nto sign the transaction with the specified one."),(0,o.kt)("h3",{id:"gas-price"},"Gas Price"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"--gas-price ")," sets the transaction's price per gas unit in\nbase units."),(0,o.kt)("h3",{id:"gas-limit"},"Gas Limit"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"--gas-limit ")," sets the maximum amount of gas that can be spend by the\ntransaction."),(0,o.kt)("h3",{id:"entity"},"Entity Management"),(0,o.kt)("h4",{id:"entity-register"},"Register your Entity"),(0,o.kt)("p",null,"In order for validators to become part of the validator set and/or the compute\ncommittee, they first need to register as an entity inside the network's\nregistry. Use the ",(0,o.kt)("inlineCode",{parentName:"p"},"account entity register ")," command to register\nyour entity and provide a JSON file with the Entity descriptor. You can use the\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#show-id-entities"},(0,o.kt)("inlineCode",{parentName:"a"},"network show"))," command to see existing entities and\nthen examine specific ones to see how entity descriptors of the currently\nregistered entities look like."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account entity register entity.json\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'Signing the entity descriptor...\n(In case you are using a hardware-based signer you may need to confirm on device.)\nYou are about to sign the following transaction:\nMethod: registry.RegisterEntity\nBody:\n {\n "untrusted_raw_value": {\n "v": 2,\n "id": "Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=",\n "nodes": [\n "nshzFvqLNNLN+HS0id5XmXrVMhIgFV456i4VQicWgjk="\n ]\n },\n "signature": {\n "public_key": "Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=",\n "signature": "DAwn+N8hKmQMbZda/fFJSEgErDAAdebXLfIPOpqUkJowJLUAL+nfrUMz5SVkKc0TnqQOavoSAVFz1yoRJ3QuBA=="\n }\n }\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 2471\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n')),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account entity register")," command.")),(0,o.kt)("h4",{id:"entity-deregister"},"Deregister Your Entity"),(0,o.kt)("p",null,"To remove an entity from the network's registry, invoke\n",(0,o.kt)("inlineCode",{parentName:"p"},"account entity deregister"),". No additional arguments are required since each\naccount can only deregister their own entity, if one exists in the registry."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account entity deregister\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: registry.DeregisterEntity\nBody:\n {}\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1231\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account entity deregister")," command.")),(0,o.kt)("h3",{id:"amend-commission-schedule"},"Change Your Commission Schedule"),(0,o.kt)("p",null,"Validators can use ",(0,o.kt)("inlineCode",{parentName:"p"},"account amend-commission-schedule")," to add or remove\ntheir commission bounds and rates at consensus layer. Rate bounds can be\ndefined by using the ",(0,o.kt)("inlineCode",{parentName:"p"},"--bounds //")," parameter.\nActual rates which can be subject to change every epoch can be defined with the\n",(0,o.kt)("inlineCode",{parentName:"p"},"--rates /")," parameter. Rates are specified in milipercents\n(100% = 100000m%). The new commission schedule will replace any previous\nschedules."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account amend-commission-schedule --bounds 29000/1000/2000,35000/900/1900 --rates 29000/1500\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.AmendCommissionSchedule\nBody:\n Amendment:\n Rates:\n (1) start: epoch 29000\n rate: 1.5%\n Rate Bounds:\n (1) start: epoch 29000\n minimum rate: 1.0%\n maximum rate: 2.0%\n (2) start: epoch 35000\n minimum rate: 0.9%\n maximum rate: 1.9%\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1355\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("p",null,"To learn more on commission rates read the section inside the Oasis Core\n",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#amend-commission-schedule"},"Staking service")," chapter."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account amend-commission-schedule")," command.")),(0,o.kt)("h3",{id:"node-unfreeze"},"Unfreeze Your Node"),(0,o.kt)("p",null,"Once the validators, based on their stake, get elected into the validator set,\nit is important that their nodes are actively participating in proposing new\nblocks and submitting votes for other proposed blocks. For regular node\nupgrades and maintenance, the validators should follow the\n",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/shutting-down-a-node"},"Shutting Down a Node")," instructions. Nevertheless, if the network froze your\nnode, the only way to unfreeze it is to execute the ",(0,o.kt)("inlineCode",{parentName:"p"},"account node-unfreeze")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account node-unfreeze fasTG3pMOwLfFA7JX3R8Kxw1zFflqeY6NP/cpjcFu5I=\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'You are about to sign the following transaction:\nMethod: registry.UnfreezeNode\nBody:\n {\n "node_id": "fasTG3pMOwLfFA7JX3R8Kxw1zFflqeY6NP/cpjcFu5I="\n }\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1274\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n')),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the\n",(0,o.kt)("inlineCode",{parentName:"p"},"account node-unfreeze")," command.")),(0,o.kt)("h3",{id:"burn"},"Burn Tokens"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"account burn ")," command will permanently destroy the amount of tokens\nin your account and remove them from circulation. This command should not be\nused on public networks since not only no one will be able to access burnt\nassets anymore, but will also permanently remove the tokens from circulation."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account burn 2.5\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Burn\nBody:\n Amount: 2.5 TEST\nNonce: 1\nFee:\n Amount: 0.0 TEST\n Gas limit: 1235\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("a",{parentName:"p",href:"#npa"},"Network and account")," selectors are available for the ",(0,o.kt)("inlineCode",{parentName:"p"},"account burn"),"\ncommand.")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0f92291a.14f29313.js b/assets/js/0f92291a.14f29313.js new file mode 100644 index 0000000000..c070fe79cb --- /dev/null +++ b/assets/js/0f92291a.14f29313.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5293],{3905:(t,e,a)=>{a.d(e,{Zo:()=>p,kt:()=>c});var n=a(7294);function i(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function r(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function o(t){for(var e=1;e=0||(i[a]=t[a]);return i}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(i[a]=t[a])}return i}var s=n.createContext({}),l=function(t){var e=n.useContext(s),a=e;return t&&(a="function"==typeof t?t(e):o(o({},e),t)),a},p=function(t){var e=l(t.components);return n.createElement(s.Provider,{value:e},t.children)},u="mdxType",k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},h=n.forwardRef((function(t,e){var a=t.components,i=t.mdxType,r=t.originalType,s=t.parentName,p=m(t,["components","mdxType","originalType","parentName"]),u=l(a),h=i,c=u["".concat(s,".").concat(h)]||u[h]||k[h]||r;return a?n.createElement(c,o(o({ref:e},p),{},{components:a})):n.createElement(c,o({ref:e},p))}));function c(t,e){var a=arguments,i=e&&e.mdxType;if("string"==typeof t||i){var r=a.length,o=new Array(r);o[0]=h;var m={};for(var s in e)hasOwnProperty.call(e,s)&&(m[s]=e[s]);m.originalType=t,m[u]="string"==typeof t?t:i,o[1]=m;for(var l=2;l{a.r(e),a.d(e,{assets:()=>s,contentTitle:()=>o,default:()=>k,frontMatter:()=>r,metadata:()=>m,toc:()=>l});var n=a(7462),i=(a(7294),a(3905));const r={},o="Join our Community",m={unversionedId:"get-involved/README",id:"get-involved/README",title:"Join our Community",description:"Welcome to the Oasis Community",source:"@site/docs/get-involved/README.md",sourceDirName:"get-involved",slug:"/get-involved/",permalink:"/get-involved/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/README.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",next:{title:"Run a Node",permalink:"/get-involved/run-node"}},s={},l=[{value:"Welcome to the Oasis Community",id:"welcome-to-the-oasis-community",level:2},{value:"Social Media Channels",id:"social-media-channels",level:2},{value:"Regional Communities",id:"regional-communities",level:2}],p={toc:l},u="wrapper";function k(t){let{components:e,...a}=t;return(0,i.kt)(u,(0,n.Z)({},p,a,{components:e,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"join-our-community"},"Join our Community"),(0,i.kt)("h2",{id:"welcome-to-the-oasis-community"},"Welcome to the Oasis Community"),(0,i.kt)("p",null,"Whether you're a blockchain enthusiast, a software developer, or someone who is\njust starting learn about crypto, we're excited to welcome you to our community.\nWe look forward to working together on our mission to build a responsible data\neconomy and empower users around the world to take back ownership of their data\nand their online privacy."),(0,i.kt)("h2",{id:"social-media-channels"},"Social Media Channels"),(0,i.kt)("p",null,"To stay up-to-date on the latest Oasis Network news, events, and programs, be\nsure to join our social media channels:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://oasis.io/discord"},"Discord")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://twitter.com/OasisProtocol"},"Twitter")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://t.me/oasisprotocolcommunity"},"Public Telegram channel")," (for community discussions open to everyone)"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://t.me/oasisprotocolfoundation"},"Telegram Announcement channel")," (for one-way updates from the Oasis Foundation)")),(0,i.kt)("h2",{id:"regional-communities"},"Regional Communities"),(0,i.kt)("p",null,"To connect with Oasis community members who live in your home region or speak\nyour native language, check out our region-based community channels:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Arabic Speaking Countries: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Arabic"},"https://t.me/OasisNetworkCommunity_Arabic")),(0,i.kt)("li",{parentName:"ul"},"Austria: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Austria"},"https://t.me/OasisNetworkCommunity_Austria")),(0,i.kt)("li",{parentName:"ul"},"Bangladesh: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Bangladesh"},"https://t.me/OasisNetworkCommunity_Bangladesh")),(0,i.kt)("li",{parentName:"ul"},"Brazil: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Brazil"},"https://t.me/OasisNetworkCommunity_Brazil")),(0,i.kt)("li",{parentName:"ul"},"China WeChat: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/oasisprotocolcommunity/27378"},"https://t.me/oasisprotocolcommunity/27378")),(0,i.kt)("li",{parentName:"ul"},"France: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_France"},"https://t.me/OasisNetworkCommunity_France")),(0,i.kt)("li",{parentName:"ul"},"Germany: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Germany"},"https://t.me/OasisNetworkCommunity_Germany")),(0,i.kt)("li",{parentName:"ul"},"India: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_India"},"https://t.me/OasisNetworkCommunity_India")),(0,i.kt)("li",{parentName:"ul"},"Indonesia: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Indonesia"},"https://t.me/OasisNetworkCommunity_Indonesia")),(0,i.kt)("li",{parentName:"ul"},"Japan: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_japan8"},"https://t.me/OasisNetworkCommunity_japan8")),(0,i.kt)("li",{parentName:"ul"},"Korea: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Korea"},"https://t.me/OasisNetworkCommunity_Korea")),(0,i.kt)("li",{parentName:"ul"},"Nigeria: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Nigeria"},"https://t.me/OasisNetworkCommunity_Nigeria")),(0,i.kt)("li",{parentName:"ul"},"Pakistan: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Pakistan"},"https://t.me/OasisNetworkCommunity_Pakistan")),(0,i.kt)("li",{parentName:"ul"},"Philippines: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Philippine"},"https://t.me/OasisNetworkCommunity_Philippine")),(0,i.kt)("li",{parentName:"ul"},"Russia: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Russia"},"https://t.me/OasisNetworkCommunity_Russia")),(0,i.kt)("li",{parentName:"ul"},"Singapore: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Singapore8"},"https://t.me/OasisNetworkCommunity_Singapore8")),(0,i.kt)("li",{parentName:"ul"},"Spanish Speaking Countries: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Spanish"},"https://t.me/OasisNetworkCommunity_Spanish")),(0,i.kt)("li",{parentName:"ul"},"Sri Lanka: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_SriLanka"},"https://t.me/OasisNetworkCommunity_SriLanka")),(0,i.kt)("li",{parentName:"ul"},"Sweden: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Sweden8"},"https://t.me/OasisNetworkCommunity_Sweden8")),(0,i.kt)("li",{parentName:"ul"},"Switzerland: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunitySwitzerland"},"https://t.me/OasisNetworkCommunitySwitzerland")),(0,i.kt)("li",{parentName:"ul"},"Turkey: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Turkey"},"https://t.me/OasisNetworkCommunity_Turkey")),(0,i.kt)("li",{parentName:"ul"},"Ukraine: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Ukraine"},"https://t.me/OasisNetworkCommunity_Ukraine")),(0,i.kt)("li",{parentName:"ul"},"Uzbekistan: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Uzbekistan"},"https://t.me/OasisNetworkCommunity_Uzbekistan")),(0,i.kt)("li",{parentName:"ul"},"Vietnam: ",(0,i.kt)("a",{parentName:"li",href:"https://t.me/OasisNetworkCommunity_Vietnam"},"https://t.me/OasisNetworkCommunity_Vietnam"))))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/10bc4617.489edd87.js b/assets/js/10bc4617.489edd87.js new file mode 100644 index 0000000000..d3fae4aba7 --- /dev/null +++ b/assets/js/10bc4617.489edd87.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5944],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var a=n.createContext({}),p=function(e){var t=n.useContext(a),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(a.Provider,{value:t},e.children)},l="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,c=e.originalType,a=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),l=p(r),f=o,d=l["".concat(a,".").concat(f)]||l[f]||m[f]||c;return r?n.createElement(d,s(s({ref:t},u),{},{components:r})):n.createElement(d,s({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=r.length,s=new Array(c);s[0]=f;var i={};for(var a in t)hasOwnProperty.call(t,a)&&(i[a]=t[a]);i.originalType=e,i[l]="string"==typeof e?e:o,s[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>m,frontMatter:()=>c,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const c={},s="Epoch Time",i={unversionedId:"core/consensus/services/epochtime",id:"core/consensus/services/epochtime",title:"Epoch Time",description:"",source:"@site/docs/core/consensus/services/epochtime.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/epochtime",permalink:"/core/consensus/services/epochtime",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/epochtime.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Services",permalink:"/core/consensus/services"},next:{title:"Random Beacon",permalink:"/core/consensus/services/beacon"}},a={},p=[],u={toc:p},l="wrapper";function m(e){let{components:t,...r}=e;return(0,o.kt)(l,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"epoch-time"},"Epoch Time"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/14eb3368.2567bcb8.js b/assets/js/14eb3368.2567bcb8.js new file mode 100644 index 0000000000..81f8ad4203 --- /dev/null +++ b/assets/js/14eb3368.2567bcb8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9817],{1310:(e,t,a)=>{a.d(t,{Z:()=>E});var n=a(7462),r=a(7294),i=a(6010),l=a(5281),s=a(3438),c=a(8596),o=a(9960),m=a(5999),d=a(4996);function u(e){return r.createElement("svg",(0,n.Z)({viewBox:"0 0 24 24"},e),r.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}const h={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function b(){const e=(0,d.Z)("/");return r.createElement("li",{className:"breadcrumbs__item"},r.createElement(o.Z,{"aria-label":(0,m.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e},r.createElement(u,{className:h.breadcrumbHomeIcon})))}const v={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function g(e){let{children:t,href:a,isLast:n}=e;const i="breadcrumbs__link";return n?r.createElement("span",{className:i,itemProp:"name"},t):a?r.createElement(o.Z,{className:i,href:a,itemProp:"item"},r.createElement("span",{itemProp:"name"},t)):r.createElement("span",{className:i},t)}function p(e){let{children:t,active:a,index:l,addMicrodata:s}=e;return r.createElement("li",(0,n.Z)({},s&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,i.Z)("breadcrumbs__item",{"breadcrumbs__item--active":a})}),t,r.createElement("meta",{itemProp:"position",content:String(l+1)}))}function E(){const e=(0,s.s1)(),t=(0,c.Ns)();return e?r.createElement("nav",{className:(0,i.Z)(l.k.docs.docBreadcrumbs,v.breadcrumbsContainer),"aria-label":(0,m.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},r.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&r.createElement(b,null),e.map(((t,a)=>{const n=a===e.length-1;return r.createElement(p,{key:a,active:n,index:a,addMicrodata:!!t.href},r.createElement(g,{href:t.href,isLast:n},t.label))})))):null}},1564:(e,t,a)=>{a.d(t,{Z:()=>b});var n=a(7294),r=a(6010),i=a(9960),l=a(3438),s=a(3919),c=a(5999);const o={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function m(e){let{href:t,children:a}=e;return n.createElement(i.Z,{href:t,className:(0,r.Z)("card padding--lg",o.cardContainer)},a)}function d(e){let{href:t,icon:a,title:i,description:l}=e;return n.createElement(m,{href:t},n.createElement("h2",{className:(0,r.Z)("text--truncate",o.cardTitle),title:i},a," ",i),l&&n.createElement("p",{className:(0,r.Z)("text--truncate",o.cardDescription),title:l},l))}function u(e){let{item:t}=e;const a=(0,l.Wl)(t);return a?n.createElement(d,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,c.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function h(e){let{item:t}=e;const a=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,l.xz)(t.docId??void 0);return n.createElement(d,{href:t.href,icon:a,title:t.label,description:t.description??r?.description})}function b(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(h,{item:t});case"category":return n.createElement(u,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,a)=>{a.d(t,{Z:()=>c});var n=a(7294),r=a(6010),i=a(3438),l=a(1564);function s(e){let{className:t}=e;const a=(0,i.jA)();return n.createElement(c,{items:a.items,className:t})}function c(e){const{items:t,className:a}=e;if(!t)return n.createElement(s,e);const c=(0,i.MN)(t);return n.createElement("section",{className:(0,r.Z)("row",a)},c.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(l.Z,{item:e})))))}},5541:(e,t,a)=>{a.r(t),a.d(t,{default:()=>g});var n=a(7294),r=a(1944),i=a(3438),l=a(4996),s=a(9268),c=a(4966),o=a(3120),m=a(4364),d=a(1310),u=a(2503);const h={generatedIndexPage:"generatedIndexPage_vN6x",list:"list_eTzJ",title:"title_kItE"};function b(e){let{categoryGeneratedIndex:t}=e;return n.createElement(r.d,{title:t.title,description:t.description,keywords:t.keywords,image:(0,l.Z)(t.image)})}function v(e){let{categoryGeneratedIndex:t}=e;const a=(0,i.jA)();return n.createElement("div",{className:h.generatedIndexPage},n.createElement(o.Z,null),n.createElement(d.Z,null),n.createElement(m.Z,null),n.createElement("header",null,n.createElement(u.Z,{as:"h1",className:h.title},t.title),t.description&&n.createElement("p",null,t.description)),n.createElement("article",{className:"margin-top--lg"},n.createElement(s.Z,{items:a.items,className:h.list})),n.createElement("footer",{className:"margin-top--lg"},n.createElement(c.Z,{previous:t.navigation.previous,next:t.navigation.next})))}function g(e){return n.createElement(n.Fragment,null,n.createElement(b,e),n.createElement(v,e))}},4966:(e,t,a)=>{a.d(t,{Z:()=>o});var n=a(7462),r=a(7294),i=a(5999),l=a(6010),s=a(9960);function c(e){const{permalink:t,title:a,subLabel:n,isNext:i}=e;return r.createElement(s.Z,{className:(0,l.Z)("pagination-nav__link",i?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},n&&r.createElement("div",{className:"pagination-nav__sublabel"},n),r.createElement("div",{className:"pagination-nav__label"},a))}function o(e){const{previous:t,next:a}=e;return r.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,i.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"})},t&&r.createElement(c,(0,n.Z)({},t,{subLabel:r.createElement(i.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),a&&r.createElement(c,(0,n.Z)({},a,{subLabel:r.createElement(i.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}},4364:(e,t,a)=>{a.d(t,{Z:()=>c});var n=a(7294),r=a(6010),i=a(5999),l=a(5281),s=a(4477);function c(e){let{className:t}=e;const a=(0,s.E)();return a.badge?n.createElement("span",{className:(0,r.Z)(t,l.k.docs.docVersionBadge,"badge badge--secondary")},n.createElement(i.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:a.label}},"Version: {versionLabel}")):null}},3120:(e,t,a)=>{a.d(t,{Z:()=>g});var n=a(7294),r=a(6010),i=a(2263),l=a(9960),s=a(5999),c=a(143),o=a(5281),m=a(373),d=a(4477);const u={unreleased:function(e){let{siteTitle:t,versionMetadata:a}=e;return n.createElement(s.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:n.createElement("b",null,a.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){let{siteTitle:t,versionMetadata:a}=e;return n.createElement(s.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:n.createElement("b",null,a.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function h(e){const t=u[e.versionMetadata.banner];return n.createElement(t,e)}function b(e){let{versionLabel:t,to:a,onClick:r}=e;return n.createElement(s.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:n.createElement("b",null,n.createElement(l.Z,{to:a,onClick:r},n.createElement(s.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function v(e){let{className:t,versionMetadata:a}=e;const{siteConfig:{title:l}}=(0,i.Z)(),{pluginId:s}=(0,c.gA)({failfast:!0}),{savePreferredVersionName:d}=(0,m.J)(s),{latestDocSuggestion:u,latestVersionSuggestion:v}=(0,c.Jo)(s),g=u??(p=v).docs.find((e=>e.id===p.mainDocId));var p;return n.createElement("div",{className:(0,r.Z)(t,o.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},n.createElement("div",null,n.createElement(h,{siteTitle:l,versionMetadata:a})),n.createElement("div",{className:"margin-top--md"},n.createElement(b,{versionLabel:v.label,to:g.path,onClick:()=>d(v.name)})))}function g(e){let{className:t}=e;const a=(0,d.E)();return a.banner?n.createElement(v,{className:t,versionMetadata:a}):null}},2503:(e,t,a)=>{a.d(t,{Z:()=>m});var n=a(7462),r=a(7294),i=a(6010),l=a(5999),s=a(6668),c=a(9960);const o={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};function m(e){let{as:t,id:a,...m}=e;const{navbar:{hideOnScroll:d}}=(0,s.L)();if("h1"===t||!a)return r.createElement(t,(0,n.Z)({},m,{id:void 0}));const u=(0,l.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof m.children?m.children:a});return r.createElement(t,(0,n.Z)({},m,{className:(0,i.Z)("anchor",d?o.anchorWithHideOnScrollNavbar:o.anchorWithStickyNavbar,m.className),id:a}),m.children,r.createElement(c.Z,{className:"hash-link",to:`#${a}`,"aria-label":u,title:u},"\u200b"))}}}]); \ No newline at end of file diff --git a/assets/js/167edc4b.9a923c2a.js b/assets/js/167edc4b.9a923c2a.js new file mode 100644 index 0000000000..76d81c192c --- /dev/null +++ b/assets/js/167edc4b.9a923c2a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3019],{4526:e=>{e.exports=JSON.parse('{"title":"Previous Upgrades","description":"This section provides documentation on previous upgrades of Oasis Network\'s Mainnet.","slug":"node/mainnet/previous-upgrades","permalink":"/node/mainnet/previous-upgrades","navigation":{"previous":{"title":"Damask Upgrade","permalink":"/node/mainnet/damask-upgrade"},"next":{"title":"Cobalt Upgrade","permalink":"/node/mainnet/previous-upgrades/cobalt-upgrade"}}}')}}]); \ No newline at end of file diff --git a/assets/js/17896441.2dcd082c.js b/assets/js/17896441.2dcd082c.js new file mode 100644 index 0000000000..e20fe4787e --- /dev/null +++ b/assets/js/17896441.2dcd082c.js @@ -0,0 +1 @@ +(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7918],{3905:(e,t,n)=>{"use strict";n.d(t,{Zo:()=>d,kt:()=>f});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=a.createContext({}),i=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},d=function(e){var t=i(e.components);return a.createElement(s.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},p=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),m=i(n),p=o,f=m["".concat(s,".").concat(p)]||m[p]||u[p]||r;return n?a.createElement(f,l(l({ref:t},d),{},{components:n})):a.createElement(f,l({ref:t},d))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,l=new Array(r);l[0]=p;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c[m]="string"==typeof e?e:o,l[1]=c;for(var i=2;i{"use strict";n.d(t,{Z:()=>v});var a=n(7462),o=n(7294),r=n(6010),l=n(5281),c=n(3438),s=n(8596),i=n(9960),d=n(5999),m=n(4996);function u(e){return o.createElement("svg",(0,a.Z)({viewBox:"0 0 24 24"},e),o.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}const p={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function f(){const e=(0,m.Z)("/");return o.createElement("li",{className:"breadcrumbs__item"},o.createElement(i.Z,{"aria-label":(0,d.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e},o.createElement(u,{className:p.breadcrumbHomeIcon})))}const h={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function g(e){let{children:t,href:n,isLast:a}=e;const r="breadcrumbs__link";return a?o.createElement("span",{className:r,itemProp:"name"},t):n?o.createElement(i.Z,{className:r,href:n,itemProp:"item"},o.createElement("span",{itemProp:"name"},t)):o.createElement("span",{className:r},t)}function b(e){let{children:t,active:n,index:l,addMicrodata:c}=e;return o.createElement("li",(0,a.Z)({},c&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,r.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,o.createElement("meta",{itemProp:"position",content:String(l+1)}))}function v(){const e=(0,c.s1)(),t=(0,s.Ns)();return e?o.createElement("nav",{className:(0,r.Z)(l.k.docs.docBreadcrumbs,h.breadcrumbsContainer),"aria-label":(0,d.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},o.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&o.createElement(f,null),e.map(((t,n)=>{const a=n===e.length-1;return o.createElement(b,{key:n,active:a,index:n,addMicrodata:!!t.href},o.createElement(g,{href:t.href,isLast:a},t.label))})))):null}},620:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>mt});var a=n(7294),o=n(1944),r=n(902);const l=a.createContext(null);function c(e){let{children:t,content:n}=e;const o=function(e){return(0,a.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return a.createElement(l.Provider,{value:o},t)}function s(){const e=(0,a.useContext)(l);if(null===e)throw new r.i6("DocProvider");return e}function i(){const{metadata:e,frontMatter:t,assets:n}=s();return a.createElement(o.d,{title:e.title,description:e.description,keywords:t.keywords,image:n.image??t.image})}var d=n(6010),m=n(7524),u=n(4966);function p(){const{metadata:e}=s();return a.createElement(u.Z,{previous:e.previous,next:e.next})}var f=n(3120),h=n(4364),g=n(5281),b=n(5999);function v(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n}=e;return a.createElement(b.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:a.createElement("b",null,a.createElement("time",{dateTime:new Date(1e3*t).toISOString()},n))}}," on {date}")}function E(e){let{lastUpdatedBy:t}=e;return a.createElement(b.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:a.createElement("b",null,t)}}," by {user}")}function y(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n,lastUpdatedBy:o}=e;return a.createElement("span",{className:g.k.common.lastUpdated},a.createElement(b.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?a.createElement(v,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:o?a.createElement(E,{lastUpdatedBy:o}):""}},"Last updated{atDate}{byUser}"),!1)}var k=n(7462);const N={iconEdit:"iconEdit_Z9Sw"};function C(e){let{className:t,...n}=e;return a.createElement("svg",(0,k.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,d.Z)(N.iconEdit,t),"aria-hidden":"true"},n),a.createElement("g",null,a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function L(e){let{editUrl:t}=e;return a.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:g.k.common.editThisPage},a.createElement(C,null),a.createElement(b.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}var Z=n(9960);const _={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function T(e){let{permalink:t,label:n,count:o}=e;return a.createElement(Z.Z,{href:t,className:(0,d.Z)(_.tag,o?_.tagWithCount:_.tagRegular)},n,o&&a.createElement("span",null,o))}const w={tags:"tags_jXut",tag:"tag_QGVx"};function B(e){let{tags:t}=e;return a.createElement(a.Fragment,null,a.createElement("b",null,a.createElement(b.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),a.createElement("ul",{className:(0,d.Z)(w.tags,"padding--none","margin-left--sm")},t.map((e=>{let{label:t,permalink:n}=e;return a.createElement("li",{key:n,className:w.tag},a.createElement(T,{label:t,permalink:n}))}))))}const x={lastUpdated:"lastUpdated_vwxv"};function O(e){return a.createElement("div",{className:(0,d.Z)(g.k.docs.docFooterTagsRow,"row margin-bottom--sm")},a.createElement("div",{className:"col"},a.createElement(B,e)))}function H(e){let{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:o,formattedLastUpdatedAt:r}=e;return a.createElement("div",{className:(0,d.Z)(g.k.docs.docFooterEditMetaRow,"row")},a.createElement("div",{className:"col"},t&&a.createElement(L,{editUrl:t})),a.createElement("div",{className:(0,d.Z)("col",x.lastUpdated)},(n||o)&&a.createElement(y,{lastUpdatedAt:n,formattedLastUpdatedAt:r,lastUpdatedBy:o})))}function A(){const{metadata:e}=s(),{editUrl:t,lastUpdatedAt:n,formattedLastUpdatedAt:o,lastUpdatedBy:r,tags:l}=e,c=l.length>0,i=!!(t||n||r);return c||i?a.createElement("footer",{className:(0,d.Z)(g.k.docs.docFooter,"docusaurus-mt-lg")},c&&a.createElement(O,{tags:l}),i&&a.createElement(H,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:r,formattedLastUpdatedAt:o})):null}var j=n(6043),S=n(6668);function I(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const a=n.slice(2,e.level);e.parentIndex=Math.max(...a),n[e.level]=t}));const a=[];return t.forEach((e=>{const{parentIndex:n,...o}=e;n>=0?t[n].children.push(o):a.push(o)})),a}function M(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return t.flatMap((e=>{const t=M({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[{...e,children:t}]:t}))}function P(e){const t=e.getBoundingClientRect();return t.top===t.bottom?P(e.parentNode):t}function U(e,t){let{anchorTopOffset:n}=t;const a=e.find((e=>P(e).top>=n));if(a){return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function V(e){const t=(0,a.useRef)(void 0),n=z();(0,a.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:a,linkActiveClassName:o,minHeadingLevel:r,maxHeadingLevel:l}=e;function c(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(a),c=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const a=[];for(let o=t;o<=n;o+=1)a.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(a.join()))}({minHeadingLevel:r,maxHeadingLevel:l}),s=U(c,{anchorTopOffset:n.current}),i=e.find((e=>s&&s.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(o),e.classList.add(o),t.current=e):e.classList.remove(o)}(e,e===i)}))}return document.addEventListener("scroll",c),document.addEventListener("resize",c),c(),()=>{document.removeEventListener("scroll",c),document.removeEventListener("resize",c)}}),[e,n])}function D(e){let{toc:t,className:n,linkClassName:o,isChild:r}=e;return t.length?a.createElement("ul",{className:r?void 0:n},t.map((e=>a.createElement("li",{key:e.id},a.createElement("a",{href:`#${e.id}`,className:o??void 0,dangerouslySetInnerHTML:{__html:e.value}}),a.createElement(D,{isChild:!0,toc:e.children,className:n,linkClassName:o}))))):null}const R=a.memo(D);function W(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:o="table-of-contents__link",linkActiveClassName:r,minHeadingLevel:l,maxHeadingLevel:c,...s}=e;const i=(0,S.L)(),d=l??i.tableOfContents.minHeadingLevel,m=c??i.tableOfContents.maxHeadingLevel,u=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:o}=e;return(0,a.useMemo)((()=>M({toc:I(t),minHeadingLevel:n,maxHeadingLevel:o})),[t,n,o])}({toc:t,minHeadingLevel:d,maxHeadingLevel:m});return V((0,a.useMemo)((()=>{if(o&&r)return{linkClassName:o,linkActiveClassName:r,minHeadingLevel:d,maxHeadingLevel:m}}),[o,r,d,m])),a.createElement(R,(0,k.Z)({toc:u,className:n,linkClassName:o},s))}const $={tocCollapsibleButton:"tocCollapsibleButton_TO0P",tocCollapsibleButtonExpanded:"tocCollapsibleButtonExpanded_MG3E"};function F(e){let{collapsed:t,...n}=e;return a.createElement("button",(0,k.Z)({type:"button"},n,{className:(0,d.Z)("clean-btn",$.tocCollapsibleButton,!t&&$.tocCollapsibleButtonExpanded,n.className)}),a.createElement(b.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component"},"On this page"))}const q={tocCollapsible:"tocCollapsible_ETCw",tocCollapsibleContent:"tocCollapsibleContent_vkbj",tocCollapsibleExpanded:"tocCollapsibleExpanded_sAul"};function G(e){let{toc:t,className:n,minHeadingLevel:o,maxHeadingLevel:r}=e;const{collapsed:l,toggleCollapsed:c}=(0,j.u)({initialState:!0});return a.createElement("div",{className:(0,d.Z)(q.tocCollapsible,!l&&q.tocCollapsibleExpanded,n)},a.createElement(F,{collapsed:l,onClick:c}),a.createElement(j.z,{lazy:!0,className:q.tocCollapsibleContent,collapsed:l},a.createElement(W,{toc:t,minHeadingLevel:o,maxHeadingLevel:r})))}const Y={tocMobile:"tocMobile_ITEo"};function J(){const{toc:e,frontMatter:t}=s();return a.createElement(G,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,d.Z)(g.k.docs.docTocMobile,Y.tocMobile)})}const Q={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"},X="table-of-contents__link toc-highlight",K="table-of-contents__link--active";function ee(e){let{className:t,...n}=e;return a.createElement("div",{className:(0,d.Z)(Q.tableOfContents,"thin-scrollbar",t)},a.createElement(W,(0,k.Z)({},n,{linkClassName:X,linkActiveClassName:K})))}function te(){const{toc:e,frontMatter:t}=s();return a.createElement(ee,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:g.k.docs.docTocDesktop})}var ne=n(2503),ae=n(3905),oe=n(5742);var re=n(2389),le=n(2949);function ce(){const{prism:e}=(0,S.L)(),{colorMode:t}=(0,le.I)(),n=e.theme,a=e.darkTheme||n;return"dark"===t?a:n}var se=n(7594),ie=n.n(se);const de=/title=(?["'])(?.*?)\1/,me=/\{(?<range>[\d,-]+)\}/,ue={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}};function pe(e,t){const n=e.map((e=>{const{start:n,end:a}=ue[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${a})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function fe(e,t){let n=e.replace(/\n$/,"");const{language:a,magicComments:o,metastring:r}=t;if(r&&me.test(r)){const e=r.match(me).groups.range;if(0===o.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${r}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=o[0].className,a=ie()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(a),code:n}}if(void 0===a)return{lineClassNames:{},code:n};const l=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return pe(["js","jsBlock"],t);case"jsx":case"tsx":return pe(["js","jsBlock","jsx"],t);case"html":return pe(["js","jsBlock","html"],t);case"python":case"py":case"bash":return pe(["bash"],t);case"markdown":case"md":return pe(["html","jsx","bash"],t);default:return pe(Object.keys(ue),t)}}(a,o),c=n.split("\n"),s=Object.fromEntries(o.map((e=>[e.className,{start:0,range:""}]))),i=Object.fromEntries(o.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),m=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let p=0;p<c.length;){const e=c[p].match(l);if(!e){p+=1;continue}const t=e.slice(1).find((e=>void 0!==e));i[t]?s[i[t]].range+=`${p},`:d[t]?s[d[t]].start=p:m[t]&&(s[m[t]].range+=`${s[m[t]].start}-${p-1},`),c.splice(p,1)}n=c.join("\n");const u={};return Object.entries(s).forEach((e=>{let[t,{range:n}]=e;ie()(n).forEach((e=>{u[e]??=[],u[e].push(t)}))})),{lineClassNames:u,code:n}}const he={codeBlockContainer:"codeBlockContainer_Ckt0"};function ge(e){let{as:t,...n}=e;const o=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[a,o]=e;const r=t[a];r&&"string"==typeof o&&(n[r]=o)})),n}(ce());return a.createElement(t,(0,k.Z)({},n,{style:o,className:(0,d.Z)(n.className,he.codeBlockContainer,g.k.common.codeBlock)}))}const be={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function ve(e){let{children:t,className:n}=e;return a.createElement(ge,{as:"pre",tabIndex:0,className:(0,d.Z)(be.codeBlockStandalone,"thin-scrollbar",n)},a.createElement("code",{className:be.codeBlockLines},t))}const Ee={attributes:!0,characterData:!0,childList:!0,subtree:!0};function ye(e,t){const[n,o]=(0,a.useState)(),l=(0,a.useCallback)((()=>{o(e.current?.closest("[role=tabpanel][hidden]"))}),[e,o]);(0,a.useEffect)((()=>{l()}),[l]),function(e,t,n){void 0===n&&(n=Ee);const o=(0,r.zX)(t),l=(0,r.Ql)(n);(0,a.useEffect)((()=>{const t=new MutationObserver(o);return e&&t.observe(e,l),()=>t.disconnect()}),[e,o,l])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),l())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}const ke={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]};var Ne={Prism:n(7410).Z,theme:ke};function Ce(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Le(){return Le=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},Le.apply(this,arguments)}var Ze=/\r\n|\r|\n/,_e=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},Te=function(e,t){var n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)};function we(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===t.indexOf(a)&&(n[a]=e[a]);return n}var Be=function(e){function t(){for(var t=this,n=[],a=arguments.length;a--;)n[a]=arguments[a];e.apply(this,n),Ce(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?function(e,t){var n=e.plain,a=Object.create(null),o=e.styles.reduce((function(e,n){var a=n.languages,o=n.style;return a&&!a.includes(t)||n.types.forEach((function(t){var n=Le({},e[t],o);e[t]=n})),e}),a);return o.root=n,o.plain=Le({},n,{backgroundColor:null}),o}(e.theme,e.language):void 0;return t.themeDict=n})),Ce(this,"getLineProps",(function(e){var n=e.key,a=e.className,o=e.style,r=Le({},we(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(r.style=l.plain),void 0!==o&&(r.style=void 0!==r.style?Le({},r.style,o):o),void 0!==n&&(r.key=n),a&&(r.className+=" "+a),r})),Ce(this,"getStyleForToken",(function(e){var n=e.types,a=e.empty,o=n.length,r=t.getThemeDict(t.props);if(void 0!==r){if(1===o&&"plain"===n[0])return a?{display:"inline-block"}:void 0;if(1===o&&!a)return r[n[0]];var l=a?{display:"inline-block"}:{},c=n.map((function(e){return r[e]}));return Object.assign.apply(Object,[l].concat(c))}})),Ce(this,"getTokenProps",(function(e){var n=e.key,a=e.className,o=e.style,r=e.token,l=Le({},we(e,["key","className","style","token"]),{className:"token "+r.types.join(" "),children:r.content,style:t.getStyleForToken(r),key:void 0});return void 0!==o&&(l.style=void 0!==l.style?Le({},l.style,o):o),void 0!==n&&(l.key=n),a&&(l.className+=" "+a),l})),Ce(this,"tokenize",(function(e,t,n,a){var o={code:t,grammar:n,language:a,tokens:[]};e.hooks.run("before-tokenize",o);var r=o.tokens=e.tokenize(o.code,o.grammar,o.language);return e.hooks.run("after-tokenize",o),r}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,a=e.code,o=e.children,r=this.getThemeDict(this.props),l=t.languages[n];return o({tokens:function(e){for(var t=[[]],n=[e],a=[0],o=[e.length],r=0,l=0,c=[],s=[c];l>-1;){for(;(r=a[l]++)<o[l];){var i=void 0,d=t[l],m=n[l][r];if("string"==typeof m?(d=l>0?d:["plain"],i=m):(d=Te(d,m.type),m.alias&&(d=Te(d,m.alias)),i=m.content),"string"==typeof i){var u=i.split(Ze),p=u.length;c.push({types:d,content:u[0]});for(var f=1;f<p;f++)_e(c),s.push(c=[]),c.push({types:d,content:u[f]})}else l++,t.push(d),n.push(i),a.push(0),o.push(i.length)}l--,t.pop(),n.pop(),a.pop(),o.pop()}return _e(c),s}(void 0!==l?this.tokenize(t,a,l,n):[a]),className:"prism-code language-"+n,style:void 0!==r?r.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},t}(a.Component);const xe=Be,Oe={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function He(e){let{line:t,classNames:n,showLineNumbers:o,getLineProps:r,getTokenProps:l}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const c=r({line:t,className:(0,d.Z)(n,o&&Oe.codeLine)}),s=t.map(((e,t)=>a.createElement("span",(0,k.Z)({key:t},l({token:e,key:t})))));return a.createElement("span",c,o?a.createElement(a.Fragment,null,a.createElement("span",{className:Oe.codeLineNumber}),a.createElement("span",{className:Oe.codeLineContent},s)):s,a.createElement("br",null))}function Ae(e){return a.createElement("svg",(0,k.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"}))}function je(e){return a.createElement("svg",(0,k.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))}const Se={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function Ie(e){let{code:t,className:n}=e;const[o,r]=(0,a.useState)(!1),l=(0,a.useRef)(void 0),c=(0,a.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const a=document.createElement("textarea"),o=document.activeElement;a.value=e,a.setAttribute("readonly",""),a.style.contain="strict",a.style.position="absolute",a.style.left="-9999px",a.style.fontSize="12pt";const r=document.getSelection(),l=r.rangeCount>0&&r.getRangeAt(0);n.append(a),a.select(),a.selectionStart=0,a.selectionEnd=e.length;let c=!1;try{c=document.execCommand("copy")}catch{}a.remove(),l&&(r.removeAllRanges(),r.addRange(l)),o&&o.focus()}(t),r(!0),l.current=window.setTimeout((()=>{r(!1)}),1e3)}),[t]);return(0,a.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),a.createElement("button",{type:"button","aria-label":o?(0,b.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,b.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,b.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,d.Z)("clean-btn",n,Se.copyButton,o&&Se.copyButtonCopied),onClick:c},a.createElement("span",{className:Se.copyButtonIcons,"aria-hidden":"true"},a.createElement(Ae,{className:Se.copyButtonIcon}),a.createElement(je,{className:Se.copyButtonSuccessIcon})))}function Me(e){return a.createElement("svg",(0,k.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"}))}const Pe={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function Ue(e){let{className:t,onClick:n,isEnabled:o}=e;const r=(0,b.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return a.createElement("button",{type:"button",onClick:n,className:(0,d.Z)("clean-btn",t,o&&Pe.wordWrapButtonEnabled),"aria-label":r,title:r},a.createElement(Me,{className:Pe.wordWrapButtonIcon,"aria-hidden":"true"}))}function ze(e){let{children:t,className:n="",metastring:o,title:r,showLineNumbers:l,language:c}=e;const{prism:{defaultLanguage:s,magicComments:i}}=(0,S.L)(),m=c??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??s,u=ce(),p=function(){const[e,t]=(0,a.useState)(!1),[n,o]=(0,a.useState)(!1),r=(0,a.useRef)(null),l=(0,a.useCallback)((()=>{const n=r.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[r,e]),c=(0,a.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=r.current,n=e>t||r.current.querySelector("code").hasAttribute("style");o(n)}),[r]);return ye(r,c),(0,a.useEffect)((()=>{c()}),[e,c]),(0,a.useEffect)((()=>(window.addEventListener("resize",c,{passive:!0}),()=>{window.removeEventListener("resize",c)})),[c]),{codeBlockRef:r,isEnabled:e,isCodeScrollable:n,toggle:l}}(),f=function(e){return e?.match(de)?.groups.title??""}(o)||r,{lineClassNames:h,code:g}=fe(t,{metastring:o,language:m,magicComments:i}),b=l??function(e){return Boolean(e?.includes("showLineNumbers"))}(o);return a.createElement(ge,{as:"div",className:(0,d.Z)(n,m&&!n.includes(`language-${m}`)&&`language-${m}`)},f&&a.createElement("div",{className:be.codeBlockTitle},f),a.createElement("div",{className:be.codeBlockContent},a.createElement(xe,(0,k.Z)({},Ne,{theme:u,code:g,language:m??"text"}),(e=>{let{className:t,tokens:n,getLineProps:o,getTokenProps:r}=e;return a.createElement("pre",{tabIndex:0,ref:p.codeBlockRef,className:(0,d.Z)(t,be.codeBlock,"thin-scrollbar")},a.createElement("code",{className:(0,d.Z)(be.codeBlockLines,b&&be.codeBlockLinesWithNumbering)},n.map(((e,t)=>a.createElement(He,{key:t,line:e,getLineProps:o,getTokenProps:r,classNames:h[t],showLineNumbers:b})))))})),a.createElement("div",{className:be.buttonGroup},(p.isEnabled||p.isCodeScrollable)&&a.createElement(Ue,{className:be.codeButton,onClick:()=>p.toggle(),isEnabled:p.isEnabled}),a.createElement(Ie,{className:be.codeButton,code:g}))))}function Ve(e){let{children:t,...n}=e;const o=(0,re.Z)(),r=function(e){return a.Children.toArray(e).some((e=>(0,a.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),l="string"==typeof r?ze:ve;return a.createElement(l,(0,k.Z)({key:String(o)},n),r)}const De={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function Re(e){return!!e&&("SUMMARY"===e.tagName||Re(e.parentElement))}function We(e,t){return!!e&&(e===t||We(e.parentElement,t))}function $e(e){let{summary:t,children:n,...o}=e;const r=(0,re.Z)(),l=(0,a.useRef)(null),{collapsed:c,setCollapsed:s}=(0,j.u)({initialState:!o.open}),[i,m]=(0,a.useState)(o.open),u=a.isValidElement(t)?t:a.createElement("summary",null,t??"Details");return a.createElement("details",(0,k.Z)({},o,{ref:l,open:i,"data-collapsed":c,className:(0,d.Z)(De.details,r&&De.isBrowser,o.className),onMouseDown:e=>{Re(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;Re(t)&&We(t,l.current)&&(e.preventDefault(),c?(s(!1),m(!0)):s(!0))}}),u,a.createElement(j.z,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{s(e),m(!e)}},a.createElement("div",{className:De.collapsibleContent},n)))}const Fe={details:"details_b_Ee"},qe="alert alert--info";function Ge(e){let{...t}=e;return a.createElement($e,(0,k.Z)({},t,{className:(0,d.Z)(qe,Fe.details,t.className)}))}function Ye(e){return a.createElement(ne.Z,e)}const Je={containsTaskList:"containsTaskList_mC6p"};const Qe={img:"img_ev3q"};const Xe="admonition_LlT9",Ke="admonitionHeading_tbUL",et="admonitionIcon_kALy",tt="admonitionContent_S0QG";const nt={note:{infimaClassName:"secondary",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:a.createElement(b.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:a.createElement(b.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:a.createElement(b.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:a.createElement(b.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 16 16"},a.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:a.createElement(b.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},at={secondary:"note",important:"info",success:"tip",warning:"danger"};function ot(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=a.Children.toArray(e),n=t.find((e=>a.isValidElement(e)&&"mdxAdmonitionTitle"===e.props?.mdxType)),o=a.createElement(a.Fragment,null,t.filter((e=>e!==n)));return{mdxAdmonitionTitle:n,rest:o}}(e.children);return{...e,title:e.title??t,children:n}}const rt={head:function(e){const t=a.Children.map(e.children,(e=>a.isValidElement(e)?function(e){if(e.props?.mdxType&&e.props.originalType){const{mdxType:t,originalType:n,...o}=e.props;return a.createElement(e.props.originalType,o)}return e}(e):e));return a.createElement(oe.Z,e,t)},code:function(e){const t=["a","abbr","b","br","button","cite","code","del","dfn","em","i","img","input","ins","kbd","label","object","output","q","ruby","s","small","span","strong","sub","sup","time","u","var","wbr"];return a.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")||(0,a.isValidElement)(e)&&t.includes(e.props?.mdxType)))?a.createElement("code",e):a.createElement(Ve,e)},a:function(e){return a.createElement(Z.Z,e)},pre:function(e){return a.createElement(Ve,(0,a.isValidElement)(e.children)&&"code"===e.children.props?.originalType?e.children.props:{...e})},details:function(e){const t=a.Children.toArray(e.children),n=t.find((e=>a.isValidElement(e)&&"summary"===e.props?.mdxType)),o=a.createElement(a.Fragment,null,t.filter((e=>e!==n)));return a.createElement(Ge,(0,k.Z)({},e,{summary:n}),o)},ul:function(e){return a.createElement("ul",(0,k.Z)({},e,{className:(t=e.className,(0,d.Z)(t,t?.includes("contains-task-list")&&Je.containsTaskList))}));var t},img:function(e){return a.createElement("img",(0,k.Z)({loading:"lazy"},e,{className:(t=e.className,(0,d.Z)(t,Qe.img))}));var t},h1:e=>a.createElement(Ye,(0,k.Z)({as:"h1"},e)),h2:e=>a.createElement(Ye,(0,k.Z)({as:"h2"},e)),h3:e=>a.createElement(Ye,(0,k.Z)({as:"h3"},e)),h4:e=>a.createElement(Ye,(0,k.Z)({as:"h4"},e)),h5:e=>a.createElement(Ye,(0,k.Z)({as:"h5"},e)),h6:e=>a.createElement(Ye,(0,k.Z)({as:"h6"},e)),admonition:function(e){const{children:t,type:n,title:o,icon:r}=ot(e),l=function(e){const t=at[e]??e,n=nt[t];return n||(console.warn(`No admonition config found for admonition type "${t}". Using Info as fallback.`),nt.info)}(n),c=o??l.label,{iconComponent:s}=l,i=r??a.createElement(s,null);return a.createElement("div",{className:(0,d.Z)(g.k.common.admonition,g.k.common.admonitionType(e.type),"alert",`alert--${l.infimaClassName}`,Xe)},a.createElement("div",{className:Ke},a.createElement("span",{className:et},i),c),a.createElement("div",{className:tt},t))},mermaid:()=>null};function lt(e){let{children:t}=e;return a.createElement(ae.Zo,{components:rt},t)}function ct(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=s();return t.hide_title||void 0!==n?null:e.title}();return a.createElement("div",{className:(0,d.Z)(g.k.docs.docMarkdown,"markdown")},n&&a.createElement("header",null,a.createElement(ne.Z,{as:"h1"},n)),a.createElement(lt,null,t))}var st=n(1310);const it={docItemContainer:"docItemContainer_Djhp",docItemCol:"docItemCol_VOVn"};function dt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=s(),n=(0,m.i)(),o=e.hide_table_of_contents,r=!o&&t.length>0;return{hidden:o,mobile:r?a.createElement(J,null):void 0,desktop:!r||"desktop"!==n&&"ssr"!==n?void 0:a.createElement(te,null)}}();return a.createElement("div",{className:"row"},a.createElement("div",{className:(0,d.Z)("col",!n.hidden&&it.docItemCol)},a.createElement(f.Z,null),a.createElement("div",{className:it.docItemContainer},a.createElement("article",null,a.createElement(st.Z,null),a.createElement(h.Z,null),n.mobile,a.createElement(ct,null,t),a.createElement(A,null)),a.createElement(p,null))),n.desktop&&a.createElement("div",{className:"col col--3"},n.desktop))}function mt(e){const t=`docs-doc-id-${e.content.metadata.unversionedId}`,n=e.content;return a.createElement(c,{content:e.content},a.createElement(o.FG,{className:t},a.createElement(i,null),a.createElement(dt,null,a.createElement(n,null))))}},4966:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var a=n(7462),o=n(7294),r=n(5999),l=n(6010),c=n(9960);function s(e){const{permalink:t,title:n,subLabel:a,isNext:r}=e;return o.createElement(c.Z,{className:(0,l.Z)("pagination-nav__link",r?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},a&&o.createElement("div",{className:"pagination-nav__sublabel"},a),o.createElement("div",{className:"pagination-nav__label"},n))}function i(e){const{previous:t,next:n}=e;return o.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,r.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"})},t&&o.createElement(s,(0,a.Z)({},t,{subLabel:o.createElement(r.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),n&&o.createElement(s,(0,a.Z)({},n,{subLabel:o.createElement(r.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}},4364:(e,t,n)=>{"use strict";n.d(t,{Z:()=>s});var a=n(7294),o=n(6010),r=n(5999),l=n(5281),c=n(4477);function s(e){let{className:t}=e;const n=(0,c.E)();return n.badge?a.createElement("span",{className:(0,o.Z)(t,l.k.docs.docVersionBadge,"badge badge--secondary")},a.createElement(r.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label}},"Version: {versionLabel}")):null}},3120:(e,t,n)=>{"use strict";n.d(t,{Z:()=>g});var a=n(7294),o=n(6010),r=n(2263),l=n(9960),c=n(5999),s=n(143),i=n(5281),d=n(373),m=n(4477);const u={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(c.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(c.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function p(e){const t=u[e.versionMetadata.banner];return a.createElement(t,e)}function f(e){let{versionLabel:t,to:n,onClick:o}=e;return a.createElement(c.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:a.createElement("b",null,a.createElement(l.Z,{to:n,onClick:o},a.createElement(c.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function h(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:l}}=(0,r.Z)(),{pluginId:c}=(0,s.gA)({failfast:!0}),{savePreferredVersionName:m}=(0,d.J)(c),{latestDocSuggestion:u,latestVersionSuggestion:h}=(0,s.Jo)(c),g=u??(b=h).docs.find((e=>e.id===b.mainDocId));var b;return a.createElement("div",{className:(0,o.Z)(t,i.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},a.createElement("div",null,a.createElement(p,{siteTitle:l,versionMetadata:n})),a.createElement("div",{className:"margin-top--md"},a.createElement(f,{versionLabel:h.label,to:g.path,onClick:()=>m(h.name)})))}function g(e){let{className:t}=e;const n=(0,m.E)();return n.banner?a.createElement(h,{className:t,versionMetadata:n}):null}},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var a=n(7462),o=n(7294),r=n(6010),l=n(5999),c=n(6668),s=n(9960);const i={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};function d(e){let{as:t,id:n,...d}=e;const{navbar:{hideOnScroll:m}}=(0,c.L)();if("h1"===t||!n)return o.createElement(t,(0,a.Z)({},d,{id:void 0}));const u=(0,l.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof d.children?d.children:n});return o.createElement(t,(0,a.Z)({},d,{className:(0,r.Z)("anchor",m?i.anchorWithHideOnScrollNavbar:i.anchorWithStickyNavbar,d.className),id:n}),d.children,o.createElement(s.Z,{className:"hash-link",to:`#${n}`,"aria-label":u,title:u},"\u200b"))}},7594:(e,t)=>{function n(e){let t,n=[];for(let a of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(a))n.push(parseInt(a,10));else if(t=a.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,a,o,r]=t;if(a&&r){a=parseInt(a),r=parseInt(r);const e=a<r?1:-1;"-"!==o&&".."!==o&&"\u2025"!==o||(r+=e);for(let t=a;t!==r;t+=e)n.push(t)}}return n}t.default=n,e.exports=n}}]); \ No newline at end of file diff --git a/assets/js/1a4e3797.6bfd8fb9.js b/assets/js/1a4e3797.6bfd8fb9.js new file mode 100644 index 0000000000..44639d6f10 --- /dev/null +++ b/assets/js/1a4e3797.6bfd8fb9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7920],{2027:(e,t,a)=>{a.r(t),a.d(t,{default:()=>F});var r=a(7294),n=a(2263),s=a(179),l=a(5742),c=a(9960),o=a(5999);const u=["zero","one","two","few","many","other"];function m(e){return u.filter((t=>e.includes(t)))}const h={locale:"en",pluralForms:m(["one","other"]),select:e=>1===e?"one":"other"};function i(){const{i18n:{currentLocale:e}}=(0,n.Z)();return(0,r.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:m(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${t.message}\n`),h}}),[e])}function p(){const e=i();return{selectMessage:(t,a)=>function(e,t,a){const r=e.split("|");if(1===r.length)return r[0];r.length>a.pluralForms.length&&console.error(`For locale=${a.locale}, a maximum of ${a.pluralForms.length} plural forms are expected (${a.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const n=a.select(t),s=a.pluralForms.indexOf(n);return r[Math.min(s,r.length-1)]}(a,t,e)}}var d=a(6010),g=a(6550),f=a(412);const y=function(){const e=(0,g.k6)(),t=(0,g.TH)(),{siteConfig:{baseUrl:a}}=(0,n.Z)(),r=f.Z.canUseDOM?new URLSearchParams(t.search):null,s=r?.get("q")||"",l=r?.get("ctx")||"",c=r?.get("version")||"",o=e=>{const a=new URLSearchParams(t.search);return e?a.set("q",e):a.delete("q"),a};return{searchValue:s,searchContext:l,searchVersion:c,updateSearchPath:t=>{const a=o(t);e.replace({search:a.toString()})},updateSearchContext:a=>{const r=new URLSearchParams(t.search);r.set("ctx",a),e.replace({search:r.toString()})},generateSearchPageLink:e=>{const t=o(e);return`${a}search?${t.toString()}`}}};var E=a(22),S=a(8202),I=a(2539),v=a(726),w=a(1073),R=a(311),C=a(3926),P=a(1029);const x={searchVersionInput:"searchVersionInput_t5lH",searchQueryInput:"searchQueryInput_CFBF",searchResultItem:"searchResultItem_U687",searchResultItemPath:"searchResultItemPath_uIbk",searchResultItemSummary:"searchResultItemSummary_oZHr"};function _(){const{siteConfig:{baseUrl:e}}=(0,n.Z)(),{selectMessage:t}=p(),{searchValue:a,searchContext:s,searchVersion:c,updateSearchPath:u,updateSearchContext:m}=y(),[h,i]=(0,r.useState)(a),[g,f]=(0,r.useState)(),[I,v]=(0,r.useState)(),w=`${e}${c}`,C=(0,r.useMemo)((()=>h?(0,o.I)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:h}):(0,o.I)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"})),[h]);(0,r.useEffect)((()=>{u(h),g&&(h?g(h,(e=>{v(e)})):v(void 0))}),[h,g]);const _=(0,r.useCallback)((e=>{i(e.target.value)}),[]);return(0,r.useEffect)((()=>{a&&a!==h&&i(a)}),[a]),(0,r.useEffect)((()=>{!async function(){const{wrappedIndexes:e,zhDictionary:t}=await(0,E.w)(w,s);f((()=>(0,S.v)(e,t,100)))}()}),[s,w]),r.createElement(r.Fragment,null,r.createElement(l.Z,null,r.createElement("meta",{property:"robots",content:"noindex, follow"}),r.createElement("title",null,C)),r.createElement("div",{className:"container margin-vert--lg"},r.createElement("h1",null,C),r.createElement("div",{className:"row"},r.createElement("div",{className:(0,d.Z)("col",x.searchQueryColumn,{"col--9":Array.isArray(P.Kc),"col--12":!Array.isArray(P.Kc)})},r.createElement("input",{type:"search",name:"q",className:x.searchQueryInput,"aria-label":"Search",onChange:_,value:h,autoComplete:"off",autoFocus:!0})),Array.isArray(P.Kc)?r.createElement("div",{className:(0,d.Z)("col","col--3","padding-left--none",x.searchVersionColumn)},r.createElement("select",{name:"search-context",className:x.searchVersionInput,id:"context-selector",value:s,onChange:e=>m(e.target.value)},r.createElement("option",{value:""},P.pQ?(0,o.I)({id:"theme.SearchPage.searchContext.everywhere",message:"everywhere"}):""),P.Kc.map((e=>r.createElement("option",{key:e,value:e},e))))):null),!g&&h&&r.createElement("div",null,r.createElement(R.Z,null)),I&&(I.length>0?r.createElement("p",null,t(I.length,(0,o.I)({id:"theme.SearchPage.documentsFound.plurals",message:"1 document found|{count} documents found",description:'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)'},{count:I.length}))):r.createElement("p",null,(0,o.I)({id:"theme.SearchPage.noResultsText",message:"No documents were found",description:"The paragraph for empty search result"}))),r.createElement("section",null,I&&I.map((e=>r.createElement(b,{key:e.document.i,searchResult:e}))))))}function b(e){let{searchResult:{document:t,type:a,page:n,tokens:s,metadata:l}}=e;const o=0===a,u=2===a,m=(o?t.b:n.b).slice(),h=u?t.s:t.t;o||m.push(n.t);let i="";if(P.vc&&s.length>0){const e=new URLSearchParams;for(const t of s)e.append("_highlight",t);i=`?${e.toString()}`}return r.createElement("article",{className:x.searchResultItem},r.createElement("h2",null,r.createElement(c.Z,{to:t.u+i+(t.h||""),dangerouslySetInnerHTML:{__html:u?(0,I.C)(h,s):(0,v.o)(h,(0,w.m)(l,"t"),s,100)}})),m.length>0&&r.createElement("p",{className:x.searchResultItemPath},(0,C.e)(m)),u&&r.createElement("p",{className:x.searchResultItemSummary,dangerouslySetInnerHTML:{__html:(0,v.o)(t.t,(0,w.m)(l,"t"),s,100)}}))}const F=function(){return r.createElement(s.Z,null,r.createElement(_,null))}}}]); \ No newline at end of file diff --git a/assets/js/1a50dc2d.f9685b8d.js b/assets/js/1a50dc2d.f9685b8d.js new file mode 100644 index 0000000000..cc58829315 --- /dev/null +++ b/assets/js/1a50dc2d.f9685b8d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7489],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>k});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function p(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var i=a.createContext({}),s=function(e){var t=a.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},c=function(e){var t=s(e.components);return a.createElement(i.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,i=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=s(n),m=r,k=d["".concat(i,".").concat(m)]||d[m]||u[m]||o;return n?a.createElement(k,p(p({ref:t},c),{},{components:n})):a.createElement(k,p({ref:t},c))}));function k(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,p=new Array(o);p[0]=m;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[d]="string"==typeof e?e:r,p[1]=l;for(var s=2;s<o;s++)p[s]=n[s];return a.createElement.apply(null,p)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},6242:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>p,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={},p="Setup",l={unversionedId:"dapp/opl/setup",id:"dapp/opl/setup",title:"Setup",description:"Let's get started and make our new project. You will need Node.js",source:"@site/docs/dapp/opl/setup.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/setup",permalink:"/dapp/opl/setup",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/setup.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Overview",permalink:"/dapp/opl/introduction"},next:{title:"DAO Contract",permalink:"/dapp/opl/host"}},i={},s=[{value:"Workspace",id:"workspace",level:2},{value:"Hardhat",id:"hardhat",level:2}],c={toc:s},d="wrapper";function u(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"setup"},"Setup"),(0,r.kt)("p",null,"Let's get started and make our new project. You will need ",(0,r.kt)("a",{parentName:"p",href:"https://nodejs.org/en/download"},"Node.js"),"\nversion ",(0,r.kt)("a",{parentName:"p",href:"https://nodejs.org/en/blog/announcements/v18-release-announce"},"18"),"."),(0,r.kt)("p",null,"We will be using a monorepo for both the frontend and backend of our dApp."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"mkdir opl-secret-ballot;\nmkdir opl-secret-ballot/backend;\nmkdir opl-secret-ballot/frontend;\n")),(0,r.kt)("p",null,"Our smart contracts will live inside a Hardhat project under\n",(0,r.kt)("inlineCode",{parentName:"p"},"opl-secret-ballot/backend"),", and our VueJS app will be in the\n",(0,r.kt)("inlineCode",{parentName:"p"},"opl-secret-ballot/frontend"),"."),(0,r.kt)("h2",{id:"workspace"},"Workspace"),(0,r.kt)("p",null,"We suggest using ",(0,r.kt)("a",{parentName:"p",href:"https://pnpm.io/motivation"},(0,r.kt)("inlineCode",{parentName:"a"},"pnpm")),", and creating a workspace\nfile ",(0,r.kt)("inlineCode",{parentName:"p"},"opl-secret-ballot/pnpm-workspace.yaml")," with the following content:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"packages: [frontend, backend]\n")),(0,r.kt)("h2",{id:"hardhat"},"Hardhat"),(0,r.kt)("p",null,"Let's create a new Hardhat project."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Currently we are compatible with Hardhat up to ",(0,r.kt)("inlineCode",{parentName:"p"},"2.12.7"),". You may need to\nspecify the version of Hardhat to install.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"cd opl-secret-ballot/backend && npx hardhat\n")),(0,r.kt)("p",null,"When initializing the Hardhat application, we would like to use the ",(0,r.kt)("inlineCode",{parentName:"p"},"backend"),"\ndirectory as the project root."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"Hardhat project root: \xb7 /Users/oasis/opl-secret-ballot/backend\n")),(0,r.kt)("p",null,"We would like to set ",(0,r.kt)("inlineCode",{parentName:"p"},"@oasisprotocol/secret-ballot-backend")," as the package name\ninside ",(0,r.kt)("inlineCode",{parentName:"p"},"package.json")," at ",(0,r.kt)("inlineCode",{parentName:"p"},"version")," of ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0.0"),"."),(0,r.kt)("p",null,"Finally, we need to install the following dependencies:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"@oasisprotocol/sapphire-contracts")," contains the OPL Solidity smart contracts."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"@oasisprotocol/sapphire-hardhat")," integrates Sapphire using the Hardhat\nconfig file."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"@openzeppelin/contracts")," contains standardized DAO contracts which we will\nuse to build the secret ballot application.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm install -D @openzeppelin/contracts @oasisprotocol/sapphire-contracts @oasisprotocol/sapphire-hardhat\n")),(0,r.kt)("p",null,"You should be able to start your localhost Hardhat node."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1a9d3710.c86e7daa.js b/assets/js/1a9d3710.c86e7daa.js new file mode 100644 index 0000000000..65ad842978 --- /dev/null +++ b/assets/js/1a9d3710.c86e7daa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3446],{3905:(e,t,o)=>{o.d(t,{Zo:()=>d,kt:()=>y});var r=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function a(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function i(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?a(Object(o),!0).forEach((function(t){n(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):a(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}function s(e,t){if(null==e)return{};var o,r,n=function(e,t){if(null==e)return{};var o,r,n={},a=Object.keys(e);for(r=0;r<a.length;r++)o=a[r],t.indexOf(o)>=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)o=a[r],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var l=r.createContext({}),u=function(e){var t=r.useContext(l),o=t;return e&&(o="function"==typeof e?e(t):i(i({},t),e)),o},d=function(e){var t=u(e.components);return r.createElement(l.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var o=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),c=u(o),m=n,y=c["".concat(l,".").concat(m)]||c[m]||p[m]||a;return o?r.createElement(y,i(i({ref:t},d),{},{components:o})):r.createElement(y,i({ref:t},d))}));function y(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=o.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:n,i[1]=s;for(var u=2;u<a;u++)i[u]=o[u];return r.createElement.apply(null,i)}return r.createElement.apply(null,o)}m.displayName="MDXCreateElement"},7358:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var r=o(7462),n=(o(7294),o(3905));const a={},i="Token Delivery & KYC Guide",s={unversionedId:"get-involved/token-delivery-and-kyc",id:"get-involved/token-delivery-and-kyc",title:"Token Delivery & KYC Guide",description:"If you're visiting this page, you may have recently earned ROSE tokens via the Community Cup program, the Ambassador Rewards program, or a recent hackathon. Congratulations!",source:"@site/docs/get-involved/token-delivery-and-kyc.md",sourceDirName:"get-involved",slug:"/get-involved/token-delivery-and-kyc",permalink:"/get-involved/token-delivery-and-kyc",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/token-delivery-and-kyc.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"Delegation Policy",permalink:"/get-involved/delegation-policy"}},l={},u=[],d={toc:u},c="wrapper";function p(e){let{components:t,...o}=e;return(0,n.kt)(c,(0,r.Z)({},d,o,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"token-delivery--kyc-guide"},"Token Delivery & KYC Guide"),(0,n.kt)("p",null,"If you're visiting this page, you may have recently earned ROSE tokens via the Community Cup program, the Ambassador Rewards program, or a recent hackathon. Congratulations!"),(0,n.kt)("p",null,"Let's review the process for receiving your ROSE tokens from the Oasis Foundation:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Step 1: Wait to be contacted regarding KYC by an Oasis Foundation core team member.")," We will reach out to you via email to the email address we have on file for you for Oasis-related activities. This email will contain information about how to complete the KYC process. Please allow our team approximately 1 to 3 weeks after the day you have won or earned your ROSE tokens before reaching out to us with any questions. If 3 weeks have passed since the day you won or earned your ROSE tokens, you are welcome to reach out to us via our ",(0,n.kt)("a",{parentName:"li",href:"https://airtable.com/shrGmpohTNnytBpQU"},"token delivery question form"),".")),(0,n.kt)("admonition",{type:"caution"},(0,n.kt)("p",{parentName:"admonition"},"Please be sure to use the same email address for all Oasis-related activities. For example, if you registered for the Oasis Ambassador Rewards program with a specific email address, use that same email address when you complete the KYC process and when you contact the Oasis team if you have any questions.")),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"For the Ambassador Rewards program, reward submissions will be tallied up after each quarter (every 3 months) and will require an additional 3 weeks to update the leaderboard and apply any bonuses. Rewards will be sent out on the third Friday following the end of a given quarter. If you have rewards outstanding past any given quarterly distribution date, we will be doing weekly distributions on Fridays, but only if you have completed all of the steps described in his document.")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Step 2: Complete the KYC process.")," The KYC email you receive will contain everything you need to complete the KYC process which lets us know that you are eligible to receive ROSE tokens. In particular, you first need to request access to Synaps, which is the online KYC tool the Oasis Foundation uses. Once you get access to Synaps, you need to get verified in all 3 of the required categories. How long this step takes depends on how long you take to submit all of the required documentation, following all of the required guidelines. Assuming you submit all of the necessary documents correctly right away, you can expect this step to take around 1 week. When your documents and information have been verified, we'll reach out again via email with next steps")),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"The Proof of Residency document required for Synaps must be dated within 3 months of the date you are submitting it, and the document must include your name and your address, matching the information you have submitted to Oasis.")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Step 3: Submit your ROSE wallet address.")," After you complete the KYC process, you will receive an follow-up email from the Oasis Foundation with information on how to submit your ROSE wallet address via a unique code that connects your ROSE wallet to your KYC data. Please allow at least 1 full week to pass after you complete KYC to receive the follow-up email with instructions on how to submit your ROSE wallet address."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Step 4: Receive the tokens deposited to your ROSE wallet.")," After you have completed KYC and submitted your ROSE wallet address, allow 1 to 2 weeks for your ROSE tokens to be deposited into your wallet. We will be doing weekly token distributions on Fridays, but only if you have completed all of the steps described in his document.")),(0,n.kt)("admonition",{type:"caution"},(0,n.kt)("p",{parentName:"admonition"},"Before reaching out to our team with questions, please make sure you have closely reviewed each of the steps described in this document and that you have correctly completed each step. Please consider only reaching out for support via our ",(0,n.kt)("a",{parentName:"p",href:"https://airtable.com/shrGmpohTNnytBpQU"},"token delivery question form")," if you have correctly followed all of the instructions but for some reason have not received any communications from our team. Thank you for your cooperation in helping us manage our resources so that we can more effectively support the community.")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1be78505.08155ed7.js b/assets/js/1be78505.08155ed7.js new file mode 100644 index 0000000000..7e6cf7c370 --- /dev/null +++ b/assets/js/1be78505.08155ed7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9514,4972],{9963:(e,t,n)=>{n.r(t),n.d(t,{default:()=>ge});var a=n(7294),l=n(6010),o=n(1944),r=n(5281),c=n(3320),i=n(3438),s=n(4477),d=n(1116),m=n(179),u=n(5999),b=n(2466),p=n(5936);const h={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};function E(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,l]=(0,a.useState)(!1),o=(0,a.useRef)(!1),{startScroll:r,cancelScroll:c}=(0,b.Ct)();return(0,b.RF)(((e,n)=>{let{scrollY:a}=e;const r=n?.scrollY;r&&(o.current?o.current=!1:a>=r?(c(),l(!1)):a<t?l(!1):a+window.innerHeight<document.documentElement.scrollHeight&&l(!0))})),(0,p.S)((e=>{e.location.hash&&(o.current=!0,l(!1))})),{shown:n,scrollToTop:()=>r(0)}}({threshold:300});return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,l.Z)("clean-btn",r.k.common.backToTopButton,h.backToTopButton,e&&h.backToTopButtonShow),type:"button",onClick:t})}var f=n(1442),g=n(6550),_=n(7524),k=n(6668),v=n(1327),C=n(7462);function S(e){return a.createElement("svg",(0,C.Z)({width:"20",height:"20","aria-hidden":"true"},e),a.createElement("g",{fill:"#7a7a7a"},a.createElement("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),a.createElement("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})))}const I={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function N(e){let{onClick:t}=e;return a.createElement("button",{type:"button",title:(0,u.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,l.Z)("button button--secondary button--outline",I.collapseSidebarButton),onClick:t},a.createElement(S,{className:I.collapseSidebarButtonIcon}))}var T=n(9689),Z=n(902);const x=Symbol("EmptyContext"),B=a.createContext(x);function y(e){let{children:t}=e;const[n,l]=(0,a.useState)(null),o=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:l})),[n]);return a.createElement(B.Provider,{value:o},t)}var w=n(6043),L=n(8596),A=n(9960),M=n(2389);function F(e){let{categoryLabel:t,onClick:n}=e;return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel",message:"Toggle the collapsible sidebar category '{label}'",description:"The ARIA label to toggle the collapsible sidebar category"},{label:t}),type:"button",className:"clean-btn menu__caret",onClick:n})}function H(e){let{item:t,onItemClick:n,activePath:o,level:c,index:s,...d}=e;const{items:m,label:u,collapsible:b,className:p,href:h}=t,{docs:{sidebar:{autoCollapseCategories:E}}}=(0,k.L)(),f=function(e){const t=(0,M.Z)();return(0,a.useMemo)((()=>e.href?e.href:!t&&e.collapsible?(0,i.Wl)(e):void 0),[e,t])}(t),g=(0,i._F)(t,o),_=(0,L.Mg)(h,o),{collapsed:v,setCollapsed:S}=(0,w.u)({initialState:()=>!!b&&(!g&&t.collapsed)}),{expandedItem:I,setExpandedItem:N}=function(){const e=(0,a.useContext)(B);if(e===x)throw new Z.i6("DocSidebarItemsExpandedStateProvider");return e}(),T=function(e){void 0===e&&(e=!v),N(e?null:s),S(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:l}=e;const o=(0,Z.D9)(t);(0,a.useEffect)((()=>{t&&!o&&n&&l(!1)}),[t,o,n,l])}({isActive:g,collapsed:v,updateCollapsed:T}),(0,a.useEffect)((()=>{b&&null!=I&&I!==s&&E&&S(!0)}),[b,I,s,S,E]),a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemCategory,r.k.docs.docSidebarItemCategoryLevel(c),"menu__list-item",{"menu__list-item--collapsed":v},p)},a.createElement("div",{className:(0,l.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":_})},a.createElement(A.Z,(0,C.Z)({className:(0,l.Z)("menu__link",{"menu__link--sublist":b,"menu__link--sublist-caret":!h&&b,"menu__link--active":g}),onClick:b?e=>{n?.(t),h?T(!1):(e.preventDefault(),T())}:()=>{n?.(t)},"aria-current":_?"page":void 0,"aria-expanded":b?!v:void 0,href:b?f??"#":f},d),u),h&&b&&a.createElement(F,{categoryLabel:u,onClick:e=>{e.preventDefault(),T()}})),a.createElement(w.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:v},a.createElement(j,{items:m,tabIndex:v?-1:0,onItemClick:n,activePath:o,level:c+1})))}var P=n(3919),W=n(9471);const D={menuExternalLink:"menuExternalLink_NmtK"};function R(e){let{item:t,onItemClick:n,activePath:o,level:c,index:s,...d}=e;const{href:m,label:u,className:b,autoAddBaseUrl:p}=t,h=(0,i._F)(t,o),E=(0,P.Z)(m);return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(c),"menu__list-item",b),key:u},a.createElement(A.Z,(0,C.Z)({className:(0,l.Z)("menu__link",!E&&D.menuExternalLink,{"menu__link--active":h}),autoAddBaseUrl:p,"aria-current":h?"page":void 0,to:m},E&&{onClick:n?()=>n(t):void 0},d),u,!E&&a.createElement(W.Z,null)))}const V={menuHtmlItem:"menuHtmlItem_M9Kj"};function z(e){let{item:t,level:n,index:o}=e;const{value:c,defaultStyle:i,className:s}=t;return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(n),i&&[V.menuHtmlItem,"menu__list-item"],s),key:o,dangerouslySetInnerHTML:{__html:c}})}function U(e){let{item:t,...n}=e;switch(t.type){case"category":return a.createElement(H,(0,C.Z)({item:t},n));case"html":return a.createElement(z,(0,C.Z)({item:t},n));default:return a.createElement(R,(0,C.Z)({item:t},n))}}function K(e){let{items:t,...n}=e;return a.createElement(y,null,t.map(((e,t)=>a.createElement(U,(0,C.Z)({key:t,item:e,index:t},n)))))}const j=(0,a.memo)(K),G={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function Y(e){let{path:t,sidebar:n,className:o}=e;const c=function(){const{isActive:e}=(0,T.nT)(),[t,n]=(0,a.useState)(e);return(0,b.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return a.createElement("nav",{"aria-label":(0,u.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,l.Z)("menu thin-scrollbar",G.menu,c&&G.menuWithAnnouncementBar,o)},a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:n,activePath:t,level:1})))}const q="sidebar_njMd",O="sidebarWithHideableNavbar_wUlq",X="sidebarHidden_VK0M",J="sidebarLogo_isFc";function Q(e){let{path:t,sidebar:n,onCollapse:o,isHidden:r}=e;const{navbar:{hideOnScroll:c},docs:{sidebar:{hideable:i}}}=(0,k.L)();return a.createElement("div",{className:(0,l.Z)(q,c&&O,r&&X)},c&&a.createElement(v.Z,{tabIndex:-1,className:J}),a.createElement(Y,{path:t,sidebar:n}),i&&a.createElement(N,{onClick:o}))}const $=a.memo(Q);var ee=n(3102),te=n(3163);const ne=e=>{let{sidebar:t,path:n}=e;const o=(0,te.e)();return a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(j,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&o.toggle(),"link"===e.type&&o.toggle()},level:1}))};function ae(e){return a.createElement(ee.Zo,{component:ne,props:e})}const le=a.memo(ae);function oe(e){const t=(0,_.i)(),n="desktop"===t||"ssr"===t,l="mobile"===t;return a.createElement(a.Fragment,null,n&&a.createElement($,e),l&&a.createElement(le,e))}const re={expandButton:"expandButton_m80_",expandButtonIcon:"expandButtonIcon_BlDH"};function ce(e){let{toggleSidebar:t}=e;return a.createElement("div",{className:re.expandButton,title:(0,u.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t},a.createElement(S,{className:re.expandButtonIcon}))}const ie={docSidebarContainer:"docSidebarContainer_b6E3",docSidebarContainerHidden:"docSidebarContainerHidden_b3ry",sidebarViewport:"sidebarViewport_Xe31"};function se(e){let{children:t}=e;const n=(0,d.V)();return a.createElement(a.Fragment,{key:n?.name??"noSidebar"},t)}function de(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:o}=e;const{pathname:c}=(0,g.TH)(),[i,s]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{i&&s(!1),!i&&(0,f.n)()&&s(!0),o((e=>!e))}),[o,i]);return a.createElement("aside",{className:(0,l.Z)(r.k.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&s(!0)}},a.createElement(se,null,a.createElement("div",{className:(0,l.Z)(ie.sidebarViewport,i&&ie.sidebarViewportHidden)},a.createElement(oe,{sidebar:t,path:c,onCollapse:d,isHidden:i}),i&&a.createElement(ce,{toggleSidebar:d}))))}const me={docMainContainer:"docMainContainer_gTbr",docMainContainerEnhanced:"docMainContainerEnhanced_Uz_u",docItemWrapperEnhanced:"docItemWrapperEnhanced_czyv"};function ue(e){let{hiddenSidebarContainer:t,children:n}=e;const o=(0,d.V)();return a.createElement("main",{className:(0,l.Z)(me.docMainContainer,(t||!o)&&me.docMainContainerEnhanced)},a.createElement("div",{className:(0,l.Z)("container padding-top--md padding-bottom--lg",me.docItemWrapper,t&&me.docItemWrapperEnhanced)},n))}const be={docPage:"docPage__5DB",docsWrapper:"docsWrapper_BCFX"};function pe(e){let{children:t}=e;const n=(0,d.V)(),[l,o]=(0,a.useState)(!1);return a.createElement(m.Z,{wrapperClassName:be.docsWrapper},a.createElement(E,null),a.createElement("div",{className:be.docPage},n&&a.createElement(de,{sidebar:n.items,hiddenSidebarContainer:l,setHiddenSidebarContainer:o}),a.createElement(ue,{hiddenSidebarContainer:l},t)))}var he=n(4972),Ee=n(197);function fe(e){const{versionMetadata:t}=e;return a.createElement(a.Fragment,null,a.createElement(Ee.Z,{version:t.version,tag:(0,c.os)(t.pluginId,t.version)}),a.createElement(o.d,null,t.noIndex&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"})))}function ge(e){const{versionMetadata:t}=e,n=(0,i.hI)(e);if(!n)return a.createElement(he.default,null);const{docElement:c,sidebarName:m,sidebarItems:u}=n;return a.createElement(a.Fragment,null,a.createElement(fe,e),a.createElement(o.FG,{className:(0,l.Z)(r.k.wrapper.docsPages,r.k.page.docsDocPage,e.versionMetadata.className)},a.createElement(s.q,{version:t},a.createElement(d.b,{name:m,items:u},a.createElement(pe,null,c)))))}},4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>c});var a=n(7294),l=n(5999),o=n(1944),r=n(179);function c(){return a.createElement(a.Fragment,null,a.createElement(o.d,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/assets/js/1d621f19.6a323974.js b/assets/js/1d621f19.6a323974.js new file mode 100644 index 0000000000..629615b8b6 --- /dev/null +++ b/assets/js/1d621f19.6a323974.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9250],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>u});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},m=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,m=i(e,["components","mdxType","originalType","parentName"]),c=p(n),h=r,u=c["".concat(l,".").concat(h)]||c[h]||d[h]||o;return n?a.createElement(u,s(s({ref:t},m),{},{components:n})):a.createElement(u,s({ref:t},m))}));function u(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,s=new Array(o);s[0]=h;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[c]="string"==typeof e?e:r,s[1]=i;for(var p=2;p<o;p++)s[p]=n[p];return a.createElement.apply(null,s)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},605:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const o={},s="Genesis Document",i={unversionedId:"node/genesis-doc",id:"node/genesis-doc",title:"Genesis Document",description:"A genesis document contains a set of parameters that outline the initial state",source:"@site/docs/node/genesis-doc.md",sourceDirName:"node",slug:"/node/genesis-doc",permalink:"/node/genesis-doc",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/genesis-doc.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Upgrade Log",permalink:"/node/testnet/upgrade-log"},next:{title:"Run Your Node",permalink:"/node/run-your-node"}},l={},p=[{value:"Genesis File vs. Genesis Document",id:"genesis-file-vs-genesis-document",level:2},{value:"Parameters",id:"parameters",level:2},{value:"Height, Genesis Time and Chain ID",id:"height-genesis-time-and-chain-id",level:3},{value:"Registry",id:"registry",level:3},{value:"Gas Costs",id:"gas-costs",level:3},{value:"Root Hash",id:"root-hash",level:3},{value:"Staking",id:"staking",level:3},{value:"Token Supply & Ledger",id:"token-supply--ledger",level:4},{value:"Delegations",id:"delegations",level:4},{value:"Node & ParaTime Token Thresholds",id:"staking-thresholds",level:4},{value:"Rewards",id:"rewards",level:4},{value:"Commission Schedule",id:"commission-schedule",level:4},{value:"Slashing",id:"slashing",level:4},{value:"Committee Scheduler",id:"committee-scheduler",level:3},{value:"Random Beacon",id:"random-beacon",level:3},{value:"VRF Beacon",id:"vrf-beacon",level:4},{value:"<strong>Governance</strong>",id:"governance",level:3},{value:"Consensus",id:"consensus",level:3}],m={toc:p},c="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"genesis-document"},"Genesis Document"),(0,r.kt)("p",null,"A genesis document contains a set of parameters that outline the initial state\nof an Oasis network."),(0,r.kt)("p",null,"The state defined in the network's genesis document contains all the necessary\ninformation for launching that particular network (i.e. Mainnet,\n",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet"),"), including initial token allocations, network\nparameters, and more."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For a more in-depth explanation of the genesis document, see the\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/genesis"},"Genesis Document")," part of Oasis Core's developer\ndocumentation.")),(0,r.kt)("p",null,"The important thing to note is that the genesis document is used to compute the\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/genesis#genesis-documents-hash"},"genesis document's hash"),".\nThis hash is used to verify for which network a given transaction is intended\nfor."),(0,r.kt)("h2",{id:"genesis-file-vs-genesis-document"},"Genesis File vs. Genesis Document"),(0,r.kt)("p",null,"A genesis file is a JSON file corresponding to a serialized genesis document. As\nsuch, it is more convenient for distribution and sharing."),(0,r.kt)("p",null,"When Oasis Node loads a genesis file, it converts it to a genesis document."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Up to date information about the current genesis file and the current genesis\ndocument's hash can be found on the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),"\npage.")),(0,r.kt)("h2",{id:"parameters"},"Parameters"),(0,r.kt)("p",null,"This sections explains some of the key parameters of the genesis document."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The concrete parameter values in the following sections pertain to the Mainnet.\nOther Oasis networks (e.g. ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet"),") might use different\nvalues.")),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"The token balances in a genesis document (or a genesis file) are enumerated in\nbase units."),(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.token_value_exponent"))," parameter defines the token value's\nbase-10 exponent. For the Mainnet it is set to 9 which means 1 ROSE equals 10^9\n(i.e. billion) base units.")),(0,r.kt)("h3",{id:"height-genesis-time-and-chain-id"},"Height, Genesis Time and Chain ID"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"height"))," parameter specifies the network's initial block height. When a\nnetwork is upgraded, its height is retained. For example, for the\n",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt upgrade")," the height of the\nMainnet state dump was bumped by 1 from 3,027,600 to 3,027,601."),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"genesis_time"))," parameter is an ISO8601 UTC timestamp that specifies when\nthe network is officially going to launch. At the time of genesis, validators\nare expected to come online and start participating in the consensus process for\noperating the network. The network starts once validators representing more than\n2/3 of stake in the initial consensus committee are online."),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"chain_id"))," is a human-readable version identifier for a network."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"It is important to note that this value alone doesn't dictate the version of an\nOasis network. Rather, the hash of the whole genesis document, i.e. the\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/genesis#genesis-documents-hash"},"genesis document's hash"),",\nis the network's unique identifier.")),(0,r.kt)("h3",{id:"registry"},"Registry"),(0,r.kt)("p",null,"Within the ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry"))," object, there are a broad range of parameters that\nspecify the initial set of node operators and their corresponding initial node\nstatuses."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.max_node_expiration"))," The maximum duration (in epochs)\nthat node registrations last. The starting value is set to 2 in order to\nensure that a node is continuously online, since the node\u2019s registration would\nexpire each time 2 epochs pass, requiring the node to re-register.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.enable_runtime_governance_models"))," The set of\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#runtimes"},"runtime governance models")," that are allowed to be used when creating/updating\nregistrations. It is set to ",(0,r.kt)("inlineCode",{parentName:"p"},'{"entity": true, "runtime": true}')," which means a\nruntime can choose between ",(0,r.kt)("strong",{parentName:"p"},"entity governance")," and ",(0,r.kt)("strong",{parentName:"p"},"runtime-defined\ngovernance"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.entities"))," The entity registrations for initial node operators,\nincluding public key and signature information.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes"))," The initial runtime registrations. Each item describes\na runtime's operational parameters, including its identifier, kind, admission\npolicy, committee scheduling, storage, governance model, etc. For a full\ndescription of the runtime descriptor see the ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime"},(0,r.kt)("inlineCode",{parentName:"a"},"Runtime")," structure"),"\ndocumentation.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.suspended_runtimes"))," The initial suspended runtime registrations.\nEach item describes a suspended runtime's operational parameters, including\nits identifier, kind, admission policy, committee scheduling, storage,\ngovernance model, etc. For a full description of the runtime descriptor see\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime"},(0,r.kt)("inlineCode",{parentName:"a"},"Runtime")," structure")," documentation.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.nodes"))," The node registrations for initial node operators,\nincluding public key and signature information."))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For a new network, the entity and node registrations are obtained via the entity\npackage collection process (e.g. ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-entities"},"Mainnet Network Entities"),")."),(0,r.kt)("p",{parentName:"admonition"},"For an upgrade to an existing network, the network's state dump tool captures\nthe network's current entity and node registrations.")),(0,r.kt)("h3",{id:"gas-costs"},"Gas Costs"),(0,r.kt)("p",null,"The following parameters define the gas costs for various types of transactions\non the network:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs.add_escrow"))," The cost for an add escrow (i.e.\nstake tokens) transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs.burn"))," The cost for a burn (i.e. destroy tokens)\ntransaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs.reclaim_escrow"))," The cost for a reclaim escrow\ntransaction (i.e. unstake tokens). The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs.transfer"))," The cost for a transfer transaction.\nThe value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs.amend_commission_schedule"))," The cost for\namending, or changing, a commission schedule. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.deregister_entity"))," The cost for a deregister\nentity transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.register_entity"))," The cost for a register entity\ntransaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.register_node"))," The cost for a register node\ntransaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.register_runtime"))," The cost for a register\nParaTime transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.runtime_epoch_maintenance"))," The cost of a\nmaintenance fee that a node that is registered for a ParaTime pays each epoch.\nThe value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.unfreeze_node"))," The cost for unfreeze node (i.e.\nafter the node is slashed and frozen) transaction. The current value is 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"keymanager.params.gas_costs.publish_ephemeral_secret"))," The cost for\nkeymanager ephemeral secret publication transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"keymanager.params.gas_costs.publish_master_secret"))," The cost for\nkeymanager master secret publication transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"keymanager.params.gas_costs.update_policy"))," The cost for keymanager update\npolicy transaction. The value is set to 1000."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.gas_costs.compute_commit"))," The cost for a ParaTime compute\ncommitment transaction. The value is set to 10000.")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"In addition to the gas costs specified above, each transaction also incurs a\ncost proportional to its size."),(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.gas_costs.tx_byte"))," parameter specifies the additional\ngas cost for each byte of a transaction. The value is set to 1."),(0,r.kt)("p",{parentName:"admonition"},"For example, a staking transfer transaction of size 230 bytes would have a total\ngas cost of 1000 + 230.")),(0,r.kt)("h3",{id:"root-hash"},"Root Hash"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash"))," object contains parameters related to the ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"Root Hash service"),"\nand minimal state related to runtimes."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_runtime_messages"))," The global limit on the number of\n",(0,r.kt)("a",{parentName:"p",href:"/core/runtime/messages"},"messages")," that can be emitted in each round by the runtime. The value is set\nto 256.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_evidence_age"))," The maximum age (in the number of\nrounds) of submitted evidence for ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0005-runtime-compute-slashing"},"compute node slashing"),". The value is set to\n100."))),(0,r.kt)("h3",{id:"staking"},"Staking"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking"))," object contains parameters controlling the Staking service and\nall state related to accounts, delegations, special pools of tokens..."),(0,r.kt)("h4",{id:"token-supply--ledger"},"Token Supply & Ledger"),(0,r.kt)("p",null,"The following parameters specify the total token supply, total token pool\nreserved for staking rewards, and account balances across the network at the\ntime of genesis:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.total_supply"))," The total token supply (in base units) for the\nnetwork. This is fixed at 10 billion ROSE tokens (the value is set to\n10,000,000,000,000,000,000 base units).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.common_pool"))," The tokens (in base units) reserved for staking\nrewards to be paid out over time.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.governance_deposits"))," The tokens (in base units) collected from\ngovernance proposal deposits.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.ledger"))," The staking ledger, encoding all accounts and\ncorresponding account balances on the network at the time of genesis,\nincluding accounts for initial operators, backers, custodial wallets, etc.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.delegations"))," The encoding of the initial delegations at the time\nof genesis."))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"Interpreting your account balance in the ",(0,r.kt)("inlineCode",{parentName:"strong"},"staking.ledger"))),(0,r.kt)("p",{parentName:"admonition"},"Your account's ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"general.balance"))," includes all of your tokens that have not\nbeen staked or delegated. Within your account's ",(0,r.kt)("inlineCode",{parentName:"p"},"escrow")," field, the\n",(0,r.kt)("inlineCode",{parentName:"p"},"active.balance")," holds the total amount of tokens are (actively) delegated ",(0,r.kt)("em",{parentName:"p"},"to"),"\nyou.")),(0,r.kt)("h4",{id:"delegations"},"Delegations"),(0,r.kt)("p",null,"The following parameters control how delegations behave on the network:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.debonding_interval"))," The period of time (in epochs) that\nmust pass before staked or delegated tokens that are requested to be withdrawn\nare returned to the account's general balance. The value is set to 336 epochs,\nwhich is expected to be approximately 14 days."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.min_delegation"))," The minimum amount of tokens one can\ndelegate. The value is set to 100,000,000,000 base units, or 100 ROSE tokens."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.allow_escrow_messages"))," Indicator whether to enable support\nfor ",(0,r.kt)("inlineCode",{parentName:"li"},"AddEscrow")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"ReclaimEscrow")," ",(0,r.kt)("a",{parentName:"li",href:"/core/runtime/messages"},"runtime messages"),".\nThe value is set to ",(0,r.kt)("inlineCode",{parentName:"li"},"true"),".")),(0,r.kt)("h4",{id:"staking-thresholds"},"Node & ParaTime Token Thresholds"),(0,r.kt)("p",null,"There are several ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.thresholds"))," parameters that specify the\nminimum number of tokens that need to be staked in order for a particular entity\nor a particular type of node to participate in the network."),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"entity"),",")," ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"node-compute"),", ",(0,r.kt)("inlineCode",{parentName:"strong"},"node-keymanager"),", and "),(0,r.kt)("inlineCode",{parentName:"p"},"node-validator"),"**\nparameters are set to 100,000,000,000 base units for each, indicating that you\nneed to stake at least 100 ROSE tokens in order to have your entity or any of\nthe specified nodes go live on the network."),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.thresholds"))," parameters also specify the minimum\nthresholds for registering new ParaTimes. The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"runtime-compute"))," and\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"runtime-keymanager"))," parameters are set to 50,000,000,000,000 base units,\nindicating that you need to stake at least 50,000 ROSE tokens in order to\nregister a compute/key manager ParaTime."),(0,r.kt)("h4",{id:"rewards"},"Rewards"),(0,r.kt)("p",null,"The following parameters control the staking rewards on the network:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.reward_schedule"))," The staking reward schedule, indicating\nhow the staking reward rate changes over time, defined at an epoch-by-epoch\ngranular basis. The reward schedule uses a tapering formula with higher\nrewards being paid out at earlier epochs and then gradually decreasing over\ntime. For more details, see the ",(0,r.kt)("a",{parentName:"li",href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives"},"Staking Incentives")," doc."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.signing_reward_threshold_numerator"))," and\n",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.signing_reward_threshold_denominator"))," These parameters\ndefine the proportion of blocks that a validator must sign during each epoch\nto receive staking rewards. The set fraction of 3/4 means that a validator\nmust maintain an uptime of at least 75% blocks during an epoch in order to\nreceive staking rewards for that period."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.fee_split_weight_propose"))," The block proposer's share of\ntransaction fees. The value is set to 2."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.fee_split_weight_next_propose"))," The next block proposer's\nshare of transaction fees. The value is set to 1."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.fee_split_weight_vote"))," The block signer\u2019s/voter\u2019s share of\ntransaction fees. The value is set to 1."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.reward_factor_epoch_signed"))," The factor for rewards\ndistributed to validators who signed at least threshold blocks in a given\nepoch. The value is set to 1."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.reward_factor_block_proposed"))," The factor for rewards\nearned for block proposal. The value is set to 0, indicating validators get no\nextra staking rewards for proposing a block.")),(0,r.kt)("h4",{id:"commission-schedule"},"Commission Schedule"),(0,r.kt)("p",null,"The following parameters control how commission rates and bounds can be defined\nand changed:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.commision_schedule_rules.rate_change_interval"))," The time\ninterval (in epochs) at which rate changes can be specified in a commission\nschedule. The value is set to 1 indicating that the commission rate can change\non every epoch.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.commision_schedule_rules.rate_bound_lead"))," The minimum lead\ntime (in epochs) needed for changes to commission rate bounds. This is set to\nprotect the delegators from unexpected changes in an operator's commission\nrates. The value is set to 336, which is expected to be approximately 14 days.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.commision_schedule_rules.max_rate_steps"))," The maximum\nnumber of rate step changes in a commission schedule. The value is set to 10,\nindicating that the commission schedule can have a maximum of 10 rate steps.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.commision_schedule_rules.max_bound_steps"))," The maximum\nnumber of commission rate bound step changes in the commission schedule. The\nvalue is set to 10, indicating that the commission schedule can have a maximum\nof 10 rate bound steps."))),(0,r.kt)("h4",{id:"slashing"},"Slashing"),(0,r.kt)("p",null,"These parameters specify key values for the network's slashing mechanism:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-equivocation.amount"))," The amount of\ntokens to slash for equivocation (i.e. double signing). The value is set to\n100,000,000,000 base units, or 100 ROSE tokens.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-equivocation.freeze_interval"))," The\nduration (in epochs) for which a node that has been slashed for equivocation\nis \u201cfrozen,\u201d or barred from participating in the network's consensus\ncommittee. The value of 18446744073709551615 (the maximum value for a 64-bit\nunsigned integer) means that any node slashed for equivocation is, in effect,\npermanently banned from the network.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-light-client-attack.amount"))," The amount\nof tokens to slash for light client attack. The value is set to\n100,000,000,000 base units, or 100 ROSE tokens.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-light-client-attack.freeze_interval")),"\nThe duration (in epochs) for which a node that has been slashed for light\nclient attack is \u201cfrozen,\u201d or barred from participating in the network's\nconsensus committee. The value of 18446744073709551615 (the maximum value for\na 64-bit unsigned integer) means that any node slashed for light client attack\nis, in effect, permanently banned from the network."))),(0,r.kt)("h3",{id:"committee-scheduler"},"Committee Scheduler"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler"))," object contains parameters controlling how various\ncommittees (validator, compute, key manager) are periodically ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"scheduled"),"."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.min_validators"))," The minimum size for the consensus\ncommittee. The value is set to 15 validators.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators"))," The maximum size for the consensus\ncommittee. The value is set to 100 validators.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators_per_entity"))," The maximum number of nodes\nfrom a given entity that can be in the consensus committee at any time. The\nvalue is set to 1."))),(0,r.kt)("h3",{id:"random-beacon"},"Random Beacon"),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon"))," object contains parameters controlling the network's random\nbeacon."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.base"))," Network's starting epoch. When a network is upgraded, its\nepoch is retained. For example, for the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt upgrade"),"\nthe epoch of the Mainnet state dump was bumped by 1 from 5,046 to 5,047.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.backend")),' The random beacon backend to use. The value is set\nto "vrf" indicating that the beacon implementing a VRF (verifiable random\nfunction) should be used.'))),(0,r.kt)("h4",{id:"vrf-beacon"},"VRF Beacon"),(0,r.kt)("p",null,"These parameters control the behavior of the VRF random beacon:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.alpha_hq_threshold"))," The minimum number of\nproofs that must be received for the next input to be considered high quality.\nIf the VRF input is not high quality, runtimes will be disabled for the next\nepoch. The value is set to 20.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.interval"))," The epoch interval in blocks. The\nvalue is set to 600 blocks, which is expected to be approximately 1 hour.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.proof_delay"))," The wait period in blocks after\nan epoch transition that nodes must wait before attempting to submit a VRF\nproof for the next epoch's elections. The value is set to 400 blocks."))),(0,r.kt)("h3",{id:"governance"},(0,r.kt)("strong",{parentName:"h3"},"Governance")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance"))," object contains parameters controlling the network's\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/governance"},"on-chain governance")," introduced in\nthe ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt upgrade"),":"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.min_proposal_deposit"))," The amount of tokens (in base\nunits) that are deposited when creating a new proposal. The value is set to\n10,000,000,000,000 base units, or 10,000 ROSE tokens.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.voting_period"))," The number of epochs after which the\nvoting for a proposal is closed and the votes are tallied. The value is set to\n168, which is expected to be approximately 7 days.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.stake_threshold"))," The percentage of ",(0,r.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes in\nterms of total voting power for a governance proposal to pass. The value is\nset to 68 (i.e. 68%).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.upgrade_min_epoch_diff"))," The minimum number of epochs\nbetween the current epoch and the proposed upgrade epoch for the upgrade\nproposal to be valid. Additionally, it specifies the minimum number of epochs\nbetween two consecutive pending upgrades."),(0,r.kt)("p",{parentName:"li"},"The value is set to 336, which is expected to be approximately 14 days.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.upgrade_cancel_min_epoch_diff"))," The minimum number of\nepochs between the current epoch and the proposed upgrade epoch for the\nupgrade cancellation proposal to be valid. The value is set to 192, which is\nexpected to be approximately 8 days."))),(0,r.kt)("h3",{id:"consensus"},"Consensus"),(0,r.kt)("p",null,"The following parameters are used to define key values for the network's\nconsensus protocol:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.backend")),' Defines the backend consensus protocol. The value is\nset to "tendermint" indicating that the Tendermint BFT protocol is used.')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.timeout_commit"))," Specifies how long to wait (in\nnanoseconds) after committing a block before starting a new block height (this\naffects the block interval). The value is set to 5,000,000,000 nanoseconds, or\n5 seconds.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_tx_size"))," Maximum size (in bytes) for consensus-layer\ntransactions. The value is set to 32,768 bytes, or 32 kB.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_block_size"))," Maximum block size (in bytes). The value\nis set to 22,020,096 bytes, or 22 MB.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_block_gas"))," Maximum block gas. The value is set to 0,\nwhich specifies an unlimited amount of gas.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_evidence_size"))," Maximum evidence size (in bytes). The\nvalue is set to 51,200 bytes, or 50 kB.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.public_key_blacklist"))," A list of the public keys that\ncannot be used on the network. Currently, there are no blacklisted public\nkeys.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_interval"))," The interval (in blocks) on\nwhich state checkpoints should be taken. The value is set to 10000.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_num_kept"))," The number of past state\ncheckpoints to keep. The value is set to 2.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_chunk_size"))," The chunk size (in bytes)\nthat should be used when creating state checkpoints. The value is set to\n8,388,608 bytes, or 8 MB."))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1dbb95b6.8145b0f7.js b/assets/js/1dbb95b6.8145b0f7.js new file mode 100644 index 0000000000..3c1311f8dc --- /dev/null +++ b/assets/js/1dbb95b6.8145b0f7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4208],{3649:(e,t,l)=>{l.r(t),l.d(t,{assets:()=>z,contentTitle:()=>A,default:()=>Z,frontMatter:()=>D,metadata:()=>F,toc:()=>M});var a=l(7462),o=l(7294),c=l(3905),i=l(1262),n=l(2949);const s=JSON.parse('{"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#f2f5fa"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"rgb(17,17,17)","plot_bgcolor":"rgb(17,17,17)","polar":{"bgcolor":"rgb(17,17,17)","angularaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"radialaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""}},"ternary":{"bgcolor":"rgb(17,17,17)","aaxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"baxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""},"caxis":{"gridcolor":"#506784","linecolor":"#506784","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"sequentialminus":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"#283442","linecolor":"#506784","ticks":"","title":{"standoff":15},"zerolinecolor":"#283442","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"#283442","linecolor":"#506784","ticks":"","title":{"standoff":15},"zerolinecolor":"#283442","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2},"yaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2},"zaxis":{"backgroundcolor":"rgb(17,17,17)","gridcolor":"#506784","linecolor":"#506784","showbackground":true,"ticks":"","zerolinecolor":"#C8D4E3","gridwidth":2}},"shapedefaults":{"line":{"color":"#f2f5fa"}},"annotationdefaults":{"arrowcolor":"#f2f5fa","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"rgb(17,17,17)","landcolor":"rgb(17,17,17)","subunitcolor":"#506784","showland":true,"showlakes":true,"lakecolor":"rgb(17,17,17)"},"title":{"x":0.05},"updatemenudefaults":{"bgcolor":"#506784","borderwidth":0},"sliderdefaults":{"bgcolor":"#C8D4E3","borderwidth":1,"bordercolor":"rgb(17,17,17)","tickwidth":0},"mapbox":{"style":"dark"}},"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"heatmapgl":[{"type":"heatmapgl","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"marker":{"line":{"color":"#283442"}},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#f2f5fa"},"error_y":{"color":"#f2f5fa"},"marker":{"line":{"color":"rgb(17,17,17)","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"marker":{"line":{"color":"#283442"}},"type":"scattergl"}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermapbox":[{"type":"scattermapbox","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#A2B1C6","gridcolor":"#506784","linecolor":"#506784","minorgridcolor":"#506784","startlinecolor":"#A2B1C6"},"baxis":{"endlinecolor":"#A2B1C6","gridcolor":"#506784","linecolor":"#506784","minorgridcolor":"#506784","startlinecolor":"#A2B1C6"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#506784"},"line":{"color":"rgb(17,17,17)"}},"header":{"fill":{"color":"#2a3f5f"},"line":{"color":"rgb(17,17,17)"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"rgb(17,17,17)","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]}}'),r=e=>{const{colorMode:t}=(0,n.I)(),a={...e.chart,layout:{template:"dark"===t?s:void 0,paper_bgcolor:"dark"===t?"#1b1b1d":void 0,plot_bgcolor:"dark"===t?"#1b1b1d":void 0,autosize:!0,...e.chart.layout},config:{showLink:!0,plotlyServerURL:"https://chart-studio.plotly.com",...e.chart.config}};return o.createElement("div",null,o.createElement(i.Z,{fallback:o.createElement("div",null,o.createElement("img",{alt:e.label,style:{width:"100%"},className:"text--center",src:e.fallbackSvg}),o.createElement("p",{className:"text--center"},o.createElement("i",null,"Enable javascript to see interactive chart")))},(()=>{const t=l(3262),c=(0,l(4922).Z)(t);return o.createElement(c,{data:a.data,layout:a.layout,config:a.config,useResizeHandler:!0,style:{width:"100%",height:e.height??"600px"}})})),o.createElement("p",null))},p=l.p+"eade0b46da8fcc687b971f401cc035a9.svg",u=JSON.parse('{"e7":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122],"wB":[12500000,0,0,0,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0,12500000,0,0],"Kb":[370000000,0,0,0,0,0,0,0,0,0,0,0,407000000,0,0,0,0,0,370000000,0,0,37000000,0,0,37000000,0,0,37000000,0,0,37000000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0,18500000,0,0],"_1":[250000000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100000000,0,0,0,0,0,0,0,0,0,0,0,25000000,0,0,0,0,0,0,0,0,0,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0,25000000,0,0],"AS":[0,0,0,0,0,0,0,0,0,0,0,0,300000000,0,0,150000000,0,0,150000000,0,0,150000000,0,0,150000000,0,0,150000000,0,0,150000000,0,0,140000000,0,0,140000000,0,0,140000000,0,0,140000000,0,0,120000000,0,0,120000000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"b1":[759000000,0,0,0,0,0,0,0,0,0,0,0,759000000,0,0,0,0,0,782000000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"p8":{"AS":"Core Contributors","b1":"Backers","_1":"Foundation Endowment","Kb":"Community & Ecosystem","wB":"Strategic Partners & Reserve","xh":"Staking Rewards"},"O9":{"AS":"#4f78ee","b1":"#f04a3c","_1":"#fbc339","Kb":"#00ab5b","wB":"#ff7426","xh":"#36bbc5"}}'),h=e=>e.reduce(((e,t)=>e+t),0),d=()=>{const e={data:[{values:[h(u.AS),h(u.b1),h(u._1),h(u.Kb),h(u.wB),235e7],labels:[u.p8.AS,u.p8.b1,u.p8._1,u.p8.Kb,u.p8.wB,u.p8.xh],type:"pie",marker:{colors:[u.O9.AS,u.O9.b1,u.O9._1,u.O9.Kb,u.O9.wB,u.O9.xh]},textinfo:"label+percent",textposition:"outside",automargin:!0}],layout:{title:{text:"Token Distribution",font:{size:20},x:.05,yref:"container",y:.95},margin:{t:50,b:50,l:0,r:0},showlegend:!1},config:{}};return o.createElement(r,{label:"Token Distribution",height:400,chart:e,fallbackSvg:p})},E=l.p+"f00e9c1a71f2d8ec8fa31031daf02445.svg",k=e=>{let t=0;return e.map((e=>t+=e))},g=e=>{const t=new Date(2020,10,18);return t.setMonth(t.getMonth()+e),t},m=e=>e.map((e=>g(e).toLocaleDateString(void 0,{dateStyle:"short"}))),b=e=>{const t=e.findIndex((e=>g(e).getTime()>(new Date).getTime()));if(t-1<0)return"";const l=e[t-1];return g(l).toLocaleDateString(void 0,{dateStyle:"short"})},f=()=>{const e={data:[{x:m(u.e7),y:k(u.AS),mode:"lines",name:u.p8.AS,stackgroup:"one",marker:{color:u.O9.AS}},{x:m(u.e7),y:k(u.b1),mode:"lines",name:u.p8.b1,stackgroup:"one",marker:{color:u.O9.b1}},{x:m(u.e7),y:k(u._1),mode:"lines",name:u.p8._1,stackgroup:"one",marker:{color:u.O9._1}},{x:m(u.e7),y:k(u.Kb),mode:"lines",name:u.p8.Kb,stackgroup:"one",marker:{color:u.O9.Kb}},{x:m(u.e7),y:k(u.wB),mode:"lines",name:u.p8.wB,stackgroup:"one",marker:{color:u.O9.wB}},{x:[b(u.e7),b(u.e7)],y:[0,8e9],mode:"lines",name:"Today",marker:{color:"gray"},hoverinfo:"none",showlegend:!1}],layout:{title:{text:"10-Year Token Circulation Schedule",font:{size:20},x:.05,yref:"container",y:.95},xaxis:{tickangle:-45,dtick:6},yaxis:{title:"Tokens in Circulation",fixedrange:!0,rangemode:"nonnegative"},margin:{t:120,r:0},legend:{orientation:"h",x:.5,xanchor:"center",y:1.15,yanchor:"top"},hoverlabel:{namelength:30},hovermode:"x unified"},config:{}};return o.createElement(r,{label:"Circulation Schedule",chart:e,fallbackSvg:E})},w=l.p+"ac606558d6f27b4be4291abfe7a419d1.svg",y=JSON.parse('[{"untilEpoch":1170,"scale":2081},{"untilEpoch":4842,"scale":2081},{"untilEpoch":4866,"scale":2080},{"untilEpoch":4890,"scale":2079},{"untilEpoch":4914,"scale":2078},{"untilEpoch":4938,"scale":2076},{"untilEpoch":4962,"scale":2075},{"untilEpoch":4986,"scale":2073},{"untilEpoch":5010,"scale":2071},{"untilEpoch":5034,"scale":2069},{"untilEpoch":5058,"scale":2067},{"untilEpoch":5082,"scale":2065},{"untilEpoch":5106,"scale":2063},{"untilEpoch":5130,"scale":2060},{"untilEpoch":5154,"scale":2057},{"untilEpoch":5178,"scale":2054},{"untilEpoch":5202,"scale":2050},{"untilEpoch":5226,"scale":2046},{"untilEpoch":5250,"scale":2041},{"untilEpoch":5274,"scale":2036},{"untilEpoch":5298,"scale":2030},{"untilEpoch":5322,"scale":2024},{"untilEpoch":5346,"scale":2017},{"untilEpoch":5370,"scale":2008},{"untilEpoch":5394,"scale":1999},{"untilEpoch":5418,"scale":1988},{"untilEpoch":5442,"scale":1975},{"untilEpoch":5466,"scale":1961},{"untilEpoch":5490,"scale":1945},{"untilEpoch":5514,"scale":1927},{"untilEpoch":5538,"scale":1909},{"untilEpoch":5562,"scale":1889},{"untilEpoch":5586,"scale":1870},{"untilEpoch":5610,"scale":1851},{"untilEpoch":5634,"scale":1834},{"untilEpoch":5658,"scale":1818},{"untilEpoch":5682,"scale":1803},{"untilEpoch":5706,"scale":1791},{"untilEpoch":5730,"scale":1779},{"untilEpoch":5754,"scale":1769},{"untilEpoch":5778,"scale":1761},{"untilEpoch":5802,"scale":1753},{"untilEpoch":5826,"scale":1747},{"untilEpoch":5850,"scale":1741},{"untilEpoch":5874,"scale":1736},{"untilEpoch":5898,"scale":1731},{"untilEpoch":5922,"scale":1727},{"untilEpoch":5946,"scale":1723},{"untilEpoch":5970,"scale":1720},{"untilEpoch":5994,"scale":1717},{"untilEpoch":6018,"scale":1714},{"untilEpoch":6042,"scale":1711},{"untilEpoch":6066,"scale":1709},{"untilEpoch":6090,"scale":1707},{"untilEpoch":6114,"scale":1705},{"untilEpoch":6138,"scale":1703},{"untilEpoch":6162,"scale":1701},{"untilEpoch":6186,"scale":1700},{"untilEpoch":6210,"scale":1698},{"untilEpoch":6234,"scale":1697},{"untilEpoch":6258,"scale":1696},{"untilEpoch":9234,"scale":1694},{"untilEpoch":9258,"scale":1693},{"untilEpoch":9282,"scale":1692},{"untilEpoch":9306,"scale":1690},{"untilEpoch":9330,"scale":1689},{"untilEpoch":9354,"scale":1687},{"untilEpoch":9378,"scale":1686},{"untilEpoch":9402,"scale":1684},{"untilEpoch":9426,"scale":1682},{"untilEpoch":9450,"scale":1680},{"untilEpoch":9474,"scale":1677},{"untilEpoch":9498,"scale":1675},{"untilEpoch":9522,"scale":1672},{"untilEpoch":9546,"scale":1669},{"untilEpoch":9570,"scale":1666},{"untilEpoch":9594,"scale":1662},{"untilEpoch":9618,"scale":1658},{"untilEpoch":9642,"scale":1653},{"untilEpoch":9666,"scale":1648},{"untilEpoch":9690,"scale":1642},{"untilEpoch":9714,"scale":1635},{"untilEpoch":9738,"scale":1627},{"untilEpoch":9762,"scale":1619},{"untilEpoch":9786,"scale":1609},{"untilEpoch":9810,"scale":1597},{"untilEpoch":9834,"scale":1584},{"untilEpoch":9858,"scale":1570},{"untilEpoch":9882,"scale":1553},{"untilEpoch":9906,"scale":1535},{"untilEpoch":9930,"scale":1516},{"untilEpoch":9954,"scale":1496},{"untilEpoch":9978,"scale":1476},{"untilEpoch":10002,"scale":1456},{"untilEpoch":10026,"scale":1438},{"untilEpoch":10050,"scale":1422},{"untilEpoch":10074,"scale":1407},{"untilEpoch":10098,"scale":1393},{"untilEpoch":10122,"scale":1382},{"untilEpoch":10146,"scale":1372},{"untilEpoch":10170,"scale":1363},{"untilEpoch":10194,"scale":1355},{"untilEpoch":10218,"scale":1348},{"untilEpoch":10242,"scale":1342},{"untilEpoch":10266,"scale":1336},{"untilEpoch":10290,"scale":1332},{"untilEpoch":10314,"scale":1327},{"untilEpoch":10338,"scale":1323},{"untilEpoch":10362,"scale":1320},{"untilEpoch":10386,"scale":1317},{"untilEpoch":10410,"scale":1314},{"untilEpoch":10434,"scale":1311},{"untilEpoch":10458,"scale":1309},{"untilEpoch":10482,"scale":1307},{"untilEpoch":10506,"scale":1305},{"untilEpoch":10530,"scale":1303},{"untilEpoch":10554,"scale":1301},{"untilEpoch":10578,"scale":1299},{"untilEpoch":10602,"scale":1298},{"untilEpoch":10626,"scale":1296},{"untilEpoch":10650,"scale":1295},{"untilEpoch":13602,"scale":1294},{"untilEpoch":13626,"scale":1293},{"untilEpoch":13674,"scale":1292},{"untilEpoch":13698,"scale":1291},{"untilEpoch":13722,"scale":1290},{"untilEpoch":13746,"scale":1289},{"untilEpoch":13770,"scale":1288},{"untilEpoch":13794,"scale":1287},{"untilEpoch":13818,"scale":1286},{"untilEpoch":13842,"scale":1285},{"untilEpoch":13866,"scale":1284},{"untilEpoch":13890,"scale":1282},{"untilEpoch":13914,"scale":1281},{"untilEpoch":13938,"scale":1279},{"untilEpoch":13962,"scale":1277},{"untilEpoch":13986,"scale":1275},{"untilEpoch":14010,"scale":1272},{"untilEpoch":14034,"scale":1270},{"untilEpoch":14058,"scale":1267},{"untilEpoch":14082,"scale":1263},{"untilEpoch":14106,"scale":1259},{"untilEpoch":14130,"scale":1255},{"untilEpoch":14154,"scale":1249},{"untilEpoch":14178,"scale":1244},{"untilEpoch":14202,"scale":1237},{"untilEpoch":14226,"scale":1229},{"untilEpoch":14250,"scale":1221},{"untilEpoch":14274,"scale":1212},{"untilEpoch":14298,"scale":1202},{"untilEpoch":14322,"scale":1191},{"untilEpoch":14346,"scale":1181},{"untilEpoch":14370,"scale":1171},{"untilEpoch":14394,"scale":1162},{"untilEpoch":14418,"scale":1153},{"untilEpoch":14442,"scale":1146},{"untilEpoch":14466,"scale":1139},{"untilEpoch":14490,"scale":1133},{"untilEpoch":14514,"scale":1128},{"untilEpoch":14538,"scale":1123},{"untilEpoch":14562,"scale":1119},{"untilEpoch":14586,"scale":1116},{"untilEpoch":14610,"scale":1113},{"untilEpoch":14634,"scale":1110},{"untilEpoch":14658,"scale":1107},{"untilEpoch":14682,"scale":1105},{"untilEpoch":14706,"scale":1103},{"untilEpoch":14730,"scale":1101},{"untilEpoch":14754,"scale":1100},{"untilEpoch":14778,"scale":1098},{"untilEpoch":14802,"scale":1097},{"untilEpoch":14826,"scale":1096},{"untilEpoch":14850,"scale":1095},{"untilEpoch":14874,"scale":1094},{"untilEpoch":14898,"scale":1093},{"untilEpoch":14922,"scale":1092},{"untilEpoch":14946,"scale":1091},{"untilEpoch":14970,"scale":1090},{"untilEpoch":15018,"scale":1089},{"untilEpoch":17994,"scale":1088},{"untilEpoch":18018,"scale":1087},{"untilEpoch":18042,"scale":1085},{"untilEpoch":18066,"scale":1084},{"untilEpoch":18090,"scale":1082},{"untilEpoch":18114,"scale":1081},{"untilEpoch":18138,"scale":1079},{"untilEpoch":18162,"scale":1077},{"untilEpoch":18186,"scale":1075},{"untilEpoch":18210,"scale":1073},{"untilEpoch":18234,"scale":1070},{"untilEpoch":18258,"scale":1067},{"untilEpoch":18282,"scale":1065},{"untilEpoch":18306,"scale":1061},{"untilEpoch":18330,"scale":1058},{"untilEpoch":18354,"scale":1054},{"untilEpoch":18378,"scale":1049},{"untilEpoch":18402,"scale":1044},{"untilEpoch":18426,"scale":1039},{"untilEpoch":18450,"scale":1033},{"untilEpoch":18474,"scale":1025},{"untilEpoch":18498,"scale":1017},{"untilEpoch":18522,"scale":1008},{"untilEpoch":18546,"scale":998},{"untilEpoch":18570,"scale":986},{"untilEpoch":18594,"scale":972},{"untilEpoch":18618,"scale":956},{"untilEpoch":18642,"scale":939},{"untilEpoch":18666,"scale":920},{"untilEpoch":18690,"scale":900},{"untilEpoch":18714,"scale":879},{"untilEpoch":18738,"scale":857},{"untilEpoch":18762,"scale":837},{"untilEpoch":18786,"scale":818},{"untilEpoch":18810,"scale":800},{"untilEpoch":18834,"scale":784},{"untilEpoch":18858,"scale":770},{"untilEpoch":18882,"scale":758},{"untilEpoch":18906,"scale":747},{"untilEpoch":18930,"scale":738},{"untilEpoch":18954,"scale":730},{"untilEpoch":18978,"scale":722},{"untilEpoch":19002,"scale":716},{"untilEpoch":19026,"scale":710},{"untilEpoch":19050,"scale":705},{"untilEpoch":19074,"scale":701},{"untilEpoch":19098,"scale":697},{"untilEpoch":19122,"scale":693},{"untilEpoch":19146,"scale":689},{"untilEpoch":19170,"scale":686},{"untilEpoch":19194,"scale":684},{"untilEpoch":19218,"scale":681},{"untilEpoch":19242,"scale":679},{"untilEpoch":19266,"scale":677},{"untilEpoch":19290,"scale":675},{"untilEpoch":19314,"scale":673},{"untilEpoch":19338,"scale":671},{"untilEpoch":19362,"scale":669},{"untilEpoch":19386,"scale":668},{"untilEpoch":19410,"scale":666},{"untilEpoch":22386,"scale":665},{"untilEpoch":22410,"scale":664},{"untilEpoch":22434,"scale":663},{"untilEpoch":22458,"scale":662},{"untilEpoch":22482,"scale":661},{"untilEpoch":22506,"scale":660},{"untilEpoch":22530,"scale":659},{"untilEpoch":22554,"scale":658},{"untilEpoch":22578,"scale":657},{"untilEpoch":22602,"scale":656},{"untilEpoch":22626,"scale":655},{"untilEpoch":22650,"scale":653},{"untilEpoch":22674,"scale":651},{"untilEpoch":22698,"scale":649},{"untilEpoch":22722,"scale":647},{"untilEpoch":22746,"scale":645},{"untilEpoch":22770,"scale":643},{"untilEpoch":22794,"scale":640},{"untilEpoch":22818,"scale":636},{"untilEpoch":22842,"scale":633},{"untilEpoch":22866,"scale":629},{"untilEpoch":22890,"scale":624},{"untilEpoch":22914,"scale":618},{"untilEpoch":22938,"scale":612},{"untilEpoch":22962,"scale":605},{"untilEpoch":22986,"scale":597},{"untilEpoch":23010,"scale":588},{"untilEpoch":23034,"scale":578},{"untilEpoch":23058,"scale":568},{"untilEpoch":23082,"scale":557},{"untilEpoch":23106,"scale":546},{"untilEpoch":23130,"scale":536},{"untilEpoch":23154,"scale":526},{"untilEpoch":23178,"scale":517},{"untilEpoch":23202,"scale":509},{"untilEpoch":23226,"scale":502},{"untilEpoch":23250,"scale":495},{"untilEpoch":23274,"scale":490},{"untilEpoch":23298,"scale":485},{"untilEpoch":23322,"scale":481},{"untilEpoch":23346,"scale":477},{"untilEpoch":23370,"scale":474},{"untilEpoch":23394,"scale":471},{"untilEpoch":23418,"scale":468},{"untilEpoch":23442,"scale":466},{"untilEpoch":23466,"scale":464},{"untilEpoch":23490,"scale":462},{"untilEpoch":23514,"scale":460},{"untilEpoch":23538,"scale":459},{"untilEpoch":23562,"scale":457},{"untilEpoch":23586,"scale":456},{"untilEpoch":23610,"scale":455},{"untilEpoch":23634,"scale":454},{"untilEpoch":23658,"scale":453},{"untilEpoch":23682,"scale":452},{"untilEpoch":23706,"scale":451},{"untilEpoch":23730,"scale":450},{"untilEpoch":23754,"scale":449},{"untilEpoch":26754,"scale":448},{"untilEpoch":26802,"scale":447},{"untilEpoch":26826,"scale":446},{"untilEpoch":26874,"scale":445},{"untilEpoch":26898,"scale":444},{"untilEpoch":26946,"scale":443},{"untilEpoch":26970,"scale":442},{"untilEpoch":26994,"scale":441},{"untilEpoch":27018,"scale":440},{"untilEpoch":27042,"scale":438},{"untilEpoch":27066,"scale":437},{"untilEpoch":27090,"scale":436},{"untilEpoch":27114,"scale":434},{"untilEpoch":27138,"scale":432},{"untilEpoch":27162,"scale":430},{"untilEpoch":27186,"scale":428},{"untilEpoch":27210,"scale":426},{"untilEpoch":27234,"scale":423},{"untilEpoch":27258,"scale":420},{"untilEpoch":27282,"scale":416},{"untilEpoch":27306,"scale":412},{"untilEpoch":27330,"scale":407},{"untilEpoch":27354,"scale":402},{"untilEpoch":27378,"scale":396},{"untilEpoch":27402,"scale":389},{"untilEpoch":27426,"scale":381},{"untilEpoch":27450,"scale":373},{"untilEpoch":27474,"scale":365},{"untilEpoch":27498,"scale":357},{"untilEpoch":27522,"scale":349},{"untilEpoch":27546,"scale":341},{"untilEpoch":27570,"scale":334},{"untilEpoch":27594,"scale":328},{"untilEpoch":27618,"scale":323},{"untilEpoch":27642,"scale":318},{"untilEpoch":27666,"scale":314},{"untilEpoch":27690,"scale":310},{"untilEpoch":27714,"scale":307},{"untilEpoch":27738,"scale":304},{"untilEpoch":27762,"scale":302},{"untilEpoch":27786,"scale":299},{"untilEpoch":27810,"scale":297},{"untilEpoch":27834,"scale":296},{"untilEpoch":27858,"scale":294},{"untilEpoch":27882,"scale":293},{"untilEpoch":27906,"scale":291},{"untilEpoch":27930,"scale":290},{"untilEpoch":27954,"scale":289},{"untilEpoch":27978,"scale":288},{"untilEpoch":28002,"scale":287},{"untilEpoch":28050,"scale":286},{"untilEpoch":28074,"scale":285},{"untilEpoch":28122,"scale":284},{"untilEpoch":28146,"scale":283},{"untilEpoch":31170,"scale":282},{"untilEpoch":31266,"scale":281},{"untilEpoch":31338,"scale":280},{"untilEpoch":31410,"scale":279},{"untilEpoch":31458,"scale":278},{"untilEpoch":31506,"scale":277},{"untilEpoch":31530,"scale":276},{"untilEpoch":31554,"scale":275},{"untilEpoch":31602,"scale":274},{"untilEpoch":31626,"scale":272},{"untilEpoch":31650,"scale":271},{"untilEpoch":31674,"scale":270},{"untilEpoch":31698,"scale":268},{"untilEpoch":31722,"scale":266},{"untilEpoch":31746,"scale":264},{"untilEpoch":31770,"scale":262},{"untilEpoch":31794,"scale":259},{"untilEpoch":31818,"scale":257},{"untilEpoch":31842,"scale":254},{"untilEpoch":31866,"scale":251},{"untilEpoch":31890,"scale":249},{"untilEpoch":31914,"scale":246},{"untilEpoch":31938,"scale":244},{"untilEpoch":31962,"scale":242},{"untilEpoch":31986,"scale":240},{"untilEpoch":32010,"scale":238},{"untilEpoch":32034,"scale":237},{"untilEpoch":32058,"scale":236},{"untilEpoch":32106,"scale":234},{"untilEpoch":32130,"scale":233},{"untilEpoch":32154,"scale":232},{"untilEpoch":32202,"scale":231},{"untilEpoch":32250,"scale":230},{"untilEpoch":32298,"scale":229},{"untilEpoch":32394,"scale":228},{"untilEpoch":32490,"scale":227},{"untilEpoch":35514,"scale":226},{"untilEpoch":35562,"scale":225},{"untilEpoch":35586,"scale":224},{"untilEpoch":35610,"scale":223},{"untilEpoch":35634,"scale":222},{"untilEpoch":35658,"scale":221},{"untilEpoch":35682,"scale":220},{"untilEpoch":35706,"scale":219},{"untilEpoch":35730,"scale":218},{"untilEpoch":35754,"scale":216},{"untilEpoch":35778,"scale":215},{"untilEpoch":35802,"scale":213},{"untilEpoch":35826,"scale":212},{"untilEpoch":35850,"scale":210},{"untilEpoch":35874,"scale":208},{"untilEpoch":35898,"scale":205},{"untilEpoch":35922,"scale":203},{"untilEpoch":35946,"scale":200},{"untilEpoch":35970,"scale":196},{"untilEpoch":35994,"scale":192},{"untilEpoch":36018,"scale":188},{"untilEpoch":36042,"scale":183},{"untilEpoch":36066,"scale":177},{"untilEpoch":36090,"scale":171},{"untilEpoch":36114,"scale":164},{"untilEpoch":36138,"scale":155},{"untilEpoch":36162,"scale":146},{"untilEpoch":36186,"scale":136},{"untilEpoch":36210,"scale":125},{"untilEpoch":36234,"scale":114},{"untilEpoch":36258,"scale":102},{"untilEpoch":36282,"scale":91},{"untilEpoch":36306,"scale":81},{"untilEpoch":36330,"scale":72},{"untilEpoch":36354,"scale":63},{"untilEpoch":36378,"scale":56},{"untilEpoch":36402,"scale":49},{"untilEpoch":36426,"scale":44},{"untilEpoch":36450,"scale":39},{"untilEpoch":36474,"scale":34},{"untilEpoch":36498,"scale":30},{"untilEpoch":36522,"scale":27},{"untilEpoch":36546,"scale":24},{"untilEpoch":36570,"scale":21},{"untilEpoch":36594,"scale":19},{"untilEpoch":36618,"scale":17},{"untilEpoch":36642,"scale":15},{"untilEpoch":36666,"scale":13},{"untilEpoch":36690,"scale":11},{"untilEpoch":36714,"scale":10},{"untilEpoch":36738,"scale":8},{"untilEpoch":36762,"scale":7},{"untilEpoch":36786,"scale":6},{"untilEpoch":36810,"scale":5},{"untilEpoch":36834,"scale":4},{"untilEpoch":36858,"scale":3},{"untilEpoch":36882,"scale":2},{"untilEpoch":36930,"scale":1}]'),v={beta:{epoch:0,date:"2020-10-01T16:00:00Z"},mainnet:{epoch:1170,date:"2020-11-18T16:00:00.000Z"},recent:{epoch:15835,date:"2022-07-20T16:11:11.000Z"},block4M:{epoch:6664,date:"2021-07-05T04:42:51.000Z"},block5M:{epoch:8328,date:"2021-09-12T03:57:19.000Z"},block6M:{epoch:9992,date:"2021-11-19T23:18:41.000Z"},block7M:{epoch:11656,date:"2022-01-28T05:06:25.000Z"},block8M:{epoch:13320,date:"2022-04-07T22:49:44.000Z"},block9M:{epoch:14987,date:"2022-06-15T16:22:57.000Z"}},N=v.recent,x=(v.recent.epoch-v.mainnet.epoch)/((new Date(v.recent.date).getTime()-new Date(v.mainnet.date).getTime())/1e3/60/60),S=8760*x,T=1e8,C=e=>e.map((e=>{const t=(e-N.epoch)/x*60*60*1e3;return new Date(new Date(N.date).getTime()+t).toISOString()})),O=()=>{const e={data:[{x:C(y.map((e=>e.untilEpoch))),y:(t=y.map((e=>e.scale)),t.map((e=>{const t=1*e/T;return Math.expm1(Math.log1p(t)*S)}))),mode:"lines",name:"Annualized rewards",marker:{color:"#4285F4"},text:y.map((e=>`<i>Reward per epoch: ${100*e.scale*1/T}%<br>Epoch: ${e.untilEpoch}</i>`)),hoverinfo:"all"},{x:[(new Date).toISOString(),(new Date).toISOString()],y:[0,.205],mode:"lines",name:"Today",marker:{color:"gray"},hoverinfo:"none",showlegend:!1}],layout:{title:{text:"Staking Rewards Schedule (time estimated from epoch interval)",font:{size:20},x:.05,yref:"container",y:.95},xaxis:{tickangle:-45},yaxis:{title:"Estimated Annualized Rewards",fixedrange:!0,tickformat:"0%",hoverformat:".3%",dtick:.02,rangemode:"nonnegative"},margin:{r:0},showlegend:!1,hoverlabel:{namelength:30},hovermode:"x unified"},config:{}};var t;return o.createElement(r,{label:"Staking Rewards Schedule (time estimated from epoch interval)",chart:e,fallbackSvg:w})};const D={},A="Token Metrics and Distribution",F={unversionedId:"general/oasis-network/token-metrics-and-distribution",id:"general/oasis-network/token-metrics-and-distribution",title:"Token Metrics and Distribution",description:"Background illustration",source:"@site/docs/general/oasis-network/token-metrics-and-distribution.mdx",sourceDirName:"general/oasis-network",slug:"/general/oasis-network/token-metrics-and-distribution",permalink:"/general/oasis-network/token-metrics-and-distribution",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/token-metrics-and-distribution.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Why Oasis?",permalink:"/general/oasis-network/why-oasis"},next:{title:"Frequently Asked Questions",permalink:"/general/oasis-network/faq"}},z={},M=[{value:"Quick Token Facts",id:"quick-token-facts",level:2},{value:"Token Distribution",id:"token-distribution",level:2},{value:"Token Distribution Glossary",id:"token-distribution-glossary",level:3},{value:"Circulating Supply",id:"circulating-supply",level:3},{value:"Fundraising History",id:"fundraising-history",level:2},{value:"Staking Incentives",id:"staking-incentives",level:2},{value:"Delegation Policy",id:"delegation-policy",level:2},{value:"Change Log",id:"change-log",level:2}],B={toc:M},_="wrapper";function Z(e){let{components:t,...o}=e;return(0,c.kt)(_,(0,a.Z)({},B,o,{components:t,mdxType:"MDXLayout"}),(0,c.kt)("h1",{id:"token-metrics-and-distribution"},"Token Metrics and Distribution"),(0,c.kt)("p",null,(0,c.kt)("img",{alt:"Background illustration",src:l(4877).Z,width:"4800",height:"2400"})),(0,c.kt)("h2",{id:"quick-token-facts"},"Quick Token Facts"),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Supply"),": The ROSE native token is a capped supply token. The circulating supply at launch will be approximately 1.5 billion tokens, and the total cap is fixed at 10 billion tokens."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Token utility:")," The ROSE token will be used for transaction fees, staking, and delegation at the consensus layer."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Staking rewards"),": ","~","2.3 billion tokens will be automatically paid out as staking rewards to stakers and delegators for securing the network over time."),(0,c.kt)("h2",{id:"token-distribution"},"Token Distribution"),(0,c.kt)("p",null,"The quantity of ROSE tokens reserved for various network functions, as a percentage of the total existing token supply, approximately follows the distribution below."),(0,c.kt)("admonition",{type:"caution"},(0,c.kt)("p",{parentName:"admonition"},"Please note that these percentages and allocations are subject to change as we finalize the logistics for the network and its related programs.")),(0,c.kt)(d,{mdxType:"FinalDistributionPieChart"}),(0,c.kt)("h3",{id:"token-distribution-glossary"},"Token Distribution Glossary"),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Backers"),": Tokens sold directly to backers prior to mainnet launch. The vast majority of these sales took place in 2018."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Core Contributors"),": Compensation to core contributors for contributing to the development of the Oasis Network."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Foundation Endowment"),": Endowment to the Oasis Foundation to foster the development and maintenance of the Oasis Network."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Community and Ecosystem"),": Funding programs and services that engage the Oasis Network community, including developer grants and other community incentives by the Oasis Foundation."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Strategic Partners and Reserve"),": Funding programs and services provided by key strategic partners in the Oasis Network."),(0,c.kt)("p",null,(0,c.kt)("strong",{parentName:"p"},"Staking Rewards"),": Rewards to be paid out on-chain to stakers and delegators for contributing to the security of the Oasis Network."),(0,c.kt)("h3",{id:"circulating-supply"},"Circulating Supply"),(0,c.kt)("p",null,"Not all tokens have been released publicly or will be released publicly by Mainnet launch. Due to release schedules and locks, only a fraction of the total existing token supply will be in circulation at the time of Mainnet. Approximately 1.5 billion tokens out of a fixed supply of 10 billion tokens in total will be in circulation immediately upon Mainnet. In addition, a portion of Foundation tokens that are not in the circulation supply at launch are staked on the network. Any staking rewards earned will go back into the network via future validator delegations, network feature development, and ecosystem grants."),(0,c.kt)("p",null,"Tokens set aside for Staking Rewards will be disbursed in accordance with on-chain reward mechanisms which calculate rewards based on how many blocks are proposed by validator, how many blocks are signed by a\nvalidator, how many nodes are participating in staking, and how many tokens are staked etc.\nThe remaining allocations will be disbursed according to the following release schedule:"),(0,c.kt)(f,{mdxType:"TokenDistributionChart"}),(0,c.kt)("p",null,"Alternative formats: ",(0,c.kt)("a",{target:"_blank",href:l(8845).Z},"CSV")),(0,c.kt)("h2",{id:"fundraising-history"},"Fundraising History"),(0,c.kt)("p",null,"Between 2018 and 2020 Oasis has raised over $45 million from backers including:"),(0,c.kt)("p",null,(0,c.kt)("img",{alt:"Fundraising History",src:l(8186).Z,width:"1200",height:"816"})),(0,c.kt)("h2",{id:"staking-incentives"},"Staking Incentives"),(0,c.kt)("p",null,"Given the Oasis Network\u2019s founding vision to become a world-class, public, permissionless blockchain platform, the contributing team at Oasis has been focused on ensuring that setting up a node is as seamless as possible for all community members. To that end, we\u2019ve put a lot of thought into making sure our staking conditions minimize barriers to entry and encourage meaningful engagement on the network. Some key parameters include:"),(0,c.kt)("ul",null,(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Number of validators to participate in the consensus committee (and receive staking rewards):")," 120. Validators will be based on the stake weight on the network."),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Minimum stake"),": 100 tokens per entity"),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Selection to the consensus committee"),": Each entity can have at most one node elected to the consensus committee at a time."),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Staking rewards"),": The network is targeted to reward stakers with rewards of between 2.0% to 20.0% depending on the length of time staked to provide staking services on the network. In order to be eligible for staking rewards per epoch, a node would need to sign at least 75% of blocks in that epoch."),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Slashing"),": At the time of Mainnet launch, the network will only slash for forms of double-signing. The network would slash the minimum stake amount (100 tokens) and freeze the node. Freezing the node is a precaution in order to prevent the node from being over-penalized. The Network will not slash for liveness or uptime at launch."),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Unbonding period"),": The network will have a ","~","14 day unbonding period. During this time, staked tokens are at risk of getting slashed for double-signing and do not accrue rewards during this time."),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Consensus voting power"),": The current voting power mechanism is stake-weighted. This means that the consensus voting power of a validator is proportional to its stake. In this model, the network will require signatures by validators representing +2/3 of the total stake of the committee to sign a block. Note that in Tendermint, a validator's opportunities to propose a block in the round-robin block proposer order are also proportional to its voting power.")),(0,c.kt)(O,{mdxType:"StakingRewardsChart"}),(0,c.kt)("p",null,"Alternative formats: ",(0,c.kt)("a",{target:"_blank",href:l(6588).Z},"CSV")),(0,c.kt)("h2",{id:"delegation-policy"},"Delegation Policy"),(0,c.kt)("p",null,"The Oasis Protocol Foundation is committed to give delegations to entities participating in various incentivized networks."),(0,c.kt)("p",null,"For more details, see its ",(0,c.kt)("a",{parentName:"p",href:"/get-involved/delegation-policy"},"Delegation Policy"),"."),(0,c.kt)("h2",{id:"change-log"},"Change Log"),(0,c.kt)("ul",null,(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Jul 28, 2022:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Created interactive Staking Rewards Schedule chart."),(0,c.kt)("li",{parentName:"ul"},"Created interactive Token Distribution pie chart."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Jul 15, 2022:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Created interactive Token Circulation Schedule chart."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Apr 28, 2022:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Updated validator set to 120 as reflected in the Oasis Network 2022-04-11 Upgrade."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Nov 10, 2021:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Updated validator set to 110 as reflected in the Oasis Network 2021-08-31 Upgrade."),(0,c.kt)("li",{parentName:"ul"},"Added Circulating Supply title to the part talking about Oasis Network's circulating supply."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"April 30, 2021:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Updated validator set to 100 as reflected in the Oasis Network Cobalt Upgrade."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Jan 15, 2021:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Added section on Foundation's Delegation Policy."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Nov 15, 2020:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Corrected the initial validator consensus committee to 80 validators. This reflects what is currently in the community approved genesis file and community proposed upgrade to Mainnet."))),(0,c.kt)("li",{parentName:"ul"},(0,c.kt)("strong",{parentName:"li"},"Nov 2, 2020:"),(0,c.kt)("ul",{parentName:"li"},(0,c.kt)("li",{parentName:"ul"},"Updated Backers image to include more publicly-known backers."),(0,c.kt)("li",{parentName:"ul"},"Included a community-proposed (and foundation supported) increase in staking rewards range from 15% - 2% to 20% - 2% over the first four years of the network. Impacted charts (distribution, token delivery schedule, and expected staking rewards) also updated to reflect the increase in staking rewards.")))))}Z.isMDXComponent=!0},6588:(e,t,l)=>{l.d(t,{Z:()=>a});const a=l.p+"assets/files/data-e5c85038908548ce84bf7db10d5899b9.csv"},8845:(e,t,l)=>{l.d(t,{Z:()=>a});const a=l.p+"assets/files/data-3564fe57c5907977ab1cd7c274a1b895.csv"},8186:(e,t,l)=>{l.d(t,{Z:()=>a});const a=l.p+"assets/images/backers-68a28b448e9f1757941ef06bb6dd90e2.png"},4877:(e,t,l)=>{l.d(t,{Z:()=>a});const a=l.p+"assets/images/metrics-background-17ff1b79c8113d871e481b777779d2ae.png"}}]); \ No newline at end of file diff --git a/assets/js/1df235ce.b8cbbeb7.js b/assets/js/1df235ce.b8cbbeb7.js new file mode 100644 index 0000000000..bf76bca183 --- /dev/null +++ b/assets/js/1df235ce.b8cbbeb7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3600],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>m});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,o=function(e,t){if(null==e)return{};var n,a,o={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(n),h=o,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||r;return n?a.createElement(m,i(i({ref:t},d),{},{components:n})):a.createElement(m,i({ref:t},d))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var c=2;c<r;c++)i[c]=n[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},2582:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>c});var a=n(7462),o=(n(7294),n(3905));const r={},i="Confidential Hello World",s={unversionedId:"dapp/cipher/confidential-smart-contract",id:"dapp/cipher/confidential-smart-contract",title:"Confidential Hello World",description:"Confidential smart contract execution on Oasis is assured by three mechanisms:",source:"@site/docs/dapp/cipher/confidential-smart-contract.md",sourceDirName:"dapp/cipher",slug:"/dapp/cipher/confidential-smart-contract",permalink:"/dapp/cipher/confidential-smart-contract",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/confidential-smart-contract.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Hello World",permalink:"/dapp/cipher/hello-world"}},l={},c=[{value:"Confidential cell",id:"confidential-cell",level:2},{value:"Confidential Instantiation and Calling",id:"confidential-instantiation-and-calling",level:2}],d={toc:c},p="wrapper";function u(e){let{components:t,...n}=e;return(0,o.kt)(p,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"confidential-hello-world"},"Confidential Hello World"),(0,o.kt)("p",null,"Confidential smart contract execution on Oasis is assured by three mechanisms:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"the contract is executed in a trusted execution environment,"),(0,o.kt)("li",{parentName:"ul"},"the contract's storage on the blockchain is encrypted,"),(0,o.kt)("li",{parentName:"ul"},"the client's transactions and queries are end-to-end encrypted.")),(0,o.kt)("p",null,"The first mechanism is implemented as part of the ParaTime attestation process\non the consensus layer and is opaque to the dApp developer."),(0,o.kt)("p",null,"The other two mechanisms are available to dApp developers. The remainder of\nthis chapter will show you how to use an encrypted contract storage\nand perform contract operations with end-to-end encryption on Cipher."),(0,o.kt)("h2",{id:"confidential-cell"},"Confidential cell"),(0,o.kt)("p",null,"In the ",(0,o.kt)("a",{parentName:"p",href:"/dapp/cipher/hello-world"},"hello world")," example we used\n",(0,o.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk_storage/cell/struct.PublicCell.html"},(0,o.kt)("inlineCode",{parentName:"a"},"PublicCell<T>"))," to access the key-value store\nof that contract instance. In this case the value was stored unencrypted on the\nblockchain associated with the hash of the key we provided to the constructor\n(e.g., the ",(0,o.kt)("inlineCode",{parentName:"p"},"counter")," in ",(0,o.kt)("inlineCode",{parentName:"p"},'PublicCell::new(b"counter")'),")."),(0,o.kt)("p",null,"Cipher supports another primitive ",(0,o.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk_storage/cell/struct.ConfidentialCell.html"},(0,o.kt)("inlineCode",{parentName:"a"},"ConfidentialCell<T>")),"\nwhich enables you to store and load data confidentially assured by\nhardware-level encryption. In addition, the value is encrypted along with a\nnonce so that it appears different each time to the blockchain observer, even\nif the decrypted value remains equal. Namely, the nonce is generated from:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"the round number,"),(0,o.kt)("li",{parentName:"ul"},"the number of the sub-call during current smart contract execution,"),(0,o.kt)("li",{parentName:"ul"},"the number of confidential storage accesses from smart contracts in the\ncurrent block.")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"The location of the confidential cell inside the contract state is\n",(0,o.kt)("strong",{parentName:"p"},"still based on the initialization key passed to the constructor"),".\nConsequently, if you declare a number of confidential cells and write to the\nsame one on each call, the blockchain observers will notice that the same\ncell is being changed every time.")),(0,o.kt)("p",null,"To call the confidential cell getter and setter, you will need to provide the\ninstance of the ",(0,o.kt)("em",{parentName:"p"},"confidential store"),". The store is obtained by calling\n",(0,o.kt)("inlineCode",{parentName:"p"},"confidential_store()")," on the contract's ",(0,o.kt)("em",{parentName:"p"},"context")," object. If, for example, the\nnode operator will try to execute your code in a non-confidential environment,\nthey would not obtain the keys required to perform decryption so the operation\nwould fail."),(0,o.kt)("p",null,"Now, let's look at how a confidential version of the hello world smart contract\nwould look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-rust",metastring:'title="src/lib.rs"',title:'"src/lib.rs"'},'//! A confidential hello world smart contract.\nextern crate alloc;\n\nuse oasis_contract_sdk as sdk;\nuse oasis_contract_sdk_storage::cell::ConfidentialCell;\n\n/// All possible errors that can be returned by the contract.\n///\n/// Each error is a triplet of (module, code, message) which allows it to be both easily\n/// human readable and also identifyable programmatically.\n#[derive(Debug, thiserror::Error, sdk::Error)]\npub enum Error {\n #[error("bad request")]\n #[sdk_error(code = 1)]\n BadRequest,\n}\n\n/// All possible requests that the contract can handle.\n///\n/// This includes both calls and queries.\n#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]\npub enum Request {\n #[cbor(rename = "instantiate")]\n Instantiate { initial_counter: u64 },\n\n #[cbor(rename = "say_hello")]\n SayHello { who: String },\n}\n\n/// All possible responses that the contract can return.\n///\n/// This includes both calls and queries.\n#[derive(Clone, Debug, Eq, PartialEq, cbor::Encode, cbor::Decode)]\npub enum Response {\n #[cbor(rename = "hello")]\n Hello { greeting: String },\n\n #[cbor(rename = "empty")]\n Empty,\n}\n\n/// The contract type.\npub struct HelloWorld;\n\n/// Storage cell for the counter.\nconst COUNTER: ConfidentialCell<u64> = ConfidentialCell::new(b"counter");\n\nimpl HelloWorld {\n /// Increment the counter and return the previous value.\n fn increment_counter<C: sdk::Context>(ctx: &mut C) -> u64 {\n let counter = COUNTER.get(ctx.confidential_store()).unwrap_or_default();\n COUNTER.set(ctx.confidential_store(), counter + 1);\n\n counter\n }\n}\n\n// Implementation of the sdk::Contract trait is required in order for the type to be a contract.\nimpl sdk::Contract for HelloWorld {\n type Request = Request;\n type Response = Response;\n type Error = Error;\n\n fn instantiate<C: sdk::Context>(ctx: &mut C, request: Request) -> Result<(), Error> {\n // This method is called during the contracts.Instantiate call when the contract is first\n // instantiated. It can be used to initialize the contract state.\n match request {\n // We require the caller to always pass the Instantiate request.\n Request::Instantiate { initial_counter } => {\n // Initialize counter to specified value.\n COUNTER.set(ctx.confidential_store(), initial_counter);\n\n Ok(())\n }\n _ => Err(Error::BadRequest),\n }\n }\n\n fn call<C: sdk::Context>(ctx: &mut C, request: Request) -> Result<Response, Error> {\n // This method is called for each contracts.Call call. It is supposed to handle the request\n // and return a response.\n match request {\n Request::SayHello { who } => {\n // Increment the counter and retrieve the previous value.\n let counter = Self::increment_counter(ctx);\n\n // Return the greeting as a response.\n Ok(Response::Hello {\n greeting: format!("hello {who} ({counter})"),\n })\n }\n _ => Err(Error::BadRequest),\n }\n }\n\n fn query<C: sdk::Context>(_ctx: &mut C, _request: Request) -> Result<Response, Error> {\n // This method is called for each contracts.Query query. It is supposed to handle the\n // request and return a response.\n Err(Error::BadRequest)\n }\n}\n\n// Create the required Wasm exports required for the contract to be runnable.\nsdk::create_contract!(HelloWorld);\n\n// We define some simple contract tests below.\n#[cfg(test)]\nmod test {\n use oasis_contract_sdk::{testing::MockContext, types::ExecutionContext, Contract};\n\n use super::*;\n\n #[test]\n fn test_hello() {\n // Create a mock execution context with default values.\n let mut ctx: MockContext = ExecutionContext::default().into();\n\n // Instantiate the contract.\n HelloWorld::instantiate(\n &mut ctx,\n Request::Instantiate {\n initial_counter: 11,\n },\n )\n .expect("instantiation should work");\n\n // Dispatch the SayHello message.\n let rsp = HelloWorld::call(\n &mut ctx,\n Request::SayHello {\n who: "unit test".to_string(),\n },\n )\n .expect("SayHello call should work");\n\n // Make sure the greeting is correct.\n assert_eq!(\n rsp,\n Response::Hello {\n greeting: "hello unit test (11)".to_string()\n }\n );\n\n // Dispatch another SayHello message.\n let rsp = HelloWorld::call(\n &mut ctx,\n Request::SayHello {\n who: "second call".to_string(),\n },\n )\n .expect("SayHello call should work");\n\n // Make sure the greeting is correct.\n assert_eq!(\n rsp,\n Response::Hello {\n greeting: "hello second call (12)".to_string()\n }\n );\n }\n}\n')),(0,o.kt)("p",null,"The contract is built the same way as its non-confidential counterpart:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"cargo build --target wasm32-unknown-unknown --release\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The blockchain store containing all compiled contracts is public. This means\nthat anyone will be able to decompile your smart contract and see how it\nworks. ",(0,o.kt)("strong",{parentName:"p"},"Do not put any sensitive data inside the smart contract code!"))),(0,o.kt)("p",null,"Since the smart contracts store is public, uploading the Wasm code is\nthe same as for the non-confidential ones:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis contracts upload hello_world.wasm\n")),(0,o.kt)("h2",{id:"confidential-instantiation-and-calling"},"Confidential Instantiation and Calling"),(0,o.kt)("p",null,"To generate an encrypted transaction, the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis contracts")," subcommand\nexpects a ",(0,o.kt)("inlineCode",{parentName:"p"},"--encrypted")," flag. The client (",(0,o.kt)("inlineCode",{parentName:"p"},"oasis")," command in our case) will\ngenerate and use an ephemeral keypair for encryption. If the original\ntransaction was encrypted, the returned transaction result will also be\nencrypted inside the trusted execution environment to prevent a\nman-in-the-middle attack by the compute node."),(0,o.kt)("p",null,"Encrypted transactions have the following encrypted fields:\ncontract address, function name, parameters and the amounts and types of tokens\nsent."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Encrypted transactions are not anonymous!")," Namely, the transaction contains\nunencrypted public key of your account or a list of expected multisig keys,\nthe gas limit and the amount of fee paid for the transaction execution."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"While the transaction execution is confidential, its effects may reveal some\ninformation. For example, the account balances are public. If the effect is,\nsay, subtraction of 10 tokens from the signer's account, this most probably\nimplies that they have been transferred as part of this transaction.")),(0,o.kt)("p",null,"Before we instantiate the contract we need to consider the gas usage of our\nconfidential smart contract. Since the execution of the smart contract is\ndependent on the (confidential) smart contract state, the gas limit cannot be\ncomputed automatically. Currently, the gas limit for confidential transactions\nis tailored towards simple transaction execution (e.g. no gas is reserved for\naccessing the contract state). For more expensive transactions, we\nneed to explicitly pass the ",(0,o.kt)("inlineCode",{parentName:"p"},"--gas-limit")," parameter and ",(0,o.kt)("em",{parentName:"p"},"guess")," the sufficient\nvalue for now or we will get the ",(0,o.kt)("inlineCode",{parentName:"p"},"out of gas")," error. For example, to\ninstantiate our smart contract above with a single write to the contract state,\nwe need to raise the gas limit to ",(0,o.kt)("inlineCode",{parentName:"p"},"60000"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis contracts instantiate CODEID '{instantiate: {initial_counter: 42}}' --encrypted --gas-limit 60000\n")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"out of gas")," error can ",(0,o.kt)("strong",{parentName:"p"},"potentially reveal the (confidential) state of the\nsmart contract"),"! If your smart contract contains a branch which depends on the\nvalue stored in the contract state, an attack similar to the ",(0,o.kt)("strong",{parentName:"p"},"timing attack"),"\nknown from the design of cryptographic algorithms can succeed. To overcome this,\nyour code should ",(0,o.kt)("strong",{parentName:"p"},"never contain branches depending on secret smart contract\nstate"),"."),(0,o.kt)("p",{parentName:"admonition"},"A similar gas limit attack could reveal the ",(0,o.kt)("strong",{parentName:"p"},"client's transaction parameters"),".\nFor example, if calling function ",(0,o.kt)("inlineCode",{parentName:"p"},"A")," costs ",(0,o.kt)("inlineCode",{parentName:"p"},"50,000")," gas units and function ",(0,o.kt)("inlineCode",{parentName:"p"},"B"),"\n",(0,o.kt)("inlineCode",{parentName:"p"},"300,000")," gas units, the attacker could imply which function call was performed\nbased on the transaction's gas limit, which is public. To mitigate this attack,\nthe client should always use the maximum gas cost among all contract function\ncalls - in this case ",(0,o.kt)("inlineCode",{parentName:"p"},"300,000"),".")),(0,o.kt)("p",null,"Finally, we make a confidential call:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis contracts call INSTANCEID '{say_hello: {who: \"me\"}}' --encrypted --gas-limit 60000\n")),(0,o.kt)("admonition",{title:"Call Format",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html"},"Context")," object has a special ",(0,o.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html#tymethod.call_format"},(0,o.kt)("inlineCode",{parentName:"a"},"call_format"))," attribute which holds\ninformation on whether the transaction was encrypted by the client's ephemeral\nkey or not. Having access control based on this value is useful as an\nadditional safety precaution to prevent leakage of any confidential\ninformation unencrypted out of the trusted execution environment by mistake.")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"Regardless of the encrypted transaction and confidential storage used in the\nsmart contract, any ",(0,o.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html#tymethod.emit_event"},"emitted event")," will be public.")),(0,o.kt)("admonition",{title:"Example",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You can view and download a ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/contract-sdk/c10l-hello-world"},"complete example")," from the Oasis SDK repository.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1e60058c.91e75443.js b/assets/js/1e60058c.91e75443.js new file mode 100644 index 0000000000..b9357daf5f --- /dev/null +++ b/assets/js/1e60058c.91e75443.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[28],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var r=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){s(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,s=function(e,t){if(null==e)return{};var n,r,s={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=l(n),d=s,h=u["".concat(c,".").concat(d)]||u[d]||m[d]||a;return n?r.createElement(h,o(o({ref:t},p),{},{components:n})):r.createElement(h,o({ref:t},p))}));function h(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var a=n.length,o=new Array(a);o[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:s,o[1]=i;for(var l=2;l<a;l++)o[l]=n[l];return r.createElement.apply(null,o)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},7595:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(7462),s=(n(7294),n(3905));const a={},o="Consensus Layer",i={unversionedId:"core/consensus/README",id:"core/consensus/README",title:"Consensus Layer",description:"Oasis Core is designed around the principle of modularity. The consensus layer",source:"@site/docs/core/consensus/README.md",sourceDirName:"core/consensus",slug:"/core/consensus/",permalink:"/core/consensus/",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/README.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"High-Level Components",permalink:"/core/high-level-components"},next:{title:"Transactions",permalink:"/core/consensus/transactions"}},c={},l=[{value:"Tendermint",id:"tendermint",level:2},{value:"ABCI Application Multiplexer",id:"abci-application-multiplexer",level:3},{value:"State Storage",id:"state-storage",level:3},{value:"Service Implementations",id:"service-implementations",level:3},{value:"Queries",id:"queries",level:4},{value:"Transactions",id:"transactions",level:4}],p={toc:l},u="wrapper";function m(e){let{components:t,...a}=e;return(0,s.kt)(u,(0,r.Z)({},p,a,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("h1",{id:"consensus-layer"},"Consensus Layer"),(0,s.kt)("p",null,"Oasis Core is designed around the principle of modularity. The ",(0,s.kt)("em",{parentName:"p"},"consensus layer"),"\nis an interface that provides a number of important services to other parts of\nOasis Core. This allows, in theory, for the consensus backend to be changed. The\ndifferent backends live in ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus")),", with the general interfaces in\n",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/api"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus/api")),". The general rule is that anything outside of a specific\nconsensus backend package should be consensus backend agnostic."),(0,s.kt)("p",null,"For more details about the actual API that the consensus backends must provide\nsee the ",(0,s.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc"},"consensus backend API documentation"),"."),(0,s.kt)("p",null,"Currently the only supported consensus backend is ",(0,s.kt)("a",{parentName:"p",href:"https://tendermint.com/"},"Tendermint"),", a BFT consensus\nprotocol. For this reason some API surfaces may not be fully consensus backend\nagnostic."),(0,s.kt)("p",null,"Each consensus backend needs to provide the following services:"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/epochtime"},"Epoch Time"),", an epoch-based time keeping service."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/beacon"},"Random Beacon"),", a source of randomness for other services."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/staking"},"Staking"),", operations required to operate a PoS blockchain."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/registry"},"Registry"),", an entity/node/runtime public key and metadata registry service."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/scheduler"},"Committee Scheduler")," service."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/governance"},"Governance")," service."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/roothash"},"Root Hash"),", runtime commitment processing and minimal runtime state keeping\nservice."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/keymanager"},"Key Manager")," policy state keeping service.")),(0,s.kt)("p",null,"Each of the above services provides methods to query its current state. In order\nto mutate the current state, each operation needs to be wrapped into a\n",(0,s.kt)("a",{parentName:"p",href:"/core/consensus/transactions"},"consensus transaction")," and submitted to the consensus layer for processing."),(0,s.kt)("p",null,"Oasis Core defines an interface for each kind of service (in\n",(0,s.kt)("inlineCode",{parentName:"p"},"go/<service>/api"),"), with all concrete service implementations living together\nwith the consensus backend implementation. The service API defines the\ntransaction format for mutating state together with any query methods (both are\nconsensus backend agnostic)."),(0,s.kt)("h2",{id:"tendermint"},"Tendermint"),(0,s.kt)("p",null,(0,s.kt)("img",{alt:"Tendermint",src:n(8216).Z,width:"556",height:"261"})),(0,s.kt)("p",null,"The Tendermint consensus backend lives in ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/stable/22.2.x/go/consensus/tendermint"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus/tendermint")),"."),(0,s.kt)("p",null,"For more information about Tendermint itself see\n",(0,s.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/"},"the Tendermint Core developer documentation"),". This section assumes familiarity\nwith the Tendermint Core concepts and APIs. When used as an Oasis Core consensus\nbackend, Tendermint Core is used as a library and thus lives in the same\nprocess."),(0,s.kt)("p",null,"The Tendermint consensus backend is split into two major parts:"),(0,s.kt)("ol",null,(0,s.kt)("li",{parentName:"ol"},(0,s.kt)("p",{parentName:"li"},"The first part is the ",(0,s.kt)("strong",{parentName:"p"},"ABCI application")," that represents the core logic\nthat is replicated by Tendermint Core among the network nodes using the\nTendermint BFT protocol for consensus.")),(0,s.kt)("li",{parentName:"ol"},(0,s.kt)("p",{parentName:"li"},"The second part is the ",(0,s.kt)("strong",{parentName:"p"},"query and transaction submission glue")," that makes\nit easy to interact with the ABCI application, presenting everything via the\nOasis Core Consensus interface."))),(0,s.kt)("h3",{id:"abci-application-multiplexer"},"ABCI Application Multiplexer"),(0,s.kt)("p",null,"Tendermint Core consumes consensus layer logic via the ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/tendermint/tendermint/blob/master/spec/abci/abci.md"},"ABCI protocol"),", which\nassumes a single application. Since we have multiple services that need to be\nprovided by the consensus layer we use an ",(0,s.kt)("em",{parentName:"p"},"ABCI application multiplexer")," which\nperforms some common functions and dispatches transactions to the appropriate\nservice-specific handler."),(0,s.kt)("p",null,"The multiplexer lives in ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/stable/22.2.x/go/consensus/tendermint/abci/mux.go"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus/tendermint/abci/mux.go"))," with the\nmultiplexed applications, generally corresponding to services required by the\n",(0,s.kt)("em",{parentName:"p"},"consensus layer")," interface living in ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/stable/22.2.x/go/consensus/tendermint/apps"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus/tendermint/apps/<app>")),"."),(0,s.kt)("h3",{id:"state-storage"},"State Storage"),(0,s.kt)("p",null,"All application state for the Tendermint consensus backend is stored using our\n",(0,s.kt)("a",{parentName:"p",href:"/core/mkvs"},"Merklized Key-Value Store"),"."),(0,s.kt)("h3",{id:"service-implementations"},"Service Implementations"),(0,s.kt)("p",null,"Service implementations for the Tendermint consensus backend live in\n",(0,s.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/stable/22.2.x/go/consensus/tendermint"},(0,s.kt)("inlineCode",{parentName:"a"},"go/consensus/tendermint/<service>")),". They provide the glue between the\nservices running as part of the ABCI application multiplexer and the Oasis Core\nservice APIs. The interfaces generally provide a read-only view of the consensus\nlayer state at a given height. Internally, these perform queries against the\nABCI application state."),(0,s.kt)("h4",{id:"queries"},"Queries"),(0,s.kt)("p",null,"Queries do not use the ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/tendermint/tendermint/blob/master/spec/abci/abci.md#query-1"},"ABCI query functionality")," as that would incur needless\noverhead for our use case (with Tendermint Core running in the same process).\nInstead, each multiplexed service provides its own ",(0,s.kt)("inlineCode",{parentName:"p"},"QueryFactory")," which can be\nused to query state at a specific block height."),(0,s.kt)("p",null,"An example of a ",(0,s.kt)("inlineCode",{parentName:"p"},"QueryFactory")," and the corresponding ",(0,s.kt)("inlineCode",{parentName:"p"},"Query")," interfaces for the\nstaking service are as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"// QueryFactory is the staking query factory interface.\ntype QueryFactory interface {\n QueryAt(ctx context.Context, height int64) (Query, error)\n}\n\n// Query is the staking query interface.\ntype Query interface {\n TotalSupply(ctx context.Context) (*quantity.Quantity, error)\n CommonPool(ctx context.Context) (*quantity.Quantity, error)\n LastBlockFees(ctx context.Context) (*quantity.Quantity, error)\n\n // ... further query methods omitted ...\n}\n")),(0,s.kt)("p",null,"Implementations of this interface generally directly access the underlying ABCI\nstate storage to answer queries. Tendermint implementations of Oasis Core\nconsensus services generally follow the following pattern (example from the\nstaking service API for querying ",(0,s.kt)("inlineCode",{parentName:"p"},"TotalSupply"),"):"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"func (s *staking) TotalSupply(ctx context.Context, height int64) (*quantity.Quantity, error) {\n q, err := s.querier.QueryAt(ctx, height)\n if err != nil {\n return nil, err\n }\n\n return q.TotalSupply(ctx)\n}\n")),(0,s.kt)("h4",{id:"transactions"},"Transactions"),(0,s.kt)("p",null,"Each ",(0,s.kt)("a",{parentName:"p",href:"/core/consensus/transactions"},"serialized signed Oasis Core transaction")," directly corresponds to a\n",(0,s.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/main/tendermint-core/using-tendermint.html#transactions"},"Tendermint transaction"),". Submission is performed by pushing the serialized\ntransaction bytes into the ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/tendermint/tendermint/blob/master/spec/abci/abci.md#mempool-connection"},"mempool")," where it first undergoes basic checks and\nis then gossiped to the Tendermint P2P network."),(0,s.kt)("p",null,"Handling of basic checks and transaction execution is performed by the ABCI\napplication multiplexer mentioned above."))}m.isMDXComponent=!0},8216:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/oasis-core-consensus-tendermint-d5ec48977d94f45cfa764d6585f6b21b.svg"}}]); \ No newline at end of file diff --git a/assets/js/1fa6bbb5.d9f4c362.js b/assets/js/1fa6bbb5.d9f4c362.js new file mode 100644 index 0000000000..09b9c6f63b --- /dev/null +++ b/assets/js/1fa6bbb5.d9f4c362.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3845],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>h});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,o=function(e,t){if(null==e)return{};var n,a,o={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=p(n),u=o,h=m["".concat(l,".").concat(u)]||m[u]||d[u]||r;return n?a.createElement(h,i(i({ref:t},c),{},{components:n})):a.createElement(h,i({ref:t},c))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[m]="string"==typeof e?e:o,i[1]=s;for(var p=2;p<r;p++)i[p]=n[p];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}u.displayName="MDXCreateElement"},7998:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var a=n(7462),o=(n(7294),n(3905));const r={},i="Random Beacon",s={unversionedId:"core/consensus/services/beacon",id:"core/consensus/services/beacon",title:"Random Beacon",description:"The random beacon service is responsible for providing a source of unbiased",source:"@site/docs/core/consensus/services/beacon.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/beacon",permalink:"/core/consensus/services/beacon",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/beacon.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Epoch Time",permalink:"/core/consensus/services/epochtime"},next:{title:"Staking",permalink:"/core/consensus/services/staking"}},l={},p=[{value:"Operation",id:"operation",level:2},{value:"Commit Phase",id:"commit-phase",level:3},{value:"Reveal Phase",id:"reveal-phase",level:3},{value:"Complete (Transition Wait) Phase",id:"complete-transition-wait-phase",level:3},{value:"Methods",id:"methods",level:2},{value:"PVSS Commit",id:"pvss-commit",level:3},{value:"PVSS Reveal",id:"pvss-reveal",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:2}],c={toc:p},m="wrapper";function d(e){let{components:t,...n}=e;return(0,o.kt)(m,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"random-beacon"},"Random Beacon"),(0,o.kt)("p",null,"The random beacon service is responsible for providing a source of unbiased\nrandomness on each epoch. It uses a commit-reveal scheme backed by a PVSS scheme\nsuch that as long as the threshold of participants is met, and one participant\nis honest, secure entropy will be generated."),(0,o.kt)("p",null,"The service interface definition lives in ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/beacon/api"},(0,o.kt)("inlineCode",{parentName:"a"},"go/beacon/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/beacon/api?tab=doc"},"consensus service API documentation")," and the ",(0,o.kt)("a",{parentName:"p",href:"/adrs/0007-improved-random-beacon"},"beacon ADR specification"),"."),(0,o.kt)("h2",{id:"operation"},"Operation"),(0,o.kt)("p",null,"Each node generates and maintains a long term elliptic curve point and scalar\npair (public/private key pair), the point (public key) of which is included in\nthe node descriptor stored by the ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/registry"},"registry service"),". In the initial\nimplementation, the curve is P-256."),(0,o.kt)("p",null,"The beacon generation process is split into three sequential stages. Any\nfailures in the ",(0,o.kt)("em",{parentName:"p"},"Commit")," and ",(0,o.kt)("em",{parentName:"p"},"Reveal")," phases result in a failed protocol round,\nand the generation process will restart after disqualifying participants who\nhave induced the failure."),(0,o.kt)("h3",{id:"commit-phase"},"Commit Phase"),(0,o.kt)("p",null,"Upon epoch transition or a prior failed round the commit phase is initiated and\nthe consensus service will select ",(0,o.kt)("inlineCode",{parentName:"p"},"particpants")," nodes from the current validator\nset (in order of descending stake) to serve as entropy contributors."),(0,o.kt)("p",null,"The beacon state is (re)-initialized, and an event is broadcast to signal to the\nparticipants that they should generate and submit their encrypted shares via a\n",(0,o.kt)("inlineCode",{parentName:"p"},"beacon.SCRAPECommit")," transaction."),(0,o.kt)("p",null,"Each commit phase lasts exactly ",(0,o.kt)("inlineCode",{parentName:"p"},"commit_interval")," blocks, at the end of which,\nthe round will be closed to further commits."),(0,o.kt)("p",null,"At the end of the commit phase, the protocol state is evaluated to ensure that\n",(0,o.kt)("inlineCode",{parentName:"p"},"threshold")," of nodes have published encrypted shares, and if an insufficient\nnumber of nodes have published them, the round is considered to have failed."),(0,o.kt)("p",null,"The following behaviors are currently candidates for a node being marked as\nmalicious/non-particpatory and subject to exclusion from future rounds and\nslashing:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Not submitting a commitment.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Malformed commitments (corrupted/fails to validate/etc).")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Attempting to alter an existing commitment for a given epoch/round."))),(0,o.kt)("h3",{id:"reveal-phase"},"Reveal Phase"),(0,o.kt)("p",null,"When the ",(0,o.kt)("inlineCode",{parentName:"p"},"commit_interval")," has passed, assuming that a sufficient number of\ncommits have been received, the consensus service transitions into the reveal\nphase and broadcasts an event to signal to the participants that they should\nreveal the decrypted values of the encrypted shares received from other\nparticipants via a ",(0,o.kt)("inlineCode",{parentName:"p"},"beacon.PVSSReveal")," transaction."),(0,o.kt)("p",null,"Each reveal phase lasts exactly ",(0,o.kt)("inlineCode",{parentName:"p"},"reveal_interval")," blocks, at the end of which,\nthe round will be closed to further reveals."),(0,o.kt)("p",null,"At the end of the reveal phase, the protocol state is evaluated to ensure that\n",(0,o.kt)("inlineCode",{parentName:"p"},"threshold")," nodes have published decrypted shares, and if an insufficient number\nof nodes have published in either case, the round is considered to have failed."),(0,o.kt)("p",null,"The following behaviors are currently candidates for a node being marked as\nmalicious/non-participatory and subject to exclusion from future rounds and\nslashing:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Not submitting a reveal.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Malformed commitments (corrupted/fails to validate/etc).")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Attempting to alter an existing reveal for a given Epoch/Round."))),(0,o.kt)("h3",{id:"complete-transition-wait-phase"},"Complete (Transition Wait) Phase"),(0,o.kt)("p",null,"When the ",(0,o.kt)("inlineCode",{parentName:"p"},"reveal_interval")," has passed, assuming that a sufficient number of\nreveals have been received, the beacon service recovers the final entropy output\n(the hash of the secret shared by each participant) and transitions into the\ncomplete (transition wait) phase and broadcasting an event to signal to\nparticipants the completion of the round."),(0,o.kt)("p",null,"No meaningful protocol activity happens once a round has successfully completed,\nbeyond the scheduling of the next epoch transition."),(0,o.kt)("h2",{id:"methods"},"Methods"),(0,o.kt)("p",null,"The following sections describe the methods supported by the consensus beacon\nservice. Note that the methods can only be called by validators and only when\nthey are the block proposer."),(0,o.kt)("h3",{id:"pvss-commit"},"PVSS Commit"),(0,o.kt)("p",null,"Submits a PVSS commit."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"beacon.PVSSCommit\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type PVSSCommit struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Commit *pvss.Commit `json:"commit,omitempty"`\n}\n')),(0,o.kt)("h3",{id:"pvss-reveal"},"PVSS Reveal"),(0,o.kt)("p",null,"Submits a PVSS reveal."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"beacon.PVSSReveal\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type PVSSReveal struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Reveal *pvss.Reveal `json:"reveal,omitempty"`\n}\n')),(0,o.kt)("h2",{id:"consensus-parameters"},"Consensus Parameters"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"participants")," is the number of participants to be selected for each beacon\ngeneration protocol round.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"threshold")," is the minimum number of participants which must successfully\ncontribute entropy for the final output to be considered valid. This is also\nthe minimum number of participants that are required to reconstruct a PVSS\nsecret from the corresponding decrypted shares.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"commit_interval")," is the duration of the ",(0,o.kt)("em",{parentName:"p"},"Commit")," phase, in blocks.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"reveal_interval")," is the duration of the ",(0,o.kt)("em",{parentName:"p"},"Reveal")," phase, in blocks.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"transition_delay")," is the duration of the post ",(0,o.kt)("em",{parentName:"p"},"Reveal")," phase delay, in\nblocks."))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/20d2542b.b65383f2.js b/assets/js/20d2542b.b65383f2.js new file mode 100644 index 0000000000..5ad69d4d90 --- /dev/null +++ b/assets/js/20d2542b.b65383f2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8252],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),s=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},m=function(e){var t=s(e.components);return a.createElement(p.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,p=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=s(n),d=r,h=u["".concat(p,".").concat(d)]||u[d]||c[d]||o;return n?a.createElement(h,i(i({ref:t},m),{},{components:n})):a.createElement(h,i({ref:t},m))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l[u]="string"==typeof e?e:r,i[1]=l;for(var s=2;s<o;s++)i[s]=n[s];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}d.displayName="MDXCreateElement"},4469:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>c,frontMatter:()=>o,metadata:()=>l,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={},i="Prerequisites",l={unversionedId:"core/development-setup/prerequisites",id:"core/development-setup/prerequisites",title:"Prerequisites",description:"The following is a list of prerequisites required to start developing on Oasis",source:"@site/docs/core/development-setup/prerequisites.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/prerequisites",permalink:"/core/development-setup/prerequisites",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/prerequisites.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Build Environment Setup and Building",permalink:"/core/development-setup/build-environment-setup-and-building"},next:{title:"Building",permalink:"/core/development-setup/building"}},p={},s=[{value:"Using the Development Docker Image",id:"using-the-development-docker-image",level:2}],m={toc:s},u="wrapper";function c(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"The following is a list of prerequisites required to start developing on Oasis\nCore:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Linux (if you are not on Linux, you will need to either set up a VM with the\nproper environment or, if Docker is available for your platform, use the\nprovided Docker image which does this for you,\n",(0,r.kt)("a",{parentName:"p",href:"#using-the-development-docker-image"},"see below"),").")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"System packages:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://github.com/projectatomic/bubblewrap"},"Bubblewrap")," (at least version 0.3.3)."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"http://gcc.gnu.org/"},"GCC")," (including C++ subpackage)."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://clang.llvm.org/"},"Clang")," development package. (If you want to build a version after v22.1.9)"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://github.com/protocolbuffers/protobuf"},"Protobuf")," compiler."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://www.gnu.org/software/make/"},"GNU Make"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://cmake.org/"},"CMake"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://www.freedesktop.org/wiki/Software/pkg-config"},"pkg-config"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://www.openssl.org/"},"OpenSSL")," development package."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://github.com/seccomp/libseccomp"},"libseccomp")," development package.")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: On Ubuntu/Debian systems, compiling ",(0,r.kt)("a",{parentName:"em",href:"https://github.com/fortanix/rust-mbedtls"},"mbedtls")," crate when building the\n",(0,r.kt)("inlineCode",{parentName:"em"},"oasis-core-runtime")," binary requires having the ",(0,r.kt)("inlineCode",{parentName:"em"},"gcc-multilib")," package\ninstalled.")),(0,r.kt)("p",{parentName:"li"},"On Fedora 29+, you can install all the above with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"sudo dnf install bubblewrap gcc gcc-c++ clang-devel protobuf-compiler make cmake openssl-devel libseccomp-devel pkg-config\n")),(0,r.kt)("p",{parentName:"li"},"On Ubuntu 18.10+ (18.04 LTS provides overly-old ",(0,r.kt)("inlineCode",{parentName:"p"},"bubblewrap"),"), you can install\nall the above with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"sudo apt install bubblewrap gcc g++ gcc-multilib libclang-dev protobuf-compiler make cmake libssl-dev libseccomp-dev pkg-config\n"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://golang.org"},"Go")," (at least version 1.20.2)."),(0,r.kt)("p",{parentName:"li"},"If your distribution provides a new-enough version of Go, just use that."),(0,r.kt)("p",{parentName:"li"},"Please note that if you want to compile Oasis Core v22.1.9 or earlier,\nthen go >=1.19 is not supported yet; you need to use 1.18.x."),(0,r.kt)("p",{parentName:"li"},"Otherwise:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"install the Go version provided by your distribution,")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://tip.golang.org/doc/code.html#GOPATH"},"ensure ",(0,r.kt)("inlineCode",{parentName:"a"},"$GOPATH/bin")," is in your ",(0,r.kt)("inlineCode",{parentName:"a"},"PATH")),",")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://golang.org/doc/install#extra_versions"},"install the desired version of Go"),", e.g. 1.20.2, with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"go install golang.org/dl/go1.20.2@latest\ngo1.20.2 download\n"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"instruct the build system to use this particular version of Go by setting\nthe ",(0,r.kt)("inlineCode",{parentName:"p"},"OASIS_GO")," environment variable in your ",(0,r.kt)("inlineCode",{parentName:"p"},"~/.bashrc"),":"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"export OASIS_GO=go1.20.2\n"))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://www.rust-lang.org/"},"Rust"),"."),(0,r.kt)("p",{parentName:"li"},"We follow ",(0,r.kt)("a",{parentName:"p",href:"https://www.rust-lang.org/tools/install"},"Rust upstream's recommendation")," on using\n",(0,r.kt)("a",{parentName:"p",href:"https://rustup.rs/"},"rustup")," to install and manage Rust versions."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: rustup cannot be installed alongside a distribution packaged Rust\nversion. You will need to remove it (if it's present) before you can start\nusing rustup.")),(0,r.kt)("p",{parentName:"li"},"Install it by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,r.kt)("a",{parentName:"em",href:"https://github.com/rust-lang/rustup#other-installation-methods"},"download ",(0,r.kt)("inlineCode",{parentName:"a"},"rustup-init")," executable for your platform"),"\nand run it manually.")),(0,r.kt)("p",{parentName:"li"},"This will run ",(0,r.kt)("inlineCode",{parentName:"p"},"rustup-init")," which will download and install the latest stable\nversion of Rust on your system.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://edp.fortanix.com"},"Fortanix Rust EDP")," utilities."),(0,r.kt)("p",{parentName:"li"},"Make sure a ",(0,r.kt)("em",{parentName:"p"},"nightly")," version of the Rust toolchain is installed:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"rustup install nightly\n")),(0,r.kt)("p",{parentName:"li"},"Then install the Fortanix Rust EDP utilities by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"cargo +nightly install fortanix-sgx-tools\ncargo +nightly install sgxs-tools\n")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: These utilities must be compiled with a nightly version of the Rust\ntoolchain since they use the ",(0,r.kt)("inlineCode",{parentName:"em"},"#![feature]")," macro."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Oasis Core's Rust toolchain version with Fortanix SGX target."),(0,r.kt)("p",{parentName:"li"},"The version of the Rust toolchain we use in Oasis Core is specified in the\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/rust-toolchain.toml"},(0,r.kt)("inlineCode",{parentName:"a"},"rust-toolchain.toml"))," file."),(0,r.kt)("p",{parentName:"li"},"The rustup-installed versions of ",(0,r.kt)("inlineCode",{parentName:"p"},"cargo"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"rustc")," and other tools will\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence"},"automatically detect this file and use the appropriate version of the Rust\ntoolchain")," when invoked from the Oasis core git\ncheckout directory."),(0,r.kt)("p",{parentName:"li"},"To install the appropriate version of the Rust toolchain, make sure you are\nin an Oasis Core git checkout directory and run:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"rustup show\n")),(0,r.kt)("p",{parentName:"li"},"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"...\n\nactive toolchain\n----------------\n\nnightly-2022-08-22-x86_64-unknown-linux-gnu (overridden by '/code/rust-toolchain.toml')\nrustc 1.65.0-nightly (c0941dfb5 2022-08-21)\n"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"(",(0,r.kt)("strong",{parentName:"p"},"OPTIONAL"),") ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/mvdan/gofumpt"},"gofumpt")," and ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/golang.org/x/tools/cmd/goimports"},"goimports"),"."),(0,r.kt)("p",{parentName:"li"},"Required if you plan to change any of the Go code in order for automated code\nformatting (",(0,r.kt)("inlineCode",{parentName:"p"},"make fmt"),") to work."),(0,r.kt)("p",{parentName:"li"},"Download and install it with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"${OASIS_GO:-go} install mvdan.cc/gofumpt@v0.4.0\n${OASIS_GO:-go} install golang.org/x/tools/cmd/goimports@v0.7.0\n"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"(",(0,r.kt)("strong",{parentName:"p"},"OPTIONAL"),") ",(0,r.kt)("a",{parentName:"p",href:"https://golangci-lint.run/"},"golangci-lint"),"."),(0,r.kt)("p",{parentName:"li"},"Required if you plan to change any of the Go code in order for automated code\nlinting (",(0,r.kt)("inlineCode",{parentName:"p"},"make lint"),") to work."),(0,r.kt)("p",{parentName:"li"},"Download and install it with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"curl -sSfL \\\nhttps://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \\\n | sh -s -- -b $(${OASIS_GO:-go} env GOPATH)/bin v1.51.2\n"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"(",(0,r.kt)("strong",{parentName:"p"},"OPTIONAL"),") ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/golang/protobuf"},"protoc-gen-go"),"."),(0,r.kt)("p",{parentName:"li"},"Download and install it with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"${OASIS_GO:-go} install google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0\n")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: If you didn't/can't add ",(0,r.kt)("inlineCode",{parentName:"em"},"$GOPATH/bin")," to your ",(0,r.kt)("inlineCode",{parentName:"em"},"PATH"),", you can install\n",(0,r.kt)("inlineCode",{parentName:"em"},"protoc-gen-go")," to ",(0,r.kt)("inlineCode",{parentName:"em"},"/usr/local/bin")," (which is in ",(0,r.kt)("inlineCode",{parentName:"em"},"$PATH"),") with:")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"sudo GOBIN=/usr/local/bin ${OASIS_GO:-go} install google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0\n")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: The repository has the most up-to-date files generated by protoc-gen-go\ncommitted for convenience. Installing protoc-gen-go is only required if you\nare a developer making changes to protobuf definitions used by Go."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"(",(0,r.kt)("strong",{parentName:"p"},"OPTIONAL"),") ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/jemalloc/jemalloc"},"jemalloc")," (version 5.2.1, built with ",(0,r.kt)("inlineCode",{parentName:"p"},"'je_'")," jemalloc-prefix)"),(0,r.kt)("p",{parentName:"li"},"Alternatively set ",(0,r.kt)("inlineCode",{parentName:"p"},'OASIS_BADGER_NO_JEMALLOC="1"')," environment variable when\nbuilding ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," code, to build ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/dgraph-io/badger/"},"BadgerDB")," without ",(0,r.kt)("inlineCode",{parentName:"p"},"jemalloc")," support."),(0,r.kt)("p",{parentName:"li"},"Download and install ",(0,r.kt)("inlineCode",{parentName:"p"},"jemalloc")," with:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},"JEMALLOC_VERSION=5.2.1\nJEMALLOC_CHECKSUM=34330e5ce276099e2e8950d9335db5a875689a4c6a56751ef3b1d8c537f887f6\nJEMALLOC_GITHUB=https://github.com/jemalloc/jemalloc/releases/download/\npushd $(mktemp -d)\nwget \\\n -O jemalloc.tar.bz2 \\\n \"${JEMALLOC_GITHUB}/${JEMALLOC_VERSION}/jemalloc-${JEMALLOC_VERSION}.tar.bz2\"\n# Ensure checksum matches.\necho \"${JEMALLOC_CHECKSUM} jemalloc.tar.bz2\" | sha256sum -c\ntar -xf jemalloc.tar.bz2\ncd jemalloc-${JEMALLOC_VERSION}\n# Ensure reproducible jemalloc build.\n# https://reproducible-builds.org/docs/build-path/\nEXTRA_CXXFLAGS=-ffile-prefix-map=$(pwd -L)=. \\\n EXTRA_CFLAGS=-ffile-prefix-map=$(pwd -L)=. \\\n ./configure \\\n --with-jemalloc-prefix='je_' \\\n --with-malloc-conf='background_thread:true,metadata_thp:auto'\nmake\nsudo make install\npopd\n")),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"NOTE: jemalloc needs to be installed to the (default) ",(0,r.kt)("inlineCode",{parentName:"em"},"/usr/local")," prefix\n(i.e. you can't use ",(0,r.kt)("inlineCode",{parentName:"em"},"./configure --prefix=$HOME/.local ..."),") because upstream\nauthors ",(0,r.kt)("a",{parentName:"em",href:"https://github.com/dgraph-io/ristretto/blob/221ca9b2091d12e5d24aa5d7d56e49745fc175d8/z/calloc_jemalloc.go#L9-L13"},"hardcode its path"),".")))),(0,r.kt)("p",null,"In the following instructions, the top-level directory is the directory\nwhere the code has been checked out."),(0,r.kt)("h2",{id:"using-the-development-docker-image"},"Using the Development Docker Image"),(0,r.kt)("p",null,"If for some reason you don't want or can't install the specified prerequisites\non the host system, you can use our development Docker image. This requires that\nyou have a ",(0,r.kt)("a",{parentName:"p",href:"https://docs.docker.com/install/"},"recent version of Docker installed"),"."),(0,r.kt)("p",null,"Oasis development environment with all the dependencies preinstalled is\navailable in the ",(0,r.kt)("inlineCode",{parentName:"p"},"ghcr.io/oasisprotocol/oasis-core-dev:master")," image.\nTo run a container, do the following in the top-level directory:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make docker-shell\n")),(0,r.kt)("p",null,"If you are curious, this target will internally run the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"docker run -t -i \\\n --name oasis-core \\\n --security-opt apparmor:unconfined \\\n --security-opt seccomp=unconfined \\\n -v $(pwd):/code \\\n -w /code \\\n ghcr.io/oasisprotocol/oasis-core-dev:master \\\n bash\n")),(0,r.kt)("p",null,"All the following commands can then be used from inside the container. See the\nDocker documentation for detailed instructions on working with Docker\ncontainers."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/210fedca.0b48a36e.js b/assets/js/210fedca.0b48a36e.js new file mode 100644 index 0000000000..1b9582aaa1 --- /dev/null +++ b/assets/js/210fedca.0b48a36e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9839],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>y});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function d(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=o.createContext({}),l=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=l(e.components);return o.createElement(s.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,p=d(e,["components","mdxType","originalType","parentName"]),u=l(n),m=r,y=u["".concat(s,".").concat(m)]||u[m]||c[m]||a;return n?o.createElement(y,i(i({ref:t},p),{},{components:n})):o.createElement(y,i({ref:t},p))}));function y(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var d={};for(var s in t)hasOwnProperty.call(t,s)&&(d[s]=t[s]);d.originalType=e,d[u]="string"==typeof e?e:r,i[1]=d;for(var l=2;l<a;l++)i[l]=n[l];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}m.displayName="MDXCreateElement"},4396:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>c,frontMatter:()=>a,metadata:()=>d,toc:()=>l});var o=n(7462),r=(n(7294),n(3905));const a={},i="Wiping Node State",d={unversionedId:"node/run-your-node/maintenance/wiping-node-state",id:"node/run-your-node/maintenance/wiping-node-state",title:"Wiping Node State",description:"In some cases you might want (or need) to do a full redeploy with clean state before deploying a new version of the network. This should never actually be used during a Mainnet unless there is some serious corruption, but your node will have to spend time catching up to the rest of the network.",source:"@site/docs/node/run-your-node/maintenance/wiping-node-state.md",sourceDirName:"node/run-your-node/maintenance",slug:"/node/run-your-node/maintenance/wiping-node-state",permalink:"/node/run-your-node/maintenance/wiping-node-state",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/wiping-node-state.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Maintenance",permalink:"/node/run-your-node/maintenance"},next:{title:"Handling Network Upgrades",permalink:"/node/run-your-node/maintenance/handling-network-upgrades"}},s={},l=[{value:"State Wipe and Keep Node Identity",id:"state-wipe-and-keep-node-identity",level:2},{value:"Full State Wipe",id:"full-state-wipe",level:2}],p={toc:l},u="wrapper";function c(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"wiping-node-state"},"Wiping Node State"),(0,r.kt)("p",null,"In some cases you might want (or need) to do a full redeploy with clean state before deploying a new version of the network. This should never actually be used during a Mainnet unless there is some serious corruption, but your node will have to spend time catching up to the rest of the network."),(0,r.kt)("p",null,"The following instructions assume that your ",(0,r.kt)("inlineCode",{parentName:"p"},"datadir")," is defined as ",(0,r.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," in your node's config."),(0,r.kt)("h2",{id:"state-wipe-and-keep-node-identity"},"State Wipe and Keep Node Identity"),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Make sure to include the ",(0,r.kt)("inlineCode",{parentName:"p"},"--preserve.mkvs_database")," flag if you are wiping blockchain state on a runtime node and need to preserve runtime state.")),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Stop the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," server process (this will depend on your own deployment setup).")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Remove blockchain state using the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node unsafe-reset")," command:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# Do a dry run first to see which files will get deleted.\noasis-node unsafe-reset \\\n --preserve.mkvs_database \\\n --datadir=/serverdir/node \\\n --dry_run \\\n --log.level info\n \n# Delete.\noasis-node unsafe-reset \\\n --preserve.mkvs_database \\\n --datadir /serverdir/node \\\n --log.level info\n"))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Start the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," server process."))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," is very strict regarding the ownership of the files. If you encounter the following error:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre"},"common/Mkdir: path '/serverdir/node' has invalid owner: 1000. Expected owner: 0\n")),(0,r.kt)("p",{parentName:"admonition"},"you need to run the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," command as the exact user that owns the files, e.g.:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre"},"sudo --user=#1000 -- oasis-node unsafe-reset --datadir=/serverdir/node --dry_run --log.level info\n"))),(0,r.kt)("h2",{id:"full-state-wipe"},"Full State Wipe"),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"This is likely not what you want to do. This is destructive and might result in losing private state required to operate the given node. ",(0,r.kt)("strong",{parentName:"p"},"USE AT YOUR OWN RISK."))),(0,r.kt)("p",null,"A full state wipe will also mean that you'll need to generate a new node identity (or copy the old one)."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Stop the ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-node")," server process (this will depend on your own deployment setup)"),(0,r.kt)("li",{parentName:"ol"},"Remove the ",(0,r.kt)("inlineCode",{parentName:"li"},"/serverdir/node")," directory."),(0,r.kt)("li",{parentName:"ol"},"Redeploy your node. You'll need to copy your Node artifacts or create brand new ones.")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/220011ce.fae1eafb.js b/assets/js/220011ce.fae1eafb.js new file mode 100644 index 0000000000..3387f6274a --- /dev/null +++ b/assets/js/220011ce.fae1eafb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3193],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>h});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function r(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},l=Object.keys(e);for(o=0;o<l.length;o++)n=l[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(o=0;o<l.length;o++)n=l[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),p=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return o.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,c=r(e,["components","mdxType","originalType","parentName"]),u=p(n),m=a,h=u["".concat(s,".").concat(m)]||u[m]||d[m]||l;return n?o.createElement(h,i(i({ref:t},c),{},{components:n})):o.createElement(h,i({ref:t},c))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=m;var r={};for(var s in t)hasOwnProperty.call(t,s)&&(r[s]=t[s]);r.originalType=e,r[u]="string"==typeof e?e:a,i[1]=r;for(var p=2;p<l;p++)i[p]=n[p];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}m.displayName="MDXCreateElement"},5280:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>r,toc:()=>p});var o=n(7462),a=(n(7294),n(3905));const l={},i="Ballot Contract",r={unversionedId:"dapp/opl/enclave",id:"dapp/opl/enclave",title:"Ballot Contract",description:"Next, we will write a smart contract that holds private data. This smart",source:"@site/docs/dapp/opl/enclave.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/enclave",permalink:"/dapp/opl/enclave",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/enclave.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"DAO Contract",permalink:"/dapp/opl/host"},next:{title:"Build",permalink:"/dapp/opl/build"}},s={},p=[{value:"Autoswitch",id:"autoswitch",level:4},{value:"Event",id:"event",level:4},{value:"Private",id:"private",level:4}],c={toc:p},u="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,o.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"ballot-contract"},"Ballot Contract"),(0,a.kt)("p",null,"Next, we will write a smart contract that holds private data. This smart\ncontract will run inside a trusted execution environment (TEE) on the Oasis\nSapphire ParaTime, which why we refer to these as an ",(0,a.kt)("em",{parentName:"p"},"enclave")," smart contract."),(0,a.kt)("p",null,"Create a new Solidity contract named ",(0,a.kt)("inlineCode",{parentName:"p"},"BallotBoxV1.sol"),"."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},'// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {Enclave, Result, autoswitch} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol";\n\nerror NotActive();\n\ntype ProposalId is bytes32;\n\nstruct ProposalParams {\n string ipfsHash;\n uint16 numChoices;\n bool publishVotes;\n}\n\ncontract BallotBoxV1 is Enclave {\n error NotPublishingVotes();\n error AlreadyVoted();\n error UnknownChoice();\n\n struct Ballot {\n bool active;\n ProposalParams params;\n /// voter -> choice id\n mapping(address => Choice) votes;\n /// choice id -> vote\n uint256[32] voteCounts;\n }\n\n struct Choice {\n bool exists;\n uint8 choice;\n }\n\n event BallotClosed(ProposalId indexed id, uint256 topChoice);\n\n mapping(ProposalId => Ballot) private _ballots;\n\n constructor(address dao) Enclave(dao, autoswitch("bsc")) {\n registerEndpoint("createBallot", _oplCreateBallot);\n }\n\n function castVote(\n ProposalId proposalId,\n uint256 choiceIdBig\n ) external payable {\n Ballot storage ballot = _ballots[proposalId];\n if (!ballot.active) revert NotActive();\n uint8 choiceId = uint8(choiceIdBig & 0xff);\n if (choiceId >= ballot.params.numChoices) revert UnknownChoice();\n Choice memory existingVote = ballot.votes[_msgSender()];\n // 1 click 1 vote\n for (uint256 i; i < ballot.params.numChoices; ++i) {\n // read-modify-write all counts to make it harder to determine which one is chosen.\n ballot.voteCounts[i] ^= 1 << 255; // flip the top bit to constify gas usage a bit\n // Arithmetic is not guaranteed to be constant time, so this might still leak the choice to a highly motivated observer.\n ballot.voteCounts[i] += i == choiceId ? 1 : 0;\n ballot.voteCounts[i] -= existingVote.exists && existingVote.choice == i\n ? 1\n : 0;\n }\n ballot.votes[_msgSender()].exists = true;\n ballot.votes[_msgSender()].choice = choiceId;\n }\n\n function closeBallot(ProposalId proposalId) external payable {\n Ballot storage ballot = _ballots[proposalId];\n if (!ballot.active) revert NotActive();\n _closeBallot(proposalId, ballot);\n }\n\n function getVoteOf(ProposalId proposalId, address voter) external view returns (Choice memory) {\n Ballot storage ballot = _ballots[proposalId];\n if (voter == msg.sender) return ballot.votes[msg.sender];\n if (!ballot.params.publishVotes) revert NotPublishingVotes();\n return ballot.votes[voter];\n }\n\n function ballotIsActive(ProposalId id) external view returns (bool) {\n return _ballots[id].active;\n }\n\n function _oplCreateBallot(bytes calldata args) internal returns (Result) {\n (ProposalId id, ProposalParams memory params) = abi.decode(\n args,\n (ProposalId, ProposalParams)\n );\n Ballot storage ballot = _ballots[id];\n ballot.params = params;\n ballot.active = true;\n for (uint256 i; i < params.numChoices; ++i) ballot.voteCounts[i] = 1 << 255; // gas usage side-channel resistance.\n return Result.Success;\n }\n\n function _closeBallot(ProposalId _proposalId, Ballot storage _ballot) internal {\n uint256 topChoice;\n uint256 topChoiceCount;\n for (uint8 i; i < _ballot.params.numChoices; ++i) {\n uint256 choiceVoteCount = _ballot.voteCounts[i] & (type(uint256).max >> 1);\n if (choiceVoteCount > topChoiceCount) {\n topChoice = i;\n topChoiceCount = choiceVoteCount;\n }\n }\n postMessage("ballotClosed", abi.encode(_proposalId, topChoice));\n emit BallotClosed(_proposalId, topChoice);\n delete _ballots[_proposalId];\n }\n}\n')),(0,a.kt)("h4",{id:"autoswitch"},"Autoswitch"),(0,a.kt)("p",null,"In this tutorial, the ",(0,a.kt)("em",{parentName:"p"},"enclave")," smart contract will talk to the ",(0,a.kt)("em",{parentName:"p"},"host")," smart\ncontract deployed on the Binance Smart Chain (",(0,a.kt)("inlineCode",{parentName:"p"},"bsc"),")."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Autoswitch will automatically pick the Testnet host network if the enclave network is also Testnet.")),(0,a.kt)("p",null,"Autoswitch supports the following networks:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ethereum")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"goerli")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"optimism")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"bsc")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"bsc-testnet")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"polygon")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"fantom")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"fantom-testnet")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"moonriver")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"arbitrum-one")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"arbitrum-nova")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"sapphire")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"sapphire-testnet")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"polygon-mumbai")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"avalanche")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"avalanche-fuji")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"arbitrum-testnet"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},' constructor(address dao) Enclave(dao, autoswitch("bsc")) {\n registerEndpoint("createBallot", _oplCreateBallot);\n }\n')),(0,a.kt)("h4",{id:"event"},"Event"),(0,a.kt)("p",null,"Closing a ballot has an effect on the host chain network (",(0,a.kt)("inlineCode",{parentName:"p"},"postMessage()"),"):"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"},' function _closeBallot(ProposalId _proposalId, Ballot storage _ballot) internal {\n uint256 topChoice;\n uint256 topChoiceCount;\n for (uint8 i; i < _ballot.params.numChoices; ++i) {\n uint256 choiceVoteCount = _ballot.voteCounts[i] & (type(uint256).max >> 1);\n if (choiceVoteCount > topChoiceCount) {\n topChoice = i;\n topChoiceCount = choiceVoteCount;\n }\n }\n postMessage("ballotClosed", abi.encode(_proposalId, topChoice));\n emit BallotClosed(_proposalId, topChoice);\n delete _ballots[_proposalId];\n }\n')),(0,a.kt)("h4",{id:"private"},"Private"),(0,a.kt)("p",null,"The private variable ",(0,a.kt)("inlineCode",{parentName:"p"},"_ballots")," is encrypted on Sapphire."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-solidity"}," mapping(ProposalId => Ballot) private _ballots;\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2287f371.75b58a18.js b/assets/js/2287f371.75b58a18.js new file mode 100644 index 0000000000..a6c696c866 --- /dev/null +++ b/assets/js/2287f371.75b58a18.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4988],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>u});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},m="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,u=m["".concat(s,".").concat(d)]||m[d]||h[d]||i;return n?r.createElement(u,l(l({ref:t},p),{},{components:n})):r.createElement(u,l({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,l=new Array(i);l[0]=d;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[m]="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=n[c];return r.createElement.apply(null,l)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},4324:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const i={},l="ADR 0021: Forward-Secret Ephemeral Secrets",o={unversionedId:"adrs/0021-keymanager-ephemeral-secrets",id:"adrs/0021-keymanager-ephemeral-secrets",title:"ADR 0021: Forward-Secret Ephemeral Secrets",description:"Component",source:"@site/docs/adrs/0021-keymanager-ephemeral-secrets.md",sourceDirName:"adrs",slug:"/adrs/0021-keymanager-ephemeral-secrets",permalink:"/adrs/0021-keymanager-ephemeral-secrets",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0021-keymanager-ephemeral-secrets.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0020: Governance Support for Delegator Votes",permalink:"/adrs/0020-governance-delegator-votes"},next:{title:"ADR 0022: Forward-Secret Master Secrets",permalink:"/adrs/0022-keymanager-master-secrets"}},s={},c=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Runtime encryption key (REK)",id:"runtime-encryption-key-rek",level:3},{value:"Ephemeral secrets",id:"ephemeral-secrets",level:3},{value:"Ephemeral secret transaction",id:"ephemeral-secret-transaction",level:3},{value:"Generation",id:"generation",level:3},{value:"Replication",id:"replication",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3}],p={toc:c},m="wrapper";function h(e){let{components:t,...n}=e;return(0,a.kt)(m,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0021-forward-secret-ephemeral-secrets"},"ADR 0021: Forward-Secret Ephemeral Secrets"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2023-02-17:",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"Rename ephemeral entropy to ephemeral secret"),(0,a.kt)("li",{parentName:"ul"},"Update types and methods, add method for loading a secret"),(0,a.kt)("li",{parentName:"ul"},"Define publish ephemeral secret transaction"),(0,a.kt)("li",{parentName:"ul"},"Split instructions for generation and replication in two sections"))),(0,a.kt)("li",{parentName:"ul"},"2022-12-01: Initial proposal")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"The network needs forward-secret ephemeral secrets that are distributed\namongst enclave executors. Because of the forward-secrecy requirements,\nusing the current key manager master secret is not workable."),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("h3",{id:"runtime-encryption-key-rek"},"Runtime encryption key (REK)"),(0,a.kt)("p",null,"Let the per-enclave ",(0,a.kt)("inlineCode",{parentName:"p"},"node.CapabilityTEE")," structure and related helpers be\nammeded as follows, to faciliate the addition of a X25519 public key held\nby the enclave, so that encrypted data can be published on-chain to an\nenclave instance."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"// Note: This could also be done via the keymanager InitResponse, but\n// it is the author's opinion that having a general mechanism for this\n// may be useful in other contexts.\n\n// CapabilityTEE represents the node's TEE capability.\ntype CapabilityTEE struct {\n ...\n\n // Runtime encryption key.\n REK *x25519.PublicKey `json:\"rek,omitempty\"`\n}\n")),(0,a.kt)("h3",{id:"ephemeral-secrets"},"Ephemeral secrets"),(0,a.kt)("p",null,"The key manger enclave will gain the following additional RPC methods:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'const (\n // Local RPC methods (plaintext).\n GenerateEphemeralSecret = "generate_ephemeral_secret"\n LoadEphemeralSecret = "load_ephemeral_secret"\n\n // Remote RPC method (Noise session).\n ReplicateEphemeralSecret = "replicate_ephemeral_secret"\n)\n\ntype GenerateEphemeralSecretRequest struct {\n Epoch beacon.EpochTime `json:"epoch"`\n}\n\ntype ReplicateEphemeralSecretRequest struct {\n Epoch beacon.EpochTime `json:"epoch"`\n}\n\ntype LoadEphemeralSecretRequest struct {\n SignedSecret SignedEncryptedEphemeralSecret `json:"signed_secret"`\n}\n\ntype GenerateEphemeralSecretResponse struct {\n SignedSecret SignedEncryptedEphemeralSecret `json:"signed_secret"`\n}\n\ntype ReplicateEphemeralSecretResponse struct {\n // The request and this response are considered confidential,\n // so the channel handles authentication and confidentiality.\n EphemeralSecret [32]byte `json:"ephemeral_secret"`\n}\n')),(0,a.kt)("p",null,"Ephemeral secret generation will return a signed and encrypted ephemeral secret\nfor the requested epoch."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'type EncryptedSecret struct {\n // Checksum is the secret verification checksum.\n Checksum []byte `json:"checksum"`\n\n // PubKey is the public key used to derive the symmetric key for decryption.\n PubKey x25519.PublicKey `json:"pub_key"`\n\n // Nonce is the nonce used to decrypt the secret.\n Nonce []byte `json:"nonce"`\n\n // Ciphertexts is the map of REK encrypted ephemeral secrets for all known key manager enclaves.\n Ciphertexts map[x25519.PublicKey][]byte `json:"ciphertexts"`\n}\n\ntype EncryptedEncryptedSecret struct {\n // ID is the runtime ID of the key manager.\n ID common.Namespace `json:"runtime_id"`\n\n // Epoch is the epoch to which the secret belongs.\n Epoch beacon.EpochTime `json:"epoch"`\n\n // Secret is the encrypted secret.\n Secret EncryptedSecret `json:"secret"`\n}\n\ntype SignedEncryptedEphemeralSecret struct {\n // Secret is the encrypted ephemeral secret.\n Secret EncryptedEphemeralSecret `json:"secret"`\n\n // Signature is a signature of the ephemeral secret.\n Signature signature.RawSignature `json:"signature"`\n}\n')),(0,a.kt)("h3",{id:"ephemeral-secret-transaction"},"Ephemeral secret transaction"),(0,a.kt)("p",null,"Key manager application will be augmented with a ",(0,a.kt)("inlineCode",{parentName:"p"},"PublishEphemeralSecret"),"\ntransaction that will accept the first published secret for an epoch and\ndiscard the others."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'MethodPublishEphemeralSecret = transaction.NewMethodName(\n ModuleName, "PublishEphemeralSecret", SignedEncryptedEphemeralSecret{}\n)\n')),(0,a.kt)("h3",{id:"generation"},"Generation"),(0,a.kt)("p",null,"Each keymanager will, at a random time in a given epoch:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Check to see if another instance has published the next epoch's ephemeral\nsecret. If yes, go to step 4.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Execute a local ",(0,a.kt)("inlineCode",{parentName:"p"},"generate_ephemeral_secret")," RPC call. The enclave will,\nin-order, use the light client to query the members of the committee,\ngenerate secret, and return a ",(0,a.kt)("inlineCode",{parentName:"p"},"GenerateEphemeralSecretResponse"),".\nOn failure, go to step 1.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Publish ",(0,a.kt)("inlineCode",{parentName:"p"},"SignedEncryptedEphemeralSecret")," to consensus via\na ",(0,a.kt)("inlineCode",{parentName:"p"},"PublishEphemeralSecret")," transaction.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"This key manager instance is DONE."))),(0,a.kt)("h3",{id:"replication"},"Replication"),(0,a.kt)("p",null,"Each key manager will:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Listen to the publications of new ephemeral secrets and forward them to\nthe enclave.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Enclave will validate the secret and verify that it was published in the\nconsensus. Iff verification succeeds and there is a corresponding REK entry\nin the ",(0,a.kt)("inlineCode",{parentName:"p"},"Ciphertexts")," map, decrypt the secret and go to step 4.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Until a successful response is obtained, iterate through the enclaves\nin the ephemeral secret ",(0,a.kt)("inlineCode",{parentName:"p"},"Ciphertexts")," map, issuing\n",(0,a.kt)("inlineCode",{parentName:"p"},"replicate_ephemeral_secret")," RPC calls. On failure, repeat step 3.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"This key manager instance is DONE."))),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"It will be possible to publish ephemeral encrypted data to enclave\ninstances on-chain.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"There will be ephemeral secret per key manager committee.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Enclave compromise can not go back to previous epochs to compromise\nthe ephemeral secrets.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Ephemeral secrets are never encrypted with SGX sealing key nor stored in\ncold storage."))),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If enough key manager workers restart at the wrong time, the epoch's\nephemeral secret will be lost, and it will take until the next epoch\nto recover.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Forward-secrecy is imperfect due to the epoch granular nature of the\nephemeral secret."))))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/24323d06.f1d0fb64.js b/assets/js/24323d06.f1d0fb64.js new file mode 100644 index 0000000000..cfcbf4144d --- /dev/null +++ b/assets/js/24323d06.f1d0fb64.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9160],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>h});var o=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,o)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(e,t){if(null==e)return{};var r,o,n=function(e,t){if(null==e)return{};var r,o,n={},i=Object.keys(e);for(o=0;o<i.length;o++)r=i[o],t.indexOf(r)>=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o<i.length;o++)r=i[o],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var c=o.createContext({}),l=function(e){var t=o.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=l(e.components);return o.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var r=e.components,n=e.mdxType,i=e.originalType,c=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=l(r),m=n,h=u["".concat(c,".").concat(m)]||u[m]||d[m]||i;return r?o.createElement(h,a(a({ref:t},p),{},{components:r})):o.createElement(h,a({ref:t},p))}));function h(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=r.length,a=new Array(i);a[0]=m;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[u]="string"==typeof e?e:n,a[1]=s;for(var l=2;l<i;l++)a[l]=r[l];return o.createElement.apply(null,a)}return o.createElement.apply(null,r)}m.displayName="MDXCreateElement"},2474:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var o=r(7462),n=(r(7294),r(3905));const i={},a="Authenticated gRPC",s={unversionedId:"core/authenticated-grpc",id:"core/authenticated-grpc",title:"Authenticated gRPC",description:"Oasis Core nodes communicate between themselves over various protocols. One of",source:"@site/docs/core/authenticated-grpc.md",sourceDirName:"core",slug:"/core/authenticated-grpc",permalink:"/core/authenticated-grpc",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/authenticated-grpc.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Cryptography",permalink:"/core/crypto"},next:{title:"Merklized Key-Value Store (MKVS)",permalink:"/core/mkvs"}},c={},l=[{value:"TLS",id:"tls",level:2},{value:"gRPC",id:"grpc",level:2},{value:"CBOR Codec",id:"cbor-codec",level:3},{value:"Errors",id:"errors",level:3},{value:"Service Naming Convention",id:"service-naming-convention",level:3}],p={toc:l},u="wrapper";function d(e){let{components:t,...r}=e;return(0,n.kt)(u,(0,o.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"authenticated-grpc"},"Authenticated gRPC"),(0,n.kt)("p",null,"Oasis Core nodes communicate between themselves over various protocols. One of\nthose protocols is ",(0,n.kt)("a",{parentName:"p",href:"https://grpc.io"},"gRPC")," which is currently used for the following:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Compute nodes talking to storage nodes."),(0,n.kt)("li",{parentName:"ul"},"Compute nodes talking to key manager nodes."),(0,n.kt)("li",{parentName:"ul"},"Key manager nodes talking to other key manager nodes."),(0,n.kt)("li",{parentName:"ul"},"Clients talking to compute nodes."),(0,n.kt)("li",{parentName:"ul"},"Clients talking to key manager nodes.")),(0,n.kt)("p",null,"All these communications can have access control policies attached specifying\nwho is allowed to perform certain actions at which point in time. This first\nrequires an authentication mechanism."),(0,n.kt)("h2",{id:"tls"},"TLS"),(0,n.kt)("p",null,"In order to authenticate both ends of a connection, gRPC is always used together\nwith TLS. However, since this is a decentralized network, there are some\nspecifics on how peer verification is performed when establishing a TLS session\nbetween two nodes."),(0,n.kt)("p",null,"Instead of relying on Certificate Authorities, we use the ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/registry"},"registry service"),"\nprovided by the ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer"),". Each node publishes its own trusted public\nkeys in the registry as part of its ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node"},"signed node descriptor"),". TLS sessions use\nits own ephemeral ",(0,n.kt)("a",{parentName:"p",href:"/core/crypto"},"Ed25519 key pair")," that is used to (self-)sign a node's X509\ncertificate. When verifying peer identities the public key on the certificate is\ncompared with the public key(s) published in the registry."),(0,n.kt)("p",null,"All TLS keys are ephemeral and nodes are encouraged to frequently rotate them\n(the Oasis Core implementation in this repository supports this automatically)."),(0,n.kt)("p",null,"For details on how certificate verification is performed see\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/crypto/tls/verify.go"},"the ",(0,n.kt)("inlineCode",{parentName:"a"},"VerifyCertificate")," implementation")," in ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/crypto/tls"},(0,n.kt)("inlineCode",{parentName:"a"},"go/common/crypto/tls")),"."),(0,n.kt)("h2",{id:"grpc"},"gRPC"),(0,n.kt)("p",null,"Oasis Core uses some specific conventions that depart from the most common gRPC\nsetups and are described in the following sections."),(0,n.kt)("h3",{id:"cbor-codec"},"CBOR Codec"),(0,n.kt)("p",null,"While gRPC is most commonly used with the Protocol Buffers codec the gRPC\nprotocol is agnostic to the actual underlying serialization format. Oasis Core\nuses ",(0,n.kt)("a",{parentName:"p",href:"/core/encoding"},"CBOR")," for encoding of all messages used in our gRPC services."),(0,n.kt)("p",null,"This requires that the codec is explicitly configured while setting up\nconnections. Our ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc"},"gRPC helpers")," automatically configure the correct codec so\nusing it should be transparent. The only quirk of this setup is that service\ncodegen is not available with arbitrary codecs, so glue code for both the server\nand the client needs to be generated manually (for examples see the ",(0,n.kt)("inlineCode",{parentName:"p"},"grpc.go"),"\nfiles in various ",(0,n.kt)("inlineCode",{parentName:"p"},"api")," packages)."),(0,n.kt)("h3",{id:"errors"},"Errors"),(0,n.kt)("p",null,"As gRPC provides very limited error reporting capability in the form of a few\ndefined error codes, we extend this mechanism to support proper error remapping."),(0,n.kt)("p",null,"Detailed errors are returned as part of the ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/google.golang.org/genproto/googleapis/rpc/status?tab=doc#Status"},"gRPC error details structure"),". The\n",(0,n.kt)("inlineCode",{parentName:"p"},"Value")," field of the first detail element contains the following CBOR-serialized\nstructure that specifies the (namespaced) error:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-golang"},'type grpcError struct {\n Module string `json:"module,omitempty"`\n Code uint32 `json:"code,omitempty"`\n}\n')),(0,n.kt)("p",null,"If you use the provided ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc"},"gRPC helpers")," any errors will be mapped to registered\nerror types automatically."),(0,n.kt)("h3",{id:"service-naming-convention"},"Service Naming Convention"),(0,n.kt)("p",null,"We use the same service method namespacing convention as gRPC over Protocol\nBuffers. All Oasis Core services have unique identifiers starting with\n",(0,n.kt)("inlineCode",{parentName:"p"},"oasis-core.")," followed by the service identifier. A single slash (",(0,n.kt)("inlineCode",{parentName:"p"},"/"),") is used\nas the separator in method names, e.g., ",(0,n.kt)("inlineCode",{parentName:"p"},"/oasis-core.Storage/SyncGet"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/247783bb.630ad479.js b/assets/js/247783bb.630ad479.js new file mode 100644 index 0000000000..c69cb1ae9b --- /dev/null +++ b/assets/js/247783bb.630ad479.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9334],{3769:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/26373622.6c883900.js b/assets/js/26373622.6c883900.js new file mode 100644 index 0000000000..b8d70cc6cd --- /dev/null +++ b/assets/js/26373622.6c883900.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1102],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>m});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var l=n.createContext({}),p=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},c=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},d="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(a),u=r,m=d["".concat(l,".").concat(u)]||d[u]||h[u]||i;return a?n.createElement(m,o(o({ref:t},c),{},{components:a})):n.createElement(m,o({ref:t},c))}));function m(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,o[1]=s;for(var p=2;p<i;p++)o[p]=a[p];return n.createElement.apply(null,o)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1564:(e,t,a)=>{a.d(t,{Z:()=>m});var n=a(7294),r=a(6010),i=a(9960),o=a(3438),s=a(3919),l=a(5999);const p={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function c(e){let{href:t,children:a}=e;return n.createElement(i.Z,{href:t,className:(0,r.Z)("card padding--lg",p.cardContainer)},a)}function d(e){let{href:t,icon:a,title:i,description:o}=e;return n.createElement(c,{href:t},n.createElement("h2",{className:(0,r.Z)("text--truncate",p.cardTitle),title:i},a," ",i),o&&n.createElement("p",{className:(0,r.Z)("text--truncate",p.cardDescription),title:o},o))}function h(e){let{item:t}=e;const a=(0,o.Wl)(t);return a?n.createElement(d,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const a=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,o.xz)(t.docId??void 0);return n.createElement(d,{href:t.href,icon:a,title:t.label,description:t.description??r?.description})}function m(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(h,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},7525:(e,t,a)=>{a.d(t,{n:()=>i});var n=a(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function i(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},396:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>p,toc:()=>d});var n=a(7462),r=(a(7294),a(3905)),i=a(1564),o=a(7525);const s={description:"Guide to creating secure dApps on Sapphire"},l="Guide",p={unversionedId:"dapp/sapphire/guide",id:"dapp/sapphire/guide",title:"Guide",description:"Guide to creating secure dApps on Sapphire",source:"@site/docs/dapp/sapphire/guide.mdx",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/guide",permalink:"/dapp/sapphire/guide",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/guide.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Guide to creating secure dApps on Sapphire"},sidebar:"developers",previous:{title:"Quickstart",permalink:"/dapp/sapphire/quickstart"},next:{title:"Browser Support",permalink:"/dapp/sapphire/browser"}},c={},d=[{value:"Oasis Consensus Layer and Sapphire ParaTime",id:"oasis-consensus-layer-and-sapphire-paratime",level:2},{value:"Testnet and Mainnet",id:"testnet-and-mainnet",level:2},{value:"Sapphire vs Ethereum",id:"sapphire-vs-ethereum",level:2},{value:"Integrating Sapphire",id:"integrating-sapphire",level:2},{value:"Writing Secure dApps",id:"writing-secure-dapps",level:2},{value:"Wallets",id:"wallets",level:3},{value:"Languages & Frameworks",id:"languages--frameworks",level:3},{value:"Transactions & Calls",id:"transactions--calls",level:3},{value:"Contract State",id:"contract-state",level:3},{value:"Contract Logs",id:"contract-logs",level:3},{value:"Contract Verification",id:"contract-verification",level:2},{value:"Running a Private Oasis Network Locally",id:"running-a-private-oasis-network-locally",level:2},{value:"See also",id:"see-also",level:2}],h={toc:d},u="wrapper";function m(e){let{components:t,...s}=e;return(0,r.kt)(u,(0,n.Z)({},h,s,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"guide"},"Guide"),(0,r.kt)("p",null,"This page mainly describes the differences between Sapphire and Ethereum\nsince there are a number of excellent tutorials on developing for Ethereum.\nIf you don't know where to begin, the ",(0,r.kt)("a",{parentName:"p",href:"https://hardhat.org/tutorial"},"Hardhat tutorial"),", ",(0,r.kt)("a",{parentName:"p",href:"https://docs.soliditylang.org/en/v0.8.15/solidity-by-example.html"},"Solidity docs"),", and\n",(0,r.kt)("a",{parentName:"p",href:"/dapp/emerald/writing-dapps-on-emerald"},"Emerald dApp tutorial")," are great places to start. You can continue following\nthis guide once you've set up your development environment and have deployed\nyour contract to a non-confidential EVM network (e.g., Ropsten, Emerald)."),(0,r.kt)("h2",{id:"oasis-consensus-layer-and-sapphire-paratime"},"Oasis Consensus Layer and Sapphire ParaTime"),(0,r.kt)("p",null,"The Oasis Network consists of the consensus layer and a number of ParaTimes.\nParaTimes are independent replicated state machines that settle transactions\nusing the consensus layer (to learn more, check the ",(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network Overview"),"). Sapphire is a ParaTime which implements the Ethereum\nVirtual Machine (EVM)."),(0,r.kt)("p",null,"The minimum and also expected block time in Sapphire is ",(0,r.kt)("strong",{parentName:"p"},"6 seconds"),". Any\nSapphire transaction will require at least this amount of time to be executed,\nand probably no more."),(0,r.kt)("p",null,"ParaTimes, Sapphire included, are not allowed to directly access your tokens stored\nin consensus layer accounts. You will need to ",(0,r.kt)("em",{parentName:"p"},"deposit")," tokens from your consensus\naccount to Sapphire. Consult the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},"How to transfer ROSE into an EVM ParaTime")," chapter to learn more."),(0,r.kt)("h2",{id:"testnet-and-mainnet"},"Testnet and Mainnet"),(0,r.kt)("p",null,"Sapphire is deployed on both Testnet and Mainnet. The Testnet should be\nconsidered unstable software and may have its state wiped at any time. As\nthe name implies, only use the Testnet for testing unless you're testing how\nangry your users get when state is wiped."),(0,r.kt)("admonition",{title:"Never deploy production services on Testnet",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Because Testnet state can be wiped in the future, you should ",(0,r.kt)("strong",{parentName:"p"},"never")," deploy a\nproduction service on the Testnet! Just don't do it!"),(0,r.kt)("p",{parentName:"admonition"},"Also note that while the Testnet does use actual TEEs, due to experimental\nsoftware and different security parameters, ",(0,r.kt)("strong",{parentName:"p"},"confidentiality of Sapphire on the\nTestnet is not guaranteed")," -- all transactions and state published on the\nSapphire Testnet should be considered public.")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For testing purposes, visit our ",(0,r.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev/"},"Testnet faucet")," to obtain some TEST which you\ncan then use on the Sapphire Testnet to pay for gas fees. The faucet supports\nsending TEST both to your consensus layer address or to your address inside the\nParaTime.")),(0,r.kt)("h2",{id:"sapphire-vs-ethereum"},"Sapphire vs Ethereum"),(0,r.kt)("p",null,"Sapphire is generally compatible with Ethereum, the EVM, and all of the\nuser and developer tooling that you already use. There are a few breaking changes,\nbut we think that you'll like them:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Contract state is only visible to the contract that wrote it. With respect\nto the contract API, it's as if all state variables are declared as ",(0,r.kt)("inlineCode",{parentName:"li"},"private"),", but\nwith the further restriction that not even full nodes can read the values. Public or\naccess-controlled values are provided instead through explicit getters."),(0,r.kt)("li",{parentName:"ul"},"Transactions and calls are end-to-end encrypted into the contract. Only the caller\nand the contract can see the data sent to/received from the ParaTime. This ends up\ndefeating most of the utility of block explorers, however."),(0,r.kt)("li",{parentName:"ul"},"The ",(0,r.kt)("inlineCode",{parentName:"li"},"from")," address using of calls is derived from a signature attached to the call.\nUnsigned calls have their sender set to the zero address. This allows contract authors\nto write getters that release secrets to authenticated callers, but without\nrequiring a transaction to be posted on-chain.")),(0,r.kt)("p",null,"In addition to confidentiality, you get a few extra benefits including the ability to generate private\nentropy, and make signatures on-chain. An example of a dApp that uses both is a HSM contract\nthat generates an Ethereum wallet and signs transactions sent to it via transactions."),(0,r.kt)("p",null,"Otherwise Sapphire is like Emerald, which is like a fast, cheap Ethereum."),(0,r.kt)("h2",{id:"integrating-sapphire"},"Integrating Sapphire"),(0,r.kt)("p",null,"Once ROSE tokens are ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},"deposited into Sapphire"),", it should be painless for users to begin\nusing dApps. To achieve this ideal user experience, we have to modify the dApp a little,\nbut it's made simple by our compatibility library, ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime"},"@oasisprotocol/sapphire-paratime"),"."),(0,r.kt)("p",null,"There are compatibility layers in other languages, which may be found in ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients"},"the repo"),"."),(0,r.kt)("h2",{id:"writing-secure-dapps"},"Writing Secure dApps"),(0,r.kt)("h3",{id:"wallets"},"Wallets"),(0,r.kt)("p",null,"Sapphire is compatible with popular self-custodial wallets including MetaMask,\nLedger, Brave, and so forth. You can also use libraries like Web3.js and Ethers\nto create programmatic wallets. In general, if it generates secp256k1 signatures,\nit'll work just fine."),(0,r.kt)("h3",{id:"languages--frameworks"},"Languages & Frameworks"),(0,r.kt)("p",null,"Sapphire is programmable using any language that targets the EVM, such as Solidity\nand Vyper. If you prefer to use an Ethereum framework like Hardhat or Truffle, you\ncan also use those with Sapphire; all you need to do is set your Web3 gateway URL.\nYou can find the details of the Oasis Sapphire Web3 gateway\n",(0,r.kt)("a",{parentName:"p",href:"/dapp/sapphire#web3-gateway"},"here"),"."),(0,r.kt)("h3",{id:"transactions--calls"},"Transactions & Calls"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Client, Key Manager, Compute Node diagram",src:a(8332).Z,width:"765",height:"486"})),(0,r.kt)("p",null,"The figure above illustrates the flow of a confidential smart contract\n",(0,r.kt)("em",{parentName:"p"},"transaction")," executed on the Sapphire ParaTime."),(0,r.kt)("p",null,"Transactions and calls must be encrypted and signed for maximum security.\nYou can use the ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime"},"@oasisprotocol/sapphire-paratime")," JS package to make your life\neasy. It'll handle cryptography and signing for you."),(0,r.kt)("p",null,"You should be aware that taking actions based on the value of private data may\nleak the private data through side channels like time spent and gas use. If you\nneed to branch on private data, you should in most cases ensure that both\nbranches exhibit similar time/gas and storage patterns."),(0,r.kt)("p",null,"You can also make confidential smart contract ",(0,r.kt)("em",{parentName:"p"},"calls")," on Sapphire. If you\nuse ",(0,r.kt)("inlineCode",{parentName:"p"},"msg.sender")," for access control in your contract, the call ",(0,r.kt)("strong",{parentName:"p"},"must be\nsigned"),", otherwise ",(0,r.kt)("inlineCode",{parentName:"p"},"msg.sender")," will be zeroed. On the other hand, set the\n",(0,r.kt)("inlineCode",{parentName:"p"},"from")," address to all zeros, if you want to avoid annoying signature popups in\nthe user's wallet for calls that do not need to be signed. The JS library will\ndo this for you."),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"Inside the smart contract code, there is no way of knowing whether the\nclient's call data were originally encrypted or not.")),(0,r.kt)("details",null,(0,r.kt)("summary",null,"Detailed confidential smart contract transaction flow on Sapphire"),(0,r.kt)("div",null,(0,r.kt)("img",{src:a(1401).Z}))),(0,r.kt)("details",null,(0,r.kt)("summary",null,"Detailed confidential smart contract call flow on Sapphire"),(0,r.kt)("div",null,(0,r.kt)("img",{src:a(971).Z}))),(0,r.kt)("h3",{id:"contract-state"},"Contract State"),(0,r.kt)("p",null,"The Sapphire state model is like Ethereum's except for all state being encrypted\nand not accessible to anyone except the contract. The contract, executing in an\nactive (attested) Oasis compute node is the only entity that can request its\nstate encryption key from the Oasis key manager. Both the keys and values of the\nitems stored in state are encrypted, but the size of either is ",(0,r.kt)("em",{parentName:"p"},"not")," hidden. You\napp may need to pad state items to a constant length, or use other obfuscation.\nObservers may also be able to infer computation based on storage access patterns,\nso you might need to obfuscate that, too."),(0,r.kt)("admonition",{title:"Contract state leaks a fine-grained access pattern",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Contract state is backed by an encrypted key-value store. However, the trace of\nencrypted records is leaked to the compute node. As a concrete example, an ERC-20\ntoken transfer would leak which encrypted record is for the sender's account\nbalance and which is for the receiver's account balance. Such a token would be\ntraceable from sender address to receiver address. Obfuscating the storage access\npatterns may be done by using an ORAM implementation.")),(0,r.kt)("p",null,"Contract state may be made available to third parties through logs/events, or\nexplicit getters."),(0,r.kt)("h3",{id:"contract-logs"},"Contract Logs"),(0,r.kt)("p",null,"Contract logs/events (e.g., those emitted by the Solidity ",(0,r.kt)("inlineCode",{parentName:"p"},"emit")," keyword)\nare exactly like Ethereum. Data contained in events is ",(0,r.kt)("em",{parentName:"p"},"not")," encrypted.\nPrecompiled contracts are available to help you encrypt data that you can\nthen pack into an event, however."),(0,r.kt)("admonition",{title:"Unmodified contracts may leak state through logs",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Base contracts like those provided by OpenZeppelin often emit logs containing\nprivate information. If you don't know they're doing that, you might undermine\nthe confidentiality of your state. As a concrete example, the ERC-20 spec\nrequires implementers to emit an ",(0,r.kt)("inlineCode",{parentName:"p"},"event Transfer(from, to, amount)"),", which is\nobviously problematic if you're writing a confidential token. What you can\ndo instead is fork that contract and remove the offending emissions.")),(0,r.kt)("h2",{id:"contract-verification"},"Contract Verification"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://sourcify.dev/"},"Sourcify")," is the preferred service for the ",(0,r.kt)("a",{parentName:"p",href:"https://ethereum.org/en/developers/docs/smart-contracts/verifying/"},"verification of smart\ncontracts")," deployed on Sapphire. Make sure you have\nthe ",(0,r.kt)("strong",{parentName:"p"},"address of each deployed contract")," available (your deployment scripts\nshould report those) and the ",(0,r.kt)("strong",{parentName:"p"},"contracts JSON metadata file")," generated when\ncompiling contracts (Hardhat stores it inside the ",(0,r.kt)("inlineCode",{parentName:"p"},"artifacts/build-info")," folder\nand names it as a 32-digit hex number). If your project contains multiple\ncontracts, you will need to verify each contract separately."),(0,r.kt)("admonition",{title:"Contract deployment encryption",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("strong",{parentName:"p"},"Do not deploy your contract with an encrypted contract deployment transaction,\nif you want to verify it.")," For example, if your ",(0,r.kt)("inlineCode",{parentName:"p"},"hardhat.config.ts"),"\nor deployment script contains ",(0,r.kt)("inlineCode",{parentName:"p"},"import '@oasisprotocol/sapphire-hardhat'")," or\n",(0,r.kt)("inlineCode",{parentName:"p"},"import '@oasisprotocol/sapphire-paratime'")," lines at the beginning, you should\ncomment those out for the deployment."),(0,r.kt)("p",{parentName:"admonition"},"Verification services will try to match the contract deployment transaction code\nwith the one in the provided contract's metadata and since the transaction was\nencrypted with an ephemeral ParaTime key, the verification service will not be\nable to decrypt it. Some services may extract the contract's bytecode from the\nchain directly by calling ",(0,r.kt)("inlineCode",{parentName:"p"},"eth_getCode")," RPC, but this will not work correctly\nfor contracts with immutable variables.")),(0,r.kt)("p",null,"To verify a contract deployed on Sapphire Mainnet or Testnet:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Visit the ",(0,r.kt)("a",{parentName:"p",href:"https://sourcify.dev/"},"Sourcify"),' website and hit the "VERIFY CONTRACT" button.'),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("img",{alt:"Sourcify website",src:a(3532).Z,width:"1564",height:"979"}))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Upload the contracts JSON metadata file."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("img",{alt:"Sourcify: Upload metadata JSON file",src:a(8758).Z,width:"1564",height:"979"})),(0,r.kt)("admonition",{parentName:"li",title:"Store your metadata files",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For production deployments, it is generally a good idea to ",(0,r.kt)("strong",{parentName:"p"},"archive your\ncontract metadata JSON file")," since it is not only useful for the\nverification, but contains a copy of all the source files, produced bytecode,\nan ABI, compiler and other relevant contract-related settings that may be\nuseful in the future. Sourcify will store the metadata file for you and will\neven make it available via IPFS, but it is still a good idea to store it\nyourself."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},'Sourcify will decode the metadata and prepare a list of included contracts on\nthe right. Enter the address of the specific contract and select the "Oasis\nSapphire" or "Oasis Sapphire Testnet" chain for the Mainnet or Testnet\naccordingly. If your contract assigns any immutable variables in the\nconstructor, you will also need to correctly fill those out under the "More\nInputs (optional)" panel. Finally, click on the "Verify" button.'),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("img",{alt:"Sourcify: Verify contract",src:a(3519).Z,width:"1564",height:"2420"}))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"If everything goes well, you will get a ",(0,r.kt)("strong",{parentName:"p"}," ",(0,r.kt)("em",{parentName:"strong"},"Perfect match")," notice and your\ncontract is now verified"),". Congratulations!"))),(0,r.kt)("p",null,"In case of a ",(0,r.kt)("em",{parentName:"p"},"Partial match"),", the contracts metadata JSON differs from the one\nused for deployment although the compiled contract bytecode matched. Make sure\nthe source code ",(0,r.kt)("inlineCode",{parentName:"p"},".sol")," file of the contract is the same as the one used during the\ndeployment (including the comments, variable names and source code file\nnames) and use the same version of Hardhat and solc compiler."),(0,r.kt)("p",null,"You can also explore other verification methods on Sourcify by reading the\n",(0,r.kt)("a",{parentName:"p",href:"https://docs.sourcify.dev/docs/how-to-verify/"},"official Sourcify contract verification instructions"),"."),(0,r.kt)("h2",{id:"running-a-private-oasis-network-locally"},"Running a Private Oasis Network Locally"),(0,r.kt)("p",null,"For convenient development and testing of your dApps the Oasis team prepared\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-dev"},"ghcr.io/oasisprotocol/sapphire-dev")," Docker image which brings you a\ncomplete Oasis stack to your desktop. The Localnet Sapphire instance ",(0,r.kt)("strong",{parentName:"p"},"mimics\nconfidential transactions"),", but it does not run in a trusted execution\nenvironment nor does it require Intel's SGX on your computer. The network is\nisolated from the Mainnet or Testnet and consists of:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"single Oasis validator node with 1-second block time and 30-second epoch,"),(0,r.kt)("li",{parentName:"ul"},"single Oasis client node,"),(0,r.kt)("li",{parentName:"ul"},"three compute nodes running Oasis Sapphire,"),(0,r.kt)("li",{parentName:"ul"},"single key manager node,"),(0,r.kt)("li",{parentName:"ul"},"PostgreSQL instance,"),(0,r.kt)("li",{parentName:"ul"},"Oasis Web3 gateway with transaction indexer and enabled Oasis RPCs,"),(0,r.kt)("li",{parentName:"ul"},"helper script which populates initial test accounts for you.")),(0,r.kt)("p",null,"To run the image, execute:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-dev\n")),(0,r.kt)("p",null,"After a while, the tool will show you something like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"sapphire-dev 2023-02-28-git84730b2 (oasis-core: 22.2.6, sapphire-paratime: 0.4.0, oasis-web3-gateway: 3.2.0-git84730b2)\n\nStarting oasis-net-runner with sapphire...\nStarting postgresql...\nStarting oasis-web3-gateway...\nBootstrapping network and populating account(s) (this might take a minute)...\n\nAvailable Accounts\n==================\n(0) 0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2 (100 ROSE)\n(1) 0x903a7dce5a26a3f4DE2d157606c2191740Bc4BC9 (100 ROSE)\n(2) 0xF149ad5CBFfD92ba84F5784106f6Cb071A32a1b8 (100 ROSE)\n(3) 0x2315F40C1122400Df55483743B051D2997ef0a62 (100 ROSE)\n(4) 0xf6FdcacbA93A428A07d27dacEf1fBF25E2C65B0F (100 ROSE)\n\nPrivate Keys\n==================\n(0) 0x160f52faa5c0aecfa26c793424a04d53cbf23dcad5901ce15b50c2e85b9d6ca7\n(1) 0x0ba685723b47d8e744b1b70a9bea9d4d968f60205385ae9de99865174c1af110\n(2) 0xfa990cf0c22af455d2734c879a2a844ff99bd779b400bb0e2919758d1be284b5\n(3) 0x3bf225ef73b1b56b03ceec8bb4dfb4830b662b073b312beb7e7fec3159b1bb4f\n(4) 0xad0dd7ceb896fd5f5ddc76d56e54ee6d5c2a3ffeac7714d3ef544d3d6262512c\n\nHD Wallet\n==================\nMnemonic: bench remain brave curve frozen verify dream margin alarm world repair innocent\nBase HD Path: m/44'/60'/0'/0/%d\n\nWARNING: The chain is running in ephemeral mode. State will be lost after restart!\n\nListening on http://localhost:8545 and ws://localhost:8546\n")),(0,r.kt)("p",null,"Those familiar with local dApp environments will find the output above similar\nto ",(0,r.kt)("inlineCode",{parentName:"p"},"geth --dev")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"ganache-cli")," commands or the ",(0,r.kt)("inlineCode",{parentName:"p"},"geth-dev-assistant")," npm\npackage. ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-dev"},"sapphire-dev")," will spin up a private Oasis Network locally, generate\nand populate test accounts and make the following Web3 endpoints available for\nyou to use:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"http://localhost:8545")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ws://localhost:8546"))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you prefer using the same mnemonics each time (e.g. for testing purposes)\nor to populate just a single wallet, use ",(0,r.kt)("inlineCode",{parentName:"p"},"-to")," flag and pass the mnemonics or\nthe wallet addresses. For example"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-dev -to "bench remain brave curve frozen verify dream margin alarm world repair innocent"\ndocker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-dev -to "0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2,0xbDA5747bFD65F08deb54cb465eB87D40e51B197E"\n'))),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-dev"},"sapphire-dev")," runs in ephemeral mode. Any smart contract and wallet balance\nwill be lost after you quit the Docker container!")),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(i.Z,{item:(0,o.n)("/node/run-your-node/paratime-client-node"),mdxType:"DocCard"}),(0,r.kt)(i.Z,{item:(0,o.n)("/node/web3"),mdxType:"DocCard"}))}m.isMDXComponent=!0},971:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"275e2a9ae4c6d8823cf28823a9edad80.svg"},1401:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"1c7c6fb2382a1ffb7303101cf049a745.svg"},3532:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/sourcify1-898a49b3519501962fe80f3ba09314b1.png"},8758:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/sourcify2-d95710724b0373068c2ac0f857e07928.png"},3519:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/sourcify3-8be00790df0e04f4720273e6cde8a867.png"},8332:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/client-km-compute-8776815a499e44e00cfdd8953fdc9fb3.svg"}}]); \ No newline at end of file diff --git a/assets/js/277e601e.88c9ea66.js b/assets/js/277e601e.88c9ea66.js new file mode 100644 index 0000000000..a8707d1baf --- /dev/null +++ b/assets/js/277e601e.88c9ea66.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3408],{3905:(e,t,a)=>{a.d(t,{Zo:()=>m,kt:()=>h});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var l=n.createContext({}),p=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},m=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),d=p(a),u=r,h=d["".concat(l,".").concat(u)]||d[u]||c[u]||i;return a?n.createElement(h,o(o({ref:t},m),{},{components:a})):n.createElement(h,o({ref:t},m))}));function h(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,o[1]=s;for(var p=2;p<i;p++)o[p]=a[p];return n.createElement.apply(null,o)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1829:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>c,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var n=a(7462),r=(a(7294),a(3905));const i={},o="Cobalt Upgrade",s={unversionedId:"node/mainnet/previous-upgrades/cobalt-upgrade",id:"node/mainnet/previous-upgrades/cobalt-upgrade",title:"Cobalt Upgrade",description:"This document provides an overview of the proposed criteria and changes for the Cobalt Mainnet upgrade. This has been reviewed and approved by community members and validators of the Oasis Network and is being reproduced and summarized here for easy access.",source:"@site/docs/node/mainnet/previous-upgrades/cobalt-upgrade.md",sourceDirName:"node/mainnet/previous-upgrades",slug:"/node/mainnet/previous-upgrades/cobalt-upgrade",permalink:"/node/mainnet/previous-upgrades/cobalt-upgrade",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/previous-upgrades/cobalt-upgrade.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Previous Upgrades",permalink:"/node/mainnet/previous-upgrades"},next:{title:"Upgrade to Mainnet",permalink:"/node/mainnet/previous-upgrades/mainnet-upgrade"}},l={},p=[{value:"Major Features",id:"major-features",level:2},{value:"Mechanics of the Upgrade",id:"mechanics-of-the-upgrade",level:2},{value:"Proposed State Changes",id:"proposed-state-changes",level:2},{value:"<strong>General</strong>",id:"general",level:3},{value:"<strong>Epoch Time</strong>",id:"epoch-time",level:3},{value:"<strong>Registry</strong>",id:"registry",level:3},{value:"<strong>Root Hash</strong>",id:"root-hash",level:3},{value:"<strong>Staking</strong>",id:"staking",level:3},{value:"<strong>Committee Scheduler</strong>",id:"committee-scheduler",level:3},{value:"<strong>Random Beacon</strong>",id:"random-beacon",level:3},{value:"<strong>Governance</strong>",id:"governance",level:3},{value:"<strong>Consensus</strong>",id:"consensus",level:3},{value:"Other",id:"other",level:3},{value:"Runtime State Root Migration",id:"runtime-state-root-migration",level:3},{value:"Launch Support",id:"launch-support",level:2}],m={toc:p},d="wrapper";function c(e){let{components:t,...a}=e;return(0,r.kt)(d,(0,n.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"cobalt-upgrade"},"Cobalt Upgrade"),(0,r.kt)("p",null,"This document provides an overview of the proposed criteria and changes for the Cobalt Mainnet upgrade. This has been ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community/discussions/18"},"reviewed and approved by community members and validators of the Oasis Network")," and is being reproduced and summarized here for easy access."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"As proposed by the community, the Cobalt upgrade on Mainnet will kick off around April 28, 2021 at 16:00 UTC.")),(0,r.kt)("h2",{id:"major-features"},"Major Features"),(0,r.kt)("p",null,"All features for the Cobalt upgrade are implemented as part of ",(0,r.kt)("strong",{parentName:"p"},"Oasis Core 21.1.1")," which is a protocol-breaking release. Summary of the major features is as follows:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Light Clients and Checkpoint Sync"),": In order to make bootstrapping of new network nodes much faster, the upgrade will introduce support for light clients and restoring state from checkpoints provided by other nodes in the network."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Random Beacon"),": The random beacon is used by the consensus layer for ParaTime committee elections and is a critical component in providing security for ParaTimes with an open admission policy. The improved random beacon implementation is based on SCRAPE and provides unbiased output as long as at least one participant is honest."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"On-Chain Governance"),": The new on-chain governance service provides a simple framework for submitting governance proposals, validators voting on proposals and once an upgrade proposal passes, having a way to perform the upgrade in a controlled manner which minimizes downtime."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Support for Beneficiary Allowances"),": Each account is able to configure beneficiaries which are allowed to withdraw tokens from it in addition to the account owner."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"ROSE Transfers Between the consensus layer and ParaTimes"),": The proposed upgrade introduces a mechanism where ParaTimes can emit messages as part of processing any ParaTime block. These messages can trigger operations in the consensus layer on the ParaTime's behalf. ParaTimes get their own accounts in the consensus layer which can hold ROSE and ParaTimes are able to request them be transferred to other accounts or to withdraw from other accounts when allowed via the allowances mechanism."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"A Path Towards Self-Governing ParaTimes"),": By building on the ParaTime messages mechanism, the proposed upgrade extends ParaTime governance options and enables a path towards ParaTimes that can define their own governance mechanisms.")),(0,r.kt)("p",null,"In addition to the specified additional features we also propose the validator set size to be increased from the current 80 to 100 validators as ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community/discussions/5#discussioncomment-282746"},"suggested earlier by the community"),"."),(0,r.kt)("h2",{id:"mechanics-of-the-upgrade"},"Mechanics of the Upgrade"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"This section will be updated with more details as we get closer to the upgrade.")),(0,r.kt)("p",null,"Upgrading the Mainnet will require a coordinated upgrade of the Network. All nodes will need to configure a new genesis file that they can generate or verify independently and reset/archive any state from Mainnet. Once enough (representing 2/3+ of stake) nodes have taken this step, the upgraded network will start."),(0,r.kt)("p",null,"For the actual steps that node operators need to make on their nodes, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/upgrade-log#2021-04-28-16-00-utc-cobalt-upgrade"},"Upgrade Log"),"."),(0,r.kt)("h2",{id:"proposed-state-changes"},"Proposed State Changes"),(0,r.kt)("p",null,"The following parts of the genesis document will be updated:"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For a more detailed explanation of the parameters below, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"Genesis Document")," docs.")),(0,r.kt)("h3",{id:"general"},(0,r.kt)("strong",{parentName:"h3"},"General")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"height"))," will be set to the height of the Mainnet state dump + 1, i.e.",(0,r.kt)("inlineCode",{parentName:"li"},"3027601"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"genesis_time"))," will be set to",(0,r.kt)("inlineCode",{parentName:"li"},"2021-04-28T16:00:00Z"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"chain_id"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-2"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"halt_epoch"))," will be set to",(0,r.kt)("inlineCode",{parentName:"li"},"13807"),"(approximately 1 year from the Cobalt upgrade).")),(0,r.kt)("h3",{id:"epoch-time"},(0,r.kt)("strong",{parentName:"h3"},"Epoch Time")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"epochtime")),"object will be removed since it became obsolete with the new ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0007-improved-random-beacon"},"improved random beacon"),". It will be replaced with the new ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon"))," object described ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade#random-beacon"},"below"),"."),(0,r.kt)("h3",{id:"registry"},(0,r.kt)("strong",{parentName:"h3"},"Registry")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.params.enable_runtime_governance_models")," ")," is a new parameter that specifies the set of ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#runtimes"},"runtime governance models")," that are allowed to be used when creating/updating registrations. It will be set to:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},'{\n "entity": true,\n "runtime": true\n}\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes"))," list contains the registered runtimes' descriptors. In the Cobalt upgrade, it will be migrated from a list of ",(0,r.kt)("em",{parentName:"p"},"signed")," runtime descriptors to a list of runtime descriptors. The migration will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.suspended_runtimes"))," list contains the suspended registered runtimes' descriptors. In the Cobalt upgrade, it will be migrated from a list of ",(0,r.kt)("em",{parentName:"p"},"signed")," suspended runtime descriptors to a list of suspended runtime descriptors. The migration will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Inactive registered entities in ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.entities"))," (and their corresponding nodes in ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.nodes")),") that don't pass the ",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#node-and-paratime-token-thresholds"},"minimum staking thresholds")," will be removed. The removal will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command."))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Removing entities from ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.entities"))," will effectively deregister them but the entities' accounts in ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.ledger"))," will remain intact."),(0,r.kt)("p",{parentName:"admonition"},"Deregistered entities can always re-register by submitting the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#generating-entity-registration-transaction"},"entity registration transaction")," after the upgrade.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.node_statuses"))," object contains the registered nodes' statuses. In the Cobalt upgrade, each node's status will get a new parameter: ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"election_eligible_after")),". This parameter specifies at which epoch a node is eligible to be ",(0,r.kt)("a",{parentName:"li",href:"/core/consensus/services/scheduler"},"scheduled into various committees"),". All nodes will have the parameter set to ",(0,r.kt)("inlineCode",{parentName:"li"},"0")," which means they are immediately eligible. The migration will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis")," command.")),(0,r.kt)("h3",{id:"root-hash"},(0,r.kt)("strong",{parentName:"h3"},"Root Hash")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_runtime_messages")," ")," is a new parameter that specifies the global limit on the number of ",(0,r.kt)("a",{parentName:"li",href:"/core/runtime/messages"},"messages")," that can be emitted in each round by the runtime. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"256"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_evidence_age"))," is a new parameter that specifies the maximum age (in the number of rounds) of submitted evidence for ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0005-runtime-compute-slashing"},"compute node slashing"),". It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"100"),".")),(0,r.kt)("h3",{id:"staking"},(0,r.kt)("strong",{parentName:"h3"},"Staking")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.governance_deposits")," ")," are the tokens collected from governance proposal deposits. The initial balance will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},'"0"'),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.allow_escrow_messages"))," is a new parameter indicating whether to enable support for the newly added ",(0,r.kt)("inlineCode",{parentName:"li"},"AddEscrow")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"ReclaimEscrow")," ",(0,r.kt)("a",{parentName:"li",href:"/core/runtime/messages"},"runtime messages")," . It will be set to",(0,r.kt)("inlineCode",{parentName:"li"},"true"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.0"))," will be renamed to ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-equivocation")),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-light-client-attack.amount"))," is a new parameter controlling how much to slash for light client attack. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},'"100000000000"')," (i.e. 100,000,000,000 base units, or 100 ROSE tokens)."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.slashing.consensus-light-client-attack.freeze_interval")," ")," is a new parameter controlling the duration (in epochs) for which a node that has been slashed for light client attack is \u201cfrozen,\u201d or barred from participating in the network's consensus committee. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"18446744073709551615")," (i.e. the maximum value for a 64-bit unsigned integer) which means that any node slashed for light client attack will be, in effect, permanently banned from the network.")),(0,r.kt)("h3",{id:"committee-scheduler"},(0,r.kt)("strong",{parentName:"h3"},"Committee Scheduler")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators"))," is the maximum size of the consensus committee (i.e. the validator set). It will be increased from ",(0,r.kt)("inlineCode",{parentName:"li"},"80")," to",(0,r.kt)("inlineCode",{parentName:"li"},"100"),".")),(0,r.kt)("h3",{id:"random-beacon"},(0,r.kt)("strong",{parentName:"h3"},"Random Beacon")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon"))," object contains parameters controlling the new ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0007-improved-random-beacon"},"improved random beacon")," introduced in the Cobalt upgrade."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.base"))," is the network's starting epoch. It will be set to the epoch of Mainnet's state dump + 1, i.e. ",(0,r.kt)("inlineCode",{parentName:"li"},"5047"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.backend"))," configures the random beacon backend to use. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},'"pvss"')," indicating that the beacon implementing a ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0007-improved-random-beacon"},"PVSS (publicly verifiable secret sharing) scheme")," should be used."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters.participants"))," is the number of participants to be selected for each beacon generation protocol round. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"20"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters.threshold"))," is the minimum number of participants which must successfully contribute entropy for the final output to be considered valid. It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"10"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters.commit_interval"))," is the duration of the Commit phase (in blocks). It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"400"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters.reveal_interval"))," is the duration of the Reveal phase (in blocks). It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"196"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters.transition_delay"))," is the duration of the post Reveal phase (in blocks). It will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"4"),".")),(0,r.kt)("h3",{id:"governance"},(0,r.kt)("strong",{parentName:"h3"},"Governance")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance"))," object contains parameters controlling the network's ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/governance"},"on-chain governance")," introduced in the Cobalt upgrade",(0,r.kt)("strong",{parentName:"p"},".")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.min_proposal_deposit"))," is the amount of tokens (in base units) that are deposited when creating a new proposal. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},'"10000000000000"')," (i.e. 10,000,000,000,000 base units, or 10,000 ROSE tokens).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.voting_period"))," is the number of epochs after which the voting for a proposal is closed and the votes are tallied. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"168"),", which is expected to be approximately 7 days.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.quorum"))," is the minimum percentage of voting power that needs to be cast on a proposal for the result to be valid. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"75")," (i.e. 75%)."),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.threshold"))," is the minimum percentage of ",(0,r.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes in order for a proposal to be accepted. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"90"),"(i.e. 90%).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.upgrade_min_epoch_diff"))," is the minimum number of epochs between the current epoch and the proposed upgrade epoch for the upgrade proposal to be valid. Additionally, it specifies the minimum number of epochs between two consecutive pending upgrades."),(0,r.kt)("p",{parentName:"li"},"It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"336"),", which is expected to be approximately 14 days.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.upgrade_cancel_min_epoch_diff"))," is the minimum number of epochs between the current epoch and the proposed upgrade epoch for the upgrade cancellation proposal to be valid. It will be set to",(0,r.kt)("inlineCode",{parentName:"p"},"192"),", which is expected to be approximately 8 days."))),(0,r.kt)("h3",{id:"consensus"},(0,r.kt)("strong",{parentName:"h3"},"Consensus")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_evidence_num"))," parameter will be removed and replaced by the"),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_evidence_size"))," parameter.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_evidence_size"))," is a new parameter specifying the maximum evidence size in bytes. It replaces the ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.max_evidence_num"))," parameter and will be set to",(0,r.kt)("inlineCode",{parentName:"p"},"51200")," (51,200 bytes, or 50 kB).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_interval"))," parameter controls the interval (in blocks) on which state checkpoints should be taken. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"10000"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_num_kept"))," parameter specifies the number of past state checkpoints to keep. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"2"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_chunk_size"))," parameters controls the chunk size (in bytes) that should be used when creating state checkpoints. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"8388608")," (8,388,608 bytes, or 8 MB)."))),(0,r.kt)("h3",{id:"other"},"Other"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"extra_data"))," will be set back to the value in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18"},"Mainnet genesis file")," to include the Oasis network's genesis quote: ",(0,r.kt)("em",{parentName:"p"},"\u201d"),(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F"},(0,r.kt)("em",{parentName:"a"},"Quis custodiet ipsos custodes?")),(0,r.kt)("em",{parentName:"p"},"\u201d ","[","submitted by Oasis Community Member Daniyar Borangaziyev]:")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n')))),(0,r.kt)("h3",{id:"runtime-state-root-migration"},"Runtime State Root Migration"),(0,r.kt)("p",null,"Additionally, each runtime's state root will need to be updated for the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/upgrade-log#runtime-operators"},"runtime storage migration")," that is performed during this upgrade."),(0,r.kt)("p",null,"At this time, there is only one active runtime on the Mainnet, namely Second State's Oasis Ethereum ParaTime with ID (Base64-encoded) ",(0,r.kt)("inlineCode",{parentName:"p"},"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wM="),"."),(0,r.kt)("p",null,"After completing the runtime storage migration, Second State will communicate the new state root of their runtime and the genesis document needs to be updated as follows:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.runtime_states.<RUNTIME-ID>.state_root"))," will be set to the (Base64-encoded) migrated state root."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes.[id=<RUNTIME-ID>].genesis.state_root"))," will be set to the (Base64-encoded) migrated state root."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes.[id=<RUNTIME-ID>].genesis.state"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"li"},"null"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes.[id=<RUNTIME-ID>].genesis.round"))," will be set to the same value as ",(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.runtime_states.<RUNTIME-ID>.round")),".")),(0,r.kt)("h2",{id:"launch-support"},"Launch Support"),(0,r.kt)("p",null,"The Oasis team will be offering live video support during the Cobalt upgrade. Video call link and calendar details will be shared with node operators via email and Slack."),(0,r.kt)("p",null,"For any additional support, please reach out via the ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/"},(0,r.kt)("strong",{parentName:"a"},"#nodeoperators")," Oasis Community Slack channel")," with your questions, comments, and feedback related to Cobalt upgrade."),(0,r.kt)("p",null,"To follow the network, please use one of the many ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards"},"community block explorers"),"."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/27f9eba8.d09ea2a1.js b/assets/js/27f9eba8.d09ea2a1.js new file mode 100644 index 0000000000..085a9846e6 --- /dev/null +++ b/assets/js/27f9eba8.d09ea2a1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4440],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>f});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=o.createContext({}),d=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=d(e.components);return o.createElement(s.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),c=d(n),m=r,f=c["".concat(s,".").concat(m)]||c[m]||p[m]||a;return n?o.createElement(f,i(i({ref:t},u),{},{components:n})):o.createElement(f,i({ref:t},u))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[c]="string"==typeof e?e:r,i[1]=l;for(var d=2;d<a;d++)i[d]=n[d];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}m.displayName="MDXCreateElement"},564:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>d});var o=n(7462),r=(n(7294),n(3905));const a={},i="Delegation Policy",l={unversionedId:"get-involved/delegation-policy",id:"get-involved/delegation-policy",title:"Delegation Policy",description:"Oasis Protocol Foundation delegates ROSE tokens to node operators based on their",source:"@site/docs/get-involved/delegation-policy.md",sourceDirName:"get-involved",slug:"/get-involved/delegation-policy",permalink:"/get-involved/delegation-policy",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/delegation-policy.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"Network Governance",permalink:"/get-involved/network-governance"},next:{title:"Token Delivery & KYC Guide",permalink:"/get-involved/token-delivery-and-kyc"}},s={},d=[{value:"Requirements for Receiving Delegations",id:"requirements-for-receiving-delegations",level:2},{value:"Code of Conduct",id:"code-of-conduct",level:3},{value:"Performance Requirements",id:"performance-requirements",level:3},{value:"How to Earn Delegations?",id:"how-to-earn-delegations",level:2}],u={toc:d},c="wrapper";function p(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,o.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"delegation-policy"},"Delegation Policy"),(0,r.kt)("p",null,"Oasis Protocol Foundation delegates ROSE tokens to node operators based on their\nparticipation in the Oasis Mainnet, Testnet and ParaTimes on the network,\nnode reliability and performance, community engagement and overall support of\nthe network."),(0,r.kt)("p",null,"This page describes the Oasis Protocol Foundation's Delegation Policy."),(0,r.kt)("h2",{id:"requirements-for-receiving-delegations"},"Requirements for Receiving Delegations"),(0,r.kt)("h3",{id:"code-of-conduct"},"Code of Conduct"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Ensure commission rates and commission rate bounds are no greater than 20%."),(0,r.kt)("li",{parentName:"ol"},"Ensure commission rates are +/- 10% of the weighted median network commission\nrate."),(0,r.kt)("li",{parentName:"ol"},"Ensure your entity\u2019s website, social media and/or contact info in the\n",(0,r.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/metadata-registry"},"Oasis Metadata Registry")," is up-to-date."),(0,r.kt)("li",{parentName:"ol"},"Do not use 'Oasis' in your entity name, and do not use any Oasis Foundation\nlogos or branding in your entity logo."),(0,r.kt)("li",{parentName:"ol"},"Refrain from dishonest, fraudulent or malicious behavior."),(0,r.kt)("li",{parentName:"ol"},"Participate in on-chain governance and network upgrades proposed by Oasis\nFoundation."),(0,r.kt)("li",{parentName:"ol"},"Be available and coordinate with the node operator community in case of\nunplanned network upgrades.")),(0,r.kt)("p",null,"If there is any violation of the above Code of Conduct, Oasis Foundation\nreserves the right to revoke your entire delegation."),(0,r.kt)("h3",{id:"performance-requirements"},"Performance Requirements"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Maintain active validator status."),(0,r.kt)("li",{parentName:"ol"},"Maintain >99% uptime for your validator node as well as Emerald and/or Cipher\nParaTime nodes (if you run them)."),(0,r.kt)("li",{parentName:"ol"},"Ensure your nodes are upgraded within 1 hour after a planned network upgrade."),(0,r.kt)("li",{parentName:"ol"},"Ensure your nodes are upgraded within 24 hours after an unplanned network\nupgrade.")),(0,r.kt)("p",null,"If any of the above Performance Requirements is not met, Oasis Foundation\nreserves the right to revoke delegations. If you run into a complex technical\nissue that prevents your node from meeting the above Performance Requirements,\nplease reach out to the Oasis team as soon as possible."),(0,r.kt)("h2",{id:"how-to-earn-delegations"},"How to Earn Delegations?"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Have a meaningful amount of self-delegation and/or delegations from the Oasis\ncommunity."),(0,r.kt)("li",{parentName:"ul"},"Operate Emerald and/or Cipher ParaTime nodes on Mainnet."),(0,r.kt)("li",{parentName:"ul"},"Operate validator and/or ParaTime nodes on Testnet"),(0,r.kt)("li",{parentName:"ul"},"Participate in community discussion on the network\u2019s future roadmap."),(0,r.kt)("li",{parentName:"ul"},"Actively participate on the Oasis Network Community server on Discord\nand help answer questions from other community members."),(0,r.kt)("li",{parentName:"ul"},"Build or contribute to tools, services or dApps that benefit developers, node\noperators and/or the overall Oasis community."),(0,r.kt)("li",{parentName:"ul"},"Contribute code to Oasis projects."),(0,r.kt)("li",{parentName:"ul"},"Find and report issues related to any of the network protocols and/or their\nimplementations."),(0,r.kt)("li",{parentName:"ul"},"Demonstrate a track record of successfully operating nodes on other major\nnetworks.")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2881b1cc.2564d7f8.js b/assets/js/2881b1cc.2564d7f8.js new file mode 100644 index 0000000000..8c5fa36fa5 --- /dev/null +++ b/assets/js/2881b1cc.2564d7f8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[993],{5908:n=>{n.exports=JSON.parse('{"title":"Advanced","description":"This section provides documentation on advanced usages of the Oasis node.","slug":"node/run-your-node/advanced","permalink":"/node/run-your-node/advanced","navigation":{"previous":{"title":"Shutting Down a Node","permalink":"/node/run-your-node/maintenance/shutting-down-a-node"},"next":{"title":"Using State Sync for Quick Bootstraping","permalink":"/node/run-your-node/advanced/sync-node-using-state-sync"}}}')}}]); \ No newline at end of file diff --git a/assets/js/29c77900.29fcebed.js b/assets/js/29c77900.29fcebed.js new file mode 100644 index 0000000000..f56b1b6249 --- /dev/null +++ b/assets/js/29c77900.29fcebed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8553],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,u=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(u,".").concat(m)]||d[m]||p[m]||a;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var u in t)hasOwnProperty.call(t,u)&&(s[u]=t[u]);s.originalType=e,s[d]="string"==typeof e?e:o,i[1]=s;for(var l=2;l<a;l++)i[l]=n[l];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},711:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const a={},i="Stake Requirements",s={unversionedId:"node/run-your-node/prerequisites/stake-requirements",id:"node/run-your-node/prerequisites/stake-requirements",title:"Stake Requirements",description:"This page provides an overview of the stake requirements to become a validator",source:"@site/docs/node/run-your-node/prerequisites/stake-requirements.md",sourceDirName:"node/run-your-node/prerequisites",slug:"/node/run-your-node/prerequisites/stake-requirements",permalink:"/node/run-your-node/prerequisites/stake-requirements",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/stake-requirements.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Hardware Requirements",permalink:"/node/run-your-node/prerequisites/hardware-recommendations"},next:{title:"Install Oasis Node Binary",permalink:"/node/run-your-node/prerequisites/oasis-node"}},u={},l=[{value:"Mainnet",id:"mainnet",level:2},{value:"Testnet",id:"testnet",level:2}],c={toc:l},d="wrapper";function p(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"stake-requirements"},"Stake Requirements"),(0,o.kt)("p",null,"This page provides an overview of the stake requirements to become a validator\non the consensus layer of the Oasis Network."),(0,o.kt)("h2",{id:"mainnet"},"Mainnet"),(0,o.kt)("p",null,"To become a validator on the Oasis Network, you will need to have enough\ntokens staked in your escrow account."),(0,o.kt)("p",null,"Currently, you are going to need:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"100 ROSE staked for your entity's registration since that is the\n",(0,o.kt)("a",{parentName:"li",href:"/node/genesis-doc#staking-thresholds"},"staking thresholds"),"."),(0,o.kt)("li",{parentName:"ul"},"100 ROSE staked for your validator node's registration since that is the\n",(0,o.kt)("a",{parentName:"li",href:"/node/genesis-doc#staking-thresholds"},"staking thresholds"),"."),(0,o.kt)("li",{parentName:"ul"},"If you want to be part of the active validator set, you will need enough\nROSE staked -- this means you will have to be one of the top 120 entities\nby stake. You can check out current top 120 entities on the blockchain explorer\nsuch as ",(0,o.kt)("a",{parentName:"li",href:"https://www.oasisscan.com/validators"},"Oasis Scan"),".")),(0,o.kt)("p",null,"For more information about obtaining information on your entity's account, see\nthe ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"Account Get Info")," doc."),(0,o.kt)("p",null,"Staking thresholds may change in the future. Read the\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#show-native-token"},"native token information")," to see the current values used by the network."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"To determine if you are eligible to receive a delegation from the Oasis Protocol\nFoundation, see the ",(0,o.kt)("a",{parentName:"p",href:"/get-involved/delegation-policy"},"Delegation Policy")," document.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The size of the consensus committee (i.e. the validator set) is configured by\nthe ",(0,o.kt)("a",{parentName:"p",href:"/node/genesis-doc#consensus"},(0,o.kt)("strong",{parentName:"a"},"max_validators")," consensus parameter"),".")),(0,o.kt)("h2",{id:"testnet"},"Testnet"),(0,o.kt)("p",null,"For the Testnet you are going to need TEST tokens. You can receive a limited\nnumber of TEST by using our ",(0,o.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev/"},"Oasis Network Testnet Faucet"),". For\nmore tokens please contact us at our official ",(0,o.kt)("a",{parentName:"p",href:"https://oasis.io/discord"},"Discord #testnet channel"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2c58cae2.0bded762.js b/assets/js/2c58cae2.0bded762.js new file mode 100644 index 0000000000..b78c89b67a --- /dev/null +++ b/assets/js/2c58cae2.0bded762.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4077],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),c=p(r),h=o,m=c["".concat(l,".").concat(h)]||c[h]||d[h]||a;return r?n.createElement(m,i(i({ref:t},u),{},{components:r})):n.createElement(m,i({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:o,i[1]=s;for(var p=2;p<a;p++)i[p]=r[p];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}h.displayName="MDXCreateElement"},7119:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={description:"How to build your first smart contract on Oasis"},i="Prerequisites",s={unversionedId:"dapp/cipher/prerequisites",id:"dapp/cipher/prerequisites",title:"Prerequisites",description:"How to build your first smart contract on Oasis",source:"@site/docs/dapp/cipher/prerequisites.md",sourceDirName:"dapp/cipher",slug:"/dapp/cipher/prerequisites",permalink:"/dapp/cipher/prerequisites",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/prerequisites.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"How to build your first smart contract on Oasis"},sidebar:"developers",previous:{title:"Cipher ParaTime",permalink:"/dapp/cipher/"},next:{title:"Hello World",permalink:"/dapp/cipher/hello-world"}},l={},p=[{value:"Environment Setup",id:"environment-setup",level:2},{value:"Rust",id:"rust",level:3},{value:"Rust Toolchain Version",id:"rust-toolchain-version",level:4},{value:"WebAssembly Target Support",id:"webassembly-target-support",level:4},{value:"(OPTIONAL) Go",id:"optional-go",level:3},{value:"Oasis CLI Installation",id:"oasis-cli-installation",level:2}],u={toc:p},c="wrapper";function d(e){let{components:t,...r}=e;return(0,o.kt)(c,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"prerequisites"},"Prerequisites"),(0,o.kt)("p",null,"This section will guide you how to install the software required for developing\nsmart contracts using the Oasis SDK. After successfully completing all the\ndescribed steps you will be able to start building your first smart contract\non Oasis!"),(0,o.kt)("p",null,"If you already have everything set up, feel free to skip to the ",(0,o.kt)("a",{parentName:"p",href:"/dapp/cipher/hello-world"},"next\nsection"),"."),(0,o.kt)("h2",{id:"environment-setup"},"Environment Setup"),(0,o.kt)("p",null,"The following is a list of prerequisites required to start developing using the\nOasis SDK:"),(0,o.kt)("h3",{id:"rust"},(0,o.kt)("a",{parentName:"h3",href:"https://www.rust-lang.org/"},"Rust")),(0,o.kt)("p",null,"We follow ",(0,o.kt)("a",{parentName:"p",href:"https://www.rust-lang.org/tools/install"},"Rust upstream's recommendation")," on using\n",(0,o.kt)("a",{parentName:"p",href:"https://rustup.rs/"},"rustup")," to install and manage Rust versions."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"rustup cannot be installed alongside a distribution packaged Rust version. You\nwill need to remove it (if it's present) before you can start using rustup.")),(0,o.kt)("p",null,"Install it by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,o.kt)("a",{parentName:"p",href:"https://rust-lang.github.io/rustup/installation/other.html"},"download ",(0,o.kt)("inlineCode",{parentName:"a"},"rustup-init")," executable for your platform"),"\nand run it manually.")),(0,o.kt)("p",null,"This will run ",(0,o.kt)("inlineCode",{parentName:"p"},"rustup-init")," which will download and install the latest stable\nversion of Rust on your system."),(0,o.kt)("h4",{id:"rust-toolchain-version"},"Rust Toolchain Version"),(0,o.kt)("p",null,"The version of the Rust toolchain we use in the Oasis SDK is specified in the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/master/rust-toolchain"},"rust-toolchain")," file."),(0,o.kt)("p",null,"The rustup-installed versions of ",(0,o.kt)("inlineCode",{parentName:"p"},"cargo"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"rustc")," and other tools will\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence"},"automatically detect this file and use the appropriate version of the Rust\ntoolchain"),". When you are building applications that\nuse the SDK, it is recommended that you copy the same ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/master/rust-toolchain"},"rust-toolchain")," file to\nyour project's top-level directory as well."),(0,o.kt)("p",null,"To install the appropriate version of the Rust toolchain, make sure you are\nin the project directory and run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rustup show\n")),(0,o.kt)("p",null,"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"...\n\nactive toolchain\n----------------\n\nnightly-2022-08-22-x86_64-unknown-linux-gnu (overridden by '/code/rust-toolchain')\nrustc 1.65.0-nightly (c0941dfb5 2022-08-21)\n")),(0,o.kt)("h4",{id:"webassembly-target-support"},"WebAssembly Target Support"),(0,o.kt)("p",null,"In order to be able to compile Rust programs into WebAssembly you need to also\ninstall the WebAssembly target by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rustup target add wasm32-unknown-unknown\n")),(0,o.kt)("h3",{id:"optional-go"},"(OPTIONAL) ",(0,o.kt)("a",{parentName:"h3",href:"https://golang.org"},"Go")),(0,o.kt)("p",null,(0,o.kt)("em",{parentName:"p"},"Required if you want to use the Go Client SDK.")),(0,o.kt)("p",null,"At least version ",(0,o.kt)("strong",{parentName:"p"},"1.18.5")," is required. If your distribution provides a\nnew-enough version of Go, just use that."),(0,o.kt)("p",null,"Otherwise:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"install the Go version provided by your distribution,")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("a",{parentName:"p",href:"https://tip.golang.org/doc/code.html#GOPATH"},"ensure ",(0,o.kt)("inlineCode",{parentName:"a"},"$GOPATH/bin")," is in your ",(0,o.kt)("inlineCode",{parentName:"a"},"PATH")),",")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("a",{parentName:"p",href:"https://golang.org/doc/install#extra_versions"},"install the desired version of Go"),", e.g. 1.18.5, with:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"go get golang.org/dl/go1.18.5\ngo1.18.5 download\n")))),(0,o.kt)("h2",{id:"oasis-cli-installation"},"Oasis CLI Installation"),(0,o.kt)("p",null,"The rest of the guide uses the Oasis CLI as an easy way to interact with the\nsmart contract. You can use ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/releases"},"one of the binary releases")," or\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/blob/master/README.md"},"compile it yourself"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2e8d1096.8eb25416.js b/assets/js/2e8d1096.8eb25416.js new file mode 100644 index 0000000000..81aee62796 --- /dev/null +++ b/assets/js/2e8d1096.8eb25416.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8038],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?s(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):s(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function r(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},s=Object.keys(e);for(a=0;a<s.length;a++)n=s[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a<s.length;a++)n=s[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=a.createContext({}),u=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},d=function(e){var t=u(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,s=e.originalType,l=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),p=u(n),c=i,h=p["".concat(l,".").concat(c)]||p[c]||m[c]||s;return n?a.createElement(h,o(o({ref:t},d),{},{components:n})):a.createElement(h,o({ref:t},d))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var s=n.length,o=new Array(s);o[0]=c;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[p]="string"==typeof e?e:i,o[1]=r;for(var u=2;u<s;u++)o[u]=n[u];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},7256:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>m,frontMatter:()=>s,metadata:()=>r,toc:()=>u});var a=n(7462),i=(n(7294),n(3905));const s={},o="ADR 0003: Consensus/Runtime Token Transfer",r={unversionedId:"adrs/0003-consensus-runtime-token-transfer",id:"adrs/0003-consensus-runtime-token-transfer",title:"ADR 0003: Consensus/Runtime Token Transfer",description:"Component",source:"@site/docs/adrs/0003-consensus-runtime-token-transfer.md",sourceDirName:"adrs",slug:"/adrs/0003-consensus-runtime-token-transfer",permalink:"/adrs/0003-consensus-runtime-token-transfer",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0003-consensus-runtime-token-transfer.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0002: Go Modules Compatible Git Tags",permalink:"/adrs/0002-go-modules-compatible-git-tags"},next:{title:"ADR 0004: Runtime Governance",permalink:"/adrs/0004-runtime-governance"}},l={},u=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Addresses",id:"addresses",level:3},{value:"State",id:"state",level:3},{value:"General Accounts",id:"general-accounts",level:4},{value:"Transaction Methods",id:"transaction-methods",level:3},{value:"Allow",id:"allow",level:4},{value:"Withdraw",id:"withdraw",level:4},{value:"Queries",id:"queries",level:3},{value:"Messages",id:"messages",level:3},{value:"Staking Method Call",id:"staking-method-call",level:4},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Staking",id:"staking",level:4},{value:"Roothash",id:"roothash",level:4},{value:"Runtime Host Protocol",id:"runtime-host-protocol",level:3},{value:"Host to Runtime: Initialization",id:"host-to-runtime-initialization",level:4},{value:"Host to Runtime: Transaction Batch Dispatch",id:"host-to-runtime-transaction-batch-dispatch",level:4},{value:"Runtime to Host: Read-only Storage Access",id:"runtime-to-host-read-only-storage-access",level:4},{value:"Rust Runtime Support Library",id:"rust-runtime-support-library",level:3},{value:"Expected User/Consensus/Runtime Flow",id:"expected-userconsensusruntime-flow",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],d={toc:u},p="wrapper";function m(e){let{components:t,...n}=e;return(0,i.kt)(p,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"adr-0003-consensusruntime-token-transfer"},"ADR 0003: Consensus/Runtime Token Transfer"),(0,i.kt)("h2",{id:"component"},"Component"),(0,i.kt)("p",null,"Oasis Core"),(0,i.kt)("h2",{id:"changelog"},"Changelog"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"2020-09-16: Beneficiary allowance, add message results"),(0,i.kt)("li",{parentName:"ul"},"2020-09-08: Initial draft")),(0,i.kt)("h2",{id:"status"},"Status"),(0,i.kt)("p",null,"Accepted"),(0,i.kt)("h2",{id:"context"},"Context"),(0,i.kt)("p",null,"Currently each runtime can define its own token (or none at all) and there is no\nmechanism that would support transfer of consensus layer tokens into a runtime\nand back out."),(0,i.kt)("p",null,"Introducing such a mechanism would allow the consensus layer tokens to be used\ninside runtimes for various functions. This ADR proposes such a mechanism."),(0,i.kt)("h2",{id:"decision"},"Decision"),(0,i.kt)("p",null,"On a high level, this proposal adds support for consensus/runtime token\ntransfers as follows:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Each staking account can set an allowance for beneficiaries.")," Each staking\naccount can set an allowance, a maximum amount a beneficiary can withdraw from\nthe given account. Beneficiaries are identified by their address. This is\nsimilar to approve/transferFrom calls defined by the ",(0,i.kt)("a",{parentName:"p",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC-20 Token Standard"),".\nPreviously such functionality was already present but was removed in\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/issues/2021"},"oasis-core#2021"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Each runtime itself has an account in the consensus layer.")," This account\ncontains the balance of tokens which are managed exclusively by the runtime\nand do not belong to any specific regular account in the consensus layer."),(0,i.kt)("p",{parentName:"li"},"It is not possible to transfer directly into a runtime account and doing so\nmay result in funds to be locked without a way to reclaim them."),(0,i.kt)("p",{parentName:"li"},"The only way to perform any operations on runtime accounts is through the use\nof messages emitted by the runtime during each round. These messages are\nsubject to discrepancy detection and instruct the consensus layer what to do."))),(0,i.kt)("p",null,"Combined, the two mechanisms enable account holders to set an allowance in the\nbenefit of runtimes so that the runtimes can withdraw up to the allowed amount\nfrom the account holder's address."),(0,i.kt)("h3",{id:"addresses"},"Addresses"),(0,i.kt)("p",null,"This proposal introduces the following new address context for the runtime\naccounts:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-core/address: runtime\n")),(0,i.kt)("p",null,"Initial version for the address context is ",(0,i.kt)("inlineCode",{parentName:"p"},"0"),". To derive the address, the\nstandard address derivation scheme is used, with the runtime's 32-byte\nidentifier used as the ",(0,i.kt)("inlineCode",{parentName:"p"},"data")," part."),(0,i.kt)("h3",{id:"state"},"State"),(0,i.kt)("p",null,"This proposal introduces/updates the following consensus state in the staking\nmodule:"),(0,i.kt)("h4",{id:"general-accounts"},"General Accounts"),(0,i.kt)("p",null,"The general account data structure is modified to include an additional field\nstoring the allowances as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type GeneralAccount struct {\n // ... existing fields omitted ...\n\n Allowances map[Address]quantity.Quantity `json:"allowances,omitempty"`\n}\n')),(0,i.kt)("h3",{id:"transaction-methods"},"Transaction Methods"),(0,i.kt)("p",null,"This proposal adds the following new transaction methods in the staking module:"),(0,i.kt)("h4",{id:"allow"},"Allow"),(0,i.kt)("p",null,"Allow enables an account holder to set an allowance for a beneficiary."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"staking.Allow\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Body:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type Allow struct {\n Beneficiary Address `json:"beneficiary"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Fields:")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"beneficiary")," specifies the beneficiary account address."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"amount_change")," specifies the absolute value of the amount of base units to\nchange the allowance for."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"negative")," specifies whether the ",(0,i.kt)("inlineCode",{parentName:"li"},"amount_change")," should be subtracted instead\nof added.")),(0,i.kt)("p",null,"The transaction signer implicitly specifies the general account. Upon executing\nthe allow the following actions are performed:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"If either the ",(0,i.kt)("inlineCode",{parentName:"p"},"disable_transfers")," staking consensus parameter is set to ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),"\nor the ",(0,i.kt)("inlineCode",{parentName:"p"},"max_allowances")," staking consensus parameter is set to zero, the method\nfails with ",(0,i.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"It is checked whether either the transaction signer address or the\n",(0,i.kt)("inlineCode",{parentName:"p"},"beneficiary")," address are reserved. If any are reserved, the method fails with\n",(0,i.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Address specified by ",(0,i.kt)("inlineCode",{parentName:"p"},"beneficiary")," is compared with the transaction signer\naddress. If the addresses are the same, the method fails with\n",(0,i.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The account indicated by the signer is loaded.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"If the allow would create a new allowance and the maximum number of allowances\nfor an account has been reached, the method fails with ",(0,i.kt)("inlineCode",{parentName:"p"},"ErrTooManyAllowances"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The set of allowances is updated so that the allowance is updated as specified\nby ",(0,i.kt)("inlineCode",{parentName:"p"},"amount_change"),"/",(0,i.kt)("inlineCode",{parentName:"p"},"negative"),". In case the change would cause the allowance to\nbe equal to zero or negative, the allowance is removed.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The account is saved.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The corresponding ",(0,i.kt)("inlineCode",{parentName:"p"},"AllowanceChangeEvent")," is emitted with the following\nstructure:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type AllowanceChangeEvent struct {\n Owner Address `json:"owner"`\n Beneficiary Address `json:"beneficiary"`\n Allowance quantity.Quantity `json:"allowance"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n')),(0,i.kt)("p",{parentName:"li"},"Where ",(0,i.kt)("inlineCode",{parentName:"p"},"allowance")," contains the new total allowance, the ",(0,i.kt)("inlineCode",{parentName:"p"},"amount_change"),"\ncontains the absolute amount the allowance has changed for and ",(0,i.kt)("inlineCode",{parentName:"p"},"negative"),"\nspecifies whether the allowance has been reduced rather than increased. The\nevent is emitted even if the new allowance is zero."))),(0,i.kt)("h4",{id:"withdraw"},"Withdraw"),(0,i.kt)("p",null,"Withdraw enables a beneficiary to withdraw from the given account."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"staking.Withdraw\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Body:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type Withdraw struct {\n From Address `json:"from"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Fields:")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"from")," specifies the account address to withdraw from."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"amount")," specifies the amount of base units to withdraw.")),(0,i.kt)("p",null,"The transaction signer implicitly specifies the destination general account.\nUpon executing the withdrawal the following actions are performed:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"If either the ",(0,i.kt)("inlineCode",{parentName:"p"},"disable_transfers")," staking consensus parameter is set to ",(0,i.kt)("inlineCode",{parentName:"p"},"true"),"\nor the ",(0,i.kt)("inlineCode",{parentName:"p"},"max_allowances")," staking consensus parameter is set to zero, the method\nfails with ",(0,i.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"It is checked whether either the transaction signer address or the\n",(0,i.kt)("inlineCode",{parentName:"p"},"from")," address are reserved. If any are reserved, the method fails with\n",(0,i.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Address specified by ",(0,i.kt)("inlineCode",{parentName:"p"},"from")," is compared with the transaction signer address.\nIf the addresses are the same, the method fails with ",(0,i.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The source account indicated by ",(0,i.kt)("inlineCode",{parentName:"p"},"from")," is loaded.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The destination account indicated by the transaction signer is loaded.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"amount")," is deducted from the corresponding allowance in the source account.\nIf this would cause the allowance to go negative, the method fails with\n",(0,i.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"amount")," is deducted from the source general account balance. If this would\ncause the balance to go negative, the method fails with\n",(0,i.kt)("inlineCode",{parentName:"p"},"ErrInsufficientBalance"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"amount")," is added to the destination general account balance.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Both source and destination accounts are saved.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The corresponding ",(0,i.kt)("inlineCode",{parentName:"p"},"TransferEvent")," is emitted.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The corresponding ",(0,i.kt)("inlineCode",{parentName:"p"},"AllowanceChangeEvent")," is emitted with the updated\nallowance."))),(0,i.kt)("h3",{id:"queries"},"Queries"),(0,i.kt)("p",null,"This proposal adds the following new query methods in the staking module by\nupdating the ",(0,i.kt)("inlineCode",{parentName:"p"},"staking.Backend")," interface as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type Backend interface {\n // ... existing methods omitted ...\n\n // Allowance looks up the allowance for the given owner/beneficiary combination.\n Allowance(ctx context.Context, query *AllowanceQuery) (*quantity.Quantity, error)\n}\n\n// AllowanceQuery is an allowance query.\ntype AllowanceQuery struct {\n Height int64 `json:"height"`\n Owner Address `json:"owner"`\n Beneficiary Address `json:"beneficiary"`\n}\n')),(0,i.kt)("h3",{id:"messages"},"Messages"),(0,i.kt)("p",null,"Since this is the first proposal that introduces a new runtime message type that\ncan be emitted from a runtime during a round, it also defines some general\nproperties of runtime messages and the dispatch mechanism:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Each message has an associated gas cost that needs to be paid by the\nsubmitter (e.g. as part of the ",(0,i.kt)("inlineCode",{parentName:"p"},"roothash.ExecutorCommit")," method call). The gas\ncost is split among the committee members.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"There is a maximum number of messages that can be emitted by a runtime during\na given round. The limit is defined both globally (e.g. a roothash consensus\nparameter) and per-runtime (which needs to be equal to or lower than the\nglobal limit).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Messages are serialized using a sum type describing all possible messages,\nwhere each message type is assigned a ",(0,i.kt)("em",{parentName:"p"},"field name"),":"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type Message struct {\n Message1 *Message1 `json:"message1,omitempty"`\n Message2 *Message2 `json:"message2,omitempty"`\n // ...\n}\n'))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"All messages are versioned by embeding the ",(0,i.kt)("inlineCode",{parentName:"p"},"cbor.Versioned")," structure which\nprovides a single ",(0,i.kt)("inlineCode",{parentName:"p"},"uint16")," field ",(0,i.kt)("inlineCode",{parentName:"p"},"v"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"A change is made to how messages are included in commitments, to reduce the\nsize of submitted transactions."),(0,i.kt)("p",{parentName:"li"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"ComputeResultsHeader")," is changed so that the ",(0,i.kt)("inlineCode",{parentName:"p"},"Messages")," field is replaced\nwith a ",(0,i.kt)("inlineCode",{parentName:"p"},"MessagesHash")," field containing a hash of the CBOR-encoded messages\nemitted by the runtime."),(0,i.kt)("p",{parentName:"li"},"At the same time ",(0,i.kt)("inlineCode",{parentName:"p"},"ComputeBody")," is changed to include an additional field\n",(0,i.kt)("inlineCode",{parentName:"p"},"Messages")," as follows:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type ComputeBody struct {\n // ... existing fields omitted ...\n Messages []*block.Message `json:"messages,omitempty"`\n}\n')),(0,i.kt)("p",{parentName:"li"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"Messages")," field must only be populated in the commitment by the\ntransaction scheduler and must match the ",(0,i.kt)("inlineCode",{parentName:"p"},"MessagesHash"),".")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"If any of the included messages is deemed ",(0,i.kt)("em",{parentName:"p"},"malformed"),", the round fails and the\nruntime state is not updated.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"In order to support messages that fail to execute, a new roothash event is\nemitted for each executed message:"),(0,i.kt)("pre",{parentName:"li"},(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type MessageEvent struct {\n Index uint32 `json:"index,omitempty"`\n Module string `json:"module,omitempty"`\n Code uint32 `json:"code,omitempty"`\n}\n')),(0,i.kt)("p",{parentName:"li"},"Where the ",(0,i.kt)("inlineCode",{parentName:"p"},"index")," specifies the index of the executed message and the ",(0,i.kt)("inlineCode",{parentName:"p"},"module"),"\nand ",(0,i.kt)("inlineCode",{parentName:"p"},"code")," specify the module and error code accoording to Oasis Core error\nencoding convention (note that the usual human readable message field is not\nincluded)."))),(0,i.kt)("p",null,"This proposal introduces the following runtime messages:"),(0,i.kt)("h4",{id:"staking-method-call"},"Staking Method Call"),(0,i.kt)("p",null,"The staking method call message enables a runtime to call one of the supported\nstaking module methods."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Field name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"staking\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Body:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type StakingMessage struct {\n cbor.Versioned\n\n Transfer *staking.Transfer `json:"transfer,omitempty"`\n Withdraw *staking.Withdraw `json:"withdraw,omitempty"`\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Fields:")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"v")," must be set to ",(0,i.kt)("inlineCode",{parentName:"li"},"0"),"."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"transfer")," indicates that the ",(0,i.kt)("inlineCode",{parentName:"li"},"staking.Transfer")," method should be executed."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"withdraw")," indicates that the ",(0,i.kt)("inlineCode",{parentName:"li"},"staking.Withdraw")," method should be executed.")),(0,i.kt)("p",null,"Exactly one of the supported method fields needs to be non-nil, otherwise the\nmessage is considered malformed."),(0,i.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,i.kt)("h4",{id:"staking"},"Staking"),(0,i.kt)("p",null,"This proposal introduces the following new consensus parameters in the staking\nmodule:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"max_allowances")," (uint32) specifies the maximum number of allowances an\naccount can store. Zero means that allowance functionality is disabled.")),(0,i.kt)("h4",{id:"roothash"},"Roothash"),(0,i.kt)("p",null,"This proposal introduces the following new consensus parameters in the roothash\nmodule:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"max_runtime_messages")," (uint32) specifies the global limit on the number of\nmessages that can be emitted in each round by the runtime. The default value\nof ",(0,i.kt)("inlineCode",{parentName:"li"},"0")," disables the use of runtime messages.")),(0,i.kt)("h3",{id:"runtime-host-protocol"},"Runtime Host Protocol"),(0,i.kt)("p",null,"This proposal modifies the runtime host protocol as follows:"),(0,i.kt)("h4",{id:"host-to-runtime-initialization"},"Host to Runtime: Initialization"),(0,i.kt)("p",null,"The existing ",(0,i.kt)("inlineCode",{parentName:"p"},"RuntimeInfoRequest")," message body is updated to contain a field\ndenoting the consensus backend used by the host and its consensus protocol\nversion as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type RuntimeInfoRequest struct {\n ConsensusBackend string `json:"consensus_backend"`\n ConsensusProtocolVersion uint64 `json:"consensus_protocol_version"`\n\n // ... existing fields omitted ...\n}\n')),(0,i.kt)("p",null,"This information can be used by the runtime to ensure that it supports the\nconsensus layer used by the host. In case the backend and/or protocol version is\nnot supported, the runtime should return an error and terminate. In case the\nruntime does not interact with the consensus layer it may ignore the consensus\nlayer information."),(0,i.kt)("h4",{id:"host-to-runtime-transaction-batch-dispatch"},"Host to Runtime: Transaction Batch Dispatch"),(0,i.kt)("p",null,"The existing ",(0,i.kt)("inlineCode",{parentName:"p"},"RuntimeExecuteTxBatchRequest")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"RuntimeCheckTxBatchRequest"),"\nmessage bodies are updated to include the consensus layer light block at the\nlast finalized round height (specified in ",(0,i.kt)("inlineCode",{parentName:"p"},".Block.Header.Round"),") and the list of\n",(0,i.kt)("inlineCode",{parentName:"p"},"MessageEvent"),"s emitted while processing the runtime messages emitted in the\nprevious round as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type RuntimeExecuteTxBatchRequest struct {\n // ConsensusBlock is the consensus light block at the last finalized round\n // height (e.g., corresponding to .Block.Header.Round).\n ConsensusBlock consensus.LightBlock `json:"consensus_block"`\n\n // MessageResults are the results of executing messages emitted by the\n // runtime in the previous round (sorted by .Index).\n MessageResults []roothash.MessageEvent `json:"message_results,omitempty"`\n\n // ... existing fields omitted ...\n}\n\ntype RuntimeCheckTxBatchRequest struct {\n // ConsensusBlock is the consensus light block at the last finalized round\n // height (e.g., corresponding to .Block.Header.Round).\n ConsensusBlock consensus.LightBlock `json:"consensus_block"`\n\n // ... existing fields omitted ...\n}\n')),(0,i.kt)("p",null,"The information from the light block can be used to access consensus layer\nstate."),(0,i.kt)("h4",{id:"runtime-to-host-read-only-storage-access"},"Runtime to Host: Read-only Storage Access"),(0,i.kt)("p",null,"The existing ",(0,i.kt)("inlineCode",{parentName:"p"},"HostStorageSyncRequest")," message body is updated to include an\nendpoint identifier as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type HostStorageSyncRequest struct {\n // Endpoint is the storage endpoint to which this request should be routed.\n Endpoint string `json:"endpoint,omitempty"`\n\n // ... existing fields omitted ...\n}\n')),(0,i.kt)("p",null,"The newly introduced ",(0,i.kt)("inlineCode",{parentName:"p"},"endpoint")," field can take the following values:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"runtime")," (or empty string) denotes the runtime state endpoint. The empty\nvalue is allowed for backwards compatibility as this was the only endpoint\navailable before this proposal.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"consensus")," denotes the consensus state endpoint, providing access to\nconsensus state."))),(0,i.kt)("h3",{id:"rust-runtime-support-library"},"Rust Runtime Support Library"),(0,i.kt)("p",null,"The Rust runtime support library (",(0,i.kt)("inlineCode",{parentName:"p"},"oasis-core-runtime"),") must be updated to\nsupport the updated message structures. Additionally, there needs to be basic\nsupport for interpreting the data from the Tendermint consensus layer backend:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Decoding light blocks.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Decoding staking-related state structures."))),(0,i.kt)("p",null,"The Tendermint-specific functionality should be part of a separate crate."),(0,i.kt)("h3",{id:"expected-userconsensusruntime-flow"},"Expected User/Consensus/Runtime Flow"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Scenario:")),(0,i.kt)("p",null,"Account holder has 100 tokens in her account in the consensus layer staking\nledger and would like to spend 50 tokens to execute an action in runtime X."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Flow:")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holder sets an allowance of 50 tokens for runtime X by submitting an\nallow transaction to the consensus layer.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holder submits a runtime transaction that performs some action costing\n50 tokens.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holder's runtime transaction is executed in runtime X round R:"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Runtime X emits a message to transfer 50 tokens from the user's account to\nthe runtime's own account."),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("em",{parentName:"p"},"As an optimization runtime X can verify current consensus layer state and\nreject the transaction early to prevent paying for needless consensus layer\nmessage processing."))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Runtime X updates its state to indicate a pending transfer of 50 tokens from\nthe user. It uses the index of the emitted message to be able to match the\nmessage execution result once it arrives.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Runtime X submits commitments to the consensus layer.")))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"When finalizing round R for runtime X, the consensus layer transfers 50 tokens\nfrom the account holder's account to the runtime X account.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Corresponding message result event is emitted, indicating success.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"When runtime X processes round R+1, the runtime receives the set of emitted\nmessage result events.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Runtime X processes message result events, using the index field to match the\ncorresponding pending action and executes whatever action it queued."),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"In case the message result event would indicate failure, the pending action\ncan be pruned.")))),(0,i.kt)("h2",{id:"consequences"},"Consequences"),(0,i.kt)("h3",{id:"positive"},"Positive"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Consensus layer tokens can be transferred into and out of runtimes, enabling\nmore use cases.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Any tokens must be explicitly made available to the runtime which limits the\ndamage from badly written or malicious runtimes.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holders can change the allowance at any time."))),(0,i.kt)("h3",{id:"negative"},"Negative"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"A badly written or malicious runtime could steal the tokens explicitly\ndeposited into the runtime. This includes any actions by the runtime owner\nwhich would modify the runtime's security parameters.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"A badly written, malicious or forever suspended runtime can lock tokens in\nthe runtime account forever. This could be mitigated via an unspecified\nconsensus layer governance mechanism.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holders may mistakenly transfer tokens directly into a runtime account\nwhich may cause such tokens to be locked forever.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Account holders may change the allowance or reduce their account balance right\nbefore the runtime round is finalized, causing the emitted messages to fail\nwhile the runtime still needs to pay for gas to execute the messages."))),(0,i.kt)("h3",{id:"neutral"},"Neutral"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"The runtime must handle all message results in the next round as otherwise it\ncannot easily get past messages.")),(0,i.kt)("h2",{id:"references"},"References"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eips.ethereum.org/EIPS/eip-20"},"ERC-20 Token Standard")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/issues/2021"},"oasis-core#2021"))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2ea67962.066c2780.js b/assets/js/2ea67962.066c2780.js new file mode 100644 index 0000000000..a2b0201d21 --- /dev/null +++ b/assets/js/2ea67962.066c2780.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5603],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>y});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),p=d(n),m=o,y=p["".concat(l,".").concat(m)]||p[m]||c[m]||a;return n?r.createElement(y,i(i({ref:t},u),{},{components:n})):r.createElement(y,i({ref:t},u))}));function y(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var d=2;d<a;d++)i[d]=n[d];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},9210:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var r=n(7462),o=(n(7294),n(3905));const a={},i="Install Oasis Node Binary",s={unversionedId:"node/run-your-node/prerequisites/oasis-node",id:"node/run-your-node/prerequisites/oasis-node",title:"Install Oasis Node Binary",description:"The Oasis Node is a binary that is created from the Oasis Core repository's go/ path.",source:"@site/docs/node/run-your-node/prerequisites/oasis-node.md",sourceDirName:"node/run-your-node/prerequisites",slug:"/node/run-your-node/prerequisites/oasis-node",permalink:"/node/run-your-node/prerequisites/oasis-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/oasis-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Stake Requirements",permalink:"/node/run-your-node/prerequisites/stake-requirements"},next:{title:"System Configuration",permalink:"/node/run-your-node/prerequisites/system-configuration"}},l={},d=[{value:"Downloading a Binary Release",id:"downloading-a-binary-release",level:2},{value:"Building From Source",id:"building-from-source",level:2},{value:"Adding <code>oasis-node</code> Binary to <code>PATH</code>",id:"adding-oasis-node-binary-to-path",level:2},{value:"Running ParaTimes",id:"running-paratimes",level:2}],u={toc:d},p="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(p,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"install-oasis-node-binary"},"Install Oasis Node Binary"),(0,o.kt)("p",null,"The Oasis Node is a binary that is created from the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," repository's ",(0,o.kt)("inlineCode",{parentName:"p"},"go/")," path."),(0,o.kt)("p",null,"It contains both the logic for running an Oasis node and also provides a CLI for handling registry, staking and other operations."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The Oasis Node is currently only supported on x86_64 Linux systems.")),(0,o.kt)("h2",{id:"downloading-a-binary-release"},"Downloading a Binary Release"),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We suggest that you build Oasis Node from source yourself for a production deployment of an Oasis node.")),(0,o.kt)("p",null,"For convenience, we provide binaries that have been built by the Oasis Protocol Foundation. Links to the binaries are provided in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," page."),(0,o.kt)("h2",{id:"building-from-source"},"Building From Source"),(0,o.kt)("p",null,"Although highly suggested, building from source is currently beyond the scope of this documentation."),(0,o.kt)("p",null,"See ",(0,o.kt)("a",{parentName:"p",href:"../../../core/development-setup/build-environment-setup-and-building"},"Oasis Core's Build Environment Setup and Building")," documentation for more details."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"The code in the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/"},(0,o.kt)("inlineCode",{parentName:"a"},"master")," branch")," might be incompatible with the code used by other nodes in the Mainnet."),(0,o.kt)("p",{parentName:"admonition"},"Make sure to use the version specified in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),".")),(0,o.kt)("h2",{id:"adding-oasis-node-binary-to-path"},"Adding ",(0,o.kt)("inlineCode",{parentName:"h2"},"oasis-node")," Binary to ",(0,o.kt)("inlineCode",{parentName:"h2"},"PATH")),(0,o.kt)("p",null,"To install the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary for the current user, copy/symlink it to ",(0,o.kt)("inlineCode",{parentName:"p"},"~/.local/bin"),"."),(0,o.kt)("p",null,"To install the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary for all users of the system, copy it to ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/local/bin"),"."),(0,o.kt)("h2",{id:"running-paratimes"},"Running ParaTimes"),(0,o.kt)("p",null,"If you intend to ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"run a ParaTime node")," you will need to additionally install the following software packages:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/projectatomic/bubblewrap"},"Bubblewrap")," 0.4.1+, needed for creating process sandboxes.")),(0,o.kt)("p",null," On Ubuntu 20.04+, you can install it with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"sudo apt install bubblewrap\n")),(0,o.kt)("p",null," On Fedora, you can install it with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"sudo dnf install bubblewrap\n")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/30129561.4d85e802.js b/assets/js/30129561.4d85e802.js new file mode 100644 index 0000000000..e9a52a50f3 --- /dev/null +++ b/assets/js/30129561.4d85e802.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4072],{3905:(e,t,i)=>{i.d(t,{Zo:()=>c,kt:()=>h});var o=i(7294);function n(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function a(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,o)}return i}function s(e){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?a(Object(i),!0).forEach((function(t){n(e,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(i)):a(Object(i)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(i,t))}))}return e}function r(e,t){if(null==e)return{};var i,o,n=function(e,t){if(null==e)return{};var i,o,n={},a=Object.keys(e);for(o=0;o<a.length;o++)i=a[o],t.indexOf(i)>=0||(n[i]=e[i]);return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)i=a[o],t.indexOf(i)>=0||Object.prototype.propertyIsEnumerable.call(e,i)&&(n[i]=e[i])}return n}var l=o.createContext({}),m=function(e){var t=o.useContext(l),i=t;return e&&(i="function"==typeof e?e(t):s(s({},t),e)),i},c=function(e){var t=m(e.components);return o.createElement(l.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var i=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,c=r(e,["components","mdxType","originalType","parentName"]),p=m(i),u=n,h=p["".concat(l,".").concat(u)]||p[u]||d[u]||a;return i?o.createElement(h,s(s({ref:t},c),{},{components:i})):o.createElement(h,s({ref:t},c))}));function h(e,t){var i=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=i.length,s=new Array(a);s[0]=u;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[p]="string"==typeof e?e:n,s[1]=r;for(var m=2;m<a;m++)s[m]=i[m];return o.createElement.apply(null,s)}return o.createElement.apply(null,i)}u.displayName="MDXCreateElement"},685:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>r,toc:()=>m});var o=i(7462),n=(i(7294),i(3905));const a={},s="Runtime Host Protocol",r={unversionedId:"core/runtime/runtime-host-protocol",id:"core/runtime/runtime-host-protocol",title:"Runtime Host Protocol",description:"The Runtime Host Protocol (RHP) is a simple RPC protocol which is used to",source:"@site/docs/core/runtime/runtime-host-protocol.md",sourceDirName:"core/runtime",slug:"/core/runtime/runtime-host-protocol",permalink:"/core/runtime/runtime-host-protocol",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/runtime-host-protocol.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime Layer",permalink:"/core/runtime/"},next:{title:"Runtime IDs",permalink:"/core/runtime/identifiers"}},l={},m=[{value:"Transport",id:"transport",level:2},{value:"Framing",id:"framing",level:2},{value:"Messages",id:"messages",level:2},{value:"Operation",id:"operation",level:2},{value:"Initialization",id:"initialization",level:3},{value:"Remote Attestation",id:"remote-attestation",level:3},{value:"Host-to-runtime",id:"host-to-runtime",level:3},{value:"Transaction Batch Dispatch",id:"transaction-batch-dispatch",level:4},{value:"EnclaveRPC",id:"enclaverpc",level:4},{value:"Key Manager Policy Update",id:"key-manager-policy-update",level:4},{value:"Abort",id:"abort",level:4},{value:"Extensions",id:"extensions",level:4},{value:"Runtime-to-host",id:"runtime-to-host",level:3},{value:"EnclaveRPC to Remote Endpoints",id:"enclaverpc-to-remote-endpoints",level:4},{value:"Read-only Runtime Storage Access",id:"read-only-runtime-storage-access",level:4},{value:"Untrusted Local Storage Access",id:"untrusted-local-storage-access",level:4}],c={toc:m},p="wrapper";function d(e){let{components:t,...a}=e;return(0,n.kt)(p,(0,o.Z)({},c,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"runtime-host-protocol"},"Runtime Host Protocol"),(0,n.kt)("p",null,"The Runtime Host Protocol (RHP) is a simple RPC protocol which is used to\ncommunicate between a runtime and an Oasis Core Compute Node."),(0,n.kt)("h2",{id:"transport"},"Transport"),(0,n.kt)("p",null,"The RHP assumes a reliable byte stream oriented transport underneath. The only\ncurrent implementation uses AF_LOCAL sockets and ",(0,n.kt)("a",{parentName:"p",href:"https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#streams"},"Fortanix ABI streams")," backed\nby shared memory to communicate with runtimes inside Intel SGX enclaves."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Runtime Execution",src:i(5819).Z,width:"381",height:"161"})),(0,n.kt)("h2",{id:"framing"},"Framing"),(0,n.kt)("p",null,"All RHP messages use simple length-value framing with the value being encoded\nusing ",(0,n.kt)("a",{parentName:"p",href:"/core/encoding"},"canonical CBOR"),". The frames are serialized on the wire as follows:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre"},"[4-byte message length (big endian)] [CBOR-serialized message]\n")),(0,n.kt)("p",null,"Maximum allowed message size is 16 MiB."),(0,n.kt)("h2",{id:"messages"},"Messages"),(0,n.kt)("p",null,"Each ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Message"},"message")," can be either a request or a response as specified by the type\nfield. Each request is assigned a unique 64-bit sequence number by the caller to\nmake it possible to correlate responses."),(0,n.kt)("p",null,"See the API reference (",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body"},"Go"),", ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime/src/types.rs"},"Rust"),") for a list of all supported message bodies.\nIn case the request resulted in an error, the special ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Error"},(0,n.kt)("inlineCode",{parentName:"a"},"Error"))," response body\nmust be used."),(0,n.kt)("h2",{id:"operation"},"Operation"),(0,n.kt)("p",null,"RHP allows two forms of communication:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("strong",{parentName:"p"},"Host-to-runtime")," where the host (compute node) submits requests to the\nruntime to handle and the runtime provides responses. All such request\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body"},"messages")," are prefixed with ",(0,n.kt)("inlineCode",{parentName:"p"},"Runtime"),".")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("strong",{parentName:"p"},"Runtime-to-host")," where the runtime submits requests to the host and the\nhost provides responses. All such request ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body"},"messages")," are prefixed with\n",(0,n.kt)("inlineCode",{parentName:"p"},"Host"),"."))),(0,n.kt)("p",null,"In its lifetime, from connection establishment to its termination, the RHP\nconnection goes through the following states:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"Uninitialized")," is the default state of a newly created connection. In this\nstate the connection could be used either on the runtime side or the host\nside. To proceed to the next state, the connection must be initialized either\nas a runtime or as a host. The ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime"},"Rust implementation")," only supports runtime\nmode while the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol"},"Go implementation")," can be initialized in either mode by using\neither ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Connection"},(0,n.kt)("inlineCode",{parentName:"a"},"InitHost")," or ",(0,n.kt)("inlineCode",{parentName:"a"},"InitGuest")),".")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"Initializing")," is the state when the connection is being initialized (see\nbelow for details). After a connection has been successfully initialized it\nwill transition into ",(0,n.kt)("em",{parentName:"p"},"ready")," state. If the initialization failed, it will\ninstead transition into ",(0,n.kt)("em",{parentName:"p"},"closed")," state.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"Ready")," is the state when the connection can be used to exchange messages in\neither direction.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"Closed")," is the state of the connection after it is considered closed. No\nmessages may be exchanged at this point."))),(0,n.kt)("p",null,"If either the runtime or the host generates an invalid message, either end may\nterminate the connection (and/or the runtime process)."),(0,n.kt)("h3",{id:"initialization"},"Initialization"),(0,n.kt)("p",null,"Before a connection can be used, it must be initialized as either representing\nthe runtime end or the host (compute node) end. The ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime"},"Rust implementation")," only\nsupports being initialized as the runtime and the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol"},"Go implementation")," is\ncurrently only used as the host. If one uses the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime"},(0,n.kt)("inlineCode",{parentName:"a"},"oasis-core-runtime")," crate"),"\nto build a runtime, initialization is handled automatically."),(0,n.kt)("p",null,"The initialization procedure is driven by the host and it proceeds as follows:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The host sends ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeInfoRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeInfoRequest"))," providing the runtime with its\n",(0,n.kt)("a",{parentName:"p",href:"/core/runtime/identifiers"},"designated identifier"),". The identifier comes from the ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#runtimes"},"registry service")," in\nthe consensus layer.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The runtime must reply with a ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeInfoResponse"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeInfoResponse"))," specifying its own\nversion and the version of the runtime host protocol that it supports. If the\nprotocol version is incompatible, initialization fails."))),(0,n.kt)("p",null,"After the initialization procedure, the connection can be used for other\nmessages. In case the runtime is running in a trusted execution environment\n(TEE) like Intel SGX, the next required step is to perform remote attestation."),(0,n.kt)("h3",{id:"remote-attestation"},"Remote Attestation"),(0,n.kt)("p",null,"When a runtime is executed in a TEE, it must perform remote attestation\nimmediately after initialization. The ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime"},"Rust implementation")," also requires that\nremote attestation is periodically renewed and will start rejecting requests\notherwise. In case a runtime is not executed in a TEE, this step is skipped."),(0,n.kt)("p",null,(0,n.kt)("em",{parentName:"p"},"NOTE: As currently Intel SGX is the only supported TEE, the elements of the\nremote attestation protocol are in some parts very specific to Intel SGX. This\nmay change in the future when support for additional TEEs is added.")),(0,n.kt)("p",null,"Upon initialization the host performs the following steps:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"[Intel SGX]")," The host obtains information for the runtime to be able to\ngenerate an attestation report. This includes talking to the AESM service and\nthe IAS configuration. The information includes the identity of the Quoting\nEnclave.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The host sends ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakInitRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeCapabilityTEERakInitRequest"))," passing the information\nrequired for the runtime to initialize its own ephemeral Runtime Attestation\nKey (RAK). The RAK is valid for as long as the runtime is running."))),(0,n.kt)("p",null,"The initialization then proceeds as follows, with the following steps also\nbeing performed as part of periodic re-attestation:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The host sends ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakReportRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeCapabilityTEERakReportRequest"))," requesting the runtime\nto generate an attestation report.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The runtime prepares an attestation report based on the information provided\nduring the first initialization step. It responds with\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakReportResponse"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeCapabilityTEERakReportResponse"))," containing the public part of the\nRAK, the attestation report (binding RAK to the TEE identity) and a replay\nprotection nonce.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"[Intel SGX]")," The host proceeds to submit the attestation report to the\nQuoting Enclave to receive a quote. It submits the received quote to the\nIntel Attestation Service (IAS) to receive a signed Attestation Verification\nReport (AVR). It submits the AVR to the runtime by sending a\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakAvrRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeCapabilityTEERakAvrRequest")),".")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("em",{parentName:"p"},"[Intel SGX]")," The runtime verifies the validity of the AVR, making sure that\nit is not a replay and that it in fact contains the correct enclave identity\nand the RAK binding.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Upon successful verification the runtime is now ready to accept requests. As\nmentioned the attestation procedure must be performed periodically by the host\nas otherwise the runtime may start rejecting requests."))),(0,n.kt)("p",null,"The compute node will submit remote attestation information to the consensus\n",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#runtimes"},"registry service")," as part of its ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node"},"node registration descriptor"),". The registry\nservice will verify that the submitted AVR is in fact valid and corresponds to\nthe registered runtime enclave identity. It will reject node registrations\notherwise."),(0,n.kt)("h3",{id:"host-to-runtime"},"Host-to-runtime"),(0,n.kt)("p",null,"The following section describes the calls that a host can make to request\nprocessing from the runtime after successfully performing initialization (and\ninitial remote attestation if running in a TEE)."),(0,n.kt)("h4",{id:"transaction-batch-dispatch"},"Transaction Batch Dispatch"),(0,n.kt)("p",null,"When a compute node needs to verify whether individual transactions are valid\nit can optionally request the runtime to perform a simplified transaction check.\nIt can do this by sending a ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCheckTxBatchRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeCheckTxBatchRequest"))," message. The runtime\nshould perform the required non-expensive checks, but should not fully execute\nthe transactions."),(0,n.kt)("p",null,"When a compute node receives a batch of transactions to process from the\ntransaction scheduler executor, it passes the batch to the runtime via the\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeExecuteTxBatchRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeExecuteTxBatchRequest"))," message. The runtime must execute the\ntransactions in the given batch and produce a set of state changes (storage\nupdates for the output and state roots). In case the runtime is running in a TEE\nthe execution results must be signed by the Runtime Attestation Key (see above)."),(0,n.kt)("h4",{id:"enclaverpc"},"EnclaveRPC"),(0,n.kt)("h4",{id:"key-manager-policy-update"},"Key Manager Policy Update"),(0,n.kt)("h4",{id:"abort"},"Abort"),(0,n.kt)("p",null,"The host can request the runtime to abort processing the current batch by\nsending the ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeAbortRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeAbortRequest"))," message. The request does not take any\narguments. In case the response does not indicate an error the abort is deemed\nsuccessful by the host."),(0,n.kt)("p",null,"In case the runtime does not reply quickly enough the host may terminate the\nruntime and start a new instance."),(0,n.kt)("h4",{id:"extensions"},"Extensions"),(0,n.kt)("p",null,"RHP provides a way for runtimes to support custom protocol extensions by\nutilizing the ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeLocalRPCCallRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeLocalRPCCallRequest"))," and ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeLocalRPCCallResponse"},(0,n.kt)("inlineCode",{parentName:"a"},"RuntimeLocalRPCCallResponse")),"\nmessages."),(0,n.kt)("h3",{id:"runtime-to-host"},"Runtime-to-host"),(0,n.kt)("p",null,"The following section describes the calls that a runtime can make to request\nprocessing from the host (or the wider distributed network on host's behalf)."),(0,n.kt)("h4",{id:"enclaverpc-to-remote-endpoints"},"EnclaveRPC to Remote Endpoints"),(0,n.kt)("h4",{id:"read-only-runtime-storage-access"},"Read-only Runtime Storage Access"),(0,n.kt)("p",null,"The host exposes the ",(0,n.kt)("a",{parentName:"p",href:"/core/mkvs#read-syncer"},"MKVS read syncer")," interface (via the\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostStorageSyncRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"HostStorageSyncRequest"))," message) to enable runtimes read-only access to\nglobal runtime storage."),(0,n.kt)("h4",{id:"untrusted-local-storage-access"},"Untrusted Local Storage Access"),(0,n.kt)("p",null,"The host exposes a simple key-value local store that can be used by the runtime\nto store arbitrary instance-specific data. ",(0,n.kt)("strong",{parentName:"p"},"Note that if the runtime is running\nin a TEE this store must be treated as UNTRUSTED as the host may perform\narbitrary attacks. The runtime should use TEE-specific sealing to ensure\nintegrity and confidentiality of any stored data.")),(0,n.kt)("p",null,"There are two local storage operations, namely get and set, exposed via\n",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostLocalStorageGetRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"HostLocalStorageGetRequest"))," and ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostLocalStorageSetRequest"},(0,n.kt)("inlineCode",{parentName:"a"},"HostLocalStorageSetRequest"))," messages,\nrespectively."))}d.isMDXComponent=!0},5819:(e,t,i)=>{i.d(t,{Z:()=>o});const o="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIzODFweCIgaGVpZ2h0PSIxNjFweCIgdmlld0JveD0iLTAuNSAtMC41IDM4MSAxNjEiIGNvbnRlbnQ9IiZsdDtteGZpbGUgaG9zdD0mcXVvdDthcHAuZGlhZ3JhbXMubmV0JnF1b3Q7IG1vZGlmaWVkPSZxdW90OzIwMjAtMDctMjBUMjI6MDM6NTIuNjAzWiZxdW90OyBhZ2VudD0mcXVvdDs1LjAgKE1hY2ludG9zaDsgSW50ZWwgTWFjIE9TIFggMTBfMTRfNikgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzg0LjAuNDE0Ny44OSBTYWZhcmkvNTM3LjM2JnF1b3Q7IGV0YWc9JnF1b3Q7anZjbC1DYkd2THY0c3JRQmhkRjcmcXVvdDsgdmVyc2lvbj0mcXVvdDsxMy40LjkmcXVvdDsgdHlwZT0mcXVvdDtkZXZpY2UmcXVvdDsmZ3Q7Jmx0O2RpYWdyYW0gaWQ9JnF1b3Q7REpYWk9tNWJmMmRqOFNFSVE4Sl8mcXVvdDsgbmFtZT0mcXVvdDtQYWdlLTEmcXVvdDsmZ3Q7N1pmTGNwc3dGSWFmeGpQdEloMHU1dEpsZkVuU1R0cVoxcDFwMHAyTURxQkVTSzRRQWZmcEs5bkNnQ0ZPTWdsZGRXTnpmdDIvLzNCc1RkeDVWbDBLdEVtL2NBeDA0bGk0bXJpTGllUFlkdWlyTDYxczkwb1F1SHNoRVFTYlRvMndJbi9BaUpaUkM0SWg3M1NVbkZOSk5sMHg0b3hCSkRzYUVvS1gzVzR4cDkxVk55aUJuckNLRU8yclB3bVc2VjROUGF2UnI0QWthYjJ5YlptV0ROV2RqWkNuQ1BPeUpibkxpVHNYbk12OVUxYk5nV3A0TlpmOXVJdEhXZzhiRThEa2N3YUVpK25zbnBibDR0ZnRqODkwL3UyT2lPVE16UEtBYUdFTy9GVlpPSEY4cXVhY3JZWGV0OXdhR1A3dlFtOTJGbk1tei9LZFZlZXFnKzFzcXFaUlBTWDYrOTMzZ2ttU3FibXNLNTdMOXdiQ1lUSkg4SUpoMEp1elZmY3lKUkpXR3hUcDFsTGxrdEpTbVZIVHJKYzB5V0U3T2lhVXpqbmxZamVYRzhleEUwVkt6NlhnOTlCcXdmN2E5L3pkdm81eDFXY0hJYUZxU1FiZkpmQU1wTmlxTHFiVk5VNmFWTFlkYngrWFRXTFl0ZHRwS3lsOG95R1RpOGxoNXNZdTlXQWNlNEY3VHMrOUU1U3QxMU1PSXhpbXZBNjlxYWNYd0NoUEQ1NitBWExINmpLdlViYVFIMHBGRzdrOUhZdTUyMk8rUWd5dmVkVkRyNDRvdTN5NzNCaG5jQVRaU0lpU2hLa3dVdUJBNlRNTmpLaWlkRzRhTW9LeFhtYlEwSzdsSFVkNkJ1dlk3SGlnb0x6YXJ1a3o3WExHY212YWM2c3BTOWNjWVVWMzFEZm1uOVNsQTlMNk43WlAzZjQ0UU4wZGk3bzNjbDNxNW5RWE9kallnMkFJK1VjL2NORkl5QTkxL3lubXdWak0vUjd6VDZwNDZHR3J5eHYxdVdRUlJRL3d2MG9ObUdjOTA3elJ5bFJ3b2t6TkNFTm1pYkhLRkVZUXhvTmx5bzlDV01kdjlNNDRSOWpkQWV6QkFIWnZMT3hoanlwZzllL2ZoRnpJbENlY0licHMxS084YmZwY2M3NHh0TzlBeXEzQmpRckp1MTVBUmVSTjYvbFdUL1hCTTlHaU1qUHZnbTBkTUhYY20zYlFHcVhEWnRndXFzY2QrNTVMSk9TNXZoYnA5NWFpUENkUkxWOFFXbS94VWJOelhvZ0lUaEN0cjJoSUpDQ2ZUbmlOKzJUcUNLQklrb2Z1WmV3RmVhREM1b2ExYTJ2ZFU5M2xYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjAiIHk9Ijg1IiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjYwIiByeD0iOSIgcnk9IjkiIGZpbGw9IiNmZmYyY2MiIHN0cm9rZT0iI2Q2YjY1NiIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMThweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTVweDsgbWFyZ2luLWxlZnQ6IDFweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+Tm9kZTxiciBzdHlsZT0iZm9udC1zaXplOiAxMnB4IiAvPihSdW50aW1lIEhvc3QpPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYwIiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+Tm9kZS4uLjwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTcwIiB5PSIyMCIgd2lkdGg9IjIxMCIgaGVpZ2h0PSIxNDAiIGZpbGw9IiNmOGNlY2MiIHN0cm9rZT0iI2I4NTQ1MCIgc3Ryb2tlLWRhc2hhcnJheT0iMyAzIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PHJlY3QgeD0iMTcwIiB5PSIwIiB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMjA4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTBweDsgbWFyZ2luLWxlZnQ6IDE3MXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+U2FuZGJveDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9IjE0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSJib2xkIj5TYW5kYm94PC90ZXh0Pjwvc3dpdGNoPjwvZz48cmVjdCB4PSIxODAiIHk9IjMwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZmZmMmNjIiBzdHJva2U9IiNkNmI2NTYiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMTg4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNDVweDsgbWFyZ2luLWxlZnQ6IDE4MXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5SdW50aW1lIExvYWRlcjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9IjQ5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlJ1bnRpbWUgTG9hZGVyPC90ZXh0Pjwvc3dpdGNoPjwvZz48cmVjdCB4PSIxODAiIHk9IjgwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjcwIiBmaWxsPSIjZTFkNWU3IiBzdHJva2U9IiM5NjczYTYiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMyIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxyZWN0IHg9IjE4MCIgeT0iNjAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxODhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA3MHB4OyBtYXJnaW4tbGVmdDogMTgxcHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGNlbnRlcjsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5JbnRlbCBTR1ggRW5jbGF2ZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9Ijc0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSJib2xkIj5JbnRlbCBTR1ggRW5jbGF2ZTwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTkwIiB5PSI5MCIgd2lkdGg9IjE3MCIgaGVpZ2h0PSI1MCIgZmlsbD0iI2RhZThmYyIgc3Ryb2tlPSIjNmM4ZWJmIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDE2OHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDExNXB4OyBtYXJnaW4tbGVmdDogMTkxcHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGNlbnRlcjsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPlJ1bnRpbWUgQmluYXJ5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjI3NSIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlJ1bnRpbWUgQmluYXJ5PC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDEyNi4zNyAxMTUgTCAxODMuNjMgMTE1IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxwYXRoIGQ9Ik0gMTIxLjEyIDExNSBMIDEyOC4xMiAxMTEuNSBMIDEyNi4zNyAxMTUgTCAxMjguMTIgMTE4LjUgWiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cGF0aCBkPSJNIDE4OC44OCAxMTUgTCAxODEuODggMTE4LjUgTCAxODMuNjMgMTE1IEwgMTgxLjg4IDExMS41IFoiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vZGVzay5kcmF3LmlvL3N1cHBvcnQvc29sdXRpb25zL2FydGljbGVzLzE2MDAwMDQyNDg3IiB0YXJnZXQ9Il9ibGFuayI+PHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMHB4IiB4PSI1MCUiIHk9IjEwMCUiPlZpZXdlciBkb2VzIG5vdCBzdXBwb3J0IGZ1bGwgU1ZHIDEuMTwvdGV4dD48L2E+PC9zd2l0Y2g+PC9zdmc+"}}]); \ No newline at end of file diff --git a/assets/js/30beaf32.657b4b9c.js b/assets/js/30beaf32.657b4b9c.js new file mode 100644 index 0000000000..295f80dcc8 --- /dev/null +++ b/assets/js/30beaf32.657b4b9c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6784],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>f});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},c="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),c=p(n),u=r,f=c["".concat(l,".").concat(u)]||c[u]||h[u]||o;return n?a.createElement(f,i(i({ref:t},d),{},{components:n})):a.createElement(f,i({ref:t},d))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:r,i[1]=s;for(var p=2;p<o;p++)i[p]=n[p];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}u.displayName="MDXCreateElement"},1564:(e,t,n)=>{n.d(t,{Z:()=>f});var a=n(7294),r=n(6010),o=n(9960),i=n(3438),s=n(3919),l=n(5999);const p={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:n}=e;return a.createElement(o.Z,{href:t,className:(0,r.Z)("card padding--lg",p.cardContainer)},n)}function c(e){let{href:t,icon:n,title:o,description:i}=e;return a.createElement(d,{href:t},a.createElement("h2",{className:(0,r.Z)("text--truncate",p.cardTitle),title:o},n," ",o),i&&a.createElement("p",{className:(0,r.Z)("text--truncate",p.cardDescription),title:i},i))}function h(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?a.createElement(c,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return a.createElement(c,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(u,{item:t});case"category":return a.createElement(h,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var a=n(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function o(e){const t=(0,a.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},6795:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>f,frontMatter:()=>s,metadata:()=>p,toc:()=>c});var a=n(7462),r=(n(7294),n(3905)),o=n(1564),i=n(7525);const s={},l="Quickstart",p={unversionedId:"dapp/sapphire/quickstart",id:"dapp/sapphire/quickstart",title:"Quickstart",description:"In this tutorial, you'll port an Eth project in under 10 minutes, and then go on",source:"@site/docs/dapp/sapphire/quickstart.mdx",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/quickstart",permalink:"/dapp/sapphire/quickstart",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/quickstart.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Sapphire ParaTime",permalink:"/dapp/sapphire/"},next:{title:"Guide",permalink:"/dapp/sapphire/guide"}},d={},c=[{value:"Port an Eth project",id:"port-an-eth-project",level:2},{value:"Setup",id:"setup",level:3},{value:"Deploy to Emerald (non-confidential EVM)",id:"deploy-to-emerald-non-confidential-evm",level:3},{value:"Get some Emerald Testnet tokens",id:"get-some-emerald-testnet-tokens",level:4},{value:"Add the Emerald Testnet to Truffle",id:"add-the-emerald-testnet-to-truffle",level:4},{value:"Do the Truffle Thing",id:"do-the-truffle-thing",level:4},{value:"Deploy to Sapphire (confidential EVM)",id:"deploy-to-sapphire-confidential-evm",level:3},{value:"Get some Sapphire Testnet tokens",id:"get-some-sapphire-testnet-tokens",level:4},{value:"Add the Sapphire Testnet to Truffle",id:"add-the-sapphire-testnet-to-truffle",level:4},{value:"Port to Sapphire",id:"port-to-sapphire",level:4},{value:"Create a Sapphire-Native dApp",id:"create-a-sapphire-native-dapp",level:2},{value:"Init a new Hardhat project",id:"init-a-new-hardhat-project",level:3},{value:"Add the Sapphire Testnet to Hardhat",id:"add-the-sapphire-testnet-to-hardhat",level:3},{value:"Get the Contract",id:"get-the-contract",level:3},{value:"Vigil.sol, the interesting parts",id:"vigilsol-the-interesting-parts",level:4},{value:"Run the Contract",id:"run-the-contract",level:3},{value:"All done!",id:"all-done",level:2},{value:"See also",id:"see-also",level:2}],h={toc:c},u="wrapper";function f(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"quickstart"},"Quickstart"),(0,r.kt)("p",{style:{width:"100%"}},(0,r.kt)("iframe",{style:{margin:"auto",display:"block"},width:"560",height:"315",src:"https://www.youtube-nocookie.com/embed/ePp1fFSmKgI",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})),(0,r.kt)("p",null,"In this tutorial, you'll port an Eth project in under 10 minutes, and then go on\nto deploy a unique dApp that requires confidentiality to work.\nBy the end of the tutorial, you should feel comfortable setting up your Eth\ndevelopment environment to target Sapphire, and know how and when to use\nconfidentiality."),(0,r.kt)("p",null,"The expected completion time of this tutorial is 30 minutes."),(0,r.kt)("h2",{id:"port-an-eth-project"},"Port an Eth project"),(0,r.kt)("h3",{id:"setup"},"Setup"),(0,r.kt)("p",null,"Start by installing ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/trufflesuite/truffle#install"},"Truffle"),"."),(0,r.kt)("p",null,"Then, run these commands in your terminal:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'mkdir MetaCoin && cd MetaCoin\ntruffle unbox MetaCoin\ngit init\ngit add :/ && git commit -m "Initial commit"\npnpm init && pnpm add -D @truffle/hdwallet-provider\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"This tutorial uses ",(0,r.kt)("a",{parentName:"p",href:"https://pnpm.io/installation"},"pnpm"),", an efficient Node\npackage manager. You can just as easily use ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"yarn")," by replacing\n",(0,r.kt)("inlineCode",{parentName:"p"},"pnpm")," with either of those.")),(0,r.kt)("h3",{id:"deploy-to-emerald-non-confidential-evm"},"Deploy to Emerald (non-confidential EVM)"),(0,r.kt)("h4",{id:"get-some-emerald-testnet-tokens"},"Get some Emerald Testnet tokens"),(0,r.kt)("p",null,"In order to deploy to the Emerald Testnet, we'll need some tokens.\nGet those by heading to ",(0,r.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev/"},"Oasis Testnet faucet"),' and selecting "Emerald" as\nthe first dropdown.\nSet the second box to the address of a burner wallet.\nIt\'ll take a few moments to receive your tokens after submitting the form.'),(0,r.kt)("h4",{id:"add-the-emerald-testnet-to-truffle"},"Add the Emerald Testnet to Truffle"),(0,r.kt)("p",null,"Apply this patch to ",(0,r.kt)("inlineCode",{parentName:"p"},"truffle-config.js"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-diff"},'diff --git a/truffle-config.js b/truffle-config.js\nindex 68d534c..15c671d 100644\n--- a/truffle-config.js\n+++ b/truffle-config.js\n@@ -22,7 +22,7 @@\n // const mnemonic = process.env["MNEMONIC"];\n // const infuraProjectId = process.env["INFURA_PROJECT_ID"];\n\n-// const HDWalletProvider = require(\'@truffle/hdwallet-provider\');\n+const HDWalletProvider = require(\'@truffle/hdwallet-provider\');\n\n module.exports = {\n /**\n@@ -53,6 +53,14 @@ module.exports = {\n // network_id: 5, // Goerli\'s id\n // chain_id: 5\n // }\n+ // This is Testnet! If you want Mainnet, add a new network config item.\n+ emerald_testnet: {\n+ provider: () =>\n+ new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.emerald.oasis.dev"),\n+ network_id: 0xa515,\n+ },\n },\n\n // Set default mocha options here, use special reporters etc.\n')),(0,r.kt)("h4",{id:"do-the-truffle-thing"},"Do the Truffle Thing"),(0,r.kt)("p",null,"You'll want a script to run some methods on the contract.\nPop open your favorite editor and paste in this code:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript"},'const keccak256 = require("web3").utils.keccak256;\n\nconst MetaCoin = artifacts.require("MetaCoin");\n\nasync function exerciseContract() {\n const mc = await MetaCoin.deployed();\n\n const tx = await mc.sendCoin(mc.address, 42);\n console.log(`\\nSent some coins in ${tx.tx}.`);\n const t = tx.logs[0].args;\n console.log(`A Transfer(${t[0]}, ${t[0]}, ${t[2].toNumber()}) was emitted.`);\n\n const storageSlot = await new Promise((resolve, reject) => {\n const getStoragePayload = {\n method: "eth_getStorageAt",\n params: [\n mc.address,\n keccak256(\n "0x" + "00".repeat(12) + mc.address.slice(2) + "00".repeat(32)\n ),\n "latest",\n ],\n jsonrpc: "2.0",\n id: "test",\n };\n mc.contract.currentProvider.send(getStoragePayload, (err, res) => {\n if (err) reject(err);\n else resolve(res.result);\n });\n });\n console.log(`The balance storage slot contains ${storageSlot}.`);\n\n const balance = await mc.getBalance(mc.address);\n console.log(`The contract now has balance: ${balance.toNumber()}.`);\n}\n\nmodule.exports = async function (callback) {\n try {\n await exerciseContract();\n } catch (e) {\n console.error(e);\n }\n callback();\n};\n')),(0,r.kt)("p",null,"Save it to ",(0,r.kt)("inlineCode",{parentName:"p"},"scripts/exercise.contract.js"),".\nWe'll use it in just a bit."),(0,r.kt)("p",null,"Next, you can run the following and see the contract being deployed."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'PRIVATE_KEY="0x..." truffle migrate --network emerald_testnet\n')),(0,r.kt)("p",null,"Everything should be succeeding so far."),(0,r.kt)("p",null,"Finally, run this line and observe some output."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'> PRIVATE_KEY="0x..." truffle exec --network emerald_testnet scripts/exercise.contract.js`\n\nSent some coins in 0xf415ab586ef1c6c61b84b3bd803ae322f375d1d3164aa8ac13c9ae83c698a002\nA Transfer(0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 42) was emitted.\nThe balance storage slot contains 0x2a.\nThe contract now has balance: 42\n')),(0,r.kt)("p",null,"Great!\nThat'll be the baseline for our confidential deployment."),(0,r.kt)("h3",{id:"deploy-to-sapphire-confidential-evm"},"Deploy to Sapphire (confidential EVM)"),(0,r.kt)("h4",{id:"get-some-sapphire-testnet-tokens"},"Get some Sapphire Testnet tokens"),(0,r.kt)("p",null,"Now for the fun part.\nAs for Emerald, we need to configure the Sapphire network and get some tokens.\nHit up the one and only ",(0,r.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev/"},"Oasis Testnet faucet"),' and this time select "Sapphire".\nSubmit the form and on your way.'),(0,r.kt)("h4",{id:"add-the-sapphire-testnet-to-truffle"},"Add the Sapphire Testnet to Truffle"),(0,r.kt)("p",null,"And another diff for your applying pleasure:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-diff"},'diff --git a/truffle-config.js b/truffle-config.js\nindex 7af2f42..0cd9d36 100644\n--- a/truffle-config.js\n+++ b/truffle-config.js\n@@ -58,6 +58,11 @@ module.exports = {\n new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.emerald.oasis.dev"),\n network_id: 0xa515,\n },\n+ // This is Testnet! If you want Mainnet, add a new network config item.\n+ sapphire_testnet: {\n+ provider: () =>\n+ new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev"),\n+ network_id: 0x5aff,\n+ },\n },\n\n // Set default mocha options here, use special reporters etc.\n')),(0,r.kt)("h4",{id:"port-to-sapphire"},"Port to Sapphire"),(0,r.kt)("p",null,"Here's where things start to get interesting.\nWe're going to add confidentiality to this starter project in exactly two lines\nof code."),(0,r.kt)("p",null,"You'll need to grab the Sapphire compatibility library\n(",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime"},(0,r.kt)("inlineCode",{parentName:"a"},"@oasisprotocol/sapphire-paratime")),"), so make that happen by issuing"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm add -D @oasisprotocol/sapphire-paratime # npm also works\n")),(0,r.kt)("p",null,"So far so good.\nNext, import it by adding this line to the top of ",(0,r.kt)("inlineCode",{parentName:"p"},"truffle-config.js"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript"},"const sapphire = require('@oasisprotocol/sapphire-paratime');\n")),(0,r.kt)("p",null,"That's the first line of code.\nHere's the second:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-diff"},'diff --git a/truffle-config.js b/truffle-config.js\nindex 0cd9d36..7db7cf8 100644\n--- a/truffle-config.js\n+++ b/truffle-config.js\n@@ -60,7 +60,7 @@ module.exports = {\n },\n sapphire_testnet: {\n provider: () =>\n- new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev"),\n+ sapphire.wrap(new HDWalletProvider([process.env.PRIVATE_KEY], "https://testnet.sapphire.oasis.dev")),\n network_id: 0x5aff,\n },\n },\n')),(0,r.kt)("p",null,"This ",(0,r.kt)("inlineCode",{parentName:"p"},"wrap")," function takes any kind of provider or signer you've got and turn\nit into one that works with Sapphire and confidentiality.\nFor the most part, wrapping your signer/provider is the most you'll need to do\nto get your dApp running on Sapphire, but that's not a complete story since an\nunmodified contract may leak state through normal operation."),(0,r.kt)("p",null,"And now for the moment we've all been waiting for:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'> PRIVATE_KEY="0x..." truffle migrate --network sapphire_testnet\n> PRIVATE_KEY="0x..." truffle exec --network sapphire_testnet scripts/exercise.contract.js\n\nSent some coins in 0x6dc6774addf4c5c68a9b2c6b5e5634263e734d321f84012ab1b4cbe237fbe7c2.\nA Transfer(0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 0x56e5F834F88F9f7631E9d6a43254e173478cE06a, 42) was emitted.\nThe balance storage slot contains 0x0.\nThe contract now has balance: 42.\n')),(0,r.kt)("p",null,"So basically nothing changed, which is pretty much what we're going for.\nBut take a look at that second to last line where it says what's in the storage\nslot. Before, it said ",(0,r.kt)("inlineCode",{parentName:"p"},"0x2a"),", but now it says ",(0,r.kt)("inlineCode",{parentName:"p"},"0x0"),"."),(0,r.kt)("p",null,"Clearly the slot does contain data or else the contract balance couldn't have\nbeen returned.\nWhat's happened here is that the Web3 gateway does not have the key used to\ndecrypt the storage slot, so a default value is returned."),(0,r.kt)("p",null,"Indeed, the gateway does not even have the key needed to decrypt the ",(0,r.kt)("em",{parentName:"p"},"key")," in\nthe MKVS; it can tell ",(0,r.kt)("em",{parentName:"p"},"that")," a storage slot was written, but not which one\n(although it can make a very good guess by reading the contract code)."),(0,r.kt)("p",null,"All in all, you can see that confidentiality is in effect, but it's not\nsomething end-users need to think too much about."),(0,r.kt)("h2",{id:"create-a-sapphire-native-dapp"},"Create a Sapphire-Native dApp"),(0,r.kt)("p",null,"Porting an existing Eth app is cool, and can already provide benefits like\nprotecting against MEV.\nHowever, starting from scratch with confidentiality in mind can unlock some\nreally novel dApps and provide a ",(0,r.kt)("a",{parentName:"p",href:"/dapp/sapphire/guide#writing-secure-dapps"},"higher level of security"),"."),(0,r.kt)("p",null,"One simple-but-useful dApp that takes advantage of confidentiality is a\n",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Dead_man's_switch"},"dead person's switch")," that reveals a secret (let's say the encryption key to a\ndata trove) if the operator fails to re-up before too long.\nLet's make it happen!"),(0,r.kt)("h3",{id:"init-a-new-hardhat-project"},"Init a new Hardhat project"),(0,r.kt)("p",null,"We're going to use Hardhat this time because it's very convenient to use."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Make & enter a new directory")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"npx hardhat@~2.12.0")," then create a TypeScript project.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Add ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-hardhat"},(0,r.kt)("inlineCode",{parentName:"a"},"@oasisprotocol/sapphire-hardhat"))," as dependency:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm add -D @oasisprotocol/sapphire-hardhat\n"))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Install ",(0,r.kt)("inlineCode",{parentName:"p"},"@nomicfoundation/hardhat-toolbox"),", TypeScript and other peer\ndependencies required by HardHat."))),(0,r.kt)("h3",{id:"add-the-sapphire-testnet-to-hardhat"},"Add the Sapphire Testnet to Hardhat"),(0,r.kt)("p",null,"Open up your ",(0,r.kt)("inlineCode",{parentName:"p"},"hardhat.config.ts")," and drop in these lines.\nThey should remind you a lot about what happened with Truffle."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-diff"},'diff --git a/hardhat.config.ts b/hardhat.config.ts\nindex 414e974..49c95f9 100644\n--- a/hardhat.config.ts\n+++ b/hardhat.config.ts\n@@ -1,8 +1,19 @@\n import { HardhatUserConfig } from "hardhat/config";\n+import \'@oasisprotocol/sapphire-hardhat\';\n import "@nomicfoundation/hardhat-toolbox";\n\n const config: HardhatUserConfig = {\n solidity: "0.8.17",\n+ networks: {\n+ sapphire_testnet: {\n+ // This is Testnet! If you want Mainnet, add a new network config item.\n+ url: "https://testnet.sapphire.oasis.dev",\n+ accounts: process.env.PRIVATE_KEY\n+ ? [process.env.PRIVATE_KEY]\n+ : [],\n+ chainId: 0x5aff,\n+ },\n+ },\n };\n\n export default config;\n')),(0,r.kt)("p",null,"By importing ",(0,r.kt)("inlineCode",{parentName:"p"},"@oasisprotocol/sapphire-hardhat")," at the top of the config file,\nany network config entry corresponding to the Sapphire's chain ID will\nautomatically be wrapped with Sapphire specifics for encrypting and signing the\ntransactions."),(0,r.kt)("h3",{id:"get-the-contract"},"Get the Contract"),(0,r.kt)("p",null,"This is a Sapphire tutorial and you're already a Solidity expert, so let's not\nbore you with explaining the gritty details of the contract.\nStart by pasting ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/examples/hardhat/contracts/Vigil.sol"},"Vigil.sol")," into ",(0,r.kt)("inlineCode",{parentName:"p"},"contracts/Vigil.sol"),"."),(0,r.kt)("p",null,"While you're there, also place ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/examples/hardhat/scripts/run-vigil.ts"},"run-vigil.ts")," into ",(0,r.kt)("inlineCode",{parentName:"p"},"scripts/run-vigil.ts"),".\nWe'll need that later."),(0,r.kt)("h4",{id:"vigilsol-the-interesting-parts"},"Vigil.sol, the interesting parts"),(0,r.kt)("p",null,"The key state variables are:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"}," SecretMetadata[] public _metas;\n bytes[] private _secrets;\n")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"_metas")," is marked with ",(0,r.kt)("inlineCode",{parentName:"li"},"public")," visibility, so despite the state itself being\nencrypted and not readable directly, Solidity will generate a getter that will\ndo the decryption for you."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"_secrets")," is ",(0,r.kt)("inlineCode",{parentName:"li"},"private")," and therefore truly secret; only the contract can\naccess the data contained in this mapping.")),(0,r.kt)("p",null,"And the methods we'll care most about are"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"createSecret"),", which adds an entry to both ",(0,r.kt)("inlineCode",{parentName:"li"},"_metas")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"_secrets"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"revealSecret"),", which acts as an access-controlled getter for the data\ncontained with ",(0,r.kt)("inlineCode",{parentName:"li"},"_secrets"),". Due to trusted execution and confidentiality, the\nonly way that the secret will get revealed is if execution proceeds all the\nway to the end of the function and does not revert.")),(0,r.kt)("p",null,"The rest of the methods are useful if you actually intended to use the contract,\nbut they demonstrate that developing for Sapphire is essentially the same as for\nEthereum.\nYou can even write tests against the Hardhat network and use Hardhat plugins."),(0,r.kt)("h3",{id:"run-the-contract"},"Run the Contract"),(0,r.kt)("p",null,"And to wrap things up, we'll put ",(0,r.kt)("inlineCode",{parentName:"p"},"Vigil")," through its paces.\nFirst, let's see what's actually going on."),(0,r.kt)("p",null,"After deploying the contract, we can create a secret, check that it's not\nreadable, wait a bit, and then check that it has become readable.\nPretty cool if you ask me!"),(0,r.kt)("p",null,"Anyway, make it happen by running"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'PRIVATE_KEY="0x..." pnpm hardhat run scripts/run-vigil.ts --network sapphire_testnet\n')),(0,r.kt)("p",null,"And if you see something like the following, you'll know you're well on the road\nto deploying confidential dApps on Sapphire."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Vigil deployed to: 0x74dC4879B152FDD1DDe834E9ba187b3e14f462f1\nStoring a secret in 0x13125d868f5fb3cbc501466df26055ea063a90014b5ccc8dfd5164dc1dd67543\nChecking the secret\nfailed to fetch secret: reverted: not expired\nWaiting...\nChecking the secret again\nThe secret ingredient is brussels sprouts\n")),(0,r.kt)("h2",{id:"all-done"},"All done!"),(0,r.kt)("p",null,"Congratulations, you made it through the Sapphire tutorial! If you have any\nquestions, please check out the ",(0,r.kt)("a",{parentName:"p",href:"/dapp/sapphire/guide"},"guide")," and join the discussion on the\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/#social-media-channels"},"#sapphire-paratime Discord channel"),"."),(0,r.kt)("p",null,"Best of luck on your future forays into confidentiality!"),(0,r.kt)("admonition",{title:"Example",type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Visit the Sapphire ParaTime repository to download the final ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/truffle"},"Truffle")," and ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/hardhat"},"Hardhat")," examples of this\nquickstart.")),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(o.Z,{item:(0,i.n)("/dapp/sapphire/browser"),mdxType:"DocCard"}),(0,r.kt)(o.Z,{item:(0,i.n)("/node/run-your-node/paratime-client-node"),mdxType:"DocCard"}),(0,r.kt)(o.Z,{item:(0,i.n)("/node/web3"),mdxType:"DocCard"}))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/32b63699.c75a7eb0.js b/assets/js/32b63699.c75a7eb0.js new file mode 100644 index 0000000000..457652cab9 --- /dev/null +++ b/assets/js/32b63699.c75a7eb0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7351],{3905:(e,a,t)=>{t.d(a,{Zo:()=>d,kt:()=>h});var n=t(7294);function r(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function o(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);a&&(n=n.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var a=1;a<arguments.length;a++){var t=null!=arguments[a]?arguments[a]:{};a%2?o(Object(t),!0).forEach((function(a){r(e,a,t[a])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(t,a))}))}return e}function l(e,a){if(null==e)return{};var t,n,r=function(e,a){if(null==e)return{};var t,n,r={},o=Object.keys(e);for(n=0;n<o.length;n++)t=o[n],a.indexOf(t)>=0||(r[t]=e[t]);return r}(e,a);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)t=o[n],a.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=n.createContext({}),p=function(e){var a=n.useContext(s),t=a;return e&&(t="function"==typeof e?e(a):i(i({},a),e)),t},d=function(e){var a=p(e.components);return n.createElement(s.Provider,{value:a},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var a=e.children;return n.createElement(n.Fragment,{},a)}},c=n.forwardRef((function(e,a){var t=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=p(t),c=r,h=u["".concat(s,".").concat(c)]||u[c]||m[c]||o;return t?n.createElement(h,i(i({ref:a},d),{},{components:t})):n.createElement(h,i({ref:a},d))}));function h(e,a){var t=arguments,r=a&&a.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=c;var l={};for(var s in a)hasOwnProperty.call(a,s)&&(l[s]=a[s]);l.originalType=e,l[u]="string"==typeof e?e:r,i[1]=l;for(var p=2;p<o;p++)i[p]=t[p];return n.createElement.apply(null,i)}return n.createElement.apply(null,t)}c.displayName="MDXCreateElement"},9110:(e,a,t)=>{t.r(a),t.d(a,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var n=t(7462),r=(t(7294),t(3905));const o={description:"Web3 gateway for Emerald and Sapphire ParaTimes"},i="Oasis Web3 Gateway for your EVM ParaTime",l={unversionedId:"node/web3",id:"node/web3",title:"Oasis Web3 Gateway for your EVM ParaTime",description:"Web3 gateway for Emerald and Sapphire ParaTimes",source:"@site/docs/node/web3.md",sourceDirName:"node",slug:"/node/web3",permalink:"/node/web3",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/web3.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Web3 gateway for Emerald and Sapphire ParaTimes"},sidebar:"operators",previous:{title:"Troubleshooting",permalink:"/node/run-your-node/troubleshooting"}},s={},p=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Hardware",id:"hardware",level:3},{value:"Oasis ParaTime Client Node",id:"oasis-paratime-client-node",level:3},{value:"PostgreSQL",id:"postgresql",level:3},{value:"Download Oasis Web3 Gateway",id:"download-oasis-web3-gateway",level:2},{value:"Running the Web3 Gateway",id:"running-the-web3-gateway",level:2},{value:"Archive Web3 Gateway",id:"archive-web3-gateway",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Wipe state to force a complete reindex",id:"wipe-state-to-force-a-complete-reindex",level:3}],d={toc:p},u="wrapper";function m(e){let{components:a,...t}=e;return(0,r.kt)(u,(0,n.Z)({},d,t,{components:a,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"oasis-web3-gateway-for-your-evm-paratime"},"Oasis Web3 Gateway for your EVM ParaTime"),(0,r.kt)("p",null,"This guide will walk you through the steps needed to set up the Oasis Web3\ngateway for EVM-compatible ParaTimes, such as ",(0,r.kt)("a",{parentName:"p",href:"/dapp/emerald/"},"Emerald")," and ",(0,r.kt)("a",{parentName:"p",href:"/dapp/sapphire/"},"Sapphire"),"."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Each ParaTime requires its own instance of the Web3 gateway!")),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("h3",{id:"hardware"},"Hardware"),(0,r.kt)("p",null,"In addition to the minimum hardware requirements for running the Oasis node,\nthe following should be added for running the Web3 gateway:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"CPU:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 2.0 GHz x86-64 CPU"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs"))),(0,r.kt)("li",{parentName:"ul"},"Memory:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 4 GB of ECC RAM"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 8 GB of ECC RAM"))),(0,r.kt)("li",{parentName:"ul"},"Storage:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 300 GB of SSD or NVMe fast storage"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 500 GB of SSD or NVMe fast storage")))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"To put the figures above into perspective, the Web3 gateway for Emerald with\nPostgreSQL encountered ",(0,r.kt)("strong",{parentName:"p"},"210 GB")," of database growth in ~5 months between\nNov 18, 2021 and Apr 11, 2022 (since the ",(0,r.kt)("a",{parentName:"p",href:"https://medium.com/oasis-protocol-project/oasis-emerald-evm-paratime-is-live-on-mainnet-13afe953a4c9"},"Emerald Mainnet launch"),").")),(0,r.kt)("h3",{id:"oasis-paratime-client-node"},"Oasis ParaTime Client Node"),(0,r.kt)("p",null,"The Web3 gateway requires a locally deployed ParaTime-enabled Oasis Node.\nFirst, follow the\n",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-client-node"},"Oasis ParaTime client node"),"\nguide on how to configure the Oasis client node with one or more ParaTimes.\nAlways use the exact combination of the Oasis node/ParaTime versions as\npublished on the network parameters page for either ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Mainnet")," or ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet"),"."),(0,r.kt)("p",null,"Apart from the transactions that happen on-chain and produce some effects,\nthere are also a number of read-only queries implemented in the Oasis protocol\nand EVM. Some of them may be quite resource-hungry such as simulating EVM calls\nand are disabled by default to avoid DDOS attacks. If your Oasis node instance\nwill only be used by you and your Web3 gateway(s), you can safely enable\n",(0,r.kt)("em",{parentName:"p"},"expensive")," transactions by adding the following to your Oasis node config:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml",metastring:"title='config.yml'",title:"'config.yml'"},'# ... sections not relevant are omitted ...\nruntime:\n mode: client\n paths:\n - {{ emerald_bundle_path }}\n - {{ sapphire_bundle_path }}\n\n config:\n "{{ emerald_paratime_id }}":\n estimate_gas_by_simulating_contracts: true\n allowed_queries:\n - all_expensive: true\n "{{ sapphire_paratime_id }}":\n estimate_gas_by_simulating_contracts: true\n allowed_queries:\n - all_expensive: true\n')),(0,r.kt)("p",null,"In the config above replace ",(0,r.kt)("inlineCode",{parentName:"p"},"{{ ... }}")," placeholders with actual ParaTime IDs:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ emerald_paratime_id }}"),":",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Emerald on ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/#emerald-paratime"},"Mainnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000e2eaa99fc008f87f")),(0,r.kt)("li",{parentName:"ul"},"Emerald on ",(0,r.kt)("a",{parentName:"li",href:"/node/testnet/#emerald-paratime"},"Testnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"00000000000000000000000000000000000000000000000072c8215e60d5bca7")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ sapphire_paratime_id }}"),":",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Sapphire on ",(0,r.kt)("a",{parentName:"li",href:"/node/testnet/#sapphire-paratime"},"Testnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c"))))),(0,r.kt)("h3",{id:"postgresql"},"PostgreSQL"),(0,r.kt)("p",null,"The Web3 gateway stores blockchain data in a\n",(0,r.kt)("a",{parentName:"p",href:"https://www.postgresql.org/"},"PostgreSQL")," database version ",(0,r.kt)("strong",{parentName:"p"},"13.3")," or higher.\nInstall it by following instructions specific to your operating system and\nenvironment."),(0,r.kt)("p",null,"Because each ParaTime requires its own instance of the Web3 gateway, you will\nhave to create a separate database and a separate user for each Web3 instance."),(0,r.kt)("h2",{id:"download-oasis-web3-gateway"},"Download Oasis Web3 Gateway"),(0,r.kt)("p",null,"Check the required version of the Web3 gateway for the network you will be\ndeploying it to: ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Mainnet"),", ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet"),". Next, download the Oasis-provided\nbinaries from the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases"},"official GitHub repository"),"."),(0,r.kt)("p",null,"Alternatively, you can download the source release and compile it yourself.\nConsult the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/blob/main/README.md#building-and-testing"},"README.md")," file for more information."),(0,r.kt)("h2",{id:"running-the-web3-gateway"},"Running the Web3 Gateway"),(0,r.kt)("p",null,"Copy the content below to the config file of your Web3 gateway."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml",metastring:"title='gateway.yml'",title:"'gateway.yml'"},'# Uncomment the runtime_id below.\nruntime_id: {{ paratime_id }}\n# Path to your internal.sock file in the root Oasis node datadir.\nnode_address: "unix:{{ oasis_node_unix_socket }}"\n\n# By default, we index the entire blockchain history.\n# If you are low on disk space or you use the gateway just for submitting transactions, enable\n# pruning below.\nenable_pruning: false\npruning_step: 100000\nindexing_start: 0\n\nlog:\n level: debug\n format: json\n\ndatabase:\n # Change host and port, if PostgreSQL is running somewhere else.\n host: "127.0.0.1"\n port: 5432\n # Enter your database name, username and password.\n db: {{ postgresql_db }}\n user: {{ postgresql_user }}\n password: {{ postgresql_password }}\n dial_timeout: 5\n read_timeout: 10\n write_timeout: 5\n max_open_conns: 0\n\ngateway:\n chain_id: {{ chain_id }}\n http:\n # Change host to your external IP address if you have users accessing Web3 from the outside.\n host: "localhost"\n # Use different port for each Web3 gateway instance, if all run locally.\n port: 8545\n cors: ["*"]\n ws:\n # Change host to your external IP address if you have users accessing Web3 from the outside.\n host: "localhost"\n # Use different port for each Web3 gateway instance, if all run locally.\n port: 8546\n origins: ["*"]\n method_limits:\n get_logs_max_rounds: 100\n')),(0,r.kt)("p",null,"Use the following placeholder values:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ paratime_id }}"),": The ID of the Emerald or Sapphire ParaTime which you are\nconfiguring the Web3 gateway for (see ",(0,r.kt)("a",{parentName:"li",href:"#oasis-paratime-client-node"},"above"),")."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ oasis_node_unix_socket }}"),": Path to the ",(0,r.kt)("inlineCode",{parentName:"li"},"internal.sock")," file created by\nthe Oasis node."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ postgresql_db }}"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"{{ postgresql_user }}"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"{{ postgresql_password }}"),":\nDatabase name and credentials for your PostgreSQL database."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ chain_id }}"),": The chain ID of your EVM network:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Emerald on ",(0,r.kt)("a",{parentName:"li",href:"/dapp/emerald/#mainnet"},"Mainnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"42262")),(0,r.kt)("li",{parentName:"ul"},"Emerald on ",(0,r.kt)("a",{parentName:"li",href:"/dapp/emerald/#testnet"},"Testnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"42261")),(0,r.kt)("li",{parentName:"ul"},"Sapphire on ",(0,r.kt)("a",{parentName:"li",href:"/dapp/sapphire/#testnet"},"Testnet"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"23295"))))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"All configuration settings can also be set via environment variables. For\nexample, instead of setting up the database password in the config file above\nyou can export:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"DATABASE__PASSWORD=your_password_here\n"))),(0,r.kt)("p",null,"To start the Web3 gateway invoke:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"./oasis-web3-gateway --config gateway.yml\n")),(0,r.kt)("p",null,"The Web3 gateway will connect to your Oasis node and start indexing available\nblocks (i.e. from the last network upgrade). This may \u2014 depending on your\nhardware and the size of the blockchain \u2014 take hours."),(0,r.kt)("p",null,"If your database contains any tables populated by the previous version of the\nWeb3 gateway, migration scripts will automatically be applied upon startup."),(0,r.kt)("p",null,"If you want to migrate the database separately, run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"./oasis-web3-gateway migrate-db --config gateway.yml\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Above, we are invoking the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-web3-gateway")," process directly from the\nshell, so you can quickly start using it. If you are setting up a production\nenvironment, you should ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/system-configuration#non-root"},"configure the Web3 gateway as a system service")," and register it in the service manager for your platform.")),(0,r.kt)("h2",{id:"archive-web3-gateway"},"Archive Web3 Gateway"),(0,r.kt)("p",null,"Each Oasis Web3 gateway can only connect to and synchronize blocks from a\nsingle Oasis node instance. To enable access to older EVM blocks, you can\nconfigure the Web3 gateway to behave as a proxy to another \u2014 archive \u2014 instance\nof the Web3 gateway."),(0,r.kt)("p",null,"First, set up an instance of the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/archive-node"},"Oasis archive node"),". Then, repeat the similar\nprocess of setting up a Web3 gateway as you would normally do, but configure it\nto use the newly set up Oasis archive node."),(0,r.kt)("p",null,"Suppose the archive instances of the Web3 gateway and Oasis nodes are up\nand running and the archive Web3 gateway is listening on the local port ",(0,r.kt)("inlineCode",{parentName:"p"},"8543"),".\nEnable the proxy for historical blocks by adding the following to your (live)\nWeb3 gateway config and restart it:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml",metastring:"title='gateway.yml'",title:"'gateway.yml'"},"# URI of an archive web3 gateway instance for servicing historical queries.\narchive_uri: 'http://localhost:8543'\n")),(0,r.kt)("p",null,"If a query requires information on the block which isn't stored in the\nlive version of the Web3 gateway, the gateway will pass the query to the\nconfigured archive instance and return the obtained result."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Historical estimate gas calls are not supported.")),(0,r.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,r.kt)("h3",{id:"wipe-state-to-force-a-complete-reindex"},"Wipe state to force a complete reindex"),(0,r.kt)("p",null,"If you encounter database or hardware issues, you may need to wipe the\ndatabase and reindex all blocks. First, run the ",(0,r.kt)("inlineCode",{parentName:"p"},"truncate-db")," subcommand:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-web3-gateway truncate-db --config gateway.yml --unsafe\n")),(0,r.kt)("p",null,"Then, execute the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-web3-gateway")," normally to start reindexing the\nblocks."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"This will wipe all existing state in the PostgreSQL database and can lead to\nextended downtime while the Web3 Gateway is reindexing the blocks.")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/34c89262.d6f19289.js b/assets/js/34c89262.d6f19289.js new file mode 100644 index 0000000000..85c2e4ecb7 --- /dev/null +++ b/assets/js/34c89262.d6f19289.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3487],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},h=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(n),h=o,m=d["".concat(l,".").concat(h)]||d[h]||u[h]||i;return n?r.createElement(m,a(a({ref:t},c),{},{components:n})):r.createElement(m,a({ref:t},c))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:o,a[1]=s;for(var p=2;p<i;p++)a[p]=n[p];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}h.displayName="MDXCreateElement"},9716:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var r=n(7462),o=(n(7294),n(3905));const i={},a="ADR 0015: Randomized Paratime Proposer Selection",s={unversionedId:"adrs/0015-vrf-per-block-entropy",id:"adrs/0015-vrf-per-block-entropy",title:"ADR 0015: Randomized Paratime Proposer Selection",description:"Component",source:"@site/docs/adrs/0015-vrf-per-block-entropy.md",sourceDirName:"adrs",slug:"/adrs/0015-vrf-per-block-entropy",permalink:"/adrs/0015-vrf-per-block-entropy",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0015-vrf-per-block-entropy.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0014: Signing Runtime Transactions with Hardware Wallet",permalink:"/adrs/0014-runtime-signing-tx-with-hardware-wallet"},next:{title:"ADR 0016: Consensus Parameters Change Proposal",permalink:"/adrs/0016-consensus-parameters-change-proposal"}},l={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Prerequisites",id:"prerequisites",level:3},{value:"Vote extension",id:"vote-extension",level:3},{value:"Proposer selection",id:"proposer-selection",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],c={toc:p},d="wrapper";function u(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"adr-0015-randomized-paratime-proposer-selection"},"ADR 0015: Randomized Paratime Proposer Selection"),(0,o.kt)("h2",{id:"component"},"Component"),(0,o.kt)("p",null,"Oasis Core"),(0,o.kt)("h2",{id:"changelog"},"Changelog"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"2022-09-14: Initial import")),(0,o.kt)("h2",{id:"status"},"Status"),(0,o.kt)("p",null,"Proposed"),(0,o.kt)("h2",{id:"context"},"Context"),(0,o.kt)("p",null,"The paratime block proposer currently is selected via a round-robin algorithm,\nand it is trivial to determine the block proposer well in advance. This ADR\nproposes having a mechanism for generating per-consensus block entropy via\nECVRF",(0,o.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/"},"1"),", and randomizing the Paratime block proposer."),(0,o.kt)("h2",{id:"decision"},"Decision"),(0,o.kt)("h3",{id:"prerequisites"},"Prerequisites"),(0,o.kt)("p",null,"Let each node have a distinct long-term VRF keypair, that is published as\npart of the node's descriptor (as per ADR 0010)."),(0,o.kt)("p",null,"Let Tendermint actually implement ",(0,o.kt)("inlineCode",{parentName:"p"},"ExtendVote"),"/",(0,o.kt)("inlineCode",{parentName:"p"},"VerifyVoteExtension")," as\nper certain versions of the ABCI++ spec",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cometbft/cometbft/blob/main/docs/rfc/tendermint-core/rfc-013-abci%2B%2B.md"},"2"),". Note that it appears that this\nwill NOT be in Tendermint 0.37.x, but instead is scheduled for a later\nrelease."),(0,o.kt)("h3",{id:"vote-extension"},"Vote extension"),(0,o.kt)("p",null,"ABCI++ introduces a notion of an application defined ",(0,o.kt)("inlineCode",{parentName:"p"},"vote_extension")," blob\nthat is set by the tendermint block proposer, and verified by all of the\nvoters. Oasis will use the following datastructure, serialized to canonical\nCBOR, and signed with the node's consensus signing key."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type OasisVoteExtension struct {\n // Pi is the proposer\'s VRF proof for the current block height.\n Pi []byte `json:"pi"`\n}\n')),(0,o.kt)("p",null,"For the genesis block +1 (No previous beta), let the VRF alpha_string input\nbe derived as:"),(0,o.kt)("p",null," ",(0,o.kt)("inlineCode",{parentName:"p"},'TupleHash256((chain_context, I2OSP(height,8)), 256, "oasis-core:tm-vrf/alpha")')),(0,o.kt)("p",null,"For subsequent blocks, let the VRF alpha_string input be derived as:"),(0,o.kt)("p",null," ",(0,o.kt)("inlineCode",{parentName:"p"},'TupleHash256((chain_context, I2OSP(height,8), prev_beta), 256, "oasis-core:tm-vrf/alpha")'),"\nwhere prev_beta is the beta_string output from the previous height's ECVRF\nproof."),(0,o.kt)("p",null,"Blocks must have a valid ",(0,o.kt)("inlineCode",{parentName:"p"},"OasisVoteExtension")," blob to be considered valid,\nand nodes MUST use the same ECVRF key for the entire epoch (key changes\nmid-epoch are ignored till the epoch transition) to prevent the proposer\nfrom regenerating the ECVRF key repeatedly to fish for entropy output."),(0,o.kt)("h3",{id:"proposer-selection"},"Proposer selection"),(0,o.kt)("p",null,"Instead of round-robin through the per-epoch list of primary (non-backup)\nworkers, the index for the node can be selected as thus:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'seed = TupleHash256((chain_context, I2OSP(height,8), runtime_id, pi), 256, "oasis-core:tm-vrf/paratime")\ndrbg = drbg.New(crypto.SHA512, seed, nil, "BlockProposer")\nrng = rand.New(mathrand.New(drbg))\n\nl := len(primary_nodes)\nprimary_index = int(rng.Int63n(l))\n')),(0,o.kt)("h2",{id:"consequences"},"Consequences"),(0,o.kt)("h3",{id:"positive"},"Positive"),(0,o.kt)("p",null,"The paratime block proposer(s) will be randomized."),(0,o.kt)("p",null,"This can be done without having to patch tendermint."),(0,o.kt)("p",null,"In theory, the system will have a way to generate entropy at the consensus\nlayer again."),(0,o.kt)("h3",{id:"negative"},"Negative"),(0,o.kt)("p",null,"The tendermint block proposer still will be selected via a round robin\nalgorithm. Note that Oasis does not have smart contracts at that level so\nthe impact of being able to predict the block proposer there is less\nsignificant than other systems."),(0,o.kt)("p",null,"People may be tempted to abuse this entropy for other things (eg: inside\nparatimes), which would be incorrect (block proposer can cheat)."),(0,o.kt)("p",null,"This relies on interfaces exposed by ABCI++, which appear to no longer\nbe part of 0.37.x, so it is unknown when this will be possible to implement."),(0,o.kt)("h3",{id:"neutral"},"Neutral"),(0,o.kt)("h2",{id:"references"},"References"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/370b1912.e92e985a.js b/assets/js/370b1912.e92e985a.js new file mode 100644 index 0000000000..95dbfa7093 --- /dev/null +++ b/assets/js/370b1912.e92e985a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[245],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var s=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,s)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,s,a=function(e,t){if(null==e)return{};var n,s,a={},r=Object.keys(e);for(s=0;s<r.length;s++)n=r[s],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(s=0;s<r.length;s++)n=r[s],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=s.createContext({}),u=function(e){var t=s.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return s.createElement(l.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return s.createElement(s.Fragment,{},t)}},p=s.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),d=u(n),p=a,g=d["".concat(l,".").concat(p)]||d[p]||m[p]||r;return n?s.createElement(g,i(i({ref:t},c),{},{components:n})):s.createElement(g,i({ref:t},c))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=p;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o[d]="string"==typeof e?e:a,i[1]=o;for(var u=2;u<r;u++)i[u]=n[u];return s.createElement.apply(null,i)}return s.createElement.apply(null,n)}p.displayName="MDXCreateElement"},2948:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>u});var s=n(7462),a=(n(7294),n(3905));const r={},i="ADR 0012: Runtime Message Results",o={unversionedId:"adrs/0012-runtime-message-results",id:"adrs/0012-runtime-message-results",title:"ADR 0012: Runtime Message Results",description:"Component",source:"@site/docs/adrs/0012-runtime-message-results.md",sourceDirName:"adrs",slug:"/adrs/0012-runtime-message-results",permalink:"/adrs/0012-runtime-message-results",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0012-runtime-message-results.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0011: Incoming Runtime Messages",permalink:"/adrs/0011-incoming-runtime-messages"},next:{title:"ADR 0013: Runtime Upgrade Improvements",permalink:"/adrs/0013-runtime-upgrades"}},l={},u=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Implementation",id:"implementation",level:2},{value:"Message Execution Results",id:"message-execution-results",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"Alternatives considered",id:"alternatives-considered",level:3}],c={toc:u},d="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,s.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0012-runtime-message-results"},"ADR 0012: Runtime Message Results"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2021-12-04: Initial version"),(0,a.kt)("li",{parentName:"ul"},"2021-12-10: Extend the implementation section"),(0,a.kt)("li",{parentName:"ul"},"2022-01-27: Update the concrete result types")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"Currently, the results of emitted runtime messages are ",(0,a.kt)("inlineCode",{parentName:"p"},"MessageEvent"),"s, which\nonly provide information whether the message execution was successful or not.\nFor various use-cases additional information about message results would be\nuseful."),(0,a.kt)("p",null,"One of such is supporting staking by runtimes. Currently, a runtime can emit an\n",(0,a.kt)("inlineCode",{parentName:"p"},"AddEscrow")," message, but is unaware of the actual amount of shares it obtained\nas a result of the added escrow. For some use-cases (e.g. runtime staking user\ndeposited funds) this information is crucial for accounting."),(0,a.kt)("p",null,"Similarly, for ",(0,a.kt)("inlineCode",{parentName:"p"},"ReclaimEscrow"),", the runtime doesn't have the direct information\nat which epoch the stake gets debonded."),(0,a.kt)("p",null,"The only way to currently obtain this data is to subscribe to consensus events,\nsomething which runtime doesn't have access to."),(0,a.kt)("p",null,"Adding results to ",(0,a.kt)("inlineCode",{parentName:"p"},"MessageEvent")," solves both of the mentioned use cases:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"for ",(0,a.kt)("inlineCode",{parentName:"p"},"AddEscrow")," the result should contain amount of shares obtained with the\nescrow")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"for ",(0,a.kt)("inlineCode",{parentName:"p"},"ReclaimEscrow")," the result should contain the amount of shares and epoch\nat which the stake gets debonded"))),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("p",null,"Implement support for arbitrary result data in ",(0,a.kt)("inlineCode",{parentName:"p"},"MessageEvent")," runtime message\nresults."),(0,a.kt)("h2",{id:"implementation"},"Implementation"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Result field is added to ",(0,a.kt)("inlineCode",{parentName:"li"},"roothash.MessageEvent")," struct:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'// MessageEvent is a runtime message processed event.\ntype MessageEvent struct {\n Module string `json:"module,omitempty"`\n Code uint32 `json:"code,omitempty"`\n Index uint32 `json:"index,omitempty"`\n\n // Result contains message execution results for successfully executed messages.\n Result cbor.RawMessage `json:"result,omitempty"\n}\n')),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"Result")," field is runtime message specific and is present only when the\nmessage execution was successful (",(0,a.kt)("inlineCode",{parentName:"p"},"Code")," is ",(0,a.kt)("inlineCode",{parentName:"p"},"errors.CodeNoError"),")."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ExecuteMessage")," method in ",(0,a.kt)("inlineCode",{parentName:"li"},"MessageSubscriber")," interface is updated to include\na response:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},"// MessageSubscriber is a message subscriber interface.\ntype MessageSubscriber interface {\n // ExecuteMessage executes a given message.\n ExecuteMessage(ctx *Context, kind, msg interface{}) (interface{}, error)\n}\n")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Publish")," method of the ",(0,a.kt)("inlineCode",{parentName:"li"},"MessageDispatcher")," interface is updated to include\nthe response:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},"// MessageDispatcher is a message dispatcher interface.\ntype MessageDispatcher interface {\n // Publish publishes a message of a given kind by dispatching to all subscribers.\n // Subscribers can return a result, but at most one subscriber should return a\n // non-nil result to any published message. Panics in case more than one subscriber\n // returns a non-nil result.\n //\n // In case there are no subscribers ErrNoSubscribers is returned.\n Publish(ctx *Context, kind, msg interface{}) (interface{}, error)\n}\n")),(0,a.kt)("p",null,"In case the ",(0,a.kt)("inlineCode",{parentName:"p"},"Publish")," ",(0,a.kt)("inlineCode",{parentName:"p"},"error")," is ",(0,a.kt)("inlineCode",{parentName:"p"},"nil")," the Roothash backend propagates the\nresult to the emitted ",(0,a.kt)("inlineCode",{parentName:"p"},"MessageEvent"),"."),(0,a.kt)("p",null,"With these changes the runtime is able to obtain message execution results via\n",(0,a.kt)("inlineCode",{parentName:"p"},"MessageEvents")," in ",(0,a.kt)("inlineCode",{parentName:"p"},"RoundResults"),"."),(0,a.kt)("h3",{id:"message-execution-results"},"Message Execution Results"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"AddEscrow")," message execution result is the ",(0,a.kt)("inlineCode",{parentName:"li"},"AddEscrowResult"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type AddEscrowResult struct {\n Owner Address `json:"owner"`\n Escrow Address `json:"escrow"`\n Amount quantity.Quantity `json:"amount"`\n NewShares quantity.Quantity `json:"new_shares"`\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"ReclaimEscrow")," message execution result is the\n",(0,a.kt)("inlineCode",{parentName:"li"},"ReclaimEscrowResult"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type ReclaimEscrowResult struct {\n Owner Address `json:"owner"`\n Escrow Address `json:"escrow"`\n Amount quantity.Quantity `json:"amount"`\n DebondingShares quantity.Quantity `json:"debonding_shares"`\n RemainingShares quantity.Quantity `json:"remaining_shares"`\n DebondEndTime beacon.EpochTime `json:"debond_end_time"`\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Transfer")," message execution result is the ",(0,a.kt)("inlineCode",{parentName:"li"},"TransferResult"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type TransferResult struct {\n From Address `json:"from"`\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Withdraw")," message execution result is the ",(0,a.kt)("inlineCode",{parentName:"li"},"WithdrawResult"),":")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type WithdrawResult struct {\n Owner Address `json:"owner"`\n Beneficiary Address `json:"beneficiary"`\n Allowance quantity.Quantity `json:"allowance"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n')),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"UpdateRuntime")," message execution result is the registry ",(0,a.kt)("inlineCode",{parentName:"li"},"Runtime")," descriptor.")),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("p",null,"All the functionality for runtimes to support staking is implemented."),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("p",null,"Requires breaking changes."),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("h3",{id:"alternatives-considered"},"Alternatives considered"),(0,a.kt)("p",null,"Add support to runtimes for subscribing to consensus events. A more heavyweight\nsolution, that can still be implemented in future if desired. Decided against it\ndue to simplicity of the message events solution for the present use cases."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3812dde4.1f1b5e85.js b/assets/js/3812dde4.1f1b5e85.js new file mode 100644 index 0000000000..77af52df99 --- /dev/null +++ b/assets/js/3812dde4.1f1b5e85.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5060],{9980:e=>{e.exports=JSON.parse('{"title":"Oasis Node","slug":"core/oasis-node","permalink":"/core/oasis-node","navigation":{"previous":{"title":"Runtime Messages","permalink":"/core/runtime/messages"},"next":{"title":"RPC","permalink":"/core/oasis-node/rpc"}}}')}}]); \ No newline at end of file diff --git a/assets/js/3ae86dfc.83102d85.js b/assets/js/3ae86dfc.83102d85.js new file mode 100644 index 0000000000..e080dbb520 --- /dev/null +++ b/assets/js/3ae86dfc.83102d85.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8990],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function a(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,s=e.parentName,p=a(e,["components","mdxType","originalType","parentName"]),d=l(n),f=o,m=d["".concat(s,".").concat(f)]||d[f]||u[f]||c;return n?r.createElement(m,i(i({ref:t},p),{},{components:n})):r.createElement(m,i({ref:t},p))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,i=new Array(c);i[0]=f;var a={};for(var s in t)hasOwnProperty.call(t,s)&&(a[s]=t[s]);a.originalType=e,a[d]="string"==typeof e?e:o,i[1]=a;for(var l=2;l<c;l++)i[l]=n[l];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},4365:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>c,metadata:()=>a,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={},i="Encoding",a={unversionedId:"core/encoding",id:"core/encoding",title:"Encoding",description:"All messages exchanged by different components in Oasis Core are encoded using",source:"@site/docs/core/encoding.md",sourceDirName:"core",slug:"/core/encoding",permalink:"/core/encoding",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/encoding.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Common Functionality",permalink:"/core/common-functionality"},next:{title:"Cryptography",permalink:"/core/crypto"}},s={},l=[],p={toc:l},d="wrapper";function u(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"encoding"},"Encoding"),(0,o.kt)("p",null,"All messages exchanged by different components in Oasis Core are encoded using\n",(0,o.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc7049"},"canonical CBOR as defined by RFC 7049"),"."),(0,o.kt)("p",null,"When describing different messages in the documentation, we use Go structs with\nfield annotations that specify how different fields translate to their encoded\nform."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3bc542c3.87e3cde0.js b/assets/js/3bc542c3.87e3cde0.js new file mode 100644 index 0000000000..e7b4a74bc6 --- /dev/null +++ b/assets/js/3bc542c3.87e3cde0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6536],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>m});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=o.createContext({}),c=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=c(e.components);return o.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},g=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(n),g=r,m=p["".concat(l,".").concat(g)]||p[g]||u[g]||a;return n?o.createElement(m,i(i({ref:t},d),{},{components:n})):o.createElement(m,i({ref:t},d))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:r,i[1]=s;for(var c=2;c<a;c++)i[c]=n[c];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}g.displayName="MDXCreateElement"},1139:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var o=n(7462),r=(n(7294),n(3905));const a={},i="Custody Providers",s={unversionedId:"general/manage-tokens/holding-rose-tokens/custody-providers",id:"general/manage-tokens/holding-rose-tokens/custody-providers",title:"Custody Providers",description:"Another way to hold your ROSE tokens is by using a custody provider.",source:"@site/docs/general/manage-tokens/holding-rose-tokens/custody-providers.md",sourceDirName:"general/manage-tokens/holding-rose-tokens",slug:"/general/manage-tokens/holding-rose-tokens/custody-providers",permalink:"/general/manage-tokens/holding-rose-tokens/custody-providers",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/holding-rose-tokens/custody-providers.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"3rd Party Custody & Wallets",permalink:"/general/manage-tokens/holding-rose-tokens"},next:{title:"Self-Custody With Ledger Hardware Wallet",permalink:"/general/manage-tokens/holding-rose-tokens/ledger-wallet"}},l={},c=[{value:"Copper.co",id:"copperco",level:3},{value:"Anchorage",id:"anchorage",level:3},{value:"Finoa",id:"finoa",level:3}],d={toc:c},p="wrapper";function u(e){let{components:t,...n}=e;return(0,r.kt)(p,(0,o.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"custody-providers"},"Custody Providers"),(0,r.kt)("p",null,"Another way to hold your ROSE tokens is by using a custody provider."),(0,r.kt)("p",null,"We've partnered with industry-leaders who each support a number of top crypto assets."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Below are some simple ways to get in touch, but please do reach out to them directly for more information on insurance, fees and cross-chain support.")),(0,r.kt)("h3",{id:"copperco"},(0,r.kt)("a",{parentName:"h3",href:"https://copper.co"},"Copper.co")),(0,r.kt)("p",null,"Copper.co is a leading provider of digital asset custody and trading solutions. It provides a gateway into the cryptoasset space for institutional investors by offering custody, prime brokerage, and settlements across 250 digital assets and more than 40 exchanges. It offers a comprehensive and secure suite of tools and services required to safely acquire, trade, and store cryptocurrencies, including access to margin lending trading facilities and the DeFi space."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Delegation options:")," Copper.co allows delegation to any validator running a node on the Oasis Network."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Min holding:")," No threshold for assets under custody. They do not onboard individuals as clients. Suitable for larger token holders."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Sign up:")," Email ",(0,r.kt)("a",{parentName:"li",href:"mailto:betty.sharples@copper.co"},"betty.sharples@copper.co")," to set up an account.")),(0,r.kt)("h3",{id:"anchorage"},(0,r.kt)("a",{parentName:"h3",href:"https://anchorage.com"},"Anchorage")),(0,r.kt)("p",null,"Anchorage is an advanced digital asset platform, with a solution designed to meet the evolving needs of institutional investors. It offers world class custody, trading, and financing services, as well as on-chain participation like staking and governance."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Delegation options:")," Anchorage allows delegation to any validator running a node on the Oasis Network."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Min holding:")," Minimum custody requirements. Suitable for larger token holders."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Sign up:")," Please sign up ",(0,r.kt)("a",{parentName:"li",href:"https://www.anchorage.com/get-started/"},"here"),".")),(0,r.kt)("h3",{id:"finoa"},(0,r.kt)("a",{parentName:"h3",href:"https://finoa.io"},"Finoa")),(0,r.kt)("p",null,"Finoa is a regulated custodian for digital assets, servicing professional investors with custody and staking. The platform enables its users to securely store and manage their crypto-assets, while providing a directly accessible, highly intuitive and unique user-experience, enabling seamless access to the ecosystem of Decentralized Finance (DeFi)."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Delegation options:")," Finoa offers delegation to a number of select validators including Bison Trails, Blockdaemon, Chorus One, Figment Networks, and more."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Min holding:")," No threshold for assets under custody. Please check out details at ",(0,r.kt)("a",{parentName:"li",href:"https://www.finoa.io"},"finoa.io"),"."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Sign up:")," Email ",(0,r.kt)("a",{parentName:"li",href:"mailto:oasis@finoa.io"},"oasis@finoa.io")," to set up an account.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3c28ce58.d2bbcce3.js b/assets/js/3c28ce58.d2bbcce3.js new file mode 100644 index 0000000000..e31aacadd1 --- /dev/null +++ b/assets/js/3c28ce58.d2bbcce3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3251],{8784:e=>{e.exports=JSON.parse('{"title":"Development Setup","description":"This section provides information on how to compile and configure complete Oasis Network stack locally in order for you to start exploring and contributing to the Oasis Core.","slug":"core/development-setup","permalink":"/core/development-setup","navigation":{"previous":{"title":"Oasis Core Developer Documentation","permalink":"/core/"},"next":{"title":"Build Environment Setup and Building","permalink":"/core/development-setup/build-environment-setup-and-building"}}}')}}]); \ No newline at end of file diff --git a/assets/js/3e5e0bf3.6b6666ea.js b/assets/js/3e5e0bf3.6b6666ea.js new file mode 100644 index 0000000000..7af1f7702d --- /dev/null +++ b/assets/js/3e5e0bf3.6b6666ea.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6990],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>u});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=p(n),h=i,u=d["".concat(s,".").concat(h)]||d[h]||m[h]||o;return n?a.createElement(u,r(r({ref:t},c),{},{components:n})):a.createElement(u,r({ref:t},c))}));function u(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,r=new Array(o);r[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:i,r[1]=l;for(var p=2;p<o;p++)r[p]=n[p];return a.createElement.apply(null,r)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},7141:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var a=n(7462),i=(n(7294),n(3905));const o={},r="ADR 0007: Improved Random Beacon",l={unversionedId:"adrs/0007-improved-random-beacon",id:"adrs/0007-improved-random-beacon",title:"ADR 0007: Improved Random Beacon",description:"Component",source:"@site/docs/adrs/0007-improved-random-beacon.md",sourceDirName:"adrs",slug:"/adrs/0007-improved-random-beacon",permalink:"/adrs/0007-improved-random-beacon",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0007-improved-random-beacon.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0006: Consensus Governance",permalink:"/adrs/0006-consensus-governance"},next:{title:"ADR 0008: Standard Account Key Generation",permalink:"/adrs/0008-standard-account-key-generation"}},s={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Node Descriptor",id:"node-descriptor",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Consensus State and Events",id:"consensus-state-and-events",level:3},{value:"Transactions",id:"transactions",level:2},{value:"Beacon Generation",id:"beacon-generation",level:3},{value:"Commit Phase",id:"commit-phase",level:4},{value:"Reveal Phase",id:"reveal-phase",level:4},{value:"Complete (Transition Wait) Phase",id:"complete-transition-wait-phase",level:4},{value:"Misc. Changes/Notes",id:"misc-changesnotes",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],c={toc:p},d="wrapper";function m(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"adr-0007-improved-random-beacon"},"ADR 0007: Improved Random Beacon"),(0,i.kt)("h2",{id:"component"},"Component"),(0,i.kt)("p",null,"Oasis Core"),(0,i.kt)("h2",{id:"changelog"},"Changelog"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"2020-10-22: Initial version")),(0,i.kt)("h2",{id:"status"},"Status"),(0,i.kt)("p",null,"Proposed"),(0,i.kt)("h2",{id:"context"},"Context"),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"Any one who considers arithmetical methods of producing random digits\nis, of course, in a state of sin."),(0,i.kt)("p",{parentName:"blockquote"},"--Dr. John von Neumann")),(0,i.kt)("p",null,"The existing random beacon used by Oasis Core, is largely a placeholder\nimplementation that naively uses the previous block's commit hash as the\nentropy input. As such it is clearly insecure as it is subject to\nmanipulation."),(0,i.kt)("p",null,"A better random beacon which is harder for an adversary to manipulate\nis required to provide entropy for secure committee elections."),(0,i.kt)("h2",{id:"decision"},"Decision"),(0,i.kt)("p",null,'At a high level, this ADR proposes implementing an on-chain random beacon\nbased on "SCRAPE: Scalabe Randomness Attested by Public Entities" by\nCascudo and David. The new random beacon will use a commit-reveal scheme\nbacked by a PVSS scheme so that as long as the threshold of participants\nis met, and one participant is honest, secure entropy will be generated.'),(0,i.kt)("p",null,"Note: This document assumes the reader understands SCRAPE. Details\nregarding the underlying SCRAPE implementation are omitted for brevity."),(0,i.kt)("h3",{id:"node-descriptor"},"Node Descriptor"),(0,i.kt)("p",null,"The node descriptor of each node will be extended to include the following\ndatastructure."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type Node struct {\n // ... existing fields omitted ...\n\n // Beacon contains information for this node\'s participation\n // in the random beacon protocol.\n //\n // TODO: This is optional for now, make mandatory once enough\n // nodes provide this field.\n Beacon *BeaconInfo `json:"beacon,omitempty"`\n}\n\n// BeaconInfo contains information for this node\'s participation in\n// the random beacon protocol.\ntype BeaconInfo struct {\n // Point is the elliptic curve point used for the PVSS algorithm.\n Point scrape.Point `json:"point"`\n}\n')),(0,i.kt)("p",null,"Each node will generate and maintain a long term elliptic curve point\nand scalar pair (public/private key pair), the point (public key) of\nwhich will be included in the node descriptor."),(0,i.kt)("p",null,"For the purposes of the initial implementation, the curve will be P-256."),(0,i.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,i.kt)("p",null,"The beacon module will have the following consensus parameters that\ncontrol behavior."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type SCRAPEParameters struct {\n Participants uint64 `json:"participants"`\n Threshold uint64 `json:"threshold"`\n PVSSThreshold uint64 `json:"pvss_threshold"`\n\n CommitInterval int64 `json:"commit_interval"`\n RevealInterval int64 `json:"reveal_interval"`\n TransitionDelay int64 `json:"transition_delay"`\n}\n')),(0,i.kt)("p",null,"Fields:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Participants")," - The number of participants to be selected for each\nbeacon generation protocol round.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Threshold")," - The minimum number of participants which must\nsuccessfully contribute entropy for the final output to be\nconsidered valid.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"PVSSThreshold")," - The minimum number of participants that are\nrequired to reconstruct a PVSS secret from the corresponding\ndecrypted shares (Note: This usually should just be set to\n",(0,i.kt)("inlineCode",{parentName:"p"},"Threshold"),").")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"CommitInterval")," - The duration of the Commit phase, in blocks.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"RevealInterval")," - The duration of the Reveal phase, in blocks.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"TransitionDelay")," - The duration of the post Reveal phase delay, in blocks."))),(0,i.kt)("h3",{id:"consensus-state-and-events"},"Consensus State and Events"),(0,i.kt)("p",null,"The on-chain beacon will maintain and make available the following consensus\nstate."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'// RoundState is a SCRAPE round state.\ntype RoundState uint8\n\nconst (\n StateInvalid RoundState = 0\n StateCommit RoundState = 1\n StateReveal RoundState = 2\n StateComplete RoundState = 3\n)\n\n// SCRAPEState is the SCRAPE backend state.\ntype SCRAPEState struct {\n Height int64 `json:"height,omitempty"`\n\n Epoch EpochTime `json:"epoch,omitempty"`\n Round uint64 `json:"round,omitempty"`\n State RoundState `json:"state,omitempty"`\n\n Instance *scrape.Instance `json:"instance,omitempty"`\n Participants []signature.PublicKey `json:"participants,omitempty"`\n Entropy []byte `json:"entropy,omitempty"`\n\n BadParticipants map[signature.PublicKey]bool `json:"bad_participants,omitempty"`\n\n CommitDeadline int64 `json:"commit_deadline,omitempty"`\n RevealDeadline int64 `json:"reveal_deadline,omitempty"`\n TransitionHeight int64 `json:"transition_height,omitempty"`\n\n RuntimeDisableHeight int64 `json:"runtime_disable_height,omitempty"`\n}\n')),(0,i.kt)("p",null,"Fields:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Height")," - The block height at which the last event was emitted.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Epoch")," - The epoch in which this beacon is being generated.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Round")," - The epoch beacon generation round.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"State")," - The beacon generation step (commit/reveal/complete).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Instance")," - The SCRAPE protocol state (encrypted/decrypted shares of\nall participants).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Participants")," - The node IDs of the nodes selected to participate\nin this beacon generation round.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Entropy")," - The final raw entropy, if any.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"BadParticipants")," - A map of nodes that were selected, but have failed\nto execute the protocol correctly.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"CommitDeadline")," - The height in blocks by which participants must\nsubmit their encrypted shares.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"RevealDeadline")," - The height in blocks by which participants must\nsubmit their decrypted shares.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"TransitionHeight")," - The height at which the epoch will transition\nassuming this round completes successfully.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"RuntimeDisableHeight")," - The height at which, upon protocol failure,\nruntime transactions will be disabled. This height will be set to\nthe transition height of the 0th round."))),(0,i.kt)("p",null,"Upon transition to a next step of the protocol, the on-chain beacon will\nemit the following event."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'// SCRAPEEvent is a SCRAPE backend event.\ntype SCRAPEEvent struct {\n Height int64 `json:"height,omitempty"`\n\n Epoch EpochTime `json:"epoch,omitempty"`\n Round uint64 `json:"round,omitempty"`\n State RoundState `json:"state,omitempty"`\n\n Participants []signature.PublicKey `json:"participants,omitempty"`\n}\n')),(0,i.kt)("p",null,"Field definitions are identical to that of those in the ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEState"),"\ndatastructure."),(0,i.kt)("h2",{id:"transactions"},"Transactions"),(0,i.kt)("p",null,"Participating nodes will submit the following transactions when required,\nsigned by the node identity key."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'var (\n // MethodSCRAPECommit is the method name for a SCRAPE commitment.\n MethodSCRAPECommit = transaction.NewMethodName(ModuleName, "SCRAPECommit", SCRAPECommit{})\n\n // MethodSCRAPEReveal is the method name for a SCRAPE reveal.\n MethodSCRAPEReveal = transaction.NewMethodName(ModuleName, "SCRAPEReveal", SCRAPEReveal{})\n)\n\n// SCRAPECommit is a SCRAPE commitment transaction payload.\ntype SCRAPECommit struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Commit *scrape.Commit `json:"commit,omitempty"`\n}\n\n// SCRAPEReveal is a SCRAPE reveal transaction payload.\ntype SCRAPEReveal struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Reveal *scrape.Reveal `json:"reveal,omitempty"`\n}\n')),(0,i.kt)("p",null,"Fields:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Epoch")," - The epoch in which the transaction is applicable.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Round")," - The epoch beacon generation round for the transaction.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Commit")," - The SCRAPE commit consisting of PVSS shares encrypted to\nevery participant.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("inlineCode",{parentName:"p"},"Reveal")," - The SCRAPE reveal consisting of the decrypted result of\nPVSS shares received from every participant."))),(0,i.kt)("h3",{id:"beacon-generation"},"Beacon Generation"),(0,i.kt)("p",null,"The beacon generation process is split into three sequential stages,\nroughly corresponding to the steps in the SCRAPE protocol. Any failures\nin the Commit and Reveal phases result in a failed protocol round, and\nthe generation process will restart after disqualifying participants who\nhave induced the failure."),(0,i.kt)("h4",{id:"commit-phase"},"Commit Phase"),(0,i.kt)("p",null,"Upon epoch transition or a prior failed round the commit phase is initiated\nthe consensus application will select ",(0,i.kt)("inlineCode",{parentName:"p"},"Particpants")," nodes from the current\nvalidator set (in order of decending stake) to serve as entropy contributors."),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEState")," structure is (re)-initialized, and a ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEEvent")," is\nbroadcast to signal to the participants that they should generate and\nsubmit their encrypted shares via a ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPECommit")," transaction."),(0,i.kt)("p",null,"Each commit phase lasts exactly ",(0,i.kt)("inlineCode",{parentName:"p"},"CommitInterval")," blocks, at the end of which,\nthe round will be closed to further commits."),(0,i.kt)("p",null,"At the end of the commit phase, the SCRAPE protocol state is evaluated\nto ensure that ",(0,i.kt)("inlineCode",{parentName:"p"},"Threshold"),"/",(0,i.kt)("inlineCode",{parentName:"p"},"PVSSThreshold")," nodes have published encrypted\nshares, and if an insufficient number of nodes have published in either\ncase, the round is considered to have failed."),(0,i.kt)("p",null,"The following behaviors are currently candidates for a node being marked\nas malicious/non-particpatory (",(0,i.kt)("inlineCode",{parentName:"p"},"BadParticipant"),") and subject to exclusion\nfrom future rounds and slashing."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Not submitting a commitment.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Malformed commitments (corrupted/fails to validate/etc).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Attempting to alter an existing commitment for a given Epoch/Round."))),(0,i.kt)("h4",{id:"reveal-phase"},"Reveal Phase"),(0,i.kt)("p",null,"When the ",(0,i.kt)("inlineCode",{parentName:"p"},"CommitInterval")," has passed, assuming that a sufficient number of\ncommits have been received, the consensus application transitions into the\nreveal phase by updating the ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEState")," structure and broadcasting a\n",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEEvent")," to signal to the participants that they should reveal the\ndecrypted values of the encrypted shares received from other participants\nvia a ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEReveal")," transaction."),(0,i.kt)("p",null,"Each reveal phase lasts exactly ",(0,i.kt)("inlineCode",{parentName:"p"},"RevealInterval")," blocks, at the end of which,\nthe round will be closed to further reveals."),(0,i.kt)("p",null,"At the end of the reveal phase, the SCRAPE protocol state is evaluated to\nensure that ",(0,i.kt)("inlineCode",{parentName:"p"},"Threshold"),"/",(0,i.kt)("inlineCode",{parentName:"p"},"PVSSThreshold")," nodes have published decrypted\nshares, and if an insufficient number of nodes have published in either\ncase, the round is considered to have failed."),(0,i.kt)("p",null,"The following behaviors are currently candidates for a node being marked\nas malicious/non-participatory (",(0,i.kt)("inlineCode",{parentName:"p"},"BadParticipant"),") and subject to exclusion\nfrom future rounds and slashing."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Not submitting a reveal.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Malformed commitments (corrupted/fails to validate/etc).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Attempting to alter an existing reveal for a given Epoch/Round."))),(0,i.kt)("p",null,"Note: It is possible for anybody who can observe consensus state to derive\nthe entropy the moment a threshold number of ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEReveal")," transactions\nhave been processed. Therefore the reveal phase should be a small fraction\nof the desired epoch as it is possible to derive the results of the\ncommittee elections for the next epoch mid-reveal phase."),(0,i.kt)("h4",{id:"complete-transition-wait-phase"},"Complete (Transition Wait) Phase"),(0,i.kt)("p",null,"When the ",(0,i.kt)("inlineCode",{parentName:"p"},"RevealInterval")," has passed, assuming that a sufficient number\nof reveals have been received, the consensus application recovers the\nfinal entropy output (the hash of the secret shared by each participant)\nand transitions into the complete (transition wait) phase by updating the\n",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEState")," structure and broadcasting a ",(0,i.kt)("inlineCode",{parentName:"p"},"SCRAPEEvent")," to signal to\nparticipants the completion of the round."),(0,i.kt)("p",null,"No meaningful protocol activity happens one a round has successfully\ncompleted, beyond the scheduling of the next epoch transition."),(0,i.kt)("h3",{id:"misc-changesnotes"},"Misc. Changes/Notes"),(0,i.kt)("p",null,"Nodes MUST not be slashed for non-participation if they have not had\nthe opportunity to propose any blocks during the relevant interval."),(0,i.kt)("p",null,"Processing commitments and reveals is currently rather CPU intensive\nand thus each block SHOULD only contain one of each to prevent the\nconsesus from stalling."),(0,i.kt)("p",null,"To thwart attempts to manipulate committee placement by virute of the\nfact that it is possible to observe the entropy used for elections early\nnodes that register between the completion of the final commit phase and\nthe epoch transition in any given epoch MUST be excluded from committee\neligibility."),(0,i.kt)("h2",{id:"consequences"},"Consequences"),(0,i.kt)("h3",{id:"positive"},"Positive"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The random beacon output is unbaised, provided that at least one\nparticipant is honest.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The amount of consensus state required is relatively small.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"All protocol messages and steps can be verified on-chain, and misbehavior\ncan be attributed.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The final output can be generated on-chain."))),(0,i.kt)("h3",{id:"negative"},"Negative"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Epoch intervals are theoretically variable under this proposal, as the\nbeacon generation needs to be re-ran with new participants upon failure.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"A new failure mode is introduced at the consensus layer, where the\nbeacon generation protocol exhausts eligible participants.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Without using pairing based cryptography, the number of participants\nin the beacon generation is limited to a small subset of the anticipated\nactive validator set.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"There is a time window where the next beacon can be derived by anyone\nwith access to the consensus state before the epoch transition actually\nhappens. This should be mitigated by having a relatively short reveal\nperiod.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The commit and reveal steps of the protocol are rather slow, especially\nas the number of participants increases."))),(0,i.kt)("h3",{id:"neutral"},"Neutral"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Due to performance reasons, the curve used by the PVSS scheme will\nbe P-256 instead of Ed25519. The point and scalar pairs that each\nnode generates on this curve are exclusively for use in the random\nbeacon protocol and are not used anywhere else.")),(0,i.kt)("h2",{id:"references"},"References"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://eprint.iacr.org/2017/216.pdf"},"SCRAPE: SCalabe Randomness Attested by Public Entities")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/pull/3180"},"oasis-core#3180"))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3fb4947e.93e8ef45.js b/assets/js/3fb4947e.93e8ef45.js new file mode 100644 index 0000000000..7503a0cf15 --- /dev/null +++ b/assets/js/3fb4947e.93e8ef45.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8203],{3905:(t,e,r)=>{r.d(e,{Zo:()=>p,kt:()=>g});var a=r(7294);function n(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function o(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,a)}return r}function l(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{};e%2?o(Object(r),!0).forEach((function(e){n(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function s(t,e){if(null==t)return{};var r,a,n=function(t,e){if(null==t)return{};var r,a,n={},o=Object.keys(t);for(a=0;a<o.length;a++)r=o[a],e.indexOf(r)>=0||(n[r]=t[r]);return n}(t,e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);for(a=0;a<o.length;a++)r=o[a],e.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(n[r]=t[r])}return n}var m=a.createContext({}),i=function(t){var e=a.useContext(m),r=e;return t&&(r="function"==typeof t?t(e):l(l({},e),t)),r},p=function(t){var e=i(t.components);return a.createElement(m.Provider,{value:e},t.children)},d="mdxType",c={inlineCode:"code",wrapper:function(t){var e=t.children;return a.createElement(a.Fragment,{},e)}},u=a.forwardRef((function(t,e){var r=t.components,n=t.mdxType,o=t.originalType,m=t.parentName,p=s(t,["components","mdxType","originalType","parentName"]),d=i(r),u=n,g=d["".concat(m,".").concat(u)]||d[u]||c[u]||o;return r?a.createElement(g,l(l({ref:e},p),{},{components:r})):a.createElement(g,l({ref:e},p))}));function g(t,e){var r=arguments,n=e&&e.mdxType;if("string"==typeof t||n){var o=r.length,l=new Array(o);l[0]=u;var s={};for(var m in e)hasOwnProperty.call(e,m)&&(s[m]=e[m]);s.originalType=t,s[d]="string"==typeof t?t:n,l[1]=s;for(var i=2;i<o;i++)l[i]=r[i];return a.createElement.apply(null,l)}return a.createElement.apply(null,r)}u.displayName="MDXCreateElement"},3509:(t,e,r)=>{r.r(e),r.d(e,{assets:()=>m,contentTitle:()=>l,default:()=>c,frontMatter:()=>o,metadata:()=>s,toc:()=>i});var a=r(7462),n=(r(7294),r(3905));const o={},l="Metrics",s={unversionedId:"core/oasis-node/metrics",id:"core/oasis-node/metrics",title:"Metrics",description:"oasis-node can report a number of metrics to Prometheus server. By default,",source:"@site/docs/core/oasis-node/metrics.md",sourceDirName:"core/oasis-node",slug:"/core/oasis-node/metrics",permalink:"/core/oasis-node/metrics",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/metrics.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"RPC",permalink:"/core/oasis-node/rpc"},next:{title:"oasis-node CLI",permalink:"/core/oasis-node/cli"}},m={},i=[{value:"Configuring <code>oasis-node</code> in Pull Mode",id:"configuring-oasis-node-in-pull-mode",level:2},{value:"Metrics Reported by <code>oasis-node</code>",id:"metrics-reported-by-oasis-node",level:2},{value:"Consensus backends",id:"consensus-backends",level:2},{value:"Metrics Reported by <em>Tendermint</em>",id:"metrics-reported-by-tendermint",level:3}],p={toc:i},d="wrapper";function c(t){let{components:e,...r}=t;return(0,n.kt)(d,(0,a.Z)({},p,r,{components:e,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"metrics"},"Metrics"),(0,n.kt)("p",null,(0,n.kt)("inlineCode",{parentName:"p"},"oasis-node")," can report a number of metrics to Prometheus server. By default,\nno metrics are collected and reported. There is one way to enable metrics\nreporting:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("em",{parentName:"li"},"Pull mode")," listens on given address and waits for Prometheus to scrape the\nmetrics.")),(0,n.kt)("h2",{id:"configuring-oasis-node-in-pull-mode"},"Configuring ",(0,n.kt)("inlineCode",{parentName:"h2"},"oasis-node")," in Pull Mode"),(0,n.kt)("p",null,"To run ",(0,n.kt)("inlineCode",{parentName:"p"},"oasis-node")," in ",(0,n.kt)("em",{parentName:"p"},"pull mode")," set flag ",(0,n.kt)("inlineCode",{parentName:"p"},"--metrics.mode pull")," and provide\nthe listen address with ",(0,n.kt)("inlineCode",{parentName:"p"},"--metrics.address"),". For example"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre"},"oasis-node --metrics.mode pull --metrics.address localhost:3000\n")),(0,n.kt)("p",null,"Then, add the following segment to your ",(0,n.kt)("inlineCode",{parentName:"p"},"prometheus.yml")," and restart\nPrometheus:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-yaml"}," - job_name : 'oasis-node'\n\n scrape_interval: 5s\n\n static_configs:\n - targets: ['localhost:3000']\n")),(0,n.kt)("h2",{id:"metrics-reported-by-oasis-node"},"Metrics Reported by ",(0,n.kt)("inlineCode",{parentName:"h2"},"oasis-node")),(0,n.kt)("p",null,(0,n.kt)("inlineCode",{parentName:"p"},"oasis-node")," reports metrics starting with ",(0,n.kt)("inlineCode",{parentName:"p"},"oasis_"),"."),(0,n.kt)("p",null,"The following metrics are currently reported:"),(0,n.kt)("table",null,(0,n.kt)("thead",{parentName:"table"},(0,n.kt)("tr",{parentName:"thead"},(0,n.kt)("th",{parentName:"tr",align:null},"Name"),(0,n.kt)("th",{parentName:"tr",align:null},"Type"),(0,n.kt)("th",{parentName:"tr",align:null},"Description"),(0,n.kt)("th",{parentName:"tr",align:null},"Labels"),(0,n.kt)("th",{parentName:"tr",align:null},"Package"))),(0,n.kt)("tbody",{parentName:"table"},(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_abci_db_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Total size of the ABCI database (MiB)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/tendermint/abci/mux.go"},"consensus/tendermint/abci"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_codec_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"CBOR codec message size (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null},"call, module"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/cbor/codec.go"},"common/cbor"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_consensus_proposed_blocks"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of blocks proposed by the node."),(0,n.kt)("td",{parentName:"tr",align:null},"backend"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/metrics/metrics.go"},"consensus/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_consensus_signed_blocks"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of blocks signed by the node."),(0,n.kt)("td",{parentName:"tr",align:null},"backend"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/metrics/metrics.go"},"consensus/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_finalized_rounds"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of finalized rounds."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/metrics.go"},"roothash"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_client_calls"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of gRPC calls."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_client_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"gRPC call latency (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_client_stream_writes"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of gRPC stream writes."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_server_calls"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of gRPC calls."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_server_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"gRPC call latency (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_grpc_server_stream_writes"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of gRPC stream writes."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go"},"common/grpc"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_cpu_stime_seconds"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"CPU system time spent by worker as reported by /proc/","<","PID",">","/stat (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/cpu.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_cpu_utime_seconds"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"CPU user time spent by worker as reported by /proc/","<","PID",">","/stat (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/cpu.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_disk_read_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Read data from block storage by the worker as reported by /proc/","<","PID",">","/io (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_disk_usage_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of datadir of the worker (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_disk_written_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Written data from block storage by the worker as reported by /proc/","<","PID",">","/io (bytes)"),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_mem_rss_anon_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of resident anonymous memory of worker as reported by /proc/","<","PID",">","/status (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_mem_rss_file_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of resident file mappings of worker as reported by /proc/","<","PID",">","/status (bytes)"),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_mem_rss_shmem_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of resident shared memory of worker."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_mem_vm_size_bytes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Virtual memory size of worker (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_net_receive_bytes_total"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Received data for each network device as reported by /proc/net/dev (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null},"device"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_net_receive_packets_total"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Received data for each network device as reported by /proc/net/dev (packets)."),(0,n.kt)("td",{parentName:"tr",align:null},"device"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_net_transmit_bytes_total"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Transmitted data for each network device as reported by /proc/net/dev (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null},"device"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_node_net_transmit_packets_total"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Transmitted data for each network device as reported by /proc/net/dev (packets)."),(0,n.kt)("td",{parentName:"tr",align:null},"device"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_registry_entities"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of registry entities."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go"},"registry"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_registry_nodes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of registry nodes."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go"},"registry"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_registry_runtimes"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of registry runtimes."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go"},"registry"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_rhp_failures"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of failed Runtime Host calls."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go"},"runtime/host/protocol"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_rhp_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Runtime Host call latency (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go"},"runtime/host/protocol"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_rhp_successes"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of successful Runtime Host calls."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go"},"runtime/host/protocol"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_roothash_block_interval"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Time between roothash blocks (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/metrics.go"},"roothash"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_storage_failures"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of storage failures."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go"},"storage/api"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_storage_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Storage call latency (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go"},"storage/api"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_storage_successes"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of storage successes."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go"},"storage/api"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_storage_value_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Storage call value size (bytes)."),(0,n.kt)("td",{parentName:"tr",align:null},"call"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go"},"storage/api"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_accepted_transactions"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of accepted transactions (passing check tx)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_local_queue_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of the local transactions schedulable queue (number of entries)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_pending_check_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of the pending to be checked queue (number of entries)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_pending_schedule_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of the main schedulable queue (number of entries)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_rejected_transactions"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of rejected transactions (failing check tx)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_txpool_rim_queue_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Size of the roothash incoming message transactions schedulable queue (number of entries)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go"},"runtime/txpool"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_up"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Is oasis-test-runner active for specific scenario."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/metrics.go"},"oasis-node/cmd/common/metrics"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_aborted_batch_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of aborted batches."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_batch_processing_time"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Time it takes for a batch to finalize (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_batch_runtime_processing_time"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Time it takes for a batch to be processed by the runtime (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_batch_size"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of transactions in a batch."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_epoch_number"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Current epoch number as seen by the worker."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_epoch_transition_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of epoch transitions."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_execution_discrepancy_detected_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of detected execute discrepancies."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_committee_p2p_peers"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of executor committee P2P peers."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_is_backup_worker"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"1 if worker is currently an executor backup worker, 0 otherwise."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_is_worker"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"1 if worker is currently an executor worker, 0 otherwise."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_liveness_live_ratio"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Ratio between live and total rounds. Reports 1 if node is not in committee."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_liveness_live_rounds"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of live rounds in last epoch."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_executor_liveness_total_rounds"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of total rounds in last epoch."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_failed_round_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of failed roothash rounds."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_keymanager_compute_runtime_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of compute runtimes using the key manager."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go"},"worker/keymanager"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_keymanager_enclave_rpc_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of remote Enclave RPC requests via P2P."),(0,n.kt)("td",{parentName:"tr",align:null},"method"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/p2p/metrics.go"},"worker/keymanager/p2p"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_keymanager_policy_update_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of key manager policy updates."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go"},"worker/keymanager"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_node_registered"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Is oasis node registered (binary)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go"},"worker/registration"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_node_registration_eligible"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Is oasis node eligible for registration (binary)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go"},"worker/registration"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_node_status_frozen"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Is oasis node frozen (binary)."),(0,n.kt)("td",{parentName:"tr",align:null}),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go"},"worker/registration"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_node_status_runtime_faults"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of runtime faults."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go"},"worker/registration"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_node_status_runtime_suspended"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"Runtime node suspension status (binary)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go"},"worker/registration"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_processed_block_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of processed roothash blocks."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_processed_event_count"),(0,n.kt)("td",{parentName:"tr",align:null},"Counter"),(0,n.kt)("td",{parentName:"tr",align:null},"Number of processed roothash events."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go"},"worker/common/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_storage_commit_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Latency of storage commit calls (state + outputs) (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/node.go"},"worker/compute/executor/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_storage_full_round"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"The last round that was fully synced and finalized."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go"},"worker/storage/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_storage_pending_round"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"The last round that is in-flight for syncing."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go"},"worker/storage/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_storage_round_sync_latency"),(0,n.kt)("td",{parentName:"tr",align:null},"Summary"),(0,n.kt)("td",{parentName:"tr",align:null},"Storage round sync latency (seconds)."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go"},"worker/storage/committee"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"oasis_worker_storage_synced_round"),(0,n.kt)("td",{parentName:"tr",align:null},"Gauge"),(0,n.kt)("td",{parentName:"tr",align:null},"The last round that was synced but not yet finalized."),(0,n.kt)("td",{parentName:"tr",align:null},"runtime"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go"},"worker/storage/committee"))))),(0,n.kt)("h2",{id:"consensus-backends"},"Consensus backends"),(0,n.kt)("h3",{id:"metrics-reported-by-tendermint"},"Metrics Reported by ",(0,n.kt)("em",{parentName:"h3"},"Tendermint")),(0,n.kt)("p",null,"When ",(0,n.kt)("inlineCode",{parentName:"p"},"oasis-node")," is configured to use ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/#tendermint"},"Tendermint")," for BFT consensus, all\nTendermint metrics are also reported. Consult\n",(0,n.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/main/tendermint-core/metrics.html"},"tendermint-core documentation")," for a list of reported by Tendermint."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4079c408.1377ef62.js b/assets/js/4079c408.1377ef62.js new file mode 100644 index 0000000000..4beee7e34a --- /dev/null +++ b/assets/js/4079c408.1377ef62.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9439],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>h});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,i,r=function(e,t){if(null==e)return{};var n,i,r={},o=Object.keys(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=i.createContext({}),p=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=p(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=p(n),c=r,h=d["".concat(l,".").concat(c)]||d[c]||m[c]||o;return n?i.createElement(h,a(a({ref:t},u),{},{components:n})):i.createElement(h,a({ref:t},u))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,a=new Array(o);a[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,a[1]=s;for(var p=2;p<o;p++)a[p]=n[p];return i.createElement.apply(null,a)}return i.createElement.apply(null,n)}c.displayName="MDXCreateElement"},7685:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>m,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var i=n(7462),r=(n(7294),n(3905));const o={},a="ADR 0013: Runtime Upgrade Improvements",s={unversionedId:"adrs/0013-runtime-upgrades",id:"adrs/0013-runtime-upgrades",title:"ADR 0013: Runtime Upgrade Improvements",description:"Component",source:"@site/docs/adrs/0013-runtime-upgrades.md",sourceDirName:"adrs",slug:"/adrs/0013-runtime-upgrades",permalink:"/adrs/0013-runtime-upgrades",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0013-runtime-upgrades.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0012: Runtime Message Results",permalink:"/adrs/0012-runtime-message-results"},next:{title:"ADR 0014: Signing Runtime Transactions with Hardware Wallet",permalink:"/adrs/0014-runtime-signing-tx-with-hardware-wallet"}},l={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Implementation",id:"implementation",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3}],u={toc:p},d="wrapper";function m(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,i.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"adr-0013-runtime-upgrade-improvements"},"ADR 0013: Runtime Upgrade Improvements"),(0,r.kt)("h2",{id:"component"},"Component"),(0,r.kt)("p",null,"Oasis Core"),(0,r.kt)("h2",{id:"changelog"},"Changelog"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2022-01-25: Initial version")),(0,r.kt)("h2",{id:"status"},"Status"),(0,r.kt)("p",null,"Accepted"),(0,r.kt)("h2",{id:"context"},"Context"),(0,r.kt)("p",null,"Currently major runtime updates incur at least one epoch worth of downtime\nfor the transition period. This is suboptimal, and can be improved to allow\nseamless runtime updates, with some changes to the runtime descriptor and\nscheduler behavior."),(0,r.kt)("h2",{id:"decision"},"Decision"),(0,r.kt)("p",null,"Implement support for seamless breaking runtime upgrades."),(0,r.kt)("h2",{id:"implementation"},"Implementation"),(0,r.kt)("p",null,"Runtime descriptor related changes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'// Runtime represents a runtime.\ntype Runtime struct { // nolint: maligned\n // Deployments specifies the runtime deployments (versions).\n Deployments []*VersionInfo `json:"deployments"`\n\n // Version field is relocated to inside the VersionInfo structure.\n\n // Other unchanged fields omitted for brevity.\n}\n\n// VersionInfo is the per-runtime version information.\ntype VersionInfo struct {\n // Version of the runtime.\n Version version.Version `json:"version"`\n\n // ValidFrom stores the epoch at which, this version is valid.\n ValidFrom beacon.EpochTime `json:"valid_from"`\n\n // TEE is the enclave version information, in an enclave provider specific\n // format if any.\n TEE []byte `json:"tee,omitempty"`\n}\n')),(0,r.kt)("p",null,"The intended workflow here is to:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Deploy runtimes with the initial Deployment populated.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Update the runtime version via the deployment of a new version\nof the descriptor with an additional version info entry.\nSufficient nodes must upgrade their runtime binary and\nconfiguration by the ",(0,r.kt)("inlineCode",{parentName:"p"},"ValidFrom"),' epoch or the runtime will fail\nto be scheduled (no special handling is done, this is the existing\n"insufficient nodes" condition).')),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Aborting or altering pending updates via the deployment of a new version\nof the descriptor with the removed/ammended not-yet-valid ",(0,r.kt)("inlineCode",{parentName:"p"},"Deployments"),"\nis possible in this design, but perhaps should be forbidden.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Altering exisiting ",(0,r.kt)("inlineCode",{parentName:"p"},"Deployments")," entries is strictly forbidden,\nexcept the removal of superceded descriptors.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Deploying descriptors with ",(0,r.kt)("inlineCode",{parentName:"p"},"Deployments")," that will never be valid\n(as in one that is superceded by a newer version) is strictly\nforbidden."))),(0,r.kt)("p",null,"The existing node descriptor is a flat vector of ",(0,r.kt)("inlineCode",{parentName:"p"},"Runtime")," entries\ncontaining the runtime ID, version, and TEE information, so no changes\nare required."),(0,r.kt)("p",null,"On transition to an epoch where a new version takes effect, the consensus\nlayer MAY prune the descriptor's ",(0,r.kt)("inlineCode",{parentName:"p"},"Deployments")," field of superceded versions."),(0,r.kt)("p",null,"The only scheduler and worker side changes are to incorporate the runtime\nversion into scheduling, and to pick the correct deployed version of the\nruntime to use, both on a once-per-epoch-per-runtime basis."),(0,r.kt)("h2",{id:"consequences"},"Consequences"),(0,r.kt)("h3",{id:"positive"},"Positive"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Seamless runtime upgrades will be possible.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The code changes required are relatively minimal, and this is likely\nthe simplest possible solution that will work."))),(0,r.kt)("h3",{id:"negative"},"Negative"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"It may be overly simplistic.")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/409fc1d8.aae274fd.js b/assets/js/409fc1d8.aae274fd.js new file mode 100644 index 0000000000..83ce874652 --- /dev/null +++ b/assets/js/409fc1d8.aae274fd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[651],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var s=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,s)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,s,a=function(e,t){if(null==e)return{};var n,s,a={},i=Object.keys(e);for(s=0;s<i.length;s++)n=i[s],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(s=0;s<i.length;s++)n=i[s],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var u=s.createContext({}),l=function(e){var t=s.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},m=function(e){var t=l(e.components);return s.createElement(u.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return s.createElement(s.Fragment,{},t)}},d=s.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,u=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),c=l(n),d=a,h=c["".concat(u,".").concat(d)]||c[d]||p[d]||i;return n?s.createElement(h,r(r({ref:t},m),{},{components:n})):s.createElement(h,r({ref:t},m))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var o={};for(var u in t)hasOwnProperty.call(t,u)&&(o[u]=t[u]);o.originalType=e,o[c]="string"==typeof e?e:a,r[1]=o;for(var l=2;l<i;l++)r[l]=n[l];return s.createElement.apply(null,r)}return s.createElement.apply(null,n)}d.displayName="MDXCreateElement"},9455:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var s=n(7462),a=(n(7294),n(3905));const i={},r="ADR 0011: Incoming Runtime Messages",o={unversionedId:"adrs/0011-incoming-runtime-messages",id:"adrs/0011-incoming-runtime-messages",title:"ADR 0011: Incoming Runtime Messages",description:"Component",source:"@site/docs/adrs/0011-incoming-runtime-messages.md",sourceDirName:"adrs",slug:"/adrs/0011-incoming-runtime-messages",permalink:"/adrs/0011-incoming-runtime-messages",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0011-incoming-runtime-messages.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0010: VRF-based Committee Elections",permalink:"/adrs/0010-vrf-elections"},next:{title:"ADR 0012: Runtime Message Results",permalink:"/adrs/0012-runtime-message-results"}},u={},l=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Incoming Message",id:"incoming-message",level:3},{value:"Executor Commitments",id:"executor-commitments",level:3},{value:"Runtime Block Header",id:"runtime-block-header",level:3},{value:"Runtime Descriptor",id:"runtime-descriptor",level:3},{value:"State",id:"state",level:3},{value:"Transaction Methods",id:"transaction-methods",level:3},{value:"Submit Message",id:"submit-message",level:4},{value:"Queries",id:"queries",level:3},{value:"Runtime Host Protocol",id:"runtime-host-protocol",level:3},{value:"Rust Runtime Support Library",id:"rust-runtime-support-library",level:3},{value:"Executor Processing",id:"executor-processing",level:3},{value:"Runtime Processing",id:"runtime-processing",level:3},{value:"Root Hash Commitment Processing",id:"root-hash-commitment-processing",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3}],m={toc:l},c="wrapper";function p(e){let{components:t,...n}=e;return(0,a.kt)(c,(0,s.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0011-incoming-runtime-messages"},"ADR 0011: Incoming Runtime Messages"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2022-01-07: Update based on insights from implementation"),(0,a.kt)("li",{parentName:"ul"},"2021-12-09: Introduce an explicit fee field, clarify token transfers"),(0,a.kt)("li",{parentName:"ul"},"2021-10-26: Initial draft")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"There is currently a single mechanism through which the consensus layer and a\nruntime may interact in a consistent and secure manner. This is the mechanism\nof runtime messages that can be emitted by runtimes (see ",(0,a.kt)("a",{parentName:"p",href:"/adrs/0003-consensus-runtime-token-transfer"},"ADR 3"),") and allows\nthe consensus layer to act on a runtime's behalf. This mechanism is currently\nused for ",(0,a.kt)("em",{parentName:"p"},"pulling")," tokens from consensus layer accounts that have previously\nset proper allowances and for updating the runtime descriptor when the runtime\ngovernance model (see ",(0,a.kt)("a",{parentName:"p",href:"/adrs/0004-runtime-governance"},"ADR 4"),") is in effect."),(0,a.kt)("p",null,"This ADR proposes to implement the reverse mechanism where anyone issuing a\ntransaction at the consensus layer can queue arbitrary messages for processing\nby the runtime in its next round."),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("p",null,"On a high level this proposal affects the following components:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"A new transaction method ",(0,a.kt)("inlineCode",{parentName:"p"},"roothash.SubmitMsg")," is added to the roothash\nconsensus service to queue a new message for the specific runtime.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Additional per-runtime state is added to the roothash service containing the\ncurrently queued messages, sorted by arrival time.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"During processing of a round the proposer may propose to pop any number of\nmessages and process them by pushing them to the runtime, similar as it does\nfor transaction batches. This is of course subject to discrepancy detection.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The runtime host protocol is updated to allow the host to push arbitrary\nincoming messages in addition to the transaction batch.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The runtime descriptor is updated to include a field that specifies the\nmaximum size of the incoming message queue."))),(0,a.kt)("h3",{id:"incoming-message"},"Incoming Message"),(0,a.kt)("p",null,"Each incoming message is represented as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type IncomingMessage struct {\n // ID is the unique identifier of the message.\n ID uint64 `json:"id"`\n\n // Caller is the address of the caller authenticated by the consensus layer.\n Caller staking.Address `json:"caller"`\n\n // Tag is an optional tag provided by the caller which is ignored and can be used to match\n // processed incoming message events later.\n Tag uint64 `json:"tag,omitempty"`\n\n // Fee is the fee sent into the runtime as part of the message being sent.\n // The fee is transferred before the message is processed by the runtime.\n Fee quantity.Quantity `json:"fee,omitempty"`\n\n // Tokens are any tokens sent into the runtime as part of the message being\n // sent. The tokens are transferred before the message is processed by the\n // runtime.\n Tokens quantity.Quantity `json:"tokens,omitempty"`\n\n // Data is arbitrary runtime-dependent data.\n Data []byte `json:"data,omitempty"`\n}\n')),(0,a.kt)("h3",{id:"executor-commitments"},"Executor Commitments"),(0,a.kt)("p",null,"The compute results header structure is updated to include two fields that\nspecify the number and hash of incoming messages included in a batch as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type ComputeResultsHeader struct {\n // ... existing fields omitted ...\n\n // InMessagesHash is the hash of processed incoming messages.\n InMessagesHash *hash.Hash `json:"in_msgs_hash,omitempty"`\n // InMessagesCount is the number of processed incoming messages.\n InMessagesCount uint32 `json:"in_msgs_count,omitempty"`\n}\n')),(0,a.kt)("p",null,"Where the hash of included incoming messages is computed as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},"// InMessagesHash returns a hash of provided incoming runtime messages.\nfunc InMessagesHash(msgs []IncomingMessage) (h hash.Hash) {\n if len(msgs) == 0 {\n // Special case if there are no messages.\n h.Empty()\n return\n }\n return hash.NewFrom(msgs)\n}\n")),(0,a.kt)("p",null,"Note that this also requires the enclave RAK signature (for runtimes requiring\nthe use of TEEs) to be computed over this updated new header."),(0,a.kt)("h3",{id:"runtime-block-header"},"Runtime Block Header"),(0,a.kt)("p",null,"The runtime block header is updated to include the ",(0,a.kt)("inlineCode",{parentName:"p"},"InMessagesHash")," field as\nfollows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type Header struct {\n // ... existing fields omitted ...\n\n // InMessagesHash is the hash of processed incoming messages.\n InMessagesHash hash.Hash `json:"in_msgs_hash"`\n}\n')),(0,a.kt)("h3",{id:"runtime-descriptor"},"Runtime Descriptor"),(0,a.kt)("p",null,"This proposal updates the runtime transaction scheduler parameters (stored under\nthe ",(0,a.kt)("inlineCode",{parentName:"p"},"txn_scheduler")," field of the runtime descriptor) as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type TxnSchedulerParameters struct {\n // ... existing fields omitted ...\n\n // MaxInMessages specifies the maximum size of the incoming message queue\n // for this runtime.\n MaxInMessages uint32 `json:"max_in_messages,omitempty"`\n}\n')),(0,a.kt)("p",null,"It also updates the runtime staking parameters (stored under the ",(0,a.kt)("inlineCode",{parentName:"p"},"staking")," field\nof the runtime descriptor) as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type RuntimeStakingParameters struct {\n // ... existing fields omitted ...\n\n // MinInMessageFee specifies the minimum fee that the incoming message must\n // include for the message to be queued.\n MinInMessageFee quantity.Quantity `json:"min_in_msg_fee,omitempty"`\n}\n')),(0,a.kt)("h3",{id:"state"},"State"),(0,a.kt)("p",null,"This proposal introduces/updates the following consensus state in the roothash\nmodule:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Incoming message queue metadata (",(0,a.kt)("inlineCode",{parentName:"strong"},"0x28"),")")),(0,a.kt)("p",{parentName:"li"},"Metadata for the incoming message queue."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"0x28 <H(runtime-id) (hash.Hash)>\n")),(0,a.kt)("p",{parentName:"li"},"The value is the following CBOR-serialized structure:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type IncomingMessageQueue struct {\n // Size contains the current size of the queue.\n Size uint32 `json:"size,omitempty"`\n\n // NextSequenceNumber contains the sequence number that should be used for\n // the next queued message.\n NextSequenceNumber uint64 `json:"next_sequence_number,omitempty"`\n}\n'))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Incoming message queue item (",(0,a.kt)("inlineCode",{parentName:"strong"},"0x29"),")")),(0,a.kt)("p",{parentName:"li"},"A queue of incoming messages pending to be delivered to the runtime in the\nnext round."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"0x29 <H(runtime-id) (hash.Hash)> <sequence-no (uint64)>\n")),(0,a.kt)("p",{parentName:"li"},"The value is a CBOR-serialized ",(0,a.kt)("inlineCode",{parentName:"p"},"IncomingMessage")," structure."))),(0,a.kt)("h3",{id:"transaction-methods"},"Transaction Methods"),(0,a.kt)("p",null,"This proposal updates the following transaction methods in the roothash module:"),(0,a.kt)("h4",{id:"submit-message"},"Submit Message"),(0,a.kt)("p",null,"The submit message method allows anyone to submit incoming runtime messages to\nbe queued for delivery to the given runtime."),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Method name:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"roothash.SubmitMsg\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Body:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type SubmitMsg struct {\n ID common.Namespace `json:"id"`\n Fee quantity.Quantity `json:"fee,omitempty"`\n Tokens quantity.Quantity `json:"tokens,omitempty"`\n Data []byte `json:"data,omitempty"`\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Fields:")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"id")," specifies the destination runtime's identifier."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"fee")," specifies the fee that should be sent into the runtime as part of the\nmessage being sent. The fee is transferred before the message is processed by\nthe runtime."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"tokens")," specifies any tokens to be sent into the runtime as part of the\nmessage being sent. The tokens are transferred before the message is processed\nby the runtime."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"data")," arbitrary data to be sent to the runtime for processing.")),(0,a.kt)("p",null,"The transaction signer implicitly specifies the caller. Upon executing the\nsubmit message method the following actions are performed:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Gas is accounted for (new ",(0,a.kt)("inlineCode",{parentName:"p"},"submitmsg")," gas operation).")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The runtime descriptor for runtime ",(0,a.kt)("inlineCode",{parentName:"p"},"id")," is retrieved. If the runtime does not\nexist or is currently suspended the method fails with ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrInvalidRuntime"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"txn_scheduler.max_in_messages")," field in the runtime descriptor is\nchecked. If it is equal to zero the method fails with\n",(0,a.kt)("inlineCode",{parentName:"p"},"ErrIncomingMessageQueueFull"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If the value of the ",(0,a.kt)("inlineCode",{parentName:"p"},"fee")," field is smaller than the value of the\n",(0,a.kt)("inlineCode",{parentName:"p"},"staking.min_in_msg_fee")," field in the runtime descriptor the method fails with\n",(0,a.kt)("inlineCode",{parentName:"p"},"ErrIncomingMessageInsufficientFee"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The number of tokens corresponding to ",(0,a.kt)("inlineCode",{parentName:"p"},"fee + tokens")," are moved from the\ncaller's account into the runtime account. If there is insufficient balance to\ndo so the method fails with ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrInsufficientBalance"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The incoming queue metadata structure is fetched. If it doesn't yet exist it\nis populated with zero values.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If the value of the ",(0,a.kt)("inlineCode",{parentName:"p"},"size")," field in the metadata structure is equal to or\nlarger than the value of the ",(0,a.kt)("inlineCode",{parentName:"p"},"txn_scheduler.max_in_messages")," field in the\nruntime descriptor the method fails with ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrIncomingMessageQueueFull"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"An ",(0,a.kt)("inlineCode",{parentName:"p"},"IncomingMessage")," structure is generated based on the caller and method\nbody and the value of the ",(0,a.kt)("inlineCode",{parentName:"p"},"next_sequence_number")," metadata field is used to\ngenerate a proper key for storing it in the queue. The structure is inserted\ninto the queue.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"size")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"next_sequence_number")," fields are incremented and the updated\nmetadata is saved."))),(0,a.kt)("h3",{id:"queries"},"Queries"),(0,a.kt)("p",null,"This proposal adds the following new query methods in the roothash module by\nupdating the ",(0,a.kt)("inlineCode",{parentName:"p"},"roothash.Backend")," interface as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type Backend interface {\n // ... existing methods omitted ...\n\n // GetIncomingMessageQueueMeta returns the given runtime\'s incoming message queue metadata.\n GetIncomingMessageQueueMeta(ctx context.Context, request *RuntimeRequest) (*message.IncomingMessageQueueMeta, error)\n\n // GetIncomingMessageQueue returns the given runtime\'s queued incoming messages.\n GetIncomingMessageQueue(ctx context.Context, request *InMessageQueueRequest) ([]*message.IncomingMessage, error)\n}\n\n// IncomingMessageQueueMeta is the incoming message queue metadata.\ntype IncomingMessageQueueMeta struct {\n // Size contains the current size of the queue.\n Size uint32 `json:"size,omitempty"`\n\n // NextSequenceNumber contains the sequence number that should be used for the next queued\n // message.\n NextSequenceNumber uint64 `json:"next_sequence_number,omitempty"`\n}\n\n// InMessageQueueRequest is a request for queued incoming messages.\ntype InMessageQueueRequest struct {\n RuntimeID common.Namespace `json:"runtime_id"`\n Height int64 `json:"height"`\n\n Offset uint64 `json:"offset,omitempty"`\n Limit uint32 `json:"limit,omitempty"`\n}\n')),(0,a.kt)("h3",{id:"runtime-host-protocol"},"Runtime Host Protocol"),(0,a.kt)("p",null,"This proposal updates the existing host to runtime requests in the runtime host\nprotocol as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type RuntimeExecuteTxBatchRequest struct {\n // ... existing fields omitted ...\n\n // IncomingMessages are the incoming messages from the consensus layer that\n // should be processed by the runtime in this round.\n IncomingMessages []*IncomingMessage `json:"in_messages,omitempty"`\n}\n')),(0,a.kt)("h3",{id:"rust-runtime-support-library"},"Rust Runtime Support Library"),(0,a.kt)("p",null,"This proposal updates the ",(0,a.kt)("inlineCode",{parentName:"p"},"transaction::Dispatcher")," trait as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-rust"},"pub trait Dispatcher: Send + Sync {\n // ... existing unchanged methods omitted ...\n\n /// Execute the transactions in the given batch.\n fn execute_batch(\n &self,\n ctx: Context,\n batch: &TxnBatch,\n in_msgs: Vec<IncomingMessage>, // Added argument.\n ) -> Result<ExecuteBatchResult, RuntimeError>;\n}\n")),(0,a.kt)("h3",{id:"executor-processing"},"Executor Processing"),(0,a.kt)("p",null,"The executor processing pipeline is changed such that pending incoming messages\nare queried before the next round starts and are then passed to the runtime via\nthe runtime host protocol."),(0,a.kt)("p",null,"The executor may perform checks to estimate resource use early, similarly to how\nchecks are performed for transactions as they arrive."),(0,a.kt)("h3",{id:"runtime-processing"},"Runtime Processing"),(0,a.kt)("p",null,"The proposal requires that messages are processed by the runtime in queue order\n(e.g. on each round ",(0,a.kt)("inlineCode",{parentName:"p"},"InMessagesCount")," messages are poped from the queue). This\nsimplifies the design but the runtimes need to carefully consider how much\nresources to allocate for executing messages (vs. regular transactions) in a\nround."),(0,a.kt)("p",null,'The runtime has full autonomy in choosing how many messages to execute as it\nis given the complete message batch. It should first compute how many messages\nto process by running them in "check" mode and computing how much gas (or other\nresources) they take and then choosing as many as fits.'),(0,a.kt)("p",null,"Specifying these details is left to the runtime implementation although the SDK\nis expected to adopt an approach with separate ",(0,a.kt)("inlineCode",{parentName:"p"},"max_inmsg_gas")," and\n",(0,a.kt)("inlineCode",{parentName:"p"},"max_inmsg_slots")," parameters which limits how resources are allocated for\nincoming message processing in each round. If a single message exceeds either of\nthese limits it will result in execution failure of that message."),(0,a.kt)("h3",{id:"root-hash-commitment-processing"},"Root Hash Commitment Processing"),(0,a.kt)("p",null,"The processing of executor commitments is modified as follows:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"No changes are made to the discrepancy detection and resolution protocols\nbesides the newly added fields being taken into account in discrepancy\ndetermination.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"After a successful round, the ",(0,a.kt)("inlineCode",{parentName:"p"},"InMessagesCount")," field of the compute body is\nchecked and the corresponding number of messages are popped from the queue in\nincreasing order of their sequence numbers. The queue metadata is updated\naccoordingly by decrementing the value of the ",(0,a.kt)("inlineCode",{parentName:"p"},"size")," field and the\n",(0,a.kt)("inlineCode",{parentName:"p"},"InMessagesHash")," is added to the newly emitted block header."))),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Consensus layer transactions can trigger actions in the runtime without\nadditional runtime transactions. This would also allow pushing tokens into\nthe runtime via a consensus layer transaction or even invoking smart contracts\nthat result in consensus layer actions to happen (via emitted messages).")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Each runtime can define the format of incoming messages. The SDK would likely\nuse something that contains a transaction (either signed to support\nnon-Ed25519 callers or unsigned for smaller Ed25519-based transactions) so\narbitrary invocations would be possible."))),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Storing the queue will increase the size of consensus layer state.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"This could lead to incoming messages being used exclusively to interact with a\nruntime leading to the consensus layer getting clogged with incoming message\nsubmission transactions. Posting such messages would be more expensive though\nas it would require paying per transaction consensus layer fees in addition to\nthe runtime fees. If clogging does eventually happen the fees can be adjusted\nto encourage transaction submission to runtimes directly."))),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Allows rollup-like constructions where all transactions are posted to the\nconsensus layer first and the runtime is just executing those.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Retrieving the result of processing an incoming message is more involved."))))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4129286c.143440d1.js b/assets/js/4129286c.143440d1.js new file mode 100644 index 0000000000..3395f78f8e --- /dev/null +++ b/assets/js/4129286c.143440d1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5156],{2776:s=>{s.exports=JSON.parse('{"name":"@easyops-cn/docusaurus-search-local","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/414b6464.337876c5.js b/assets/js/414b6464.337876c5.js new file mode 100644 index 0000000000..cd37755682 --- /dev/null +++ b/assets/js/414b6464.337876c5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8905],{3905:(e,t,a)=>{a.d(t,{Zo:()=>m,kt:()=>k});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){n(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,r,n=function(e,t){if(null==e)return{};var a,r,n={},i=Object.keys(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var l=r.createContext({}),p=function(e){var t=r.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},m=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=p(a),c=n,k=u["".concat(l,".").concat(c)]||u[c]||d[c]||i;return a?r.createElement(k,o(o({ref:t},m),{},{components:a})):r.createElement(k,o({ref:t},m))}));function k(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:n,o[1]=s;for(var p=2;p<i;p++)o[p]=a[p];return r.createElement.apply(null,o)}return r.createElement.apply(null,a)}c.displayName="MDXCreateElement"},10:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var r=a(7462),n=(a(7294),a(3905));const i={},o="Testnet",s={unversionedId:"node/testnet/README",id:"node/testnet/README",title:"Testnet",description:"These are the current parameters for the Testnet, a test-only network for",source:"@site/docs/node/testnet/README.md",sourceDirName:"node/testnet",slug:"/node/testnet/",permalink:"/node/testnet/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/testnet/README.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Upgrade Log",permalink:"/node/mainnet/upgrade-log"},next:{title:"Upgrade Log",permalink:"/node/testnet/upgrade-log"}},l={},p=[{value:"ParaTimes",id:"paratimes",level:2},{value:"Cipher",id:"cipher",level:3},{value:"Emerald",id:"emerald",level:3},{value:"Sapphire",id:"sapphire",level:3},{value:"Key Manager",id:"key-manager",level:3}],m={toc:p},u="wrapper";function d(e){let{components:t,...a}=e;return(0,n.kt)(u,(0,r.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"testnet"},"Testnet"),(0,n.kt)("p",null,"These are the current parameters for the Testnet, a test-only network for\ntesting out upcoming features and changes to the protocol."),(0,n.kt)("admonition",{type:"danger"},(0,n.kt)("p",{parentName:"admonition"},(0,n.kt)("strong",{parentName:"p"},"The Testnet may be subject to frequent version upgrades and state resets.")),(0,n.kt)("p",{parentName:"admonition"},"Also note that while the Testnet does use actual TEEs, due to experimental\nsoftware and different security parameters, ",(0,n.kt)("strong",{parentName:"p"},"confidentiality of confidential\nParaTimes on the Testnet is not guaranteed")," -- all transactions and state\npublished on the Testnet should be considered public even when stored inside\nconfidential ParaTimes.")),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"On the Testnet, TEST tokens are in use -- if you need some to test your clients, nodes or paratimes, feel free to use our ",(0,n.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev"},"Testnet Faucet"),". Note that these are test-only tokens and account balances, as any other state, may be frequently reset.")),(0,n.kt)("p",null,"This page is meant to be kept up to date with the information from the currently released Testnet. Use the information here to deploy or upgrade your node on the Testnet."),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Latest Testnet version: ",(0,n.kt)("strong",{parentName:"li"},"2022-03-03")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/testnet-artifacts/releases/download/2022-03-03/genesis.json"},"Genesis file"),":",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"SHA256: ",(0,n.kt)("inlineCode",{parentName:"li"},"4c3d271253d2a324816de3b9a048261b674471e7d4f9a02995a769489bd41984")))),(0,n.kt)("li",{parentName:"ul"},"Genesis document's hash (",(0,n.kt)("a",{parentName:"li",href:"/node/genesis-doc#genesis-file-vs-genesis-document"},"explanation"),"):",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a")))),(0,n.kt)("li",{parentName:"ul"},"Oasis seed node address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"53572F689E5BACDD3C6527E6594EC49C8F3093F6@34.86.165.6:26656"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other seed nodes besides the one provided here.")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")),(0,n.kt)("li",{parentName:"ul"},"To sync from genesis, you need to start with an earlier version first\n(",(0,n.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"read more"),"):",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.0.3"},"22.0.3")," (until epoch ",(0,n.kt)("strong",{parentName:"li"},"15056"),")"))))),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway"},"Oasis Rosetta Gateway")," version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.5.0"},"2.5.0"))))),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"The Oasis Node is part of the Oasis Core release.")),(0,n.kt)("h2",{id:"paratimes"},"ParaTimes"),(0,n.kt)("p",null,"This section contains parameters for various ParaTimes known to be deployed on the Testnet. Similar to the Testnet, these may be subject to frequent version upgrades and/or state resets."),(0,n.kt)("h3",{id:"cipher"},"Cipher"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"0000000000000000000000000000000000000000000000000000000000000000")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v2.6.2-testnet"},"2.6.2-testnet")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")),(0,n.kt)("h3",{id:"emerald"},"Emerald"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"00000000000000000000000000000000000000000000000072c8215e60d5bca7")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version (or ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/emerald-paratime/tree/v10.0.0-testnet#building"},"build your own"),"):",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v10.0.0-testnet"},"10.0.0-testnet")))),(0,n.kt)("li",{parentName:"ul"},"Web3 Gateway version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v3.4.0-rc1"},"3.4.0-rc1"))))),(0,n.kt)("h3",{id:"sapphire"},"Sapphire"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.6.1-testnet"},"0.6.1-testnet")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.6.2-testnet"},"0.6.2-testnet")))),(0,n.kt)("li",{parentName:"ul"},"Web3 Gateway version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v3.4.0-rc1"},"3.4.0-rc1")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")),(0,n.kt)("h3",{id:"key-manager"},"Key Manager"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"4000000000000000000000000000000000000000000000004a1a53dff2ae482d")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/keymanager-paratime/releases/tag/v0.3.3-testnet"},"0.3.3-testnet")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/433ff9f9.43084627.js b/assets/js/433ff9f9.43084627.js new file mode 100644 index 0000000000..71bec24242 --- /dev/null +++ b/assets/js/433ff9f9.43084627.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1266],{3905:(e,n,t)=>{t.d(n,{Zo:()=>d,kt:()=>b});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?s(Object(t),!0).forEach((function(n){o(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):s(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function r(e,n){if(null==e)return{};var t,a,o=function(e,n){if(null==e)return{};var t,a,o={},s=Object.keys(e);for(a=0;a<s.length;a++)t=s[a],n.indexOf(t)>=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a<s.length;a++)t=s[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=a.createContext({}),c=function(e){var n=a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},d=function(e){var n=c(e.components);return a.createElement(p.Provider,{value:n},e.children)},l="mdxType",f={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,s=e.originalType,p=e.parentName,d=r(e,["components","mdxType","originalType","parentName"]),l=c(t),m=o,b=l["".concat(p,".").concat(m)]||l[m]||f[m]||s;return t?a.createElement(b,i(i({ref:n},d),{},{components:t})):a.createElement(b,i({ref:n},d))}));function b(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var s=t.length,i=new Array(s);i[0]=m;var r={};for(var p in n)hasOwnProperty.call(n,p)&&(r[p]=n[p]);r.originalType=e,r[l]="string"==typeof e?e:o,i[1]=r;for(var c=2;c<s;c++)i[c]=t[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},1802:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>i,default:()=>f,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var a=t(7462),o=(t(7294),t(3905));const s={title:"Network",description:"Managing Mainnet, Testnet or Localnet endpoints"},i="Manage Your Oasis Networks",r={unversionedId:"general/manage-tokens/cli/network",id:"general/manage-tokens/cli/network",title:"Network",description:"Managing Mainnet, Testnet or Localnet endpoints",source:"@site/docs/general/manage-tokens/cli/network.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/network",permalink:"/general/manage-tokens/cli/network",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/network.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Network",description:"Managing Mainnet, Testnet or Localnet endpoints"},sidebar:"general",previous:{title:"Setup",permalink:"/general/manage-tokens/cli/setup"},next:{title:"ParaTime",permalink:"/general/manage-tokens/cli/paratime"}},p={},c=[{value:"Add a Network",id:"add",level:2},{value:"Add a Local Network",id:"add-local",level:2},{value:"List Networks",id:"list",level:2},{value:"Remove a Network",id:"remove",level:2},{value:"Set Default Network",id:"set-default",level:2},{value:"Change a Network's RPC Endpoint",id:"set-rpc",level:2},{value:"Advanced",id:"advanced",level:2},{value:"Governance Operations",id:"governance",level:3},{value:"<code>list</code>",id:"governance-list",level:4},{value:"<code>show</code>",id:"governance-show",level:4},{value:"<code>cast-vote</code>",id:"governance-cast-vote",level:4},{value:"<code>create-proposal</code>",id:"governance-create-proposal",level:4},{value:"Show Network Properties",id:"show",level:3},{value:"<code>entities</code>",id:"show-entities",level:4},{value:"<code>nodes</code>",id:"show-nodes",level:4},{value:"<code>paratimes</code>",id:"show-paratimes",level:4},{value:"<code>validators</code>",id:"show-validators",level:4},{value:"<code>native-token</code>",id:"show-native-token",level:4},{value:"<code>gas-costs</code>",id:"show-gas-costs",level:4},{value:"<code><id></code>",id:"show-id",level:4},{value:"Status of the Network's Endpoint",id:"status",level:3}],d={toc:c},l="wrapper";function f(e){let{components:n,...t}=e;return(0,o.kt)(l,(0,a.Z)({},d,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"manage-your-oasis-networks"},"Manage Your Oasis Networks"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"network")," command is used to manage the Mainnet, Testnet or Localnet\nendpoints Oasis CLI will be connecting to."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"network")," command is commonly used:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"on network upgrades, because the chain domain separation context is changed\ndue to a new ",(0,o.kt)("a",{parentName:"li",href:"/core/consensus/genesis#genesis-documents-hash"},"genesis document"),","),(0,o.kt)("li",{parentName:"ul"},"when setting up a local ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node")," instance instead of relying on public\ngRPC endpoints,"),(0,o.kt)("li",{parentName:"ul"},"when running a private Localnet with ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-net-runner"),","),(0,o.kt)("li",{parentName:"ul"},"when examining network properties such as the native token, the network\nregistry, the validator set and others.")),(0,o.kt)("p",null,"Oasis CLI supports both ",(0,o.kt)("strong",{parentName:"p"},"remote endpoints via the secure gRPC protocol")," and\n",(0,o.kt)("strong",{parentName:"p"},"local Unix socket endpoints"),"."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"When running the Oasis CLI for the first time, it will automatically configure\nthe current Mainnet and Testnet endpoints.")),(0,o.kt)("h2",{id:"add"},"Add a Network"),(0,o.kt)("p",null,"Invoke ",(0,o.kt)("inlineCode",{parentName:"p"},"network add <name> <chain-context> <rpc-endpoint>")," to add a new\nendpoint with a specific chain domain separation context and a gRPC address."),(0,o.kt)("p",null,"For TCP/IP endpoints, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network add testnet_alt 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet2.grpc.oasis.dev:443\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"? Description: Testnet alternative\n? Denomination symbol: TEST\n? Denomination decimal places: (9)\n")),(0,o.kt)("p",null,"For Unix sockets, use:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network add testnet_local 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a unix:/serverdir_testnet/internal.sock\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"? Description: Testnet network, local node\n? Denomination symbol: TEST\n? Denomination decimal places: (9)\n")),(0,o.kt)("h2",{id:"add-local"},"Add a Local Network"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network add-local <name> <rpc-endpoint>")," command can be used if you are\nrunning a local instance of ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node"),". In this case, Oasis CLI will\nautodetect the native token symbol and decimal places, the chain domain\nseparation context and registered ParaTimes."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis network add-local testnet_local unix:/serverdir_testnet/internal.sock\n")),(0,o.kt)("h2",{id:"list"},"List Networks"),(0,o.kt)("p",null,"Invoke ",(0,o.kt)("inlineCode",{parentName:"p"},"network list")," to list all configured networks."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"NAME CHAIN CONTEXT RPC \nmainnet (*) b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 grpc.oasis.dev:443 \nmainnet_local b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 unix:/serverdir_mainnet/internal.sock \ntestnet 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet.grpc.oasis.dev:443 \ntestnet_alt 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet2.grpc.oasis.dev:443 \n")),(0,o.kt)("p",null,"The ",(0,o.kt)("a",{parentName:"p",href:"#set-default"},"default network")," is marked with the ",(0,o.kt)("inlineCode",{parentName:"p"},"(*)")," sign."),(0,o.kt)("h2",{id:"remove"},"Remove a Network"),(0,o.kt)("p",null,"Use ",(0,o.kt)("inlineCode",{parentName:"p"},"network remove <name>")," to remove the given network configuration including\nall dependant ParaTimes."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network remove testnet_alt\n")),(0,o.kt)("h2",{id:"set-default"},"Set Default Network"),(0,o.kt)("p",null,"To change the default network for future Oasis CLI operations, use\n",(0,o.kt)("inlineCode",{parentName:"p"},"network set-default <name>"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"NAME CHAIN CONTEXT RPC \nmainnet (*) b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 grpc.oasis.dev:443 \nmainnet_local b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 unix:/serverdir_mainnet/internal.sock \ntestnet 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet.grpc.oasis.dev:443 \n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network set-default mainnet_local\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"NAME CHAIN CONTEXT RPC \nmainnet b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 grpc.oasis.dev:443 \nmainnet_local (*) b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 unix:/serverdir_mainnet/internal.sock \ntestnet 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet.grpc.oasis.dev:443 \n")),(0,o.kt)("h2",{id:"set-rpc"},"Change a Network's RPC Endpoint"),(0,o.kt)("p",null,"To change the RPC address of the already configured network, run\n",(0,o.kt)("inlineCode",{parentName:"p"},"network set-rpc <name> <new_endpoint>"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"NAME CHAIN CONTEXT RPC \nmainnet (*) b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 grpc.oasis.dev:443 \nmainnet_local b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 unix:/serverdir_mainnet/internal.sock \ntestnet 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet.grpc.oasis.dev:443 \ntestnet_alt 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet2.grpc.oasis.dev:443 \n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network set-rpc testnet_alt testnet3.grpc.oasis.dev:443\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"NAME CHAIN CONTEXT RPC \nmainnet (*) b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 grpc.oasis.dev:443 \nmainnet_local b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535 unix:/serverdir_mainnet/internal.sock \ntestnet 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet.grpc.oasis.dev:443 \ntestnet_alt 50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a testnet3.grpc.oasis.dev:443 \n")),(0,o.kt)("h2",{id:"advanced"},"Advanced"),(0,o.kt)("h3",{id:"governance"},"Governance Operations"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network governance")," command is aimed towards validators for proposing\nor voting on-chain for network upgrades or changes to other crucial network\nparameters."),(0,o.kt)("h4",{id:"governance-list"},(0,o.kt)("inlineCode",{parentName:"h4"},"list")),(0,o.kt)("p",null,"Use ",(0,o.kt)("inlineCode",{parentName:"p"},"network list")," to view all past and still active governance proposals.\nEach proposal has its unique subsequent ID, a submitter, an epoch when the\nproposal was created and when it closes and a state."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network governance list --network testnet\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"ID KIND SUBMITTER CREATED AT CLOSES AT STATE \n1 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 5633 5645 passed \n2 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 7525 7537 passed \n3 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 8817 8829 passed \n4 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 14183 14195 passed \n5 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 14869 14881 passed \n6 cancel upgrade 5 oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 14895 14907 passed \n7 upgrade oasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj 14982 14994 passed \n")),(0,o.kt)("h4",{id:"governance-show"},(0,o.kt)("inlineCode",{parentName:"h4"},"show")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network governance show <proposal-id>")," shows detailed information on\npast or opened governance proposals on the consensus layer."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network governance show 5 --network localhost_testnet\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Network: localhost_testnet\nProposal ID: 5\nStatus: passed\nResults:\n - yes: 40353433694198429\n - no: 0\n - abstain: 0\n\n=== VOTED STAKE ===\nTotal voting stake: 50569514477387972\nVoted stake: 40353433694198429 (79.80%)\nVoted yes stake: 40353433694198429 (100.00%)\nThreshold: 68%\n\n=== VALIDATORS VOTED ===\n 1. oasis1qz2tg4hsatlxfaf8yut9gxgv8990ujaz4sldgmzx,<none>,10090915233195893 (19.95%)\n 2. oasis1qqv25adrld8jjquzxzg769689lgf9jxvwgjs8tha,<none>,10088536651526034 (19.95%)\n 3. oasis1qq2vzcvxn0js5unsch5me2xz4kr43vcasv0d5eq4,<none>,10087294462687006 (19.95%)\n 4. oasis1qz424yg28jqmgfq3xvly6ky64jqnmlylfc27d7cp,<none>,10086687346789496 (19.95%)\n\n=== VALIDATORS NOT VOTED ===\n 1. oasis1qr37y56g92chzvsew54kj7gu47cxyly7jytt5rm0,<none>,10086569233063782 (19.95%)\n 2. oasis1qrwncs459lauc77zw23efdn9dmfcp23cxv095l5z,GateOmega,36880124779329 (0.07%)\n 3. oasis1qq60zmsfca0gvmm3v8906pn5zqtt4ee2ssexramg,Validatrium,33702388192293 (0.07%)\n 4. oasis1qzjm0zwfg4egs9kk4d9rkujudzk8pjp5rvxyr3ag,Munay Network,11688006553404 (0.02%)\n 5. oasis1qpq97fm6lf87jzms9agd6z902nh7axtxvus6m352,LDV,10366034293998 (0.02%)\n 6. oasis1qpz97gfrvj5xzx8jx7x9zweeq0rcf2q6jg4a09qz,Stardust Staking,10073645442224 (0.02%)\n 7. oasis1qr2jxg57ch6p3787t2a8973v8zn8g82nxuex0773,Doorgod,9065607211215 (0.02%)\n 8. oasis1qz9x0zpja6n25hc5242k2e60l6a7ke2zsq9cqrqz,SerGo,5038002123045 (0.01%)\n 9. oasis1qqxxut9x74dutu587f9nj8787qz4dm0ueu05l88c,Princess Stake,2820051385569 (0.01%)\n 10. oasis1qq45am6gzaur2rxhk26av9qf7ryhgca6ecg28clu,Jr,2015272611166 (0.00%)\n 11. oasis1qzlzczsdme4scprjjh4h4vtljnmx3ag4vgpdnqln,Alexander (aka Bambarello) Validator,1591674847600 (0.00%)\n 12. oasis1qrq7hgvv26003hy89klcmy3mnedrmyd7lvf0k6qn,Perfect Stake,1402251445282 (0.00%)\n 13. oasis1qzwe6xywazp29tp20974wgxhdcpdf6yxfcn2jxvv,Simply Staking,1259545381854 (0.00%)\n 14. oasis1qphcvmsh6mw98vtg0cg4dvdsen5tm0g3e58eqpnp,Appload,1107161223526 (0.00%)\n 15. oasis1qpc66dgff4wrkj8kac4njrl2uvww3c9m5ycjwar2,<none>,1007401444145 (0.00%)\n 16. oasis1qpswaz4djukz0zanquyh2vswk59up22emysq5am9,StakeService,797017095508 (0.00%)\n 17. oasis1qr4vsan850vmztuy9r2pex4fj4wxnmhvlgclg500,<none>,297168911795 (0.00%)\n 18. oasis1qrdrup88pr27pjaaqh2m34dl6hu2u0lh4cfk3lnh,<none>,200192811785 (0.00%)\n 19. oasis1qqgvqelw8kmcd8k4cqypcsyajkl3gq6ppc4t34n2,AnkaStake,200004372023 (0.00%)\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Governance proposals are not indexed and an endpoint may take some time to\nrespond. If you encounter timeouts, consider setting up your own gRPC endpoint!")),(0,o.kt)("h4",{id:"governance-cast-vote"},(0,o.kt)("inlineCode",{parentName:"h4"},"cast-vote")),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network governance cast-vote <proposal-id> { yes | no | abstain }")," is used\nto submit your vote on the governance proposal. The vote can either be ",(0,o.kt)("inlineCode",{parentName:"p"},"yes"),",\n",(0,o.kt)("inlineCode",{parentName:"p"},"no")," or ",(0,o.kt)("inlineCode",{parentName:"p"},"abstein"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network governance cast-vote 5 yes\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Unlock your account.\n? Passphrase:\nYou are about to sign the following transaction:\nMethod: governance.CastVote\nBody:\n Proposal ID: 5\n Vote: yes\nNonce: 7\nFee:\n Amount: 0.0 TEST\n Gas limit: 1240\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: test\n")),(0,o.kt)("h4",{id:"governance-create-proposal"},(0,o.kt)("inlineCode",{parentName:"h4"},"create-proposal")),(0,o.kt)("p",null,"To submit a new governance proposal use ",(0,o.kt)("inlineCode",{parentName:"p"},"network governance create-proposal"),".\nThe following proposal types are currently supported:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"upgrade <descriptor.json>"),": Network upgrade proposal. Provide a JSON file\ncontaining the upgrade descriptor."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"cancel-upgrade <proposal-id>"),": Cancel network proposed upgrade. Provide the\nID of the network upgrade proposal you wish to cancel.")),(0,o.kt)("h3",{id:"show"},"Show Network Properties"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network show")," shows the network property stored in the registry, scheduler,\ngenesis document or on chain."),(0,o.kt)("p",null,"By passing ",(0,o.kt)("inlineCode",{parentName:"p"},"--height <block_number>")," with a block number, you can obtain a\nhistoric value of the property."),(0,o.kt)("p",null,"The command expects one of the following parameters:"),(0,o.kt)("h4",{id:"show-entities"},(0,o.kt)("inlineCode",{parentName:"h4"},"entities")),(0,o.kt)("p",null,"Shows all registered entities in the network registry. See the\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#entity"},(0,o.kt)("inlineCode",{parentName:"a"},"account entity"))," command, if you want to register or update your own entity."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This call is not enabled on public Oasis gRPC endpoints. You will have to run\nyour own client node to enable this functionality.")),(0,o.kt)("h4",{id:"show-nodes"},(0,o.kt)("inlineCode",{parentName:"h4"},"nodes")),(0,o.kt)("p",null,"Shows all registered nodes in the network registry. See the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#entity"},(0,o.kt)("inlineCode",{parentName:"a"},"account entity")),",\nto add a node to your entity."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This call is not enabled on public Oasis gRPC endpoints. You will have to run\nyour own client node to enable this functionality.")),(0,o.kt)("h4",{id:"show-paratimes"},(0,o.kt)("inlineCode",{parentName:"h4"},"paratimes")),(0,o.kt)("p",null,"Shows all registered ParaTimes in the network registry."),(0,o.kt)("h4",{id:"show-validators"},(0,o.kt)("inlineCode",{parentName:"h4"},"validators")),(0,o.kt)("p",null,"Shows all IDs of the nodes in the validator set."),(0,o.kt)("h4",{id:"show-native-token"},(0,o.kt)("inlineCode",{parentName:"h4"},"native-token")),(0,o.kt)("p",null,"Shows information of the network's native tokens such as its symbol, the number\nof decimal points, total supply, debonding period and staking thresholds."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network show native-token\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Network: mainnet\nToken's ticker symbol: ROSE\nToken's base-10 exponent: 9\nTotal supply: 10000000000.0 ROSE\nCommon pool: 853509298.875305407 ROSE\nLast block fees: 0.0 ROSE\nGovernance deposits: 0.0 ROSE\nDebonding interval: 336 epoch(s)\n\n=== STAKING THRESHOLDS ===\n entity: 100.0 ROSE\n node-validator: 100.0 ROSE\n node-compute: 100.0 ROSE\n node-keymanager: 100.0 ROSE\n runtime-compute: 50000.0 ROSE\n runtime-keymanager: 50000.0 ROSE\n")),(0,o.kt)("p",null,"We can see that the token's name is ROSE and that 1 token corresponds to 10^9\n(i.e. one billion) base units."),(0,o.kt)("p",null,"Next, we can observe that the ",(0,o.kt)("strong",{parentName:"p"},"total supply")," is 10 billion tokens and that\nabout 1.3 billion tokens are in the ",(0,o.kt)("strong",{parentName:"p"},"common pool"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Staking thresholds")," are important for the network validators. They show\nthe minimum staked amount required to become an active validator for the entity\nand all node kinds (validator, compute, key manager nodes). At time of writing,\nthis was 100 tokens. For example, if you wanted to register an entity running a\nvalidator and a compute node, you would need to stake (i.e. ",(0,o.kt)("em",{parentName:"p"},"escrow"),") at least\n300 tokens."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Each runtime may also require a ",(0,o.kt)("strong",{parentName:"p"},"minimum ParaTime-specific escrow")," for\nrunning a compute node. Use the ",(0,o.kt)("a",{parentName:"p",href:"#show-id"},(0,o.kt)("inlineCode",{parentName:"a"},"network show id")),"\ncommand and pass a corresponding Paratime ID to see it.")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"runtime-")," fields show you the required staked amount for\n",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/paratime#register"},(0,o.kt)("strong",{parentName:"a"},"registering a new ParaTime"))," of any kind (compute,\nkey manager) was 50,000 tokens at time of writing."),(0,o.kt)("h4",{id:"show-gas-costs"},(0,o.kt)("inlineCode",{parentName:"h4"},"gas-costs")),(0,o.kt)("p",null,"Shows minimum gas costs for each consensus transaction."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network show gas-costs\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Gas costs for network mainnet:\n - add_escrow: 1000\n - allow: 1000\n - amend_commission_schedule: 1000\n - burn: 1000\n - reclaim_escrow: 1000\n - transfer: 1000\n - withdraw: 1000\n")),(0,o.kt)("p",null,"Above, we can see that the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#gas-limit"},"maximum amount of gas")," our\ntransaction can spend must be set to at least 1000 ",(0,o.kt)("strong",{parentName:"p"},"gas units"),", otherwise it\nwill be rejected by the network."),(0,o.kt)("h4",{id:"show-id"},(0,o.kt)("inlineCode",{parentName:"h4"},"<id>")),(0,o.kt)("p",null,"The provided ID can be one of the following:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the ",(0,o.kt)("a",{parentName:"p",href:"/core/runtime/identifiers"},"ParaTime ID")," is provided, Oasis CLI shows ParaTime information stored\nin the network's registry."),(0,o.kt)("p",{parentName:"li"},"For example, at time of writing information on Sapphire stored in the Mainnet\nregistry were as follows:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network show 000000000000000000000000000000000000000000000000f80306c9858e7279\n")),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n "v": 3,\n "id": "000000000000000000000000000000000000000000000000f80306c9858e7279",\n "entity_id": "TAv9qXjV4yBphnKLJcNkzois1TLoYUjaRPrMfY58Apo=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 1,\n "key_manager": "4000000000000000000000000000000000000000000000008c5ea5e49b4bc9ac",\n "executor": {\n "group_size": 5,\n "group_backup_size": 7,\n "allowed_stragglers": 1,\n "round_timeout": 2,\n "max_messages": 256,\n "min_live_rounds_percent": 90,\n "min_live_rounds_eval": 20,\n "max_liveness_fails": 4\n },\n "txn_scheduler": {\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 1048576,\n "propose_batch_timeout": 2\n },\n "storage": {\n "checkpoint_interval": 100000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "any_node": {}\n },\n "constraints": {\n "executor": {\n "backup-worker": {\n "validator_set": {},\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 7\n }\n },\n "worker": {\n "validator_set": {},\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 7\n }\n }\n }\n },\n "staking": {\n "thresholds": {\n "node-compute": "5000000000000000"\n },\n "min_in_message_fee": "0"\n },\n "governance_model": "entity",\n "deployments": [\n {\n "version": {\n "minor": 4\n },\n "valid_from": 20944,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVgg3mqV02+CDfyth1fNyaR8jo3rVp024JOBkBGnjtLPypM="\n },\n {\n "version": {\n "minor": 5,\n "patch": 2\n },\n "valid_from": 23476,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggMBEUvUKRVLByqR+3a/KVNkkMjorOJLTw2Znb36baBQY="\n }\n ]\n}\n')),(0,o.kt)("p",{parentName:"li"},"Network validators may be interested in the ",(0,o.kt)("strong",{parentName:"p"},"ParaTime staking threshold"),"\nstored inside the ",(0,o.kt)("inlineCode",{parentName:"p"},"thresholds")," field. In the example above, the amount to run\na Sapphire compute node on the Mainnet is 5,000,000 tokens and should be\nconsidered on top of the consensus-layer validator staking thresholds\nobtained by the ",(0,o.kt)("a",{parentName:"p",href:"#show-native-token"},(0,o.kt)("inlineCode",{parentName:"a"},"network show native-token"))," command.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the entity ID is provided, Oasis CLI shows information on the entity and\nits corresponding nodes in the network registry. For example:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network show xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=\n")),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n "v": 2,\n "id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=",\n "nodes": [\n "Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM="\n ]\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the node ID is provided, Oasis CLI shows detailed information of the node\nsuch as the Oasis Core software version, the node's role, supported\nParaTimes, trusted execution environment support and more. For example:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network show Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM=\n")),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n "v": 2,\n "id": "Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM=",\n "entity_id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=",\n "expiration": 23482,\n "tls": {\n "pub_key": "SslsTv8Cq/UvKHPk8w1S/Ag/wwsscqSa05bqDAVOR1I=",\n "next_pub_key": "js0fhS02f+G3kW7uu+N47lzcfxjbBEPkPibTfeQrJTA=",\n "addresses": null\n },\n "p2p": {\n "id": "e9fyvK+2FwU805dag81qOsrKHaO5b+nQnHyzEySi258=",\n "addresses": null\n },\n "consensus": {\n "id": "3K2Vx3gTop+/GoM9Zh+ZSGPwVb2BRTFtcAo6xPo4pb4=",\n "addresses": [\n "e9fyvK+2FwU805dag81qOsrKHaO5b+nQnHyzEySi258=@125.122.166.210:26656"\n ]\n },\n "vrf": {\n "id": "3z85R+Rdud27NUTMFf4gO4NBQbMEnWqnhHhI6AtNx74="\n },\n "runtimes": null,\n "roles": "validator",\n "software_version": "22.2.7"\n}\n')))),(0,o.kt)("h3",{id:"status"},"Status of the Network's Endpoint"),(0,o.kt)("p",null,(0,o.kt)("inlineCode",{parentName:"p"},"network status")," will connect to the gRPC endpoint and request extensive status\nreport from the Oasis Core node. Node operators will find important information\nin the report such as:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"the last proposed consensus block,"),(0,o.kt)("li",{parentName:"ul"},"whether the node's storage is synchronized with the network,"),(0,o.kt)("li",{parentName:"ul"},"the Oasis Core software version,"),(0,o.kt)("li",{parentName:"ul"},"connected peers,"),(0,o.kt)("li",{parentName:"ul"},"similar information as above for each ParaTime, if the node is running it.")),(0,o.kt)("p",null,"At time of writing, the following status of the official gRPC endpoint for\nMainnet was reported:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis network status\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n "software_version": "22.2.8",\n "identity": {\n "node": "KzHeO03gpY/73myCANcPNnNPyH7OZIHpK6BQtk9WTj0=",\n "p2p": "0j16hb76BSBV7lQwgjPpxWX0RTCaMIDf4uTwEVnO8Ac=",\n "consensus": "ioX5hA28VJJgyFPHU16E7SML6pV9aX6km+ll23//Opk=",\n "tls": [\n "efMGmFw5YvJ4Ln2Ja559gs/uLQ1A86P/A/aKLGkOF+I=",\n "mm724Lx2RydBJtsfxydqPTfXjqcJYnQS4JhOT8zlFHo="\n ]\n },\n "consensus": {\n "status": "ready",\n "version": {\n "major": 6\n },\n "backend": "tendermint",\n "mode": "full",\n "features": 3,\n "node_peers": [\n "bc655c4da35ba3b8a189abb4fa831e631f21a447@131.153.242.59:40410",\n "097b640924c0a8e8080e21cd537df2b01415c202@95.217.85.213:36656",\n "aa883b624f5e2bccbc14597f018654ee7482ab3f@131.153.200.7:26656",\n "d4018c17cfacedb7e52df646594437a66753482b@65.108.6.54:30656",\n "b7b1d46b26fae3bb37c8ae6c23086c9873b6a535@40.76.70.110:55070",\n "f018d5d96c280ca888e4fd49df4494e68e80a2d9@65.108.215.176:26656",\n "902e60d6d4ceee9691ef90df41843931c07a165e@84.234.96.78:26656",\n "f9ae69d1bf77532cfe982a7bcd5cdacdefddb85f@65.109.27.142:26656",\n "ab61c9197d6687c8b1a41fe1afcfe642e36ece82@168.62.244.111:56268",\n "7539e4105002269bf176d78f97305e66a4f96d98@104.43.20.77:33032",\n "676d5f8ae9c14a27a6de7cd6157f8e0523edec66@65.21.124.228:34052",\n "73bc4e45d7d4bfc466e6f9a54d11d2d5d0ecd643@20.231.80.199:45828",\n "3681297ed4504e9028c0f2b6fa4384de29b3d93b@131.153.158.101:43024",\n "17c49d285903fc54390e37120feb3524db424c97@178.170.46.120:59898",\n "6b767e05affde66a7d5c079b153cf59231d0e5af@95.217.118.121:36656",\n "c504f34667643f7b2d5247d90c4564d1bf98a70b@213.239.215.145:40844",\n "6303b863cbdd8ac06f2126e0cdf6f9c0efbcbded@80.64.208.170:26656",\n "60e14c30fd2d48527e0ecaaccd55b334be988db5@65.108.204.252:52528",\n "726a6823bd231dae0dbdab6f443d0b0c01c3439f@65.108.201.32:37890",\n "4b3feafda8634130a1ad28da832746326fc71151@135.181.116.9:26656",\n "d0025b64c336ece450d70a7beda190baae0f1a2b@66.85.144.106:26656",\n "1076ecf9b338072fbbd017060d2ab3a1f4ecae90@95.216.247.36:43518",\n "5a424d5e4130e18c3f8e5dbb60e5d31dec75006f@20.245.174.253:55300",\n "dc1b0f926fc0e9ff660d12e90fa5d39f09d6f940@34.135.162.244:60846",\n "661f73c5b760d25254156d341172f1d2a815c91c@23.109.30.84:63652",\n "716c6f9047c2d4ec689e146044ad14757d399de7@95.217.77.154:50052",\n "9f464b3d1f7d8ac14245f0d27b609f823554d0c9@185.132.133.99:46657",\n "845e501768ce86822e75c1b2af72b0dce2db32f8@34.86.197.181:26656",\n "8775adc61538840d465f20e37d36422d0a1ca31e@135.181.211.184:46184",\n "dbbc6938b97f4ab168de1855c2ca49480a156752@148.251.246.233:47368",\n "b9a3ef0d8eddc23829da35d12c0b20de57924d9a@66.85.140.10:49030",\n "df5073625c1fdaef1e42d985baa922347b417e7c@65.108.127.220:35148",\n "7bcb02a07d161b5b576bd7b9963f39e3dbe1bfe8@142.132.203.173:60750",\n "4cf89deb5c40e4196e309b5cabbf4654700533aa@93.157.248.142:43824",\n "a499f9bd11b54f82a2c778e1c091402dce17b2cb@65.109.52.165:47168",\n "881c493ca3b1cf2a97df5392b2f297f7f1c9b599@91.90.179.51:45566",\n "19a982acb7d9d761e600b86a57141b1851586901@135.181.1.160:36656",\n "4490b4c1f5f3ee4c1ace07e663ff1cb6b63af535@194.195.212.183:47366",\n "71504a0a83c25b48691ab708f45079248bab0c31@135.181.179.38:36656",\n "404372701d0be0f79033ab52d50b8706d6d7fdef@85.15.140.73:38508",\n "0cd411b2652030caec59f0d0753d430b7c765f0e@213.21.202.23:52146",\n "ba4ae8667a9b41168481ceefc1d3340426ebcb4e@66.85.157.22:60568",\n "83302fdfe703928e9ea250214fb1552f292b64c9@138.201.250.242:50512",\n "b2f26729d87471814624f096b1fb7f3312e4e13a@65.108.159.229:26656",\n "772d93cfb3c617b132b1accd9351d410b308dff6@20.188.123.73:47366",\n "9182dd1d4f25fbdc0b560fa1bd3a833679df1673@144.137.17.159:36850",\n "2ee22ae65efbdef3708782d5cb970fbf1f419196@66.85.147.254:52906",\n "57b6225269abc5d0e6d5f49139b721b73d2d3d1d@178.63.93.41:37448",\n "721d8282b15a59abee88662d40dd941106f45f68@35.193.14.105:40742",\n "29d3fee2455c964d2b407918016ef21c4c2b1336@35.235.101.24:1285",\n "8787650b568d2c3f58a672f54ad6277b1cd2255a@194.33.45.161:35838",\n "8de09c821c83cc6dfe1c90727f8c8a2f425ea3f8@92.255.207.113:42180",\n "509d0687f51759c3043bc2cdcd776234ab56c9ac@95.216.72.47:31656",\n "6c89a15304567f97b5c415209f342b84bb6f1ea3@95.216.37.80:42678",\n "f1bfe70d4a23b2b743ee9b5b5d805bde71eca673@52.178.10.10:56588",\n "03ec0534396270bd6382bd94a60976770c066fdd@20.225.137.194:44372",\n "b5e54f50e208d86fb33b481d950bc97b923bd55d@34.135.151.3:38740",\n "ad5ba473f67735b29546415258a980d3f5d75caf@131.153.165.57:42464",\n "8e3ebe98e3bc759b8fafa231a3d10e71744f4f75@193.201.82.230:37282",\n "66fbd9c9a5f5cb8214b1d1e92b061ed2252b9bed@23.88.91.115:56724",\n "2ea665e41bc3533738856d5b8cf100dd88f30335@65.108.248.54:26656",\n "10f41e143df165752beb40ca3a7e4ad6be854c82@34.241.24.207:33086",\n "ec05ab6d196eca890d4842a768698ea4dd891ac7@34.220.204.235:5402",\n "230ff96d5466a59522cfedacafffb740a2d0d51e@20.232.215.170:45834",\n "0b549cde019d483a354c794f86e4bf98610cf2c0@13.209.252.30:15445",\n "d6f1a1b7fb6efe3be3bf954907ba41ee74449038@3.10.117.28:45042",\n "461d702c386f857d6f40fd884f1ef9b81716a04d@66.85.156.102:41492",\n "114aeb19a08cbec00d4673f8567e5d6e7647ca8c@80.64.208.20:26656",\n "721536cee14d65b591f45cd05bedf3917d8170d3@142.132.204.126:57494",\n "641517419eac9bc43124ab165dfcdd82d635d6a6@20.253.182.162:49680",\n "d47dfcb8cdaf50d8332c84e44c09974deb7d51cb@20.225.233.113:45454",\n "53572f689e5bacdd3c6527e6594ec49c8f3093f6@34.86.165.6:40050",\n "5fd8d9e2e031c4f342ba7faccc5a009c37cc42e3@46.166.138.194:1571",\n "7187d60bb22c553646d44319b697be2c5c69eaf4@131.153.47.62:37200",\n "8d3f8e6984dba66e9445c75d99a96000d55e4e40@20.168.196.165:52492",\n "3a17fbb5cf5dbc1e39406182baebdf71e7bd7063@135.181.112.38:26657",\n "da4e9879404f6175096bf7debc4c9fd5618330e3@172.104.56.217:37908",\n "49f568338f9137c734e5aa6c857e4ea79db6d663@65.52.244.40:26656",\n "3fef173fe6042e72397f488769970513b4174656@44.240.166.110:30990",\n "ab6047fff198a5c7974c70ba5b9afa6e336e4ec5@20.127.79.126:34286"\n ],\n "latest_height": 15772992,\n "latest_hash": "e5718445525ecdb149685ff6b334e32197b53c11291ad82c6b4c666b9e8b436d",\n "latest_time": "2023-06-07T13:36:34+02:00",\n "latest_epoch": 26272,\n "latest_state_root": {\n "ns": "0000000000000000000000000000000000000000000000000000000000000000",\n "version": 15772991,\n "root_type": 1,\n "hash": "ae6e36ae1d414e554952c3a951acf3acefe538b7151fe1f0ff91a7377d1f0072"\n },\n "genesis_height": 8535081,\n "genesis_hash": "5864fda0248a1fa53e65d36d9288ee89578003f8980d1900f76638737b43d0ee",\n "last_retained_height": 8535081,\n "last_retained_hash": "5864fda0248a1fa53e65d36d9288ee89578003f8980d1900f76638737b43d0ee",\n "chain_context": "50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a",\n "is_validator": false\n },\n "runtimes": {\n "0000000000000000000000000000000000000000000000000000000000000000": {\n "descriptor": {\n "v": 3,\n "id": "0000000000000000000000000000000000000000000000000000000000000000",\n "entity_id": "4eM2SdjntkGGH0DqhloG8HJsPNSoEeYHFACuOV+9qbc=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 1,\n "key_manager": "4000000000000000000000000000000000000000000000004a1a53dff2ae482d",\n "executor": {\n "group_size": 3,\n "group_backup_size": 5,\n "allowed_stragglers": 1,\n "round_timeout": 2,\n "max_messages": 256\n },\n "txn_scheduler": {\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 10485760,\n "propose_batch_timeout": 2\n },\n "storage": {\n "checkpoint_interval": 10000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "any_node": {}\n },\n "constraints": {\n "executor": {\n "backup-worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 5\n }\n },\n "worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 5\n }\n }\n }\n },\n "staking": {\n "min_in_message_fee": "0"\n },\n "governance_model": "entity",\n "deployments": [\n {\n "version": {\n "major": 2,\n "minor": 6,\n "patch": 1\n },\n "valid_from": 21574,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVgg+rF441O1/TtufRl4gK9f3R6mMQfF3MWJDgOTx3kGF6E="\n },\n {\n "version": {\n "major": 2,\n "minor": 6,\n "patch": 2\n },\n "valid_from": 22845,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggm8bEEbu18UnK96qtYtt9XqHNOSeRrmCG4IYvBVAlia8="\n }\n ]\n },\n "latest_round": 1722387,\n "latest_hash": "1c53179b80ac5ae004e0864291ee993d10a3b170ac9c401bdd8145b13c57738d",\n "latest_time": "2023-06-07T13:26:23+02:00",\n "latest_state_root": {\n "ns": "0000000000000000000000000000000000000000000000000000000000000000",\n "version": 1722387,\n "root_type": 1,\n "hash": "883af2896dfc0761e7bc22fc8966f8240aaa11e6c8dfabc53258f77a54851ede"\n },\n "genesis_round": 1675996,\n "genesis_hash": "2286ec2a7d41e031af618e64bbfc5e531be4ed05d3bf73179ed9b51c9ae50bc8",\n "last_retained_round": 1675996,\n "last_retained_hash": "2286ec2a7d41e031af618e64bbfc5e531be4ed05d3bf73179ed9b51c9ae50bc8",\n "committee": {\n "status": "ready",\n "active_version": {\n "major": 2,\n "minor": 6,\n "patch": 2\n },\n "latest_round": 1722387,\n "latest_height": 15772882,\n "executor_roles": null,\n "is_txn_scheduler": false,\n "peers": [\n "/ip4/66.85.140.10/tcp/30002/p2p/12D3KooWN93Yo85zQ5NgKcBSWTNkGX1SgVNoNCyExpPdj8Av6qW2",\n "/ip4/131.153.242.59/tcp/30004/p2p/12D3KooWDBtUt3Yknwn7UEdK4iyuvJREVs2PJrwfjGAfrjyCEXAs",\n "/ip4/66.85.156.101/tcp/31002/p2p/12D3KooWLpJ4ssESgun9yc1MmXUyF7EDYuZWfXpMq9s7BPFrZxaC",\n "/ip4/131.153.165.57/tcp/56657/p2p/12D3KooWShtALnfo2R8hAYNk2ufLvif7J3iSSZY348hfTXXJbxPE",\n "/ip4/66.85.157.22/tcp/50002/p2p/12D3KooWDeiujxENvSs9eQ8s3BrZdBDoFhppU3DJzC3adwaVWL2g",\n "/ip4/65.52.244.40/tcp/30002/p2p/12D3KooWDoGEevYNQXyaLt2JcRYcp6Sns3iCcoHbBSrteSCy9QwT",\n "/ip4/194.33.45.161/tcp/40004/p2p/12D3KooWMBv6UqfRwpPJqxgrwNSqnZhHh2BMX51QmXFFqUWXT6fe",\n "/ip4/66.85.147.254/tcp/30003/p2p/12D3KooWPGE1dGobdJRGZcBbrSgFnj4DJZZdJsnzEMtEfN2EbaC3",\n "/ip4/84.234.96.78/tcp/40002/p2p/12D3KooWRnWM8UBDsLUe56a3mLfNKR2VYSxzx8qmvWx7pTLsvVwr",\n "/ip4/131.153.200.7/tcp/30002/p2p/12D3KooWQQTToZP6TL8MbEyFJMQ3H8y7YguJyGE97L4o74AqkUCj",\n "/ip4/91.235.116.246/tcp/40002/p2p/12D3KooWGfFTqAMc2EvLGoFSMcMo4egSf8bBJSNt46ww2YtTjYAv",\n "/ip4/93.157.248.142/tcp/3020/p2p/12D3KooWCSuscbixtspKpa9gw5wasEcwRBxbL3vfV4uvR69qZqsD",\n "/ip4/213.21.202.23/tcp/30002/p2p/12D3KooWLL8KegpRcDxZznUCD9PsMwuDVWsdCWTgeLT1m8ub4sTF",\n "/ip4/66.85.144.106/tcp/30002/p2p/12D3KooWFNb7BR734YfMyQZVexcg3Ai1Y8uWyxSqENnckMcpkhrT",\n "/ip4/131.153.158.101/tcp/50002/p2p/12D3KooWBvcMkcyqskohCcUr8ZgieUoprYUrU2EZLNQ2mH4j4sm9",\n "/ip4/131.153.47.62/tcp/30002/p2p/12D3KooWKc95HoDZtuYnqx5dttkyCK9BGeYx8DBE6o1k8nrjmrMW",\n "/ip4/89.212.17.232/tcp/30002/p2p/12D3KooWEYtZz1pzwvFFUjMRKBckJ7qt6X63PjJVWFrFtezRqC4H",\n "/ip4/35.193.14.105/tcp/9002/p2p/12D3KooWPJYHjNP5sHPuFQQ83Fa7pAz93oA6oqSWQ5dpbE8MuUQ5",\n "/ip4/84.255.245.194/tcp/9200/p2p/12D3KooW9tZDg59zv5JA2yi7guggePUpR4mJnriELLKi3RqvC5Y6",\n "/ip4/34.135.151.3/tcp/9002/p2p/12D3KooWEkXQtJ4oxKnWWFucvAp7oBedgCcPhFRwZsy6b1WaJUCU",\n "/ip4/95.216.224.58/tcp/34648/p2p/12D3KooWGiJwU9ajppAA8R1tFsAezXatNC1fd18VxufnRG7veves",\n "/ip4/34.94.197.191/tcp/3022/p2p/12D3KooWQ1pjpnq5yAkG3nyawShPwt9WvLjZ6xRxZr86zntztfwK"\n ],\n "host": {\n "versions": [\n {\n "major": 2,\n "minor": 6,\n "patch": 2\n },\n {\n "major": 2,\n "minor": 6,\n "patch": 1\n }\n ]\n }\n },\n "storage": {\n "last_finalized_round": 1722387\n }\n },\n "00000000000000000000000000000000000000000000000072c8215e60d5bca7": {\n "descriptor": {\n "v": 3,\n "id": "00000000000000000000000000000000000000000000000072c8215e60d5bca7",\n "entity_id": "4eM2SdjntkGGH0DqhloG8HJsPNSoEeYHFACuOV+9qbc=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 0,\n "executor": {\n "group_size": 5,\n "group_backup_size": 9,\n "allowed_stragglers": 1,\n "round_timeout": 2,\n "max_messages": 256,\n "min_live_rounds_percent": 90,\n "min_live_rounds_eval": 5,\n "max_liveness_fails": 4\n },\n "txn_scheduler": {\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 10485760,\n "propose_batch_timeout": 2\n },\n "storage": {\n "checkpoint_interval": 1000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "any_node": {}\n },\n "constraints": {\n "executor": {\n "backup-worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 10\n }\n },\n "worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 10\n }\n }\n }\n },\n "staking": {\n "min_in_message_fee": "0"\n },\n "governance_model": "entity",\n "deployments": [\n {\n "version": {\n "major": 9,\n "patch": 1\n },\n "valid_from": 17225\n },\n {\n "version": {\n "major": 10\n },\n "valid_from": 22509\n }\n ]\n },\n "latest_round": 2209868,\n "latest_hash": "ce6edf3ae764f247a263754cf6389518ffbbffa80250ed702219308a77cc3180",\n "latest_time": "2023-06-07T13:35:39+02:00",\n "latest_state_root": {\n "ns": "00000000000000000000000000000000000000000000000072c8215e60d5bca7",\n "version": 2209868,\n "root_type": 1,\n "hash": "e2c70cab88b7f46111bedc1f1506797b2f5c0fb8a80224adaa18b5c72a222c0d"\n },\n "genesis_round": 398623,\n "genesis_hash": "c1b7a1fd55710e5c79424677af298c4ef2139b1230649bda4e6cf6e04df75bd5",\n "last_retained_round": 398623,\n "last_retained_hash": "c1b7a1fd55710e5c79424677af298c4ef2139b1230649bda4e6cf6e04df75bd5",\n "committee": {\n "status": "ready",\n "active_version": {\n "major": 10\n },\n "latest_round": 2209868,\n "latest_height": 15772982,\n "executor_roles": null,\n "is_txn_scheduler": false,\n "peers": [\n "/ip4/66.85.140.10/tcp/30002/p2p/12D3KooWN93Yo85zQ5NgKcBSWTNkGX1SgVNoNCyExpPdj8Av6qW2",\n "/ip4/23.88.91.115/tcp/50003/p2p/12D3KooWGsbKuGo9gLLLssLDngk8NJofDQxi8uPVqRwFtfAWUHKR",\n "/ip4/65.108.201.32/tcp/29002/p2p/12D3KooWAJLCfsfREXULRABPNaaMEU2XtuhqnYJvJSEnH7JJdBha",\n "/ip4/142.132.204.126/tcp/50002/p2p/12D3KooWCNXz8AU4D4aiirHp2qKJhuK5QL8DFimhxu9tYsWwvnFt",\n "/ip4/185.132.133.99/tcp/30002/p2p/12D3KooWEN4UXFzoxCUvtP83hGefJDVvuEt4e3Eqhy1hy38rzgQW",\n "/ip4/95.216.247.36/tcp/30002/p2p/12D3KooWKhGMFwNrT5mA4sMoAKMUX2YswwzJMTtrcKg917yyc1qa",\n "/ip4/131.153.200.7/tcp/30002/p2p/12D3KooWQQTToZP6TL8MbEyFJMQ3H8y7YguJyGE97L4o74AqkUCj",\n "/ip4/178.170.46.120/tcp/30002/p2p/12D3KooWFVBp2fnoDEA45C3pdkAwk3kFNDFKbhQCBLkv1ePwBPAL",\n "/ip4/95.217.85.213/tcp/30002/p2p/12D3KooWQ1YBqaQnL2JumfxTsFp5TYEDDRgzy8j5mUAvUY1EUaex",\n "/ip4/135.181.155.98/tcp/30002/p2p/12D3KooWRTp64wFccJy1S2dv9D61ruB6hGfb6w6y5L3kGawnxfh7",\n "/ip4/65.108.204.252/tcp/40003/p2p/12D3KooW9tbj2yAo7A7UnKKZwqWiREVTbnJJjKYBhLJVLR7qQfor",\n "/ip4/10.64.31.167/tcp/9200/p2p/12D3KooWDzDwvUPuN1vVWbYUaAJnJuh9Qfm1eZCaxsXRaxhvnnEe",\n "/ip4/135.181.1.160/tcp/30002/p2p/12D3KooWFdKYxjzFKZmZG69LPvisfyjQiiyRv1N1MHPrf5jufFKR",\n "/ip4/194.195.212.183/tcp/30002/p2p/12D3KooWD9vHKr1vCMf2RV558SbyaQehKtAsU74WSGfkmQWkGFxo",\n "/ip4/95.217.118.121/tcp/30002/p2p/12D3KooWGuX2sHNUSvJ63dqrUTLXwkRwBU9gNFiMHhA3vkxFihj5",\n "/ip4/95.217.77.154/tcp/30002/p2p/12D3KooWC9MRbrgJFFZGHy4JD8sN9dc7BEb4dLewKsEyE1SZrH8t",\n "/ip4/178.63.93.41/tcp/23002/p2p/12D3KooWLXKzvKnushSWERyJzSgTghw7Yq9ETUFdzhsc8zSWykrU",\n "/ip4/65.21.124.228/tcp/30002/p2p/12D3KooWSHZrQVJFkT9HhkZS5Rjz7GNR71gVdgaCihyRxt6c3tpi",\n "/ip4/135.181.179.38/tcp/30002/p2p/12D3KooW9xxbWPzU71Wd8W96juBAW2q6XAwj1HEidKwCL5p6aQqe",\n "/ip4/95.216.37.80/tcp/30002/p2p/12D3KooWRNWmsA3JXpG8TqNbvE9SqGCZTejtCZJVnn73KoC7tYhv",\n "/ip4/10.64.180.120/tcp/9200/p2p/12D3KooWAq3pGLymxzGQjL1SEwgFsD8TTvPBfxnSUdu148c4hNGJ",\n "/ip4/91.90.179.51/tcp/30002/p2p/12D3KooWFQdPUA6ojmH1JEGLq14oDzK1JjDSCkpxCKBvYnHdKc4A",\n "/ip4/213.239.215.145/tcp/50003/p2p/12D3KooWRQvW91WN8hofPtkFfkg21PjhQJjnbMeYnvBWzifPt87b",\n "/ip4/65.108.127.220/tcp/33002/p2p/12D3KooWHRgEYMcazqALiWjm5eAxGUeq5qsD2pgqvuqDi78TM7nn",\n "/ip4/66.85.144.106/tcp/30002/p2p/12D3KooWFNb7BR734YfMyQZVexcg3Ai1Y8uWyxSqENnckMcpkhrT",\n "/ip4/138.201.250.242/tcp/31002/p2p/12D3KooWHL7ijr2Moo1HMvvundEdbVeMhEpyPfgrKdUPeAVreoSX",\n "/ip4/142.132.203.173/tcp/34002/p2p/12D3KooWNSQJJDYMnujYzJU8v2dtqNTbWprhcb8E4JPpRULc4saw",\n "/ip4/65.109.52.165/tcp/33002/p2p/12D3KooWMpnvR6QVK81drJR9KQwqKTRvyanPWrpubMV25sqXDuL6",\n "/ip4/84.234.96.78/tcp/40003/p2p/12D3KooWJA4TP3zPuJqFyzHWxBqF6rTSiekM5z2smgxGrXrmRY6M",\n "/ip4/131.153.47.62/tcp/30002/p2p/12D3KooWKc95HoDZtuYnqx5dttkyCK9BGeYx8DBE6o1k8nrjmrMW",\n "/ip4/85.15.140.73/tcp/40002/p2p/12D3KooWHPcQbvEb9jYuzGj3x92rjkD6nRWUJbPs6apWYCEKBs8w",\n "/ip4/34.135.162.244/tcp/9002/p2p/12D3KooWDWjwVjZYitMpn8mpmvdFbpt9x9gQx9QBnv4s6rPAydVR",\n "/ip4/35.193.14.105/tcp/9002/p2p/12D3KooWPJYHjNP5sHPuFQQ83Fa7pAz93oA6oqSWQ5dpbE8MuUQ5",\n "/ip4/84.255.245.194/tcp/9200/p2p/12D3KooW9tZDg59zv5JA2yi7guggePUpR4mJnriELLKi3RqvC5Y6",\n "/ip4/34.135.151.3/tcp/9002/p2p/12D3KooWEkXQtJ4oxKnWWFucvAp7oBedgCcPhFRwZsy6b1WaJUCU",\n "/ip4/95.216.224.58/tcp/34648/p2p/12D3KooWGiJwU9ajppAA8R1tFsAezXatNC1fd18VxufnRG7veves",\n "/ip4/34.94.197.191/tcp/3022/p2p/12D3KooWQ1pjpnq5yAkG3nyawShPwt9WvLjZ6xRxZr86zntztfwK",\n "/ip4/89.212.17.232/tcp/30002/p2p/12D3KooWEYtZz1pzwvFFUjMRKBckJ7qt6X63PjJVWFrFtezRqC4H"\n ],\n "host": {\n "versions": [\n {\n "major": 10\n },\n {\n "major": 9,\n "patch": 1\n }\n ]\n }\n },\n "storage": {\n "last_finalized_round": 2209868\n }\n },\n "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c": {\n "descriptor": {\n "v": 3,\n "id": "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c",\n "entity_id": "4eM2SdjntkGGH0DqhloG8HJsPNSoEeYHFACuOV+9qbc=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 1,\n "key_manager": "4000000000000000000000000000000000000000000000004a1a53dff2ae482d",\n "executor": {\n "group_size": 5,\n "group_backup_size": 5,\n "allowed_stragglers": 1,\n "round_timeout": 2,\n "max_messages": 256,\n "min_live_rounds_percent": 90,\n "min_live_rounds_eval": 5,\n "max_liveness_fails": 4\n },\n "txn_scheduler": {\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 1000,\n "max_batch_size_bytes": 10485760,\n "propose_batch_timeout": 2\n },\n "storage": {\n "checkpoint_interval": 10000,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "entity_whitelist": {\n "entities": {\n "+fzk/Pi4DBmPhCzs8Gsw+jrbv9Z6HMfIdohb/hqWe7g=": {},\n "/RupFkoz/Hep2Xm1eqtzwuLw+hS2AQNiKVgqQwnMalE=": {},\n "4eM2SdjntkGGH0DqhloG8HJsPNSoEeYHFACuOV+9qbc=": {},\n "EHvOdqDElP5ozbICSKy3UOXQlcsvqZr+9rQvAJHcf9k=": {},\n "Efqu3z0lip+aDXkJUZqL9KfqpUIrgvISgGOdE/3OITw=": {},\n "IDrC50ExgNOjHYJjzHYMttOR7X94rSa33yoYXCCkTtU=": {},\n "IRvPVE480/nTZf6WqEaxVhkPxstagLuG8WVO8O8izBg=": {},\n "Jq1iRZxhzEPXOtCtZiA/SktLGyyfN4oX4tJWVspEb7U=": {},\n "L/xlgKf4Tx1XZogRBnuBmFS52NFoccW6QjMA8VS7g1g=": {},\n "OJcLY+0jDg0fhmMy7HuPE8N92SXIaocO7xduo7khnlc=": {},\n "RKCvE04I/BWb7VC6tzAetR3cLSlmPOrshElcoFLCjnk=": {},\n "W/Fj1JlO2hAgVSohQZZ3OQDb39Yf9O/jXxcOeW5E6AQ=": {},\n "W4mvWjUL27JnIbC3iQOlrKdpsIVFoQ8RDpt6wv1mocw=": {},\n "WfLM2tJM1E586dI7myztwIEUQ2mFBoQa4lIbMNfDo+A=": {},\n "Y1FLFDa4o7JbRnjHc53AwvHzUEEShwEicxREwaKkPks=": {},\n "ZxJyyH+JPdGNfjy+ZPq+GpFY0fAJKm9VFXZIPwMcKm4=": {},\n "dXBtIJ1+LMkIaydaSUS3quh4bHFgjf8kSJd6n666lk8=": {},\n "efBR83hww44OezMuvJ0T9Ewu4uPSQkOlO7EQq79KSis=": {},\n "fPCd+Ht/hfOfuvbtAE6+jwXpiETXRfqwEkw1TaUbk3M=": {},\n "h+8UuA74MU55qKDosnQ+mcPkMEbAFfqXnpGBjZQur0Q=": {},\n "np5ghSwh8QmA2CwtvgtbQ2p+BDspieZ5u9gu6pczHuo=": {},\n "nt9VYeY++mGIwmjM9wYfnF7lqTqoxNof8MsIkECtLpE=": {},\n "oLM78jZoGtkkx/0zN4CLGbucWCreI/N5JbIHP5UJO9k=": {},\n "ofyDzh2lzf+vqI9BcM+0/JCAM0rQkzaDst84CLh646U=": {},\n "pERaTagl7a57dXiVI3ZzoQbWskX3YmUHppeqcPdCVY8=": {},\n "ucBShpGap3zSeKqkAo5XRcfeOZrvQYAK37CKUHrCK9A=": {},\n "yOqwGZT2NMZdFgs01SAyDs30vaigDUwIsagTHBpEs8k=": {}\n }\n }\n },\n "constraints": {\n "executor": {\n "backup-worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 5\n }\n },\n "worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 5\n }\n }\n }\n },\n "staking": {\n "min_in_message_fee": "0"\n },\n "governance_model": "entity",\n "deployments": [\n {\n "version": {\n "minor": 5,\n "patch": 1\n },\n "valid_from": 24972,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVgg0zImD+/+Pxb7ZJa754pdbqsM8+Oz+L1kpV8dvM0iyjY="\n },\n {\n "version": {\n "minor": 5,\n "patch": 2\n },\n "valid_from": 25747,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggVZvrsFF6qV1Rl4r79g5UStNEGLxKACD9EmOVJVC33/k="\n }\n ]\n },\n "latest_round": 1481357,\n "latest_hash": "a439b18202e8d6809fa273785a074f327b5b169a40c1579b8386aff397422d3c",\n "latest_time": "2023-06-07T13:36:34+02:00",\n "latest_state_root": {\n "ns": "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c",\n "version": 1481357,\n "root_type": 1,\n "hash": "7b82bdb6afbb1d2c4a25178b061337a284b6ee5e9c942cb3e4a8eb01867e2ac7"\n },\n "genesis_round": 0,\n "genesis_hash": "5888cd04413b7a3e5e04c74354533a833c75be4aed22d162059000f973995f15",\n "last_retained_round": 0,\n "last_retained_hash": "5888cd04413b7a3e5e04c74354533a833c75be4aed22d162059000f973995f15",\n "committee": {\n "status": "ready",\n "active_version": {\n "minor": 5,\n "patch": 2\n },\n "latest_round": 1481357,\n "latest_height": 15772992,\n "executor_roles": null,\n "is_txn_scheduler": false,\n "peers": [\n "/ip4/91.235.116.246/tcp/40002/p2p/12D3KooWGfFTqAMc2EvLGoFSMcMo4egSf8bBJSNt46ww2YtTjYAv",\n "/ip4/66.85.157.18/tcp/41002/p2p/12D3KooWHqQ77Sd3auXYcYuAEyhzvAVqmMMgJ4gtQ7z49tMhgzps",\n "/ip4/52.178.10.10/tcp/9002/p2p/12D3KooWLx9Fh5RkaumFv4xFYbz73DaTtNKerMXScbZ1acJrcnbg",\n "/ip4/131.153.158.101/tcp/50003/p2p/12D3KooWF15eoo1VTTYZ7tzHohS38kPdywbAxdfh6QyADt5rXA7y",\n "/ip4/66.85.147.250/tcp/30004/p2p/12D3KooWDo1H3WGT2VzcAx1NtzoK9iZdrANw8SADx3VaqaT1JjKo",\n "/ip4/131.153.165.57/tcp/56659/p2p/12D3KooWLHS7beFWkeR36f1SB1Sg133FeDujEYWKPFtRphaV6kVe",\n "/ip4/213.21.202.23/tcp/30002/p2p/12D3KooWLL8KegpRcDxZznUCD9PsMwuDVWsdCWTgeLT1m8ub4sTF",\n "/ip4/66.85.144.110/tcp/30002/p2p/12D3KooWFNb7BR734YfMyQZVexcg3Ai1Y8uWyxSqENnckMcpkhrT",\n "/ip4/168.62.244.111/tcp/30002/p2p/12D3KooWNiymyC95m17qzrYGsUXuRK7afVQDAzRLpMXaNt3kEzXs",\n "/ip4/194.33.45.161/tcp/40005/p2p/12D3KooWC9jULB6ZiooKBZHJQHx281mVbPK4hVNXSTHehR37C243",\n "/ip4/84.234.96.78/tcp/41002/p2p/12D3KooWAmfVFWnMdEiwwTXgKe9QLZH8WU7C9jvTcxoKPZRkY6Pr",\n "/ip4/20.225.137.194/tcp/9002/p2p/12D3KooWFoVZmj99Z35ujpmWXfByFLzKdRMEtEA4svKJaKXH7ayM",\n "/ip4/131.153.47.62/tcp/30002/p2p/12D3KooWKc95HoDZtuYnqx5dttkyCK9BGeYx8DBE6o1k8nrjmrMW",\n "/ip4/131.153.242.59/tcp/30005/p2p/12D3KooWPqxbB3yW8nnzxqh3LkpAKRGt1YeUPfy8t7WhmYdej5R8",\n "/ip4/66.85.140.10/tcp/30002/p2p/12D3KooWN93Yo85zQ5NgKcBSWTNkGX1SgVNoNCyExpPdj8Av6qW2",\n "/ip4/66.85.156.101/tcp/31002/p2p/12D3KooWLpJ4ssESgun9yc1MmXUyF7EDYuZWfXpMq9s7BPFrZxaC",\n "/ip4/131.153.200.7/tcp/30002/p2p/12D3KooWQQTToZP6TL8MbEyFJMQ3H8y7YguJyGE97L4o74AqkUCj",\n "/ip4/20.245.174.253/tcp/9002/p2p/12D3KooWBmcgkuG2qRq4aD6BDyaytnknGqzZWyw7HZAY31L8rYvs",\n "/ip4/20.168.196.165/tcp/9002/p2p/12D3KooWJtDiHMyU9Srwj2r5MQABdaErW51rwaJMMTxDZ4XXSNXS",\n "/ip4/40.76.70.110/tcp/9002/p2p/12D3KooWQJJhtCwJqvQ1CHTW1xD6U9aXceCBmAJTR2GGXyTBsW1g",\n "/ip4/95.216.224.58/tcp/34648/p2p/12D3KooWGiJwU9ajppAA8R1tFsAezXatNC1fd18VxufnRG7veves",\n "/ip4/34.94.197.191/tcp/3022/p2p/12D3KooWQ1pjpnq5yAkG3nyawShPwt9WvLjZ6xRxZr86zntztfwK",\n "/ip4/172.24.72.26/tcp/9200/p2p/12D3KooWQviEyxLL2Sg1r9g6HQzDm8WN8KUwpwL3gPJfieXpmFDL",\n "/ip4/89.212.17.232/tcp/30002/p2p/12D3KooWEYtZz1pzwvFFUjMRKBckJ7qt6X63PjJVWFrFtezRqC4H",\n "/ip4/35.193.14.105/tcp/9002/p2p/12D3KooWPJYHjNP5sHPuFQQ83Fa7pAz93oA6oqSWQ5dpbE8MuUQ5",\n "/ip4/84.255.245.194/tcp/9200/p2p/12D3KooW9tZDg59zv5JA2yi7guggePUpR4mJnriELLKi3RqvC5Y6",\n "/ip4/20.232.215.170/tcp/9002/p2p/12D3KooWH1cwh3xzGQDT2Dp22Qc3fGGWqn8vYTvm232wp27M71Ft",\n "/ip4/34.135.151.3/tcp/9002/p2p/12D3KooWEkXQtJ4oxKnWWFucvAp7oBedgCcPhFRwZsy6b1WaJUCU",\n "/ip4/127.0.0.1/tcp/9200/p2p/12D3KooWDLhy9p7CLK2srzqwFHYRQtrGtRVAe66nJuqyBB61FFbv"\n ],\n "host": {\n "versions": [\n {\n "minor": 5,\n "patch": 2\n },\n {\n "minor": 5,\n "patch": 1\n }\n ]\n }\n },\n "storage": {\n "last_finalized_round": 1481357\n }\n }\n },\n "registration": {\n "last_registration": "0001-01-01T00:00:00Z"\n }\n}\n')))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4414cbb7.60a22db0.js b/assets/js/4414cbb7.60a22db0.js new file mode 100644 index 0000000000..f7a3f02aad --- /dev/null +++ b/assets/js/4414cbb7.60a22db0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3267],{3905:(e,t,a)=>{a.d(t,{Zo:()=>m,kt:()=>k});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){n(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function l(e,t){if(null==e)return{};var a,r,n=function(e,t){if(null==e)return{};var a,r,n={},i=Object.keys(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var s=r.createContext({}),p=function(e){var t=r.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},m=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=p(a),c=n,k=u["".concat(s,".").concat(c)]||u[c]||d[c]||i;return a?r.createElement(k,o(o({ref:t},m),{},{components:a})):r.createElement(k,o({ref:t},m))}));function k(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=c;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:n,o[1]=l;for(var p=2;p<i;p++)o[p]=a[p];return r.createElement.apply(null,o)}return r.createElement.apply(null,a)}c.displayName="MDXCreateElement"},5071:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var r=a(7462),n=(a(7294),a(3905));const i={},o="Mainnet",l={unversionedId:"node/mainnet/README",id:"node/mainnet/README",title:"Mainnet",description:"These are the current parameters for the Mainnet:",source:"@site/docs/node/mainnet/README.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/",permalink:"/node/mainnet/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/README.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Run Node",permalink:"/node/"},next:{title:"E* Upgrade",permalink:"/node/mainnet/e-upgrade"}},s={},p=[{value:"ParaTimes",id:"paratimes",level:2},{value:"Cipher",id:"cipher",level:3},{value:"Emerald",id:"emerald",level:3},{value:"Sapphire",id:"sapphire",level:3},{value:"Key Manager",id:"key-manager",level:3}],m={toc:p},u="wrapper";function d(e){let{components:t,...a}=e;return(0,n.kt)(u,(0,r.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"mainnet"},"Mainnet"),(0,n.kt)("p",null,"These are the current parameters for the Mainnet:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/download/2022-04-11/genesis.json"},"Genesis file"),":",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"SHA256: ",(0,n.kt)("inlineCode",{parentName:"li"},"bb379c0202cf82404d75a3ebc6466b0c3b98f32fac62111ee4736a59d2d3f266"))))),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"Genesis file is signed by ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/blob/master/README.md#pgp-keys-of-current-maintainers"},"network's current maintainers"),". To verify its authenticity, follow the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/blob/master/README.md#verifying-genesis-file-signatures"},"PGP verification instructions"),".")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Genesis document's hash (",(0,n.kt)("a",{parentName:"li",href:"/node/genesis-doc#genesis-file-vs-genesis-document"},"explanation"),"):",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535")))),(0,n.kt)("li",{parentName:"ul"},"Oasis seed node address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"E27F6B7A350B4CC2B48A6CBE94B0A02B0DCB0BF3@35.199.49.168:26656"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other seed nodes besides the one provided here.")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway"},"Oasis Rosetta Gateway")," version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.4.0"},"2.4.0"))))),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"The Oasis Node is part of the Oasis Core release.")),(0,n.kt)("admonition",{type:"danger"},(0,n.kt)("p",{parentName:"admonition"},"Do not use a newer version of Oasis Core since it likely contains changes that are incompatible with the version of Oasis Core used by other nodes.")),(0,n.kt)("p",null,"If you want to join our Testnet, see the ",(0,n.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet")," docs for the current Testnet parameters."),(0,n.kt)("h2",{id:"paratimes"},"ParaTimes"),(0,n.kt)("p",null,"This section contains parameters for various ParaTimes known to be deployed on the Mainnet."),(0,n.kt)("h3",{id:"cipher"},"Cipher"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000e199119c992377cb")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v2.6.2"},"2.6.2")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")),(0,n.kt)("h3",{id:"emerald"},"Emerald"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000e2eaa99fc008f87f")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version (or ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/emerald-paratime/tree/v10.0.0#building"},"build your own"),"):",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v10.0.0"},"10.0.0")))),(0,n.kt)("li",{parentName:"ul"},"Web3 Gateway version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v3.3.0"},"3.3.0"))))),(0,n.kt)("admonition",{type:"info"},(0,n.kt)("p",{parentName:"admonition"},"Check the ",(0,n.kt)("a",{parentName:"p",href:"/dapp/emerald/#web3-gateway"},"Emerald ParaTime page")," on how to access the public Web3 gateway.")),(0,n.kt)("h3",{id:"sapphire"},"Sapphire"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000f80306c9858e7279")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.5.2"},"0.5.2")))),(0,n.kt)("li",{parentName:"ul"},"Oasis Web3 Gateway version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v3.3.0"},"3.3.0")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")),(0,n.kt)("h3",{id:"key-manager"},"Key Manager"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.11"},"22.2.11")))),(0,n.kt)("li",{parentName:"ul"},"Runtime identifier:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"4000000000000000000000000000000000000000000000008c5ea5e49b4bc9ac")))),(0,n.kt)("li",{parentName:"ul"},"Runtime binary version:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/keymanager-paratime/releases/tag/v0.3.3"},"0.3.3")))),(0,n.kt)("li",{parentName:"ul"},"IAS proxy address:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"))))),(0,n.kt)("admonition",{type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Feel free to use other IAS proxies besides the one provided here or ",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/ias-proxy"},"run your own"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/472a807d.a6263d3e.js b/assets/js/472a807d.a6263d3e.js new file mode 100644 index 0000000000..4aa40c9f78 --- /dev/null +++ b/assets/js/472a807d.a6263d3e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9346],{8752:e=>{e.exports=JSON.parse('{"title":"Maintenance","description":"This section provides documentation on how to maintain your Oasis node setup over long run.","slug":"node/run-your-node/maintenance","permalink":"/node/run-your-node/maintenance","navigation":{"previous":{"title":"Sentry Node","permalink":"/node/run-your-node/sentry-node"},"next":{"title":"Wiping Node State","permalink":"/node/run-your-node/maintenance/wiping-node-state"}}}')}}]); \ No newline at end of file diff --git a/assets/js/4740797d.5804ada8.js b/assets/js/4740797d.5804ada8.js new file mode 100644 index 0000000000..9ac9f63ded --- /dev/null +++ b/assets/js/4740797d.5804ada8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4311],{5932:e=>{e.exports=JSON.parse('{"title":"Run Your Node","description":"This section provides documentation on how to set up an Oasis Node running on your computer.","slug":"node/run-your-node","permalink":"/node/run-your-node","navigation":{"previous":{"title":"Genesis Document","permalink":"/node/genesis-doc"},"next":{"title":"Prerequisites","permalink":"/node/run-your-node/prerequisites"}}}')}}]); \ No newline at end of file diff --git a/assets/js/4972.ac18c45f.js b/assets/js/4972.ac18c45f.js new file mode 100644 index 0000000000..38855782f9 --- /dev/null +++ b/assets/js/4972.ac18c45f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4972],{4972:(e,t,a)=>{a.r(t),a.d(t,{default:()=>i});var n=a(7294),o=a(5999),l=a(1944),r=a(179);function i(){return n.createElement(n.Fragment,null,n.createElement(l.d,{title:(0,o.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),n.createElement(r.Z,null,n.createElement("main",{className:"container margin-vert--xl"},n.createElement("div",{className:"row"},n.createElement("div",{className:"col col--6 col--offset-3"},n.createElement("h1",{className:"hero__title"},n.createElement(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),n.createElement("p",null,n.createElement(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),n.createElement("p",null,n.createElement(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/assets/js/4a27219a.9ef3562c.js b/assets/js/4a27219a.9ef3562c.js new file mode 100644 index 0000000000..13c66196e2 --- /dev/null +++ b/assets/js/4a27219a.9ef3562c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6006],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>m});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function a(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?i(Object(t),!0).forEach((function(n){o(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function d(e,n){if(null==e)return{};var t,r,o=function(e,n){if(null==e)return{};var t,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)t=i[r],n.indexOf(t)>=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)t=i[r],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),s=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},p=function(e){var n=s(e.components);return r.createElement(l.Provider,{value:n},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},y=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,p=d(e,["components","mdxType","originalType","parentName"]),c=s(t),y=o,m=c["".concat(l,".").concat(y)]||c[y]||u[y]||i;return t?r.createElement(m,a(a({ref:n},p),{},{components:t})):r.createElement(m,a({ref:n},p))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=y;var d={};for(var l in n)hasOwnProperty.call(n,l)&&(d[l]=n[l]);d.originalType=e,d[c]="string"==typeof e?e:o,a[1]=d;for(var s=2;s<i;s++)a[s]=t[s];return r.createElement.apply(null,a)}return r.createElement.apply(null,t)}y.displayName="MDXCreateElement"},1938:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>d,toc:()=>s});var r=t(7462),o=(t(7294),t(3905));const i={},a="Refreshing Node Certificates",d={unversionedId:"node/run-your-node/maintenance/refreshing-certificates",id:"node/run-your-node/maintenance/refreshing-certificates",title:"Refreshing Node Certificates",description:"Refreshing Sentry Client TLS Certificate on the Validator Node",source:"@site/docs/node/run-your-node/maintenance/refreshing-certificates.md",sourceDirName:"node/run-your-node/maintenance",slug:"/node/run-your-node/maintenance/refreshing-certificates",permalink:"/node/run-your-node/maintenance/refreshing-certificates",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/refreshing-certificates.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Adding or Removing Nodes",permalink:"/node/run-your-node/maintenance/adding-or-removing-nodes"},next:{title:"Shutting Down a Node",permalink:"/node/run-your-node/maintenance/shutting-down-a-node"}},l={},s=[{value:"Refreshing Sentry Client TLS Certificate on the Validator Node",id:"refreshing-sentry-client-tls-certificate-on-the-validator-node",level:2},{value:"Steps on the Validator Node",id:"steps-on-the-validator-node",level:3},{value:"Steps on the Sentry Node",id:"steps-on-the-sentry-node",level:3},{value:"Refreshing TLS Certificate on the Sentry Node",id:"refreshing-tls-certificate-on-the-sentry-node",level:2},{value:"Steps on the Sentry Node",id:"steps-on-the-sentry-node-1",level:3},{value:"Steps on the Validator Node",id:"steps-on-the-validator-node-1",level:3}],p={toc:s},c="wrapper";function u(e){let{components:n,...t}=e;return(0,o.kt)(c,(0,r.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"refreshing-node-certificates"},"Refreshing Node Certificates"),(0,o.kt)("h2",{id:"refreshing-sentry-client-tls-certificate-on-the-validator-node"},"Refreshing Sentry Client TLS Certificate on the Validator Node"),(0,o.kt)("h3",{id:"steps-on-the-validator-node"},"Steps on the Validator Node"),(0,o.kt)("p",null,"Go to your validator node's data directory, e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/srv/oasis"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"/node"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cd <PATH-TO-DATADIR>\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"We recommend backing up your validator's private and public keys (i.e. all ",(0,o.kt)("inlineCode",{parentName:"p"},"*.pem")," files) in your node's data directory before continuing.")),(0,o.kt)("p",null,"Remove the validator's current sentry client TLS private key and certificate by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rm sentry_client_tls_identity.pem sentry_client_tls_identity_cert.pem\n")),(0,o.kt)("p",null,"Re-generate node's keys by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node identity init --datadir ./\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This should keep all your other node's keys (i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"beacon.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus_pub.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"identity.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"identity_pub.pem"),", ...) intact.")),(0,o.kt)("p",null,"Then run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node identity show-sentry-client-pubkey --datadir ./\n")),(0,o.kt)("p",null,"to obtain the value of the validator's new sentry client TLS public key in Base64-encoding that can be put in sentry node's configuration under ",(0,o.kt)("inlineCode",{parentName:"p"},"control.authorized_pubkey")," list."),(0,o.kt)("p",null,"Restart your validator node."),(0,o.kt)("h3",{id:"steps-on-the-sentry-node"},"Steps on the Sentry Node"),(0,o.kt)("p",null,"After generating a new sentry client TLS private key and certificate on the validator node, set the new client TLS public key in your sentry node's configuration."),(0,o.kt)("p",null,"Before using the below sentry node configuration snippet, replace the following variables:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"{{ validator_sentry_client_grpc_public_key }}"),": The validator node's new sentry client TLS public key encoded in Base64-encoding (e.g. ",(0,o.kt)("inlineCode",{parentName:"li"},"KjVEdeGbtdxffQaSxIkLE+kW0sINI5/5YR/lgUkuEcw="),").")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"... trimmed ...\n\n# Worker configuration.\nworker:\n sentry:\n # Enable sentry node.\n enabled: true\n # Port used by validator nodes to query sentry node for registry\n # information.\n # IMPORTANT: Only validator nodes protected by the sentry node should have\n # access to this port. This port should not be exposed on the public\n # network.\n control:\n port: 9009\n authorized_pubkey:\n - {{ validator_sentry_client_grpc_public_key }}\n\n... trimmed ...\n")),(0,o.kt)("p",null,"Restart your sentry node."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The validator node will re-register itself automatically once it's connected to the network through the sentry again.")),(0,o.kt)("h2",{id:"refreshing-tls-certificate-on-the-sentry-node"},"Refreshing TLS Certificate on the Sentry Node"),(0,o.kt)("h3",{id:"steps-on-the-sentry-node-1"},"Steps on the Sentry Node"),(0,o.kt)("p",null,"Go to your sentry node's data directory, e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/srv/oasis"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"/node"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cd <PATH-TO-DATADIR>\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"We recommend backing up your sentry's private and public keys (i.e. all ",(0,o.kt)("inlineCode",{parentName:"p"},"*.pem")," files) in your node's data directory before continuing.")),(0,o.kt)("p",null,"Remove the sentry's current TLS private key and certificate by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rm tls_identity.pem tls_identity_cert.pem\n")),(0,o.kt)("p",null,"Re-generate node's keys by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node identity init --datadir ./\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This should keep all your other node's keys (i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"beacon.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus_pub.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"identity.pem"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"identity_pub.pem"),", ...) intact.")),(0,o.kt)("p",null,"Then run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node identity show-tls-pubkey --datadir ./\n")),(0,o.kt)("p",null,"to obtain the value of the sentry's new TLS public key in Base64-encoding that can be put in validator node's configuration under ",(0,o.kt)("inlineCode",{parentName:"p"},"worker.sentry.address")," list."),(0,o.kt)("p",null,"Restart your sentry node."),(0,o.kt)("h3",{id:"steps-on-the-validator-node-1"},"Steps on the Validator Node"),(0,o.kt)("p",null,"After generating a new TLS private key and certificate on the sentry node, set the new TLS public key in your validator node's configuration."),(0,o.kt)("p",null,"Before using the below validator node configuration snippet, replace the following variables:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"{{ sentry_node_grpc_public_key }}"),": The sentry node's new TLS public key encoded in Base64-encoding (e.g. ",(0,o.kt)("inlineCode",{parentName:"li"},"1dA4/NuYPSWXYaKpLhaofrZscIb2FDKtJclCMnVC0Xc="),")."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"{{ sentry_node_private_ip }}"),": The private IP address of the sentry node over which sentry node should be accessible to the validator.")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'... trimmed ...\n\nworker:\n registration:\n # In order for the node to register itself the entity.json of the entity\n # used to provision the node must be available on the node.\n entity: /serverdir/node/entity/entity.json\n sentry:\n address:\n - "{{ sentry_node_grpc_public_key }}@{{ sentry_node_private_ip }}:9009"\n\n... trimmed ...\n')),(0,o.kt)("p",null,"Restart your validator node."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4adca928.567f92c8.js b/assets/js/4adca928.567f92c8.js new file mode 100644 index 0000000000..35dcf37a72 --- /dev/null +++ b/assets/js/4adca928.567f92c8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1378],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=c(n),g=o,f=u["".concat(l,".").concat(g)]||u[g]||d[g]||a;return n?r.createElement(f,i(i({ref:t},p),{},{components:n})):r.createElement(f,i({ref:t},p))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var c=2;c<a;c++)i[c]=n[c];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}g.displayName="MDXCreateElement"},9684:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var r=n(7462),o=(n(7294),n(3905));const a={},i="Identifying Wallets",s={unversionedId:"oasis-core-ledger/usage/wallets",id:"oasis-core-ledger/usage/wallets",title:"Identifying Wallets",description:"Before following the instructions below, make sure your Ledger wallet is",source:"@site/docs/oasis-core-ledger/usage/wallets.md",sourceDirName:"oasis-core-ledger/usage",slug:"/oasis-core-ledger/usage/wallets",permalink:"/oasis-core-ledger/usage/wallets",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/usage/wallets.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Generating and Signing Transactions",permalink:"/oasis-core-ledger/usage/transactions"},next:{title:"Versioning",permalink:"/oasis-core-ledger/versioning"}},l={},c=[],p={toc:c},u="wrapper";function d(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"identifying-wallets"},"Identifying Wallets"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Before following the instructions below, make sure your Ledger wallet is\nunlocked and the Oasis App is open.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"While the Oasis App is available in ",(0,o.kt)("em",{parentName:"p"},"Developer mode"),', opening the App brings\nup the "Pending Ledger review" screen.\nYou need to press both buttons at once to close that screen and transition to\nthe ',(0,o.kt)("em",{parentName:"p"},"ordinary"),' "Oasis Ready" screen where the Oasis App is ready to be used.')),(0,o.kt)("p",null,"To list all Ledger wallets connected to a system, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-core-ledger list_devices\n")),(0,o.kt)("p",null,"If your Ledger wallet is properly connected, you should see an output similar to\nthe one below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"- Wallet ID: 431fc6\n App version: 1.7.2\n")),(0,o.kt)("p",null,"You can pass this ID when you need to specify which Ledger wallet you want to\nconnect to via ",(0,o.kt)("inlineCode",{parentName:"p"},"--wallet_id")," CLI flag or ",(0,o.kt)("inlineCode",{parentName:"p"},"wallet_id")," configuration key."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4ae0b297.7345ec9e.js b/assets/js/4ae0b297.7345ec9e.js new file mode 100644 index 0000000000..0a64f02299 --- /dev/null +++ b/assets/js/4ae0b297.7345ec9e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[467],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=o.createContext({}),c=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=c(n),h=r,m=p["".concat(s,".").concat(h)]||p[h]||d[h]||a;return n?o.createElement(m,i(i({ref:t},u),{},{components:n})):o.createElement(m,i({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:r,i[1]=l;for(var c=2;c<a;c++)i[c]=n[c];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}h.displayName="MDXCreateElement"},6458:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var o=n(7462),r=(n(7294),n(3905));const a={},i="Hello World",l={unversionedId:"dapp/cipher/hello-world",id:"dapp/cipher/hello-world",title:"Hello World",description:"This section will show you how to quickly create, build and test a minimal",source:"@site/docs/dapp/cipher/hello-world.md",sourceDirName:"dapp/cipher",slug:"/dapp/cipher/hello-world",permalink:"/dapp/cipher/hello-world",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/hello-world.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Prerequisites",permalink:"/dapp/cipher/prerequisites"},next:{title:"Confidential Hello World",permalink:"/dapp/cipher/confidential-smart-contract"}},s={},c=[{value:"Repository Structure and Dependencies",id:"repository-structure-and-dependencies",level:2},{value:"Smart Contract Definition",id:"smart-contract-definition",level:2},{value:"Testing",id:"testing",level:2},{value:"Building for Deployment",id:"building-for-deployment",level:2},{value:"Deploying the Contract",id:"deploying-the-contract",level:2}],u={toc:c},p="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(p,(0,o.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"hello-world"},"Hello World"),(0,r.kt)("p",null,"This section will show you how to quickly create, build and test a minimal\nOasis WebAssembly smart contract."),(0,r.kt)("h2",{id:"repository-structure-and-dependencies"},"Repository Structure and Dependencies"),(0,r.kt)("p",null,"First we create the basic directory structure for the hello world contract using\nRust's ",(0,r.kt)("a",{parentName:"p",href:"https://doc.rust-lang.org/cargo"},(0,r.kt)("inlineCode",{parentName:"a"},"cargo")),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cargo init --lib hello-world\n")),(0,r.kt)("p",null,"This will create the ",(0,r.kt)("inlineCode",{parentName:"p"},"hello-world")," directory and populate it with some\nboilerplate needed to describe a Rust application. It will also set up the\ndirectory for version control using Git. The rest of the guide assumes that you\nare executing commands from within this directory."),(0,r.kt)("p",null,"Since the Contract SDK requires a nightly version of the Rust toolchain, you\nneed to specify a version to use by creating a special file called\n",(0,r.kt)("inlineCode",{parentName:"p"},"rust-toolchain")," containing the following information:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"nightly-2023-01-16\n")),(0,r.kt)("p",null,"After you complete this guide, the minimal runtime directory structure will look\nas follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"hello-world\n\u251c\u2500\u2500 Cargo.lock # Dependency tree checksums (generated on first compilation).\n\u251c\u2500\u2500 Cargo.toml # Rust crate definition.\n\u251c\u2500\u2500 rust-toolchain # Rust toolchain version configuration.\n\u2514\u2500\u2500 src\n \u2514\u2500\u2500 lib.rs # Smart contract source code.\n")),(0,r.kt)("h2",{id:"smart-contract-definition"},"Smart Contract Definition"),(0,r.kt)("p",null,"First you need to declare some dependencies in order to be able to use the smart\ncontract SDK. Additionally, you will want to specify some optimization flags in\norder to make the compiled smart contract as small as possible. To do this, edit\nyour ",(0,r.kt)("inlineCode",{parentName:"p"},"Cargo.toml")," to look like the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-toml",metastring:'title="Cargo.toml"',title:'"Cargo.toml"'},'[package]\nname = "hello-world"\nversion = "0.0.0"\nedition = "2021"\nlicense = "Apache-2.0"\n\n[lib]\ncrate-type = ["cdylib"]\n\n[dependencies]\ncbor = { version = "0.5.1", package = "oasis-cbor" }\noasis-contract-sdk = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "contract-sdk/v0.3.0" }\noasis-contract-sdk-storage = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "contract-sdk/v0.3.0" }\n\n# Third party.\nthiserror = "1.0.30"\n\n[profile.release]\nopt-level = 3\ndebug = false\nrpath = false\nlto = true\ndebug-assertions = false\ncodegen-units = 1\npanic = "abort"\nincremental = false\noverflow-checks = true\nstrip = true\n')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"We are using Git tags for releases instead of releasing Rust packages on\ncrates.io.")),(0,r.kt)("p",null,"After you have updated your ",(0,r.kt)("inlineCode",{parentName:"p"},"Cargo.toml")," the next thing is to define the hello\nworld smart contract. To do this, edit ",(0,r.kt)("inlineCode",{parentName:"p"},"src/lib.rs")," with the following\ncontent:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust",metastring:'title="src/lib.rs"',title:'"src/lib.rs"'},'//! A minimal hello world smart contract.\nextern crate alloc;\n\nuse oasis_contract_sdk as sdk;\nuse oasis_contract_sdk_storage::cell::PublicCell;\n\n/// All possible errors that can be returned by the contract.\n///\n/// Each error is a triplet of (module, code, message) which allows it to be both easily\n/// human readable and also identifyable programmatically.\n#[derive(Debug, thiserror::Error, sdk::Error)]\npub enum Error {\n #[error("bad request")]\n #[sdk_error(code = 1)]\n BadRequest,\n}\n\n/// All possible requests that the contract can handle.\n///\n/// This includes both calls and queries.\n#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]\npub enum Request {\n #[cbor(rename = "instantiate")]\n Instantiate { initial_counter: u64 },\n\n #[cbor(rename = "say_hello")]\n SayHello { who: String },\n}\n\n/// All possible responses that the contract can return.\n///\n/// This includes both calls and queries.\n#[derive(Clone, Debug, Eq, PartialEq, cbor::Encode, cbor::Decode)]\npub enum Response {\n #[cbor(rename = "hello")]\n Hello { greeting: String },\n\n #[cbor(rename = "empty")]\n Empty,\n}\n\n/// The contract type.\npub struct HelloWorld;\n\n/// Storage cell for the counter.\nconst COUNTER: PublicCell<u64> = PublicCell::new(b"counter");\n\nimpl HelloWorld {\n /// Increment the counter and return the previous value.\n fn increment_counter<C: sdk::Context>(ctx: &mut C) -> u64 {\n let counter = COUNTER.get(ctx.public_store()).unwrap_or_default();\n COUNTER.set(ctx.public_store(), counter + 1);\n\n counter\n }\n}\n\n// Implementation of the sdk::Contract trait is required in order for the type to be a contract.\nimpl sdk::Contract for HelloWorld {\n type Request = Request;\n type Response = Response;\n type Error = Error;\n\n fn instantiate<C: sdk::Context>(ctx: &mut C, request: Request) -> Result<(), Error> {\n // This method is called during the contracts.Instantiate call when the contract is first\n // instantiated. It can be used to initialize the contract state.\n match request {\n // We require the caller to always pass the Instantiate request.\n Request::Instantiate { initial_counter } => {\n // Initialize counter to specified value.\n COUNTER.set(ctx.public_store(), initial_counter);\n\n Ok(())\n }\n _ => Err(Error::BadRequest),\n }\n }\n\n fn call<C: sdk::Context>(ctx: &mut C, request: Request) -> Result<Response, Error> {\n // This method is called for each contracts.Call call. It is supposed to handle the request\n // and return a response.\n match request {\n Request::SayHello { who } => {\n // Increment the counter and retrieve the previous value.\n let counter = Self::increment_counter(ctx);\n\n // Return the greeting as a response.\n Ok(Response::Hello {\n greeting: format!("hello {who} ({counter})"),\n })\n }\n _ => Err(Error::BadRequest),\n }\n }\n\n fn query<C: sdk::Context>(_ctx: &mut C, _request: Request) -> Result<Response, Error> {\n // This method is called for each contracts.Query query. It is supposed to handle the\n // request and return a response.\n Err(Error::BadRequest)\n }\n}\n\n// Create the required Wasm exports required for the contract to be runnable.\nsdk::create_contract!(HelloWorld);\n\n// We define some simple contract tests below.\n#[cfg(test)]\nmod test {\n use oasis_contract_sdk::{testing::MockContext, types::ExecutionContext, Contract};\n\n use super::*;\n\n #[test]\n fn test_hello() {\n // Create a mock execution context with default values.\n let mut ctx: MockContext = ExecutionContext::default().into();\n\n // Instantiate the contract.\n HelloWorld::instantiate(\n &mut ctx,\n Request::Instantiate {\n initial_counter: 11,\n },\n )\n .expect("instantiation should work");\n\n // Dispatch the SayHello message.\n let rsp = HelloWorld::call(\n &mut ctx,\n Request::SayHello {\n who: "unit test".to_string(),\n },\n )\n .expect("SayHello call should work");\n\n // Make sure the greeting is correct.\n assert_eq!(\n rsp,\n Response::Hello {\n greeting: "hello unit test (11)".to_string()\n }\n );\n\n // Dispatch another SayHello message.\n let rsp = HelloWorld::call(\n &mut ctx,\n Request::SayHello {\n who: "second call".to_string(),\n },\n )\n .expect("SayHello call should work");\n\n // Make sure the greeting is correct.\n assert_eq!(\n rsp,\n Response::Hello {\n greeting: "hello second call (12)".to_string()\n }\n );\n }\n}\n')),(0,r.kt)("p",null,"This is it! You now have a simple hello world smart contract with included unit\ntests for its functionality. You can also look at other smart contract handles\nsupported by the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/main/contract-sdk/src/contract.rs"},"Oasis Contract SDK"),"."),(0,r.kt)("admonition",{title:"PublicCell object",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"PublicCell<T>")," can use any type ",(0,r.kt)("inlineCode",{parentName:"p"},"T")," which implements ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis_cbor::Encode")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"oasis_cbor::Decode"),".")),(0,r.kt)("admonition",{title:"Context object",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("inlineCode",{parentName:"p"},"ctx")," argument contains the contract context analogous to ",(0,r.kt)("inlineCode",{parentName:"p"},"msg")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"this"),"\nin the EVM world. To learn more head to the ",(0,r.kt)("a",{parentName:"p",href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html"},"Context")," trait in our Rust API.")),(0,r.kt)("h2",{id:"testing"},"Testing"),(0,r.kt)("p",null,"To run unit tests type:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'RUSTFLAGS="-C target-feature=+aes,+ssse3" cargo test\n')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Running unit tests locally requires a physical or virtualized Intel-compatible\nCPU with AES and SSSE3 instruction sets.")),(0,r.kt)("h2",{id:"building-for-deployment"},"Building for Deployment"),(0,r.kt)("p",null,"In order to build the smart contract before it can be uploaded to the target\nchain, run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cargo build --target wasm32-unknown-unknown --release\n")),(0,r.kt)("p",null,"This will generate a binary file called ",(0,r.kt)("inlineCode",{parentName:"p"},"hello_world.wasm")," under\n",(0,r.kt)("inlineCode",{parentName:"p"},"target/wasm32-unknown-unknown/release")," which contains the smart contract\ncompiled into WebAssembly. This file can be directly deployed on chain."),(0,r.kt)("h2",{id:"deploying-the-contract"},"Deploying the Contract"),(0,r.kt)("p",null,"Deploying the contract we just built is simple using the Oasis CLI. This section\nassumes that you already have an instance of the CLI set up and that you will\nbe deploying contracts on the existing Testnet where you already have some\nTEST tokens to cover transaction fees."),(0,r.kt)("p",null,"First, switch the default network to Cipher Testnet to avoid the need to pass\nit to every following invocation."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis network set-default testnet\noasis paratime set-default testnet cipher\n")),(0,r.kt)("p",null,"The first deployment step that needs to be performed only once for the given\nbinary is uploading the Wasm binary."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis contracts upload hello_world.wasm\n")),(0,r.kt)("p",null,"After successful execution it will show the code ID that you need to use for any\nsubsequent instantiation of the same contract. Next, create an instance of the\ncontract by loading the code and calling its constructor with some dummy\narguments. Note that the arguments depend on the contract that is being deployed\nand in our hello world case we are simply taking the initial counter value."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis contracts instantiate CODEID '{instantiate: {initial_counter: 42}}'\n")),(0,r.kt)("p",null,"After successful execution it shows the instance ID that you need for calling\nthe instantiated contract. Next, you can test calling the contract."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis contracts call INSTANCEID '{say_hello: {who: \"me\"}}'\n")),(0,r.kt)("admonition",{title:"Example",type:"info"},(0,r.kt)("p",{parentName:"admonition"},"You can view and download a ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/contract-sdk/hello-world"},"complete example")," from the Oasis SDK repository.")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4c52944b.cb075801.js b/assets/js/4c52944b.cb075801.js new file mode 100644 index 0000000000..72f5175cd8 --- /dev/null +++ b/assets/js/4c52944b.cb075801.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3861],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),u=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(l.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=u(n),m=a,h=c["".concat(l,".").concat(m)]||c[m]||d[m]||o;return n?r.createElement(h,i(i({ref:t},p),{},{components:n})):r.createElement(h,i({ref:t},p))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:a,i[1]=s;for(var u=2;u<o;u++)i[u]=n[u];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},4576:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>u});var r=n(7462),a=(n(7294),n(3905));const o={description:"How to build your first runtime"},i="Prerequisites",s={unversionedId:"paratime/prerequisites",id:"paratime/prerequisites",title:"Prerequisites",description:"How to build your first runtime",source:"@site/docs/paratime/prerequisites.md",sourceDirName:"paratime",slug:"/paratime/prerequisites",permalink:"/paratime/prerequisites",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/prerequisites.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"How to build your first runtime"},sidebar:"paratime",previous:{title:"Build ParaTime",permalink:"/paratime/"},next:{title:"Minimal Runtime",permalink:"/paratime/minimal-runtime"}},l={},u=[{value:"Environment Setup",id:"environment-setup",level:2},{value:"Rust",id:"rust",level:3},{value:"Rust Toolchain Version",id:"rust-toolchain-version",level:4},{value:"(OPTIONAL) Fortanix SGX Rust Target",id:"optional-fortanix-sgx-rust-target",level:4},{value:"(OPTIONAL) Go",id:"optional-go",level:3},{value:"Oasis Core Installation",id:"oasis-core-installation",level:2},{value:"Oasis CLI Installation",id:"oasis-cli-installation",level:2}],p={toc:u},c="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(c,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"prerequisites"},"Prerequisites"),(0,a.kt)("p",null,"This section will guide you how to install the software required for developing\na runtime and client using the Oasis SDK. After successfully completing all the\ndescribed steps you will be able to start building your first runtime!"),(0,a.kt)("p",null,"If you already have everything set up, feel free to skip to the ",(0,a.kt)("a",{parentName:"p",href:"/paratime/minimal-runtime"},"next\nsection"),"."),(0,a.kt)("h2",{id:"environment-setup"},"Environment Setup"),(0,a.kt)("p",null,"The following is a list of prerequisites required to start developing using the\nOasis SDK:"),(0,a.kt)("h3",{id:"rust"},(0,a.kt)("a",{parentName:"h3",href:"https://www.rust-lang.org/"},"Rust")),(0,a.kt)("p",null,"We follow ",(0,a.kt)("a",{parentName:"p",href:"https://www.rust-lang.org/tools/install"},"Rust upstream's recommendation")," on using\n",(0,a.kt)("a",{parentName:"p",href:"https://rustup.rs/"},"rustup")," to install and manage Rust versions."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"rustup cannot be installed alongside a distribution packaged Rust version. You\nwill need to remove it (if it's present) before you can start using rustup.")),(0,a.kt)("p",null,"Install it by running:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n")),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,a.kt)("a",{parentName:"p",href:"https://rust-lang.github.io/rustup/installation/other.html"},"download ",(0,a.kt)("inlineCode",{parentName:"a"},"rustup-init")," executable for your platform"),"\nand run it manually.")),(0,a.kt)("p",null,"This will run ",(0,a.kt)("inlineCode",{parentName:"p"},"rustup-init")," which will download and install the latest stable\nversion of Rust on your system."),(0,a.kt)("h4",{id:"rust-toolchain-version"},"Rust Toolchain Version"),(0,a.kt)("p",null,"The version of the Rust toolchain we use in the Oasis SDK is specified in the\n",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/master/rust-toolchain"},"rust-toolchain")," file."),(0,a.kt)("p",null,"The rustup-installed versions of ",(0,a.kt)("inlineCode",{parentName:"p"},"cargo"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"rustc")," and other tools will\n",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence"},"automatically detect this file and use the appropriate version of the Rust\ntoolchain"),". When you are building applications that\nuse the SDK, it is recommended that you copy the same ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/master/rust-toolchain"},"rust-toolchain")," file to\nyour project's top-level directory as well."),(0,a.kt)("p",null,"To install the appropriate version of the Rust toolchain, make sure you are\nin the project directory and run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"rustup show\n")),(0,a.kt)("p",null,"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"...\n\nactive toolchain\n----------------\n\nnightly-2022-08-22-x86_64-unknown-linux-gnu (overridden by '/code/rust-toolchain')\nrustc 1.65.0-nightly (c0941dfb5 2022-08-21)\n")),(0,a.kt)("h4",{id:"optional-fortanix-sgx-rust-target"},"(OPTIONAL) Fortanix SGX Rust Target"),(0,a.kt)("p",null,(0,a.kt)("em",{parentName:"p"},"Required if you want to build runtimes that run inside the Intel SGX trusted\nexecution environment.")),(0,a.kt)("p",null,"To add the Fortanix SGX Rust target run the following in the project\ndirectory:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"rustup target add x86_64-fortanix-unknown-sgx\n")),(0,a.kt)("h3",{id:"optional-go"},"(OPTIONAL) ",(0,a.kt)("a",{parentName:"h3",href:"https://golang.org"},"Go")),(0,a.kt)("p",null,(0,a.kt)("em",{parentName:"p"},"Required if you want to use the Go Client SDK.")),(0,a.kt)("p",null,"At least version ",(0,a.kt)("strong",{parentName:"p"},"1.18.5")," is required. If your distribution provides a\nnew-enough version of Go, just use that."),(0,a.kt)("p",null,"Otherwise:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"install the Go version provided by your distribution,")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("a",{parentName:"p",href:"https://tip.golang.org/doc/code.html#GOPATH"},"ensure ",(0,a.kt)("inlineCode",{parentName:"a"},"$GOPATH/bin")," is in your ",(0,a.kt)("inlineCode",{parentName:"a"},"PATH")),",")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("a",{parentName:"p",href:"https://golang.org/doc/install#extra_versions"},"install the desired version of Go"),", e.g. 1.18.5, with:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"go get golang.org/dl/go1.18.5\ngo1.18.5 download\n")))),(0,a.kt)("h2",{id:"oasis-core-installation"},"Oasis Core Installation"),(0,a.kt)("p",null,"The SDK requires utilities provided by ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," in order to be able to run\na local test network for development purposes."),(0,a.kt)("p",null,"The recommended way is to download a pre-built release (at least version\n22.2) from the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases"},"Oasis Core releases")," page. After downloading the binary\nrelease (e.g. into ",(0,a.kt)("inlineCode",{parentName:"p"},"~/Downloads/oasis_core_22.2_linux_amd64.tar.gz"),"), unpack\nit as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"cd ~/Downloads\ntar xf ~/Downloads/oasis_core_22.2_linux_amd64.tar.gz --strip-components=1\n\n# This environment variable will be used throughout this guide.\nexport OASIS_CORE_PATH=~/Downloads/oasis_core_22.2_linux_amd64\n")),(0,a.kt)("h2",{id:"oasis-cli-installation"},"Oasis CLI Installation"),(0,a.kt)("p",null,"The rest of the guide uses the Oasis CLI as an easy way to interact with the\nParaTime. You can use ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/releases"},"one of the binary releases")," or ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/blob/master/README.md"},"compile it yourself"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4daae886.457698a8.js b/assets/js/4daae886.457698a8.js new file mode 100644 index 0000000000..465e5fbe3e --- /dev/null +++ b/assets/js/4daae886.457698a8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[450],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>m});var n=a(7294);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function s(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?r(Object(a),!0).forEach((function(t){i(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):r(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function o(e,t){if(null==e)return{};var a,n,i=function(e,t){if(null==e)return{};var a,n,i={},r=Object.keys(e);for(n=0;n<r.length;n++)a=r[n],t.indexOf(a)>=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n<r.length;n++)a=r[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var d=n.createContext({}),c=function(e){var t=n.useContext(d),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},p=function(e){var t=c(e.components);return n.createElement(d.Provider,{value:t},e.children)},l="mdxType",b={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var a=e.components,i=e.mdxType,r=e.originalType,d=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),l=c(a),h=i,m=l["".concat(d,".").concat(h)]||l[h]||b[h]||r;return a?n.createElement(m,s(s({ref:t},p),{},{components:a})):n.createElement(m,s({ref:t},p))}));function m(e,t){var a=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=a.length,s=new Array(r);s[0]=h;var o={};for(var d in t)hasOwnProperty.call(t,d)&&(o[d]=t[d]);o.originalType=e,o[l]="string"==typeof e?e:i,s[1]=o;for(var c=2;c<r;c++)s[c]=a[c];return n.createElement.apply(null,s)}return n.createElement.apply(null,a)}h.displayName="MDXCreateElement"},5809:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>b,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var n=a(7462),i=(a(7294),a(3905));const r={},s="ADR 0008: Standard Account Key Generation",o={unversionedId:"adrs/0008-standard-account-key-generation",id:"adrs/0008-standard-account-key-generation",title:"ADR 0008: Standard Account Key Generation",description:"Component",source:"@site/docs/adrs/0008-standard-account-key-generation.md",sourceDirName:"adrs",slug:"/adrs/0008-standard-account-key-generation",permalink:"/adrs/0008-standard-account-key-generation",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0008-standard-account-key-generation.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0007: Improved Random Beacon",permalink:"/adrs/0007-improved-random-beacon"},next:{title:"ADR 0009: Ed25519 Signature Verification Semantics",permalink:"/adrs/0009-ed25519-semantics"}},d={},c=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Mnemonic Codes for Master Key Derivation",id:"mnemonic-codes-for-master-key-derivation",level:3},{value:"Hierarchical Key Derivation Scheme",id:"hierarchical-key-derivation-scheme",level:3},{value:"Key Derivation Paths",id:"key-derivation-paths",level:3},{value:"Rationale",id:"rationale",level:2},{value:"SLIP-0010 for Hierarchical Key Derivation Scheme",id:"slip-0010-for-hierarchical-key-derivation-scheme",level:3},{value:"Adoption",id:"adoption",level:4},{value:"Difficulties in Adapting BIP-0032 to edwards25519 Curve",id:"difficulties-in-adapting-bip-0032-to-edwards25519-curve",level:4},{value:"Shorter Key Derivation Paths",id:"shorter-key-derivation-paths",level:3},{value:"Test Vectors",id:"test-vectors",level:2},{value:"Implementation",id:"implementation",level:2},{value:"Alternatives",id:"alternatives",level:2},{value:"BIP32-Ed25519 for Hierarchical Key Derivation",id:"bip32-ed25519-for-hierarchical-key-derivation",level:3},{value:"Adoption",id:"adoption-1",level:4},{value:"Security Concerns",id:"security-concerns",level:4},{value:"Implementation Issues",id:"implementation-issues",level:4},{value:"Tor's Next Generation Hidden Service Keys for Hierarchical Key Derivation",id:"tors-next-generation-hidden-service-keys-for-hierarchical-key-derivation",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],p={toc:c},l="wrapper";function b(e){let{components:t,...a}=e;return(0,i.kt)(l,(0,n.Z)({},p,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"adr-0008-standard-account-key-generation"},"ADR 0008: Standard Account Key Generation"),(0,i.kt)("h2",{id:"component"},"Component"),(0,i.kt)("p",null,"Oasis Core"),(0,i.kt)("h2",{id:"changelog"},"Changelog"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"2021-05-07: Add test vectors and reference implementation, extend Consequences\nsection"),(0,i.kt)("li",{parentName:"ul"},"2021-04-19: Switch from BIP32-Ed25519 to SLIP-0010 for hierarchical key\nderivation scheme"),(0,i.kt)("li",{parentName:"ul"},"2021-01-27: Initial draft")),(0,i.kt)("h2",{id:"status"},"Status"),(0,i.kt)("p",null,"Accepted"),(0,i.kt)("h2",{id:"context"},"Context"),(0,i.kt)("p",null,"Currently, each application interacting with the Oasis Network defines its own\nmethod of generating an account's private/public key pair."),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#accounts"},"Account"),"'s public key is in turn used to derive the account's address of the\nform ",(0,i.kt)("inlineCode",{parentName:"p"},"oasis1 ... 40 characters ...")," which is used to for a variety of operations\n(i.e. token transfers, delegations/undelegations, ...) on the network."),(0,i.kt)("p",null,"The blockchain ecosystem has developed many standards for generating keys which\nimprove key storage and interoperability between different applications."),(0,i.kt)("p",null,"Adopting these standards will allow the Oasis ecosystem to:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Make key derivation the same across different applications (i.e. wallets)."),(0,i.kt)("li",{parentName:"ul"},"Allow users to hold keys in hardware wallets."),(0,i.kt)("li",{parentName:"ul"},"Allow users to hold keys in cold storage more reliably (i.e. using the\nfamiliar 24 word mnemonics)."),(0,i.kt)("li",{parentName:"ul"},"Define how users can generate multiple keys from a single seed (i.e.\nthe 24 or 12 word mnemonic).")),(0,i.kt)("h2",{id:"decision"},"Decision"),(0,i.kt)("h3",{id:"mnemonic-codes-for-master-key-derivation"},"Mnemonic Codes for Master Key Derivation"),(0,i.kt)("p",null,"We use Bitcoin's ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki"},"BIP-0039"),": ",(0,i.kt)("em",{parentName:"p"},"Mnemonic code for generating deterministic keys"),"\nto derivate a binary seed from a mnemonic code."),(0,i.kt)("p",null,"The binary seed is in turn used to derive the ",(0,i.kt)("em",{parentName:"p"},"master key"),", the root key from\nwhich a hierarchy of deterministic keys is derived, as described in\n",(0,i.kt)("a",{parentName:"p",href:"#hierarchical-key-derivation-scheme"},"Hierarchical Key Derivation Scheme"),"."),(0,i.kt)("p",null,"We strongly recommend using 24 word mnemonics which correspond to 256 bits of\nentropy."),(0,i.kt)("h3",{id:"hierarchical-key-derivation-scheme"},"Hierarchical Key Derivation Scheme"),(0,i.kt)("p",null,"We use Sathoshi Labs' ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010"),": ",(0,i.kt)("em",{parentName:"p"},"Universal private key derivation from master\nprivate key"),", which is a superset of\nBitcoin's ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032"),": ",(0,i.kt)("em",{parentName:"p"},"Hierarchical Deterministic Wallets")," derivation algorithm,\nextended to work on other curves."),(0,i.kt)("p",null,"Account keys use the ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve")," from the Ed25519 signature scheme\nspecified in ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032"},"RFC 8032"),"."),(0,i.kt)("h3",{id:"key-derivation-paths"},"Key Derivation Paths"),(0,i.kt)("p",null,"We adapt ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki"},"BIP-0044"),": ",(0,i.kt)("em",{parentName:"p"},"Multi-Account Hierarchy for Deterministic Wallets")," for\ngenerating deterministic keys where ",(0,i.kt)("inlineCode",{parentName:"p"},"coin_type")," equals 474, as assigned to the\nOasis Network by ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0044.md"},"SLIP-0044"),"."),(0,i.kt)("p",null,"The following ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032")," path should be used to generate keys:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"m/44'/474'/x'\n")),(0,i.kt)("p",null,"where ",(0,i.kt)("inlineCode",{parentName:"p"},"x")," represents the key number."),(0,i.kt)("p",null,"Note that all path levels are ",(0,i.kt)("em",{parentName:"p"},"hardened"),", e.g. ",(0,i.kt)("inlineCode",{parentName:"p"},"44'")," is ",(0,i.kt)("inlineCode",{parentName:"p"},"44 | 0x8000000")," or\n",(0,i.kt)("inlineCode",{parentName:"p"},"44 + 2^31"),"."),(0,i.kt)("p",null,"The key corresponding to key number 0 (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"m/44'/474'/0'"),") is called the\n",(0,i.kt)("em",{parentName:"p"},"primary key"),"."),(0,i.kt)("p",null,"The account corresponding to the ",(0,i.kt)("em",{parentName:"p"},"primary key")," is called the ",(0,i.kt)("em",{parentName:"p"},"primary account"),".\nApplications (i.e. wallets) should use this account as a user's default Oasis\naccount."),(0,i.kt)("h2",{id:"rationale"},"Rationale"),(0,i.kt)("p",null,"BIPs and SLIPs are industry standards used by a majority of blockchain projects\nand software/hardware wallets."),(0,i.kt)("h3",{id:"slip-0010-for-hierarchical-key-derivation-scheme"},"SLIP-0010 for Hierarchical Key Derivation Scheme"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010")," defines a hierarchical key derivation scheme which is a superset of\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032")," derivation algorithm extended to work on other curves."),(0,i.kt)("p",null,"In particular, we use their adaptation for the ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve"),"."),(0,i.kt)("h4",{id:"adoption"},"Adoption"),(0,i.kt)("p",null,"It is used by Stellar (",(0,i.kt)("a",{parentName:"p",href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md"},"SEP-0005"),")."),(0,i.kt)("p",null,"It is supported by ",(0,i.kt)("a",{parentName:"p",href:"https://www.ledger.com/"},"Ledger")," and ",(0,i.kt)("a",{parentName:"p",href:"https://trezor.io/"},"Trezor")," hardware wallets."),(0,i.kt)("p",null,"It is commonly used by Ledger applications, including:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-stellar/blob/fc4ec38d9abcae9bd47c95ef93feb5e1ff25961f/src/stellar.c#L42-L49"},"Stellar's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-solana/blob/1c72216edf4e5358f719b164a8d1b6100988b34d/src/utils.c#L42-L51"},"Solana's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-near/blob/40ea52a0de81d65b993a49ac705e7edad8efff0e/workdir/app-near/src/crypto/ledger_crypto.c#L24"},"NEAR Protocol's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-sia/blob/d4dbb5a9cae2e2389d6b6a44701069e234f0f392/src/sia.c#L14"},"Siacoin's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-hedera/blob/47066dcfa02379a48a65c33efb1484bb744a30a5/src/hedera.c#L21-L30"},"Hedera Hashgraph's Ledger app"),".")),(0,i.kt)("h4",{id:"difficulties-in-adapting-bip-0032-to-edwards25519-curve"},"Difficulties in Adapting BIP-0032 to edwards25519 Curve"),(0,i.kt)("p",null,"Creating a hierarchical key derivation scheme for the ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve"),'\nproved to be very challenging due to edwards25519\'s small cofactor and bit\n"clamping".'),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032")," was designed for the ",(0,i.kt)("a",{parentName:"p",href:"https://en.bitcoin.it/wiki/Secp256k1"},"secp256k1")," elliptic curve with a prime-order\ngroup. For performance reasons, edwards25519 doesn't provide a prime-order group\nand provides a group of order ",(0,i.kt)("em",{parentName:"p"},"h")," * ",(0,i.kt)("em",{parentName:"p"},"l")," instead, where ",(0,i.kt)("em",{parentName:"p"},"h")," is a small co-factor\n(8) and ",(0,i.kt)("em",{parentName:"p"},"l")," is a 252-bit prime."),(0,i.kt)("p",null,"While using a co-factor offers better performance, it has proven to be a source\nof issues and vulnerabilities in higher-layer protocol implementations as\n",(0,i.kt)("a",{parentName:"p",href:"https://ristretto.group/why_ristretto.html#pitfalls-of-a-cofactor"},"described by Risretto authors"),"."),(0,i.kt)("p",null,'Additionally, edwards25519 curve employs bit "clamping". As ',(0,i.kt)("a",{parentName:"p",href:"https://moderncrypto.org/mail-archive/curves/2017/000874.html"},"described by Trevor\nPerrin"),', low bits are "clamped" to deal with\nsmall-subgroup attacks and high bits are "clamped" so that:'),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"the scalar is smaller than the subgroup order, and"),(0,i.kt)("li",{parentName:"ul"},"the highest bit set is constant in case the scalar is used with a\nnon-constant-time scalar multiplication algorithm that leaks based on the\nhighest set bit.")),(0,i.kt)("p",null,"These issues were discussed on ",(0,i.kt)("a",{parentName:"p",href:"https://moderncrypto.org/"},"modern crypto"),"'s mailing list ","[[1]][\nmoderncrypto-ed25519-hd1]",", ",(0,i.kt)("a",{parentName:"p",href:"https://moderncrypto.org/mail-archive/curves/2017/000866.html"},"[2]"),"."),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010")," avoids these issues because it doesn't try to support non-hardened\nparent public key to child public key derivation and only supports hardened\nprivate parent key to private child key derivation when used with the\nedwards25519 curve."),(0,i.kt)("h3",{id:"shorter-key-derivation-paths"},"Shorter Key Derivation Paths"),(0,i.kt)("p",null,"Similar to Stellar's ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md"},"SEP-0005"),", we decided not to use the full ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032"),"\nderivation path specified by ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki"},"BIP-0044")," because ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010"),"'s scheme for\n",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve")," only supports hardened private parent key to private child\nkey derivation and additionally, the Oasis Network is account-based rather than\n",(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Unspent_transaction_output"},"UTXO"),"-based."),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://trezor.io/"},"Trezor")," follows the same scheme for account-based blockchain networks as\ndescribed in their ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/trezor/trezor-firmware/blob/master/docs/misc/coins-bip44-paths.md"},"BIP-44 derivation paths")," document."),(0,i.kt)("h2",{id:"test-vectors"},"Test Vectors"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'[\n {\n "kind": "standard account key generation",\n "bip39_mnemonic": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",\n "bip39_passphrase": "",\n "bip39_seed": "5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4",\n "oasis_accounts": [\n {\n "bip32_path": "m/44\'/474\'/0\'",\n "private_key": "fb181e94e95cc6bedd2da03e6c4aca9951053f3e9865945dbc8975a6afd217c3ad55bbb7c192b8ecfeb6ad18bbd7681c0923f472d5b0c212fbde33008005ad61",\n "public_key": "ad55bbb7c192b8ecfeb6ad18bbd7681c0923f472d5b0c212fbde33008005ad61",\n "address": "oasis1qqx0wgxjwlw3jwatuwqj6582hdm9rjs4pcnvzz66"\n },\n {\n "bip32_path": "m/44\'/474\'/1\'",\n "private_key": "1792482bcb001f45bc8ab15436e62d60fe3eb8c86e8944bfc12da4dc67a5c89b73fd7c51a0f059ea34d8dca305e0fdb21134ca32216ca1681ae1d12b3d350e16",\n "public_key": "73fd7c51a0f059ea34d8dca305e0fdb21134ca32216ca1681ae1d12b3d350e16",\n "address": "oasis1qr4xfjmmfx7zuyvskjw9jl3nxcp6a48e8v5e27ty"\n },\n {\n "bip32_path": "m/44\'/474\'/2\'",\n "private_key": "765be01f40c1b78dd807e03a5099220c851cfe55870ab082be2345d63ffb9aa40f85ea84b81abded443be6ab3e16434cdddebca6e12ea27560a6ed65ff1998e0",\n "public_key": "0f85ea84b81abded443be6ab3e16434cdddebca6e12ea27560a6ed65ff1998e0",\n "address": "oasis1qqtdpw7jez243dnvmzfrhvgkm8zpndssvuwm346d"\n },\n {\n "bip32_path": "m/44\'/474\'/3\'",\n "private_key": "759b3c2af3d7129072666677b37e9e7b6d22c8bbf634816627e1704f596f60c411ebdac05bfa37b746692733f15a02be9842b29088272354012417a215666b0e",\n "public_key": "11ebdac05bfa37b746692733f15a02be9842b29088272354012417a215666b0e",\n "address": "oasis1qqs7wl20gfppe2krdy3tm4298yt9gftxpc9j27z2"\n },\n {\n "bip32_path": "m/44\'/474\'/4\'",\n "private_key": "db77a8a8508fd77083ba63f31b0a348441d4823e6ba73b65f354a93cf789358d8753c5da6085e6dbf5969773d27b08ee05eddcb3e11d570aaadf0f42036e69b1",\n "public_key": "8753c5da6085e6dbf5969773d27b08ee05eddcb3e11d570aaadf0f42036e69b1",\n "address": "oasis1qq8neyfkydj874tvs6ksljlmtxgw3plkkgf69j4w"\n },\n {\n "bip32_path": "m/44\'/474\'/5\'",\n "private_key": "318e1fba7d83ca3ea57b0f45377e77391479ec38bfb2236a2842fe1b7a624e8800e1a8016629f2882bca2174f29033ec2a57747cd9d3c27f49cc6e11e38ee7bc",\n "public_key": "00e1a8016629f2882bca2174f29033ec2a57747cd9d3c27f49cc6e11e38ee7bc",\n "address": "oasis1qrdjslqdum7wwehz3uaw6t6xkpth0a9n8clsu6xq"\n },\n {\n "bip32_path": "m/44\'/474\'/6\'",\n "private_key": "63a7f716e1994f7a8ab80f8acfae4c28c21af6b2f3084756b09651f4f4ee38606b85d0a8a9747faac85233ad5e4501b2a6862a4c02a46a0b7ea699cf2bd38f98",\n "public_key": "6b85d0a8a9747faac85233ad5e4501b2a6862a4c02a46a0b7ea699cf2bd38f98",\n "address": "oasis1qzlt62g85303qcrlm7s2wx2z8mxkr5v0yg5me0z3"\n },\n {\n "bip32_path": "m/44\'/474\'/7\'",\n "private_key": "34af69924c04d75c79bd120e03d667ff6287ab602f9285bb323667ddf9f25c974f49a7672eeadbf78f910928e3d592d17f1e14964693cfa2afd94b79f0d49f48",\n "public_key": "4f49a7672eeadbf78f910928e3d592d17f1e14964693cfa2afd94b79f0d49f48",\n "address": "oasis1qzw2gd3qq8nse6648df32zxvsryvljeyyyl3cxma"\n },\n {\n "bip32_path": "m/44\'/474\'/8\'",\n "private_key": "aa5242e7efe8dee05c21192766a11c46531f500ff7c0cc29ed59523c5e618792c0a24bf07953520f21c1c25882d9dbf00d24d0499be443fdcf07f2da9601d3e5",\n "public_key": "c0a24bf07953520f21c1c25882d9dbf00d24d0499be443fdcf07f2da9601d3e5",\n "address": "oasis1qqzjkx9u549r87ctv7x7t0un29vww6k6hckeuvtm"\n },\n {\n "bip32_path": "m/44\'/474\'/9\'",\n "private_key": "b661567dcb9b5290889e110b0e9814e72d347c3a3bad2bafe2969637541451e5da8c9830655103c726ff80a4ac2f05a7e0b948a1986734a4f63b3e658da76c66",\n "public_key": "da8c9830655103c726ff80a4ac2f05a7e0b948a1986734a4f63b3e658da76c66",\n "address": "oasis1qpawhwugutd48zu4rzjdcgarcucxydedgq0uljkj"\n },\n {\n "bip32_path": "m/44\'/474\'/2147483647\'",\n "private_key": "cc05cca118f3f26f05a0ff8e2bf5e232eede9978b7736ba10c3265870229efb19e7c2b2d03265ce4ea175e3664a678182548a7fc6db04801513cff7c98c8f151",\n "public_key": "9e7c2b2d03265ce4ea175e3664a678182548a7fc6db04801513cff7c98c8f151",\n "address": "oasis1qq7895v02vh40yc2dqfxhldww7wxsky0wgfdenrv"\n }\n ]\n },\n {\n "kind": "standard account key generation",\n "bip39_mnemonic": "equip will roof matter pink blind book anxiety banner elbow sun young",\n "bip39_passphrase": "",\n "bip39_seed": "ed2f664e65b5ef0dd907ae15a2788cfc98e41970bc9fcb46f5900f6919862075e721f37212304a56505dab99b001cc8907ef093b7c5016a46b50c01cc3ec1cac",\n "oasis_accounts": [\n {\n "bip32_path": "m/44\'/474\'/0\'",\n "private_key": "4e9ca1a4c2ed90c90da93ea181557ef9f465f444c0b7de35daeb218f9390d98545601f761af17dba50243529e629732f1c58d08ffddaa8491238540475729d85",\n "public_key": "45601f761af17dba50243529e629732f1c58d08ffddaa8491238540475729d85",\n "address": "oasis1qqjkrr643qv7yzem6g4m8rrtceh42n46usfscpcf"\n },\n {\n "bip32_path": "m/44\'/474\'/1\'",\n "private_key": "2d0d2e75a13fd9dc423a2db8dfc1db6ebacd53f22c8a7eeb269086ec3b443eb627ed04a3c0dcec6591c001e4ea307d65cbd712cb90d85ab7703c35eee07a77dd",\n "public_key": "27ed04a3c0dcec6591c001e4ea307d65cbd712cb90d85ab7703c35eee07a77dd",\n "address": "oasis1qp42qp8d5k8pgekvzz0ld47k8ewvppjtmqg7t5kz"\n },\n {\n "bip32_path": "m/44\'/474\'/2\'",\n "private_key": "351749392b02c6b7a5053bc678e71009b4fb07c37a67b44558064dc63b2efd9219456a3f0cf3f4cc5e6ce52def57d92bb3c5a651fa9626b246cfec07abc28724",\n "public_key": "19456a3f0cf3f4cc5e6ce52def57d92bb3c5a651fa9626b246cfec07abc28724",\n "address": "oasis1qqnwwhj4qvtap422ck7qjxf7wm89tgjhwczpu0f3"\n },\n {\n "bip32_path": "m/44\'/474\'/3\'",\n "private_key": "ebc13ccb62142ed5b600f398270801f8f80131b225feb278d42982ce314f896292549046214fdb4729bf7a6ee4a3bbd0f463c476acc933b2c7cce084509abee4",\n "public_key": "92549046214fdb4729bf7a6ee4a3bbd0f463c476acc933b2c7cce084509abee4",\n "address": "oasis1qp36crawwyk0gnfyf0epcsngnpuwrz0mtu8qzu2f"\n },\n {\n "bip32_path": "m/44\'/474\'/4\'",\n "private_key": "664b95ad8582831fb787afefd0febdddcf03343cc1ca5aa86057477e0f22c93b331288192d442d3a32e239515b4c019071c57ee89f91942923dd4c1535db096c",\n "public_key": "331288192d442d3a32e239515b4c019071c57ee89f91942923dd4c1535db096c",\n "address": "oasis1qz8d2zptvf44y049g9dtyqya4g0jcqxmjsf9pqa3"\n },\n {\n "bip32_path": "m/44\'/474\'/5\'",\n "private_key": "257600bfccc21e0bc772f4d1dcfb2834805e07959ad7bd586e7deec4a320bfcecbbfef21f0833744b3504a9860b42cb0bb11e2eb042a8b83e3ceb91fe0fca096",\n "public_key": "cbbfef21f0833744b3504a9860b42cb0bb11e2eb042a8b83e3ceb91fe0fca096",\n "address": "oasis1qz0cxkl3mftumy9l4g663fmwg69vmtc675xh8exw"\n },\n {\n "bip32_path": "m/44\'/474\'/6\'",\n "private_key": "10d224fbbac9d6e3084dff75ed1d3ae2ce52bce3345a48bf68d1552ed7d89594defb924439e0c93f3b14f25b3cb4044f9bc9055fa4a14d89f711528e6760133b",\n "public_key": "defb924439e0c93f3b14f25b3cb4044f9bc9055fa4a14d89f711528e6760133b",\n "address": "oasis1qz3pjvqnkyj42d0mllgcjd66fkavzywu4y4uhak7"\n },\n {\n "bip32_path": "m/44\'/474\'/7\'",\n "private_key": "517bcc41be16928d32c462ee2a38981ed15b784028eb0914cfe84acf475be342102ad25ab9e1707c477e39da2184f915669791a3a7b87df8fd433f15c926ede2",\n "public_key": "102ad25ab9e1707c477e39da2184f915669791a3a7b87df8fd433f15c926ede2",\n "address": "oasis1qr8zs06qtew5gefgs4608a4dzychwkm0ayz36jqg"\n },\n {\n "bip32_path": "m/44\'/474\'/8\'",\n "private_key": "ee7577c5cef5714ba6738635c6d9851c43428ff3f1e8db2fe7f45fb8d8be7c55a6ec8903ca9062910cc780c9b209c7767c2e57d646bbe06901d090ad81dabe8b",\n "public_key": "a6ec8903ca9062910cc780c9b209c7767c2e57d646bbe06901d090ad81dabe8b",\n "address": "oasis1qp7w82tmm6srgxqqzragdt3269334pjtlu44qpeu"\n },\n {\n "bip32_path": "m/44\'/474\'/9\'",\n "private_key": "5257b10a5fcfd008824e2216be17be6e47b9db74018f63bb55de4d747cae6d7bba734348f3ec7af939269f62828416091c0d89e14c813ebf5e64e24d6d37e7ab",\n "public_key": "ba734348f3ec7af939269f62828416091c0d89e14c813ebf5e64e24d6d37e7ab",\n "address": "oasis1qp9t7zerat3lh2f7xzc58ahqzta5kj4u3gupgxfk"\n },\n {\n "bip32_path": "m/44\'/474\'/2147483647\'",\n "private_key": "e7152f1b69ad6edfc05dccf67dad5305edb224669025c809d89de7e56b2cabe58c348f412819da57361cdbd7dfbe695a05dba7f24b8e7328ff991ffadab6c4d2",\n "public_key": "8c348f412819da57361cdbd7dfbe695a05dba7f24b8e7328ff991ffadab6c4d2",\n "address": "oasis1qzajez400yvnzcv8x8gtcxt4z5mkfchuh5ca05hq"\n }\n ]\n }\n]\n')),(0,i.kt)("p",null,"To generate these test vectors yourself, run:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"make -C go staking/gen_account_vectors\n")),(0,i.kt)("p",null,"We also provide more extensive test vectors. To generate them, run:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"make -C go staking/gen_account_vectors_extended\n")),(0,i.kt)("h2",{id:"implementation"},"Implementation"),(0,i.kt)("p",null,"Reference implementation is in Oasis Core's ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/sakg"},(0,i.kt)("inlineCode",{parentName:"a"},"go/common/crypto/sakg")," package"),"."),(0,i.kt)("h2",{id:"alternatives"},"Alternatives"),(0,i.kt)("h3",{id:"bip32-ed25519-for-hierarchical-key-derivation"},"BIP32-Ed25519 for Hierarchical Key Derivation"),(0,i.kt)("p",null,"The ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," (also sometimes referred to as ",(0,i.kt)("em",{parentName:"p"},"Ed25519 and BIP32\nbased on ",(0,i.kt)("a",{parentName:"em",href:"https://en.wikipedia.org/wiki/Dmitry_Khovratovich"},"Khovratovich")),") is a key derivation scheme that also adapts\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032"),"'s hierarchical derivation scheme for the ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve")," from\nthe Ed25519 signature scheme specified in ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032"},"RFC 8032"),"."),(0,i.kt)("h4",{id:"adoption-1"},"Adoption"),(0,i.kt)("p",null,"It is used by Cardano (",(0,i.kt)("a",{parentName:"p",href:"https://cips.cardano.org/cips/cip3/"},"CIP 3"),") and Tezos (dubbed ",(0,i.kt)("a",{parentName:"p",href:"https://medium.com/@obsidian.systems/v2-2-0-of-tezos-ledger-apps-babylon-support-and-more-e8df0e4ea161"},"bip25519 derivation scheme"),")."),(0,i.kt)("p",null,"It is supported by ",(0,i.kt)("a",{parentName:"p",href:"https://www.ledger.com/"},"Ledger")," and ",(0,i.kt)("a",{parentName:"p",href:"https://trezor.io/"},"Trezor")," hardware wallets."),(0,i.kt)("p",null,"It is commonly used by Ledger applications, including:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-polkadot/blob/7c3841a96caa5af6b78d49aac52b1373f10e3773/app/src/crypto.c#L44-L52"},"Polkadot's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-kusama/blob/90593207558ed82ad97123b730b07bcc33aeabf2/app/src/crypto.c#L44-L52"},"Kusama's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-zcash/blob/61fe324e567af59d39c609b84b591e28997c1a61/app/src/crypto.c#L173-L178"},"Zcash's Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-polymesh/blob/6228950a76c945fb0b5d7fc19fa475eccdf4160d/app/src/crypto.c#L44-L52"},"Polymath's Ledger app"),".")),(0,i.kt)("h4",{id:"security-concerns"},"Security Concerns"),(0,i.kt)("p",null,"Its advantage is that it supports non-hardened parent public key to child public\nkey derivation which enables certain use cases described in ","[BIP-0032][\nBIP-0032-use-cases]"," (i.e. audits, insecure money receiver, ...)."),(0,i.kt)("p",null,"At the same time, allowing non-hardened parent public key to child public key\nderivation presents a serious security concern due to ",(0,i.kt)("a",{parentName:"p",href:"#difficulties-in-adapting-bip-0032-to-edwards25519-curve"},"edwards25519's co-factor\nissues"),"."),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/burdges"},"Jeff Burdges (Web3 Foundation)")," warned about a potential ",(0,i.kt)("a",{parentName:"p",href:"https://web.archive.org/web/20210513183118/https://forum.w3f.community/t/key-recovery-attack-on-bip32-ed25519/44"},"key recovery attack\non the BIP32-Ed25519 scheme")," which could occur under the\nfollowing two assumptions:"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"The Ed25519 library used in BIP-Ed25519 derivation scheme does clamping\nimmediately before signing."),(0,i.kt)("li",{parentName:"ol"},"Adversary has the power to make numerous small payments in deep hierarchies\nof key derivations, observe if the victim can cash out each payment, and\nadaptively continue this process.")),(0,i.kt)("p",null,"The first assumption is very reasonable since the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," paper makes\nsupporting this part of their specification."),(0,i.kt)("p",null,"The second assumption is a bit more controversial.\nThe ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," paper's specification limits the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032")," path length\n(i.e. the number of levels in the tree) to 2",(0,i.kt)("sup",null,"20"),".\nBut in practice, no implementation checks that and the issue is that path length\nis not an explicit part of the BIP32-Ed25519 algorithm. That means that one\ndoesn't know how deep in the tree the current parent/child node is. Hence, it\nwould be very hard to enforce the 2",(0,i.kt)("sup",null,"20")," path length limit."),(0,i.kt)("h4",{id:"implementation-issues"},"Implementation Issues"),(0,i.kt)("p",null,"One practical issue with ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," is that its authors didn't provide a\nreference implementation and accompanying test vectors."),(0,i.kt)("p",null,"This has led to a number of incompatible BIP32-Ed25519 implementations."),(0,i.kt)("p",null,"For example, ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/vbmithr/ocaml-bip32-ed25519"},"Vincent Bernardoff's OCaml implementation"),"\nand ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/islishude/bip32"},"Shude Li's Go implementation")," follow ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519"),"'s\noriginal master (i.e. root) key derivation specification and use SHA512 and\nSHA256 for deriving the private key ",(0,i.kt)("em",{parentName:"p"},"k")," and chain code ",(0,i.kt)("em",{parentName:"p"},"c")," (respectively) from\nthe seed (i.e. master secret)."),(0,i.kt)("p",null,"On the other hand, Ledger's ","[Python implementation in orakolo repository][\nBIP32-Ed25519-orakolo]"," and ","[C implementation for their Speculos emulator][\nBIP32-Ed25519-speculos]"," (variant with ",(0,i.kt)("inlineCode",{parentName:"p"},"curve")," equal to ",(0,i.kt)("inlineCode",{parentName:"p"},"CX_CURVE_Ed25519")," and\n",(0,i.kt)("inlineCode",{parentName:"p"},"mode")," equal to ",(0,i.kt)("inlineCode",{parentName:"p"},"HDW_NORMAL"),") use HMAC-SHA512 and HMAC-SHA256 for deriving the\nprivate key ",(0,i.kt)("em",{parentName:"p"},"k")," and chain code ",(0,i.kt)("em",{parentName:"p"},"c")," (respectively) from the seed."),(0,i.kt)("p",null,"Furthermore, ","[Vincent Bernardoff's OCaml implementation][\nBIP32-Ed25519-OCaml-root-discard]"," follows ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," paper's instructions\nto discard the seed (i.e. master secret) if the master key's third highest bit\nof the last byte of ",(0,i.kt)("em",{parentName:"p"},"k",(0,i.kt)("sub",null,"L"))," is not zero."),(0,i.kt)("p",null,"On the other hand, ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/islishude/bip32/blob/72b7efc571fdb69a3f0ce4caf7078e5466b9273d/xprv.go#L51-L53"},"Shude Li's Go implementation"),"\njust clears the master key's third highest bit\nand ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/orakolo/blob/0b2d5e669ec61df9a824df9fa1a363060116b490/src/python/orakolo/HDEd25519.py#L130-L133"},"Ledger's implementations")," repeatedly set\nthe seed to the master key and restart the derivation process until a master key\nwith the desired property is found."),(0,i.kt)("p",null,"Cardano uses its own variants of ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519")," described in ",(0,i.kt)("a",{parentName:"p",href:"https://cips.cardano.org/cips/cip3/"},"CIP 3"),". In\nparticular, they define different variants of master key derivation from the\nseed described in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0023.md"},"SLIP-0023"),"."),(0,i.kt)("p",null,"Lastly, some implementations, notably ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/app-oasis"},"Oasis' Ledger app"),",\ndon't use use ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf"},"BIP32-Ed25519"),"'s private and public key directly but use the\nobtained ",(0,i.kt)("em",{parentName:"p"},"k",(0,i.kt)("sub",null,"L"))," (first 32 bytes) of the 64 byte BIP32-Ed25519 derived\nprivate key as Ed25519's seed (i.e. non-extended private key). For more details,\nsee ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/Zondax/ledger-oasis/issues/84#issuecomment-827017112"},"Zondax/ledger-oasis#84"),"."),(0,i.kt)("h3",{id:"tors-next-generation-hidden-service-keys-for-hierarchical-key-derivation"},"Tor's Next Generation Hidden Service Keys for Hierarchical Key Derivation"),(0,i.kt)("p",null,"The ",(0,i.kt)("a",{parentName:"p",href:"https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt"},"Next-Generation Hidden Services in Tor")," specification defines a\n",(0,i.kt)("a",{parentName:"p",href:"https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt#n2135"},"hierarchical key derivation scheme for Tor's keys")," which employs\nmultiplicative blinding instead of an additive one use by ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032"),"."),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://github.com/burdges"},"Jeff Burdges (Web3 Foundation)"),"'s post on potential ",(0,i.kt)("a",{parentName:"p",href:"https://web.archive.org/web/20210513183118/https://forum.w3f.community/t/key-recovery-attack-on-bip32-ed25519/44"},"key recovery\nattack on the BIP32-Ed25519 scheme")," mentions there is\nnothing wrong with this proposed scheme.\nLikewise, ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/jstarry"},"Justin Starry (Solana)"),"'s ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/solana-labs/solana/issues/6301#issuecomment-551184457"},"summary of approaches to adopting BIP-0032\nfor Ed25519")," recommends this scheme as one of the possible\napproaches to adapt BIP-0032 for ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve"),"."),(0,i.kt)("p",null,"One practical issue with using this scheme would be the absence of support by\nthe ",(0,i.kt)("a",{parentName:"p",href:"https://www.ledger.com/"},"Ledger")," and ",(0,i.kt)("a",{parentName:"p",href:"https://trezor.io/"},"Trezor")," hardware wallets."),(0,i.kt)("h2",{id:"consequences"},"Consequences"),(0,i.kt)("h3",{id:"positive"},"Positive"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Different applications interacting with the Oasis Network will use a\n",(0,i.kt)("em",{parentName:"p"},"standards-compliant")," (",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki"},"BIP-0039"),", ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010"),", ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki"},"BIP-0044"),") and\n",(0,i.kt)("em",{parentName:"p"},"interoperable")," account key generation process."),(0,i.kt)("p",{parentName:"li"},"Hence, there will be no vendor lock-in and users will have the option to\neasily switch between standards-compliant applications (e.g. different\nwallets).")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Using ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010")," avoids a spectrum of issues when trying to support\nnon-hardened public parent key to public child key derivation with the\n",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve"),".\nNon-hardened key derivation is practically impossible to implement securely\ndue to ",(0,i.kt)("a",{parentName:"p",href:"#difficulties-in-adapting-bip-0032-to-edwards25519-curve"},"edwards25519 curve's co-factor issues"),"."),(0,i.kt)("p",{parentName:"li"},"This is achieved by ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010")," explicitly disallowing non-hardened public\nparent key to public child key derivation with the edwards25519 curve.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Using a ",(0,i.kt)("a",{parentName:"p",href:"#key-derivation-paths"},"3-level BIP-0032 path")," (i.e. ",(0,i.kt)("inlineCode",{parentName:"p"},"m/44'/474'/x'"),")\nallows ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/app-oasis"},"Oasis' Ledger app")," to implement automatic switching\nbetween existing (legacy) account key generation and the standard account key\ngeneration proposed in this ADR."),(0,i.kt)("p",{parentName:"li"},"Since the existing (legacy) account key generation used in\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/app-oasis"},"Oasis' Ledger app")," uses a 5-level ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP-0032")," path, the\nOasis' Ledger app will be able to automatically switch between standard and\nexisting (legacy) account key generation just based on the number of levels of\nthe given BIP-0032 path."))),(0,i.kt)("h3",{id:"negative"},"Negative"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"The account key generation proposed in this ADR is incompatible with two\nexisting account key generation schemes deployed in the field:"),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/app-oasis"},"Oasis' Ledger app"),","),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"/general/manage-tokens/faq"},"Bitpie mobile wallet"),".")),(0,i.kt)("p",{parentName:"li"},"That means that these two applications will need to support two account key\ngenerations schemes simultaneously to allow existing users to access their\n(old) accounts generated via the existing (legacy) account key generation\nscheme.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("a",{parentName:"p",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010"),"'s scheme for ",(0,i.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032#section-5"},"edwards25519 curve")," only supports hardened private\nparent key to private child key derivation."),(0,i.kt)("p",{parentName:"li"},"That means it will not be possible to implement wallet features that require\nnon-hardened key derivation, e.g. watch-only feature where one is able to\nmonitor a hierarchical wallet's accounts just by knowing the root public key\nand deriving all accounts' public keys from that."))),(0,i.kt)("h3",{id:"neutral"},"Neutral"),(0,i.kt)("h2",{id:"references"},"References"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md"},"SLIP-0010")),(0,i.kt)("li",{parentName:"ul"},"Stellar's ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md"},"SEP-0005")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/jstarry"},"Justin Starry (Solana)"),"'s ",(0,i.kt)("a",{parentName:"li",href:"https://github.com/solana-labs/solana/issues/6301#issuecomment-551184457"},"summary of approaches to adopting BIP-0032 for\nEd25519")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/andrewkozlik"},"Andrew Kozlik (SatoshiLabs)"),"'s\n",(0,i.kt)("a",{parentName:"li",href:"https://github.com/satoshilabs/slips/issues/703#issuecomment-515213584"},"comments on BIP32-Ed25519, SLIP-0010 and SLIP-0023"))))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4fe2dd92.b18f2651.js b/assets/js/4fe2dd92.b18f2651.js new file mode 100644 index 0000000000..b11a5b0f80 --- /dev/null +++ b/assets/js/4fe2dd92.b18f2651.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9561],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=c(r),f=a,m=u["".concat(i,".").concat(f)]||u[f]||d[f]||o;return r?n.createElement(m,s(s({ref:t},p),{},{components:r})):n.createElement(m,s({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,s=new Array(o);s[0]=f;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[u]="string"==typeof e?e:a,s[1]=l;for(var c=2;c<o;c++)s[c]=r[c];return n.createElement.apply(null,s)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},4754:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={},s="Table of Contents",l={unversionedId:"oasis-core-ledger/SUMMARY",id:"oasis-core-ledger/SUMMARY",title:"Table of Contents",description:"Usage",source:"@site/docs/oasis-core-ledger/SUMMARY.md",sourceDirName:"oasis-core-ledger",slug:"/oasis-core-ledger/SUMMARY",permalink:"/oasis-core-ledger/SUMMARY",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/SUMMARY.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{}},i={},c=[{value:"Usage",id:"usage",level:2},{value:"Development",id:"development",level:2},{value:"Processes",id:"processes",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...r}=e;return(0,a.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"table-of-contents"},"Table of Contents"),(0,a.kt)("h2",{id:"usage"},"Usage"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/setup"},"Setup")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/address"},"Obtaining Account Address")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/entity"},"Exporting Public Key to Entity")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/transactions"},"Generating and Signing Transactions")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/wallets"},"Identifying Wallets"))),(0,a.kt)("h2",{id:"development"},"Development"),(0,a.kt)("p",null,(0,a.kt)("em",{parentName:"p"},"TODO.")),(0,a.kt)("h2",{id:"processes"},"Processes"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/versioning"},"Versioning")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/oasis-core-ledger/release-process"},"Release Process"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/527e04fa.ff01e790.js b/assets/js/527e04fa.ff01e790.js new file mode 100644 index 0000000000..cfb7a9f7fb --- /dev/null +++ b/assets/js/527e04fa.ff01e790.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5657],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function a(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},l=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,o=e.originalType,c=e.parentName,l=a(e,["components","mdxType","originalType","parentName"]),p=u(r),d=i,f=p["".concat(c,".").concat(d)]||p[d]||m[d]||o;return r?n.createElement(f,s(s({ref:t},l),{},{components:r})):n.createElement(f,s({ref:t},l))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=r.length,s=new Array(o);s[0]=d;var a={};for(var c in t)hasOwnProperty.call(t,c)&&(a[c]=t[c]);a.originalType=e,a[p]="string"==typeof e?e:i,s[1]=a;for(var u=2;u<o;u++)s[u]=r[u];return n.createElement.apply(null,s)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},1817:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>o,metadata:()=>a,toc:()=>u});var n=r(7462),i=(r(7294),r(3905));const o={},s="Runtime IDs",a={unversionedId:"core/runtime/identifiers",id:"core/runtime/identifiers",title:"Runtime IDs",description:"Identifiers for runtimes are represented by the [common.Namespace] type.",source:"@site/docs/core/runtime/identifiers.md",sourceDirName:"core/runtime",slug:"/core/runtime/identifiers",permalink:"/core/runtime/identifiers",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/identifiers.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime Host Protocol",permalink:"/core/runtime/runtime-host-protocol"},next:{title:"Runtime Messages",permalink:"/core/runtime/messages"}},c={},u=[],l={toc:u},p="wrapper";function m(e){let{components:t,...r}=e;return(0,i.kt)(p,(0,n.Z)({},l,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"runtime-ids"},"Runtime IDs"),(0,i.kt)("p",null,"Identifiers for runtimes are represented by the ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common?tab=doc#Namespace"},(0,i.kt)("inlineCode",{parentName:"a"},"common.Namespace"))," type."),(0,i.kt)("p",null,"The first 64 bits are reserved for specifying flags expressing various\nproperties of the runtime, and the last 192 bits are used as the runtime\nidentifier."),(0,i.kt)("p",null,"Currently the following flags are defined (bit positions assume the flags\nvector is interpreted as an unsigned 64 bit big endian integer):"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Bit 63: The runtime is a test runtime and not for production networks."),(0,i.kt)("li",{parentName:"ul"},"Bit 62: The runtime is a key manager runtime."),(0,i.kt)("li",{parentName:"ul"},"Bits 61-0: Reserved for future expansion and MUST be set to 0.")),(0,i.kt)("p",null,"Note: Unless the registry consensus parameter ",(0,i.kt)("inlineCode",{parentName:"p"},"DebugAllowTestRuntimes")," is\nset, attempts to register a test runtime will be rejected."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5334ec61.7db52a7b.js b/assets/js/5334ec61.7db52a7b.js new file mode 100644 index 0000000000..47ee768911 --- /dev/null +++ b/assets/js/5334ec61.7db52a7b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9200],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>v});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,v=d["".concat(s,".").concat(m)]||d[m]||c[m]||i;return n?r.createElement(v,a(a({ref:t},u),{},{components:n})):r.createElement(v,a({ref:t},u))}));function v(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:o,a[1]=l;for(var p=2;p<i;p++)a[p]=n[p];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},5022:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>c,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var r=n(7462),o=(n(7294),n(3905));const i={},a="Building",l={unversionedId:"core/development-setup/building",id:"core/development-setup/building",title:"Building",description:"This section contains a description of steps required to build Oasis Core.",source:"@site/docs/core/development-setup/building.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/building",permalink:"/core/development-setup/building",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/building.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Prerequisites",permalink:"/core/development-setup/prerequisites"},next:{title:"Running Tests and Development Networks",permalink:"/core/development-setup/running-tests-and-development-networks"}},s={},p=[{value:"Unsafe Non-SGX Environment",id:"unsafe-non-sgx-environment",level:2},{value:"SGX Environment",id:"sgx-environment",level:2}],u={toc:p},d="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"building"},"Building"),(0,o.kt)("p",null,"This section contains a description of steps required to build Oasis Core.\nBefore proceeding, make sure to look at the ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites"},"prerequisites")," required for running\nan Oasis Core environment."),(0,o.kt)("h2",{id:"unsafe-non-sgx-environment"},"Unsafe Non-SGX Environment"),(0,o.kt)("p",null,"To build everything required for running an Oasis node locally, simply execute\nthe following in the top-level directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'export OASIS_UNSAFE_SKIP_AVR_VERIFY="1"\nexport OASIS_UNSAFE_SKIP_KM_POLICY="1"\nexport OASIS_UNSAFE_ALLOW_DEBUG_ENCLAVES="1"\nmake\n')),(0,o.kt)("p",null,"To build BadgerDB without ",(0,o.kt)("inlineCode",{parentName:"p"},"jemalloc")," support (and avoid installing ",(0,o.kt)("inlineCode",{parentName:"p"},"jemalloc"),"\non your system), set"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'export OASIS_BADGER_NO_JEMALLOC="1"\n')),(0,o.kt)("p",null,"Not using ",(0,o.kt)("inlineCode",{parentName:"p"},"jemalloc")," is fine for development purposes."),(0,o.kt)("p",null,"This will build all the required parts (build tools, Oasis node, runtime\nlibraries, runtime loader, key manager and test runtimes). The AVR and KM flags\nare supported on production SGX systems only and these features must be disabled\nin our environment."),(0,o.kt)("h2",{id:"sgx-environment"},"SGX Environment"),(0,o.kt)("p",null,"Compilation procedure under SGX environment is similar to the non-SGX with\nslightly different environmental variables set:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'export OASIS_UNSAFE_SKIP_AVR_VERIFY="1"\nexport OASIS_UNSAFE_ALLOW_DEBUG_ENCLAVES="1"\nmake\n')),(0,o.kt)("p",null,"The AVR flag is there because we are running the node in a local development\nenvironment and we will not do any attestation with Intel's remote servers. The\ndebug enclaves flag allows enclaves in debug mode to be used."),(0,o.kt)("p",null,"To run an Oasis node under SGX make sure:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Your hardware has SGX support.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"You either explicitly enabled SGX in BIOS or made a\n",(0,o.kt)("inlineCode",{parentName:"p"},"sgx_cap_enable_device()")," system call, if SGX is in software controlled state.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"You installed ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/intel/linux-sgx-driver"},"Intel's SGX driver")," (check that ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev/isgx")," exists).")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"You have the AESM daemon running. The easiest way is to just run it in a\nDocker container by doing (this will keep the container running and it will\nbe automatically started on boot):"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"docker run \\\n --detach \\\n --restart always \\\n --device /dev/isgx \\\n --volume /var/run/aesmd:/var/run/aesmd \\\n --name aesmd \\\n ghcr.io/oasisprotocol/aesmd:master\n")))),(0,o.kt)("p",null,"Run ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect")," (part of fortanix rust tools) to verify that everything is\nconfigured correctly."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5525.7df0659a.js b/assets/js/5525.7df0659a.js new file mode 100644 index 0000000000..6c647dc310 --- /dev/null +++ b/assets/js/5525.7df0659a.js @@ -0,0 +1 @@ +(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5525],{5525:()=>{}}]); \ No newline at end of file diff --git a/assets/js/553dc0b4.ae0b48f9.js b/assets/js/553dc0b4.ae0b48f9.js new file mode 100644 index 0000000000..b9e54f5a8e --- /dev/null +++ b/assets/js/553dc0b4.ae0b48f9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8543],{5629:s=>{s.exports=JSON.parse('{"title":"Services","slug":"core/consensus/services","permalink":"/core/consensus/services","navigation":{"previous":{"title":"Transactions","permalink":"/core/consensus/transactions"},"next":{"title":"Epoch Time","permalink":"/core/consensus/services/epochtime"}}}')}}]); \ No newline at end of file diff --git a/assets/js/5583c17b.d584093b.js b/assets/js/5583c17b.d584093b.js new file mode 100644 index 0000000000..5121ed3953 --- /dev/null +++ b/assets/js/5583c17b.d584093b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8061],{3905:(q,e,t)=>{t.d(e,{Zo:()=>p,kt:()=>c});var n=t(7294);function A(q,e,t){return e in q?Object.defineProperty(q,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):q[e]=t,q}function a(q,e){var t=Object.keys(q);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(q);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(q,e).enumerable}))),t.push.apply(t,n)}return t}function r(q){for(var e=1;e<arguments.length;e++){var t=null!=arguments[e]?arguments[e]:{};e%2?a(Object(t),!0).forEach((function(e){A(q,e,t[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(q,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(e){Object.defineProperty(q,e,Object.getOwnPropertyDescriptor(t,e))}))}return q}function o(q,e){if(null==q)return{};var t,n,A=function(q,e){if(null==q)return{};var t,n,A={},a=Object.keys(q);for(n=0;n<a.length;n++)t=a[n],e.indexOf(t)>=0||(A[t]=q[t]);return A}(q,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(q);for(n=0;n<a.length;n++)t=a[n],e.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(q,t)&&(A[t]=q[t])}return A}var i=n.createContext({}),s=function(q){var e=n.useContext(i),t=e;return q&&(t="function"==typeof q?q(e):r(r({},e),q)),t},p=function(q){var e=s(q.components);return n.createElement(i.Provider,{value:e},q.children)},l="mdxType",d={inlineCode:"code",wrapper:function(q){var e=q.children;return n.createElement(n.Fragment,{},e)}},h=n.forwardRef((function(q,e){var t=q.components,A=q.mdxType,a=q.originalType,i=q.parentName,p=o(q,["components","mdxType","originalType","parentName"]),l=s(t),h=A,c=l["".concat(i,".").concat(h)]||l[h]||d[h]||a;return t?n.createElement(c,r(r({ref:e},p),{},{components:t})):n.createElement(c,r({ref:e},p))}));function c(q,e){var t=arguments,A=e&&e.mdxType;if("string"==typeof q||A){var a=t.length,r=new Array(a);r[0]=h;var o={};for(var i in e)hasOwnProperty.call(e,i)&&(o[i]=e[i]);o.originalType=q,o[l]="string"==typeof q?q:A,r[1]=o;for(var s=2;s<a;s++)r[s]=t[s];return n.createElement.apply(null,r)}return n.createElement.apply(null,t)}h.displayName="MDXCreateElement"},1405:(q,e,t)=>{t.r(e),t.d(e,{assets:()=>i,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>s});var n=t(7462),A=(t(7294),t(3905));const a={description:"Writing Sapphire dApp for browser and Metamask"},r="Browser Support",o={unversionedId:"dapp/sapphire/browser",id:"dapp/sapphire/browser",title:"Browser Support",description:"Writing Sapphire dApp for browser and Metamask",source:"@site/docs/dapp/sapphire/browser.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/browser",permalink:"/dapp/sapphire/browser",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/browser.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Writing Sapphire dApp for browser and Metamask"},sidebar:"developers",previous:{title:"Guide",permalink:"/dapp/sapphire/guide"},next:{title:"Gasless Transactions",permalink:"/dapp/sapphire/gasless"}},i={},s=[{value:"Signing Sapphire Calls and Transactions in Browser",id:"signing-sapphire-calls-and-transactions-in-browser",level:2},{value:"Trying it",id:"trying-it",level:2}],p={toc:s},l="wrapper";function d(q){let{components:e,...a}=q;return(0,A.kt)(l,(0,n.Z)({},p,a,{components:e,mdxType:"MDXLayout"}),(0,A.kt)("h1",{id:"browser-support"},"Browser Support"),(0,A.kt)("p",null,"Confidential Sapphire dApps work in web browsers by wrapping the\nEthereum provider such as Metamask to enable signing and encrypting\ncalls and transactions."),(0,A.kt)("p",null,"Let's begin with the ",(0,A.kt)("a",{parentName:"p",href:"https://hardhat.org/tutorial/boilerplate-project"},"Hardhat boilerplate"),". As mentioned on their website\nthe boilerplate provides the following:"),(0,A.kt)("ul",null,(0,A.kt)("li",{parentName:"ul"},"The Solidity contract implementing an ERC-20 token"),(0,A.kt)("li",{parentName:"ul"},"Tests for the entire functionality of the contract"),(0,A.kt)("li",{parentName:"ul"},"A minimal React front-end to interact with the contract using ethers.js")),(0,A.kt)("p",null,"Go ahead and clone the original ",(0,A.kt)("a",{parentName:"p",href:"https://github.com/NomicFoundation/hardhat-boilerplate"},"Hardhat boilerplate repo"),". Move to the checked\nout folder and ",(0,A.kt)("strong",{parentName:"p"},"apply the Sapphire-specific changes")," to ",(0,A.kt)("inlineCode",{parentName:"p"},"hardhat.config.js"),"\nas ",(0,A.kt)("a",{parentName:"p",href:"/dapp/sapphire/quickstart#add-the-sapphire-testnet-to-hardhat"},"described in the quickstart"),"."),(0,A.kt)("p",null,"Next, install dependencies and deploy the contract on the Testnet with the private\nkey of the account holding some ",(0,A.kt)("a",{parentName:"p",href:"/dapp/sapphire/quickstart#get-some-sapphire-testnet-tokens"},"TEST tokens"),":"),(0,A.kt)("pre",null,(0,A.kt)("code",{parentName:"pre"},'pnpm install\npnpm add -D @oasisprotocol/sapphire-paratime\nPRIVATE_KEY="0x..." pnpm hardhat run scripts/deploy.js --network sapphire_testnet\n')),(0,A.kt)("p",null,"This will compile the contract and deploy it on the Testnet. In addition\nto the quickstart steps, ",(0,A.kt)("strong",{parentName:"p"},"the contract address and ABI will also automatically\nbe copied over to the ",(0,A.kt)("inlineCode",{parentName:"strong"},"frontend/src/contracts")," folder so that the frontend can\naccess them!")),(0,A.kt)("admonition",{type:"warning"},(0,A.kt)("p",{parentName:"admonition"},"The contract in the Hardhat boilerplate is ERC-20-compatible and emits the\n",(0,A.kt)("inlineCode",{parentName:"p"},"transfer")," event. If your wish to preserve confidentiality, you can comment\nout ",(0,A.kt)("a",{parentName:"p",href:"https://github.com/NomicFoundation/hardhat-boilerplate/blob/13bd712c1285b2de572f14d20e6a750ae08565c0/contracts/Token.sol#L66"},"line 66"),". Read ",(0,A.kt)("a",{parentName:"p",href:"/dapp/sapphire/guide#contract-logs"},"the guide")," to learn more.")),(0,A.kt)("h2",{id:"signing-sapphire-calls-and-transactions-in-browser"},"Signing Sapphire Calls and Transactions in Browser"),(0,A.kt)("p",null,"Now, let's explore the frontend of our dApp. Begin by moving into the\n",(0,A.kt)("inlineCode",{parentName:"p"},"frontend")," folder and install dependencies:"),(0,A.kt)("pre",null,(0,A.kt)("code",{parentName:"pre",className:"language-shell"},"pnpm install\npnpm add -D @oasisprotocol/sapphire-paratime\n")),(0,A.kt)("p",null,"The main frontend logic is stored in ",(0,A.kt)("inlineCode",{parentName:"p"},"frontend/src/components/Dapp.js"),". Apply\nthe following changes:"),(0,A.kt)("pre",null,(0,A.kt)("code",{parentName:"pre",className:"language-diff",metastring:'title="frontend/src/components/Dapp.js"',title:'"frontend/src/components/Dapp.js"'},"--- a/hardhat-boilerplate/frontend/src/components/Dapp.js\n+++ b/hardhat-boilerplate/frontend/src/components/Dapp.js\n@@ -2,6 +2,7 @@\n \n // We'll use ethers to interact with the Ethereum network and our contract\n import { ethers } from \"ethers\";\n+import * as sapphire from '@oasisprotocol/sapphire-paratime';\n \n // We import the contract's artifacts and address here, as we are going to be\n // using them with ethers\n@@ -22,7 +23,7 @@\n // This is the Hardhat Network id that we set in our hardhat.config.js.\n // Here's a list of network ids https://docs.metamask.io/guide/ethereum-provider.html#properties\n // to use when deploying to other networks.\n-const HARDHAT_NETWORK_ID = '1337';\n+const HARDHAT_NETWORK_ID = '23295'; // Sapphire Testnet\n \n // This is an error code that indicates that the user canceled a transaction\n const ERROR_CODE_TX_REJECTED_BY_USER = 4001;\n@@ -225,14 +226,20 @@\n \n async _initializeEthers() {\n // We first initialize ethers by creating a provider using window.ethereum\n- this._provider = new ethers.providers.Web3Provider(window.ethereum);\n+ this._provider = sapphire.wrap(new ethers.providers.Web3Provider(window.ethereum));\n \n- // Then, we initialize the contract using that provider and the token's\n- // artifact. You can do this same thing with your contracts.\n+ // Then, we initialize two contract instances:\n+ // - _token: Used for eth_calls (e.g. balanceOf, name, symbol)\n+ // - _tokenWrite: Used for on-chain transactions (e.g. transfer)\n this._token = new ethers.Contract(\n contractAddress.Token,\n TokenArtifact.abi,\n- this._provider.getSigner(0)\n+ this._provider,\n+ );\n+ this._tokenWrite = new ethers.Contract(\n+ contractAddress.Token,\n+ TokenArtifact.abi,\n+ sapphire.wrap(new ethers.providers.Web3Provider(window.ethereum).getSigner())\n );\n }\n \n@@ -294,7 +301,7 @@\n \n // We send the transaction, and save its hash in the Dapp's state. This\n // way we can indicate that we are waiting for it to be mined.\n- const tx = await this._token.transfer(to, amount);\n+ const tx = await this._tokenWrite.transfer(to, amount);\n this.setState({ txBeingSent: tx.hash });\n \n // We use .wait() to wait for the transaction to be mined. This method\n@@ -360,8 +367,8 @@\n return true;\n }\n \n- this.setState({ \n- networkError: 'Please connect Metamask to Localhost:8545'\n+ this.setState({\n+ networkError: 'Please connect to Sapphire ParaTime Testnet'\n });\n \n return false;\n")),(0,A.kt)("p",null,"Beside the obvious change to the chain ID and wrapping ethers.js objects with the\nSapphire wrapper you can notice that we initialized ",(0,A.kt)("strong",{parentName:"p"},"two")," contract\ninstances:"),(0,A.kt)("ul",null,(0,A.kt)("li",{parentName:"ul"},(0,A.kt)("inlineCode",{parentName:"li"},"this._token")," object will be used for unsigned eth calls. This is the\nHardhat method of ",(0,A.kt)("a",{parentName:"li",href:"/dapp/sapphire/guide#transactions--calls"},"setting ",(0,A.kt)("inlineCode",{parentName:"a"},"from")," transaction field to all zeros")," in order to avoid Metamask signature popups.\nAlthough the call is unsigned, ",(0,A.kt)("strong",{parentName:"li"},"it is still encrypted")," with the\ncorresponding runtime key to preserve confidentiality."),(0,A.kt)("li",{parentName:"ul"},(0,A.kt)("inlineCode",{parentName:"li"},"this._tokenWrite")," object will be used for signed calls and transactions. The\nuser will be prompted by Metamask for the signature. Both \u2014 calls and\ntransactions \u2014 will be encrypted.")),(0,A.kt)("h2",{id:"trying-it"},"Trying it"),(0,A.kt)("p",null,"Start the frontend by typing ",(0,A.kt)("inlineCode",{parentName:"p"},"pnpm run start"),". If all goes well the web server\nwill spin up and your browser should automatically open\n",(0,A.kt)("inlineCode",{parentName:"p"},"http://localhost:3000"),"."),(0,A.kt)("p",null,(0,A.kt)("img",{alt:"Hardhat boilerplate frontend",src:t(8905).Z,width:"1489",height:"979"})),(0,A.kt)("p",null,"Go ahead and connect the wallet. If you haven't done it yet, you will have\nto add the ",(0,A.kt)("a",{parentName:"p",href:"/dapp/sapphire/#testnet"},"Sapphire ParaTime Testnet network to your Metamask"),". Once connected, the frontend will make an unsigned call to\nthe ",(0,A.kt)("inlineCode",{parentName:"p"},"balanceOf")," view and show you the amount of ",(0,A.kt)("inlineCode",{parentName:"p"},"MHT"),"s in your selected\nMetamask account."),(0,A.kt)("p",null,(0,A.kt)("img",{alt:"MHT balance of your account",src:t(4423).Z,width:"1489",height:"979"})),(0,A.kt)("p",null,"Next, let's transfer some ",(0,A.kt)("inlineCode",{parentName:"p"},"MHT"),"s. Fill in the amount, the address and hit the\n",(0,A.kt)("em",{parentName:"p"},"Transfer")," button. Metamask will show you the popup to sign and submit the\ntransfer transaction. Once confirmed, Metamask will both ",(0,A.kt)("strong",{parentName:"p"},"sign and encrypt")," the transaction."),(0,A.kt)("p",null,(0,A.kt)("img",{alt:"Sign and encrypt the transfer transaction",src:t(4670).Z,width:"360",height:"635"})),(0,A.kt)("p",null,"Once the transaction is processed, you will get a notification from Metamask\nand the balance in the dApp will be updated."),(0,A.kt)("admonition",{type:"tip"},(0,A.kt)("p",{parentName:"admonition"},"If you commented out ",(0,A.kt)("inlineCode",{parentName:"p"},"emit Transfer(...)"),", the transfer of ",(0,A.kt)("inlineCode",{parentName:"p"},"MHT"),"s would have\nbeen completely confidential. In the example above, the ",(0,A.kt)("a",{parentName:"p",href:"https://testnet.explorer.sapphire.oasis.dev/tx/0x3303dea5d48291d1564cad573f21fc71fcbdc2b862e17e056287fd9207e3bc53"},"following transaction")," was generated. Go ahead and check your transaction on the\nblock explorer too, to make sure no sensitive data was leaked!")),(0,A.kt)("p",null,"Congratulations, you successfully implemented your first truly confidential\ndApp which runs in the browser and wraps Metamask to both sign and encrypt the\ntransactions!"),(0,A.kt)("p",null,"Should you have any questions or ideas to share, feel free to reach out to us\non ",(0,A.kt)("a",{parentName:"p",href:"/get-involved/#social-media-channels"},"discord and other social media channels"),"."),(0,A.kt)("admonition",{title:"Example",type:"info"},(0,A.kt)("p",{parentName:"admonition"},"You can download a full working example from the ",(0,A.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/hardhat-boilerplate"},"Sapphire ParaTime examples"),"\nrepository.")))}d.isMDXComponent=!0},8905:(q,e,t)=>{t.d(e,{Z:()=>n});const n="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABdEAAAPTCAMAAABok7AJAAABX1BMVEX////+/v77+/v39/fy8/P/88zv7/Dt7u7p6erm5ufj4+Tf4ODa29zX19jV1tbR0tPQ0dLOz9DJysv/yCLExcb/xh3AwcL/wQj/wQe9vsD+wAb8vga6u7z6vQa2t7n1uQfxtgjttAmvsLLmrwqpq63fqgump6nXpAygoqOdn6HRoA3Qnw2Zm53Kmw6WmJqUlpjDlg+SlJaPkZO+khCMjpC5jxC0jBGGiIqthxKphBOAgoWkgRSefRR5e32aehV1eHqWdxZydHeTdRaQcxdvcXRsb3GKbxdoa22FahllaGt+ZhliZWdeYWR4Yhp3YRtbXmFxXRtYW15VWFtpWB1TVllQVFdkVB5OUVReUB5KTlFWSh9GSU1DRklQRiBNRCFAQ0dLQiE8QENEPiI5PEA9OSM1ODw5NiQwNDg2NCQ0MiUyMSUtMDQuLiYoLDArLCYmKi4mKSckKCwiJikhJSkhJSifXin8AAAN6UlEQVR42uzY0UvybBjH8Z9ONKdlRgSCeDAkGkhRCEIgIfQg4kCMQsRAZIgHQ8a8/394t+kzi07fDh78fg5U8LrunX3RWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAvy2UffvERAHDCuiYWLnuW6uZCv6gy0d5NX/+T0NV9oNjxZAA4YV3jum7n1Qx+u+huqL2R91tFj08GgBPWNUq8RCWKDgD/tkPRHVNLi14dB8GgJOU6izAYV6Wz4Wb7diXpZhb6TzntnXvB+qWYjG+CP2XJXbSX4fxaGvV763Bsf51vzbarh9y9MaatmBd/sLPFxHwsyQruVOz7Yfysw7+F9ZNqxtlsbElNE78+py8zFZ79aN0vZEXPdZbhovX3ZAA4WV1zeEt/o5c3i5azmuV1H3Wu2+upNJk1b7ygqJvdsNHZPitlBx8tZ+2pGrzH46ui3HB+VfU2lkbhn/P6aqzjfMsMGp3ovtgNqwXFypO3aj5bTLhRSWpFJWvht5uTqP616Ou7B8UKUVuaG0daPsnznevH6Ckrem/Xazyb1v5kAcDJ6hrbti/utl7a0efgTKrsHL10JXV2uaSaOuvZms9yUntXViweK0jNZel1bUmV6FFuvKuaudJok5c6Uf44P59K6o2/37pki4lSdCuNxrpNDsl/Tr4W/VF704GKu3lftqkX3pqSxtND0eP1nqTBklsXAKeua1IzO+3o3MvHPl8klertibE0CQdOUSqah/iLM+Mo8TFSyu8r9jaRG7dfZdPQaCrJMVY2bxn35z36cTGW1rkYtpIox7ph7kvRG9q799X0O5+63eQk2dfu8uNv0ZumHj/KMWWKDuDEdU2z2bypSGnRfZMa6/zdhPOpsVTs+SYaWBWz11Fi2Vdq21VsOEtyfSi6lxa9kM2XjfOz6MfFVMuUbwNL4zfF7oz1peiX2js3lefXuikNB1JrZYLpIit62+xdUnQAJ65rlDgUfTGuJSr51ewyn8RVsfOeeSiZp1riTInZSJJ1U/T7ir17P4uezReMK6l8lf9W9Gwxld/ceX1lv9FVNzVJ26ToNR34t/Pb/La1cXQeDSo5DbOit0yzlihQdAAn7nvR+74lWV7bNm1JI2Od+Q1Jq74+h5IuphfHe/SGqaTX4Xb0+LPox/nFRFLPz92F2ht6Ura41/8Ir3S8R6+apnRpvhX9ZRxVNXnfldT+j127fUoqDeM4fvdcU9u6ZutPDVGJxcnc0SUYHxgy3SmWFqPFNaJahQDFDnD07v+fPSfkjK6z7jiFrvX9vLpgzg3vvsPcXP5Cy6VaUPQbu5PGmPvPL5lnFB3AN+1w0W96OyhDLz/culh71d//2NprZq18f2DBDphR+3hoovz20v6uy9q9iffPzK2mt7Ky8f7a0aIHz/vDjw/bk96bs9912rw1ebV7MPjq8gWv0m+9XZffd/vNhfLGxE/l2qGij9qtC2bWrhlz2z7pG/rDvukW3Sw0ZwceNh93Prnv+Q8GAL5Nh4ruL5o3P7zo8168atZ+G/ASff3XWvv1hJ/U1+3ak+um4/aLZm3hsjF9L5pb3lr50aIfeH70TXtj0pjLa+2fO2fL7f7uwa6tR8Zz/clW82W/N/T92X47+vJQ0a/uPjOm3856o7f6Xl6Y3L3aLfrF2XK7/Ohi55OH7D0DADgzffamAQCcf9//svHcAAC+Av0fXt0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7blbuDOkuDd68YAMAXcGVQZ22QpAPAl3BHZ++OAQB8vkGdvUEDAPh8+j8wAACKDgCg6ADwtdHxKDoAnBs6HkUHgHNDx6PoAHBu6HgUHQDODR2PogPAuaEvYvikz1N0AOh10cefVtx6PqqTSafki9k5SaGW9c9P2bi63JSWHCkwk6PoANDjokfrTnZxpd6a0ok4S/IN72QlTe85i5LSbvhfi75epOgA0Nuij2xWI5LGq5WTF91X2JS0srle8OeSKDoAnCYdNGOT8iWzYwqlK25lXpKTKrScXOjAMJbbcUsxP/2rDacYk2ttVb7FvbBUyqScEamxorFs3W3kwkHRh9NVt5KUitbaCEUHgF4WPeMVuWvVXY5nbVpy3KVo0j0wjJScVKLoRBTabCzG322PRVuZqDzDUTutsBuP2Sn5Y7E+N7O8txIU/eleJp79mFCkWIqGKDoA9LLohbq6on7MtdoKy1mXtF5SMCRsXApVc94wLY1XZ4JbFzWWFHfD2l7WXCsULiUkFUvdoo+7GUn5KrcuAND7oucb6pq3EUkzdlrOiqTVdwqGbCvkyVWVcdQRFL2wrmxJype0WpQnMpOqvusWPWGnvXNJG6HoANDzoj/dv3UJR5W2IUkxG+/kevUvBUPefuIqV/1n0Rd3VFmW5txQJS0lqrZVqgRFn7cdUxQdAE7tn9F5O939jT51tOjZxoNP9n+jz0QUFD1qp7wTitj4x5hibj46rEJQ9KRNPPCFKToAnNr2Yr0y3L1HDx0tetLGJGUz+/fo7qJ2lrRvO++MSKoUdkY0b6NSeDsoemQvJWl+PawCRQfwNzt30NlAEAZgOD3kF1TsR4X0UDlUCVESiaqWqNAIpYdQoiJqRS3N/9dpKqewl4jt6vNcZoyxx/ey4+PERY9unj+NJvlnN2K+e+tyH4dFby/Xo970a5A2H8P+YtWJ1dsgfs2Ll0imP0t3O7/uL7bv+6Kn08feXTGLmOXjjqIDnLTocfW8Kla7KQDtyXr3Hv2w6HE5y4vlINJmvtm8psvDzaa9/6E6iuR2twzTt6bjorMv+sVDOpikm911caPoAH9yUlc5sxcBFB0ARQf4f6KcogPURpRTdIDaiHKKDlAbUU7RAWojyik6QG1EOUUHqI0sqpc1ADjeeVTvvAHA8ZpZVC1rNgA43lmzlUWVspagAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDNHhwIAAAAAAD5vzaCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoKe3AgAAAAAADk/9oIqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoq7MGBAAAAAACQ/2sjqKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtAeHBAAAAACC/r92hgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4BdH5jrGCCBdOAAAAAElFTkSuQmCC"},4423:(q,e,t)=>{t.d(e,{Z:()=>n});const n=t.p+"assets/images/hardhat-boilerplate-frontend2-6d2fe4701649136e7c90270f572a86be.png"},4670:(q,e,t)=>{t.d(e,{Z:()=>n});const n=t.p+"assets/images/hardhat-boilerplate-frontend3-727893cadf6a2874b868f655cb84d059.png"}}]); \ No newline at end of file diff --git a/assets/js/59b1a96c.e877de67.js b/assets/js/59b1a96c.e877de67.js new file mode 100644 index 0000000000..b5e3584d62 --- /dev/null +++ b/assets/js/59b1a96c.e877de67.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[67],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=l(n),u=a,h=p["".concat(c,".").concat(u)]||p[u]||m[u]||o;return n?r.createElement(h,i(i({ref:t},d),{},{components:n})):r.createElement(h,i({ref:t},d))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[p]="string"==typeof e?e:a,i[1]=s;for(var l=2;l<o;l++)i[l]=n[l];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}u.displayName="MDXCreateElement"},1564:(e,t,n)=>{n.d(t,{Z:()=>h});var r=n(7294),a=n(6010),o=n(9960),i=n(3438),s=n(3919),c=n(5999);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:n}=e;return r.createElement(o.Z,{href:t,className:(0,a.Z)("card padding--lg",l.cardContainer)},n)}function p(e){let{href:t,icon:n,title:o,description:i}=e;return r.createElement(d,{href:t},r.createElement("h2",{className:(0,a.Z)("text--truncate",l.cardTitle),title:o},n," ",o),i&&r.createElement("p",{className:(0,a.Z)("text--truncate",l.cardDescription),title:i},i))}function m(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?r.createElement(p,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,c.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,i.xz)(t.docId??void 0);return r.createElement(p,{href:t.href,icon:n,title:t.label,description:t.description??a?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(u,{item:t});case"category":return r.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,n)=>{n.d(t,{Z:()=>c});var r=n(7294),a=n(6010),o=n(3438),i=n(1564);function s(e){let{className:t}=e;const n=(0,o.jA)();return r.createElement(c,{items:n.items,className:t})}function c(e){const{items:t,className:n}=e;if(!t)return r.createElement(s,e);const c=(0,o.MN)(t);return r.createElement("section",{className:(0,a.Z)("row",n)},c.map(((e,t)=>r.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},r.createElement(i.Z,{item:e})))))}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var r=n(4477);function a(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&a(t.items)}}function o(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)a(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},2075:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>f,frontMatter:()=>c,metadata:()=>d,toc:()=>m});var r=n(7462),a=(n(7294),n(3905)),o=n(1564),i=n(9268),s=n(7525);const c={},l="Getting Started",d={unversionedId:"README",id:"README",title:"Getting Started",description:"Use Oasis",source:"@site/docs/README.mdx",sourceDirName:".",slug:"/",permalink:"/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{}},p={},m=[{value:"Use Oasis",id:"use-oasis",level:2},{value:"Create dApp",id:"create-dapp",level:2},{value:"Get Involved",id:"get-involved",level:2},{value:"Run Node",id:"run-node",level:2},{value:"Build ParaTimes",id:"build-paratimes",level:2},{value:"Develop Core",id:"develop-core",level:2}],u={toc:m},h="wrapper";function f(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"getting-started"},"Getting Started"),(0,a.kt)("h2",{id:"use-oasis"},"Use Oasis"),(0,a.kt)("p",null,"The introductory section contains general overview of the Oasis Network such as\nthe distinction between the consensus layer and different ParaTimes. It\nalso covers wallets and other tools for managing your assets across the Oasis\nchains and how to use unique Oasis features."),(0,a.kt)(i.Z,{items:[(0,s.n)("/general/oasis-network/"),(0,s.n)("/general/manage-tokens/")],mdxType:"DocCardList"}),(0,a.kt)("h2",{id:"create-dapp"},"Create dApp"),(0,a.kt)("p",null,"Contains learning material for the smart contract developers. Since the Oasis\nplatform is best known for confidentiality, the most notable ParaTime is\n",(0,a.kt)("a",{parentName:"p",href:"/dapp/sapphire/"},"Oasis Sapphire"),", an ",(0,a.kt)("strong",{parentName:"p"},"EVM-compatible")," ParaTime with ",(0,a.kt)("strong",{parentName:"p"},"built-in contract state\nencryption"),". The Oasis team also prepared a set of libraries called the\n",(0,a.kt)("a",{parentName:"p",href:"/dapp/opl/"},"Oasis Privacy Layer")," to ",(0,a.kt)("strong",{parentName:"p"},"bridge existing dApps running on other chains")," to\nuse the unique Sapphire's confidentiality."),(0,a.kt)("p",null,"The section also covers other ParaTimes such as the non-confidential\n",(0,a.kt)("a",{parentName:"p",href:"/dapp/emerald/"},"Oasis Emerald")," and Wasm-compatible, confidential ",(0,a.kt)("a",{parentName:"p",href:"/dapp/emerald/"},"Oasis Cipher"),"."),(0,a.kt)(i.Z,{items:[(0,s.n)("/dapp/sapphire/"),(0,s.n)("/dapp/opl/"),(0,s.n)("/dapp/emerald/"),(0,s.n)("/dapp/cipher/")],mdxType:"DocCardList"}),(0,a.kt)("h2",{id:"get-involved"},"Get Involved"),(0,a.kt)("p",null,"Contains information on official channels to get in touch with the Oasis Network\ndevelopers and how to contribute to the network."),(0,a.kt)(i.Z,{items:[(0,s.n)("/get-involved/"),(0,s.n)("https://oasisrose.garden"),(0,s.n)("/get-involved/run-node"),(0,s.n)("/get-involved/oasis-core")],mdxType:"DocCardList"}),(0,a.kt)("h2",{id:"run-node"},"Run Node"),(0,a.kt)("p",null,"If you want to run your own Oasis node, the following section will provide you\nwith guides on the current Mainnet and Testnet network parameters and how to\nset up your node, let it be a validator node, perhaps running a ParaTime or\njust a simple client node for your server to submit transactions and perform\nqueries on the network."),(0,a.kt)(i.Z,{items:[(0,s.n)("/node/"),(0,s.n)("/node/mainnet/"),(0,s.n)("/node/testnet/"),(0,s.n)("/node/run-your-node")],mdxType:"DocCardList"}),(0,a.kt)("h2",{id:"build-paratimes"},"Build ParaTimes"),(0,a.kt)("p",null,"Apart from Emerald, Cipher, Sapphire and the Key manager ParaTimes, developers\ncan learn how to write, compile, sign and deploy their own ParaTimes on the\nOasis Network."),(0,a.kt)(o.Z,{item:(0,s.n)("/paratime/"),mdxType:"DocCard"}),(0,a.kt)("h2",{id:"develop-core"},"Develop Core"),(0,a.kt)("p",null,"Whether you want to contribute your code to the core components of the Oasis\nNetwork or just learn more about the Oasis core, this is the place for you."),(0,a.kt)(o.Z,{item:(0,s.n)("/core/"),mdxType:"DocCard"}),(0,a.kt)("p",null,"Development of interoperable Oasis network components are made by consensus.\nSimilar to the Ethereum's ERC/EIP mechanism, Oasis follows Architectural\nDecision Records (ADRs) which are first proposed, voted on and can then be\nimplemented, if accepted."),(0,a.kt)(o.Z,{item:(0,s.n)("/adrs"),mdxType:"DocCard"}))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/59e83093.6ac1d9b8.js b/assets/js/59e83093.6ac1d9b8.js new file mode 100644 index 0000000000..ec82a3625c --- /dev/null +++ b/assets/js/59e83093.6ac1d9b8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7206],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),u=p(n),m=r,h=u["".concat(l,".").concat(m)]||u[m]||c[m]||o;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:r,i[1]=s;for(var p=2;p<o;p++)i[p]=n[p];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},1396:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const o={},i="E* Upgrade",s={unversionedId:"node/mainnet/e-upgrade",id:"node/mainnet/e-upgrade",title:"E* Upgrade",description:"This document is a work in progress and details around when the upgrade will be",source:"@site/docs/node/mainnet/e-upgrade.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/e-upgrade",permalink:"/node/mainnet/e-upgrade",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/e-upgrade.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Mainnet",permalink:"/node/mainnet/"},next:{title:"Damask Upgrade",permalink:"/node/mainnet/damask-upgrade"}},l={},p=[{value:"Major Features",id:"major-features",level:2},{value:"Mechanics of the Upgrade",id:"mechanics-of-the-upgrade",level:2}],d={toc:p},u="wrapper";function c(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"e-upgrade"},"E* Upgrade"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"This document is a work in progress and details around when the upgrade will be\nproposed and how it will be called are still not known and will be determined\nby the Oasis community."),(0,r.kt)("p",{parentName:"admonition"},"The upgrade will first happen on Testnet and will only be proposed for Mainnet\nafter sufficient testing has been done to ensure everything will progress as\nplanned.")),(0,r.kt)("p",null,"This document provides an overview of the changes for the E* Mainnet\nupgrade."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The E* upgrade on Mainnet is scheduled at epoch TODO which will happen\naround TODO.")),(0,r.kt)("h2",{id:"major-features"},"Major Features"),(0,r.kt)("p",null,"All features for the E* upgrade are implemented as part of\n",(0,r.kt)("strong",{parentName:"p"},"Oasis Core 23.0.x")," release series which is a consensus protocol-breaking\nrelease."),(0,r.kt)("p",null,"Summary of the major features is as follows:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"On-Chain Governance"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The upgrade adds support for delegators to participate in on-chain\ngovernance. So far, only validators have been able to vote on governance\nproposals on upgrades. From now on, anyone who is staking will be able to\noverride the votes of the validator."),(0,r.kt)("li",{parentName:"ul"},"Prior to this upgrade, validators could vote solely on one specific type of\nupgrade proposal. This upgrade adds support for voting on parameter changes.\nAn example of such a change includes voting on the staking rewards schedule\nmodifications."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Node Operators UX"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"With the enhancement of the P2P Stack in the latest upgrade, we've\nintegrated support for state sync. This improvement simplifies the process\nof initiating a new node, enabling immediate synchronization without the\nneed for manual RPC node configuration."),(0,r.kt)("li",{parentName:"ul"},"The upgrade lays the foundation for the system to distribute bundles\nautomatically. While this update doesn't enable this feature, in the future\nnodes will have the capability to upgrade automatically to the appropriate\nversion immediately after a governance vote passes."),(0,r.kt)("li",{parentName:"ul"},"Enhancements have been made to bolster security and optimize the efficiency\nof specific queries."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Key Rotations"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The upgrade introduces major updates to facilitate key rotations, both for\nephemeral and state keys.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Key derivation for ephemeral keys will be modified such that the master\nephemeral key will be rotated on every epoch and old entropy will be\ndiscarded after a few epochs. As a result, past transaction keys will be\nirretrievable unless the user keeps additional data to enable disclosure\nof past transactions."),(0,r.kt)("li",{parentName:"ul"},"The upgrade introduces support for state key rotations, incorporating key\ngenerations. ParaTimes can now rotate state keys daily, and use new keys\nfor newer state. This facilitates re-encryption and, in the event of a TCB\nrecovery, helps to partially mitigate the effects of compromised nodes."))))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Confidential Query Latency"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The current confidential ParaTimes have a block delay when querying\nconfidential state following transaction execution. This is due to the fact\nthat the ParaTime needs to independently verify finalization in the\nconsensus layer to guard against attacks. The upcoming version introduces\nsame-block execution. As soon as a block gets finalized on the consensus\nlayer, ParaTimes can promptly obtain the latest state root hash and verify\nthe state without delay. This reduces latency for those looking to query\noutcomes of their transactions, e.g. dApp users and developers."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Upgrades"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The upgrade reduces downtime associated with upgrading confidential\nParaTimes. Previously, an upgrade to Sapphire mandated an epoch of downtime.\nNow, as compute nodes transition to the new version, the upgrade will be\ninstantaneous, ensuring no delays or downtime."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Performance"),":"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The upgrade implements a series of modifications to enhance the robustness\nof runtimes. These improvements encompass better response mechanisms for SGX\nTCB recovery events, expanded support for new SGX platforms, and improved\nproof validation within runtimes."),(0,r.kt)("li",{parentName:"ul"},"The upgrade improves runtime performance, especially in scenarios involving\nnode failures. Should nodes malfunction, the impact on performance will now\nbe significantly reduced.")))),(0,r.kt)("h2",{id:"mechanics-of-the-upgrade"},"Mechanics of the Upgrade"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"This section will be updated with the exact details as we get closer to the\nupgrade. For now, please take a look at the related ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/upgrade-log"},"Testnet upgrade"),".")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5a14fd4c.5110d1ee.js b/assets/js/5a14fd4c.5110d1ee.js new file mode 100644 index 0000000000..8210cbb358 --- /dev/null +++ b/assets/js/5a14fd4c.5110d1ee.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5115],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,i,a=function(e,t){if(null==e)return{};var n,i,a={},o=Object.keys(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=i.createContext({}),p=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},c=function(e){var t=p(e.components);return i.createElement(l.Provider,{value:t},e.children)},h="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},u=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),h=p(n),u=a,m=h["".concat(l,".").concat(u)]||h[u]||d[u]||o;return n?i.createElement(m,r(r({ref:t},c),{},{components:n})):i.createElement(m,r({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[h]="string"==typeof e?e:a,r[1]=s;for(var p=2;p<o;p++)r[p]=n[p];return i.createElement.apply(null,r)}return i.createElement.apply(null,n)}u.displayName="MDXCreateElement"},8690:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var i=n(7462),a=(n(7294),n(3905));const o={},r="ADR 0010: VRF-based Committee Elections",s={unversionedId:"adrs/0010-vrf-elections",id:"adrs/0010-vrf-elections",title:"ADR 0010: VRF-based Committee Elections",description:"Component",source:"@site/docs/adrs/0010-vrf-elections.md",sourceDirName:"adrs",slug:"/adrs/0010-vrf-elections",permalink:"/adrs/0010-vrf-elections",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0010-vrf-elections.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0009: Ed25519 Signature Verification Semantics",permalink:"/adrs/0009-ed25519-semantics"},next:{title:"ADR 0011: Incoming Runtime Messages",permalink:"/adrs/0011-incoming-runtime-messages"}},l={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Cryptographic Primitives",id:"cryptographic-primitives",level:3},{value:"Node Descriptor Changes",id:"node-descriptor-changes",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Consensus State, Events, and Transactions",id:"consensus-state-events-and-transactions",level:3},{value:"VRF Operation",id:"vrf-operation",level:3},{value:"VRF Committee Elections",id:"vrf-committee-elections",level:3},{value:"VRF Validator Elections",id:"vrf-validator-elections",level:3},{value:"Timekeeping Changes",id:"timekeeping-changes",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],c={toc:p},h="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,i.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0010-vrf-based-committee-elections"},"ADR 0010: VRF-based Committee Elections"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2021-05-10: Initial version")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"While functional, the current PVSS-based random beacon is neither all that\nperformant, nor all that scalable. To address both concerns, this ADR\nproposes transitioning the election procedure to one that is based on\ncryptographic sortition of Verifiable Random Function (VRF) outputs."),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("h3",{id:"cryptographic-primitives"},"Cryptographic Primitives"),(0,a.kt)("p",null,"Let the VRF to be used across the system be ECVRF-EDWARDS25519-SHA512-ELL2\nfrom the ",(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/"},"Verifiable Random Functions (VRFs) draft (v10)"),", with the\nfollowing additions and extra clarifications:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},'All public keys MUST be validated via the "ECVRF Validate Key" procedure\nas specified in section 5.6.1 (Small order public keys MUST be\nrejected).')),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The string_to_point routine MUST reject non-canonically encoded points\nas specified in RFC 8032. Many ed25519 implementations are lax about\nenforcing this when decoding.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"When decoding s in the ECVRF_verify routine, the s scalar MUST fall\nwithin the range 0 <= i < L. This change will make proofs\nnon-malleable. Note that this check is unneeded for the c scalar\nas it is 128-bits, and thus will always lie within the valid range.\nThis check was not present in the IETF draft prior to version 10.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Implementations MAY choose to incorporate additional randomness into\nthe ECVRF_nonce_generation_RFC8032 function. Note that proofs (pi_string)\nare not guaranteed to be unique or deterministic even without this\nextension (the signer can use any arbitrary value for the nonce and\nproduce a valid proof, without altering beta_string)."))),(0,a.kt)("p",null,"Let the tuple oriented cryptographic hash function be TupleHash256 from\n",(0,a.kt)("a",{parentName:"p",href:"https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf"},"NIST SP 800-185"),"."),(0,a.kt)("h3",{id:"node-descriptor-changes"},"Node Descriptor Changes"),(0,a.kt)("p",null,"The node descriptor of each node will be extended to include the following\ndatastructure."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type Node struct {\n // ... existing fields omitted ...\n\n // VRF is the public key used by the node to generate VRF proofs.\n VRF *VRFInfo `json:"vrf,omitempty"`\n}\n\ntype VRFInfo struct {\n // ID is the unique identifier of the node used to generate VRF proofs.\n ID signature.PublicKey `json:"id"`\n}\n')),(0,a.kt)("p",null,"The VRF public key shall be a long-term Ed25519 public key, that is distinct\nfrom every other key used by the node. The key MUST not be small order."),(0,a.kt)("p",null,"The existing ",(0,a.kt)("inlineCode",{parentName:"p"},"Beacon")," member of the node descriptor is considered deprecated\nand will first be ignored by the consensus layer, and then removed in a\nsubsequent version following a transitionary period."),(0,a.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,a.kt)("p",null,"The scheduler module will have the following additional consensus parameters\nthat control behavior."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type ConsensusParameters struct {\n // ... existing fields omitted ...\n\n // VRFParameters is the paramenters for the VRF-based cryptographic\n // sortition based election system.\n VRFParameters *VRFParameters `json:"vrf_params"`\n}\n\n// VRFParameters are the VRF scheduler parameters.\ntype VRFParameters struct {\n // AlphaHighQualityThreshold is the minimum number of proofs (Pi)\n // that must be received for the next input (Alpha) to be considered\n // high quality. If the VRF input is not high quality, runtimes will\n // be disabled for the next epoch.\n AlphaHighQualityThreshold uint64 `json:"alpha_hq_threshold,omitempty"`\n\n // Interval is the epoch interval (in blocks).\n Interval int64 `json:"interval,omitempty"`\n\n // ProofSubmissionDelay is the wait peroid in blocks after an epoch\n // transition that nodes MUST wait before attempting to submit a\n // VRF proof for the next epoch\'s elections.\n ProofSubmissionDelay int64 `json:"proof_delay,omitempty"`\n\n // PrevState is the VRF state from the previous epoch, for the\n // current epoch\'s elections.\n PrevState *PrevVRFState `json:"prev_state,omitempty"`\n}\n\n// PrevVRFState is the previous epoch\'s VRF state that is to be used for\n// elections.\ntype PrevVRFState struct {\n // Pi is the accumulated pi_string (VRF proof) outputs for the\n // previous epoch.\n Pi map[signature.PublicKey]*signature.Proof `json:"pi.omitempty"`\n\n // CanElectCommittees is true iff the previous alpha was generated\n // from high quality input such that committee elections are possible.\n CanElectCommittees bool `json:"can_elect,omitempty"`\n}\n\n')),(0,a.kt)("h3",{id:"consensus-state-events-and-transactions"},"Consensus State, Events, and Transactions"),(0,a.kt)("p",null,"The scheduler component will maintain and make available the following additonal\nconsensus state."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'// VRFState is the VRF scheduler state.\ntype VRFState struct {\n // Epoch is the epoch for which this alpha is valid.\n Epoch EpochTime `json:"epoch"`\n\n // Alpha is the active VRF alpha_string input.\n Alpha []byte `json:"alpha"`\n\n // Pi is the accumulated pi_string (VRF proof) outputs.\n Pi map[signature.PublicKey]*signature.Proof `json:"pi,omitempty"`\n\n // AlphaIsHighQuality is true iff the alpha was generated from\n // high quality input such that elections will be possible.\n AlphaIsHighQuality bool `json:"alpha_hq"`\n\n // SubmitAfter is the block height after which nodes may submit\n // VRF proofs for the current epoch.\n SubmitAfter int64 `json:"submit_after"`\n}\n')),(0,a.kt)("p",null,"Implementations MAY cache the beta_string values that are generated from valid\npi_strings for performance reasons, however as this is trivial to recalculate,\nit does not need to be explicitly exposed."),(0,a.kt)("p",null,"Upon epoch transition, the scheduler will emit the following event."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'// VRFEvent is the VRF scheduler event.\ntype VRFEvent struct {\n // Epoch is the epoch that Alpha is valid for.\n Epoch EpochTime `json:"epoch,omitempty"`\n\n // Alpha is the active VRF alpha_string input.\n Alpha []byte `json:"alpha,omitempty"`\n\n // SubmitAfter is the block height after which nodes may submit\n // VRF proofs for the current epoch.\n SubmitAfter int64 `json:"submit_after"`\n}\n\n')),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type VRFProve struct {\n // Epoch is the epoch that this VRF proof is for.\n Epoch epochtime.EpochTime `json:"epoch"`\n\n // Pi is the VRF proof for the current epoch.\n Pi []byte `json:"pi"`\n}\n')),(0,a.kt)("h3",{id:"vrf-operation"},"VRF Operation"),(0,a.kt)("p",null,"For the genesis epoch, let the VRF alpha_string input be derived as:"),(0,a.kt)("p",null," ",(0,a.kt)("inlineCode",{parentName:"p"},'TupleHash256((chain_context, I2OSP(epoch,8)), 256, "oasis-core:vrf/alpha")')),(0,a.kt)("p",null,"For every subsequent epoch, let alpha_string be derived as:"),(0,a.kt)("p",null," ",(0,a.kt)("inlineCode",{parentName:"p"},'TupleHash256((chain_context, I2OSP(epoch, 8), beta_0, ... beta_n), 256, "oasis-core:vrf/alpha")')),(0,a.kt)("p",null,'where beta_0 through beta_n are the beta_string outputs gathered from\nall valid pi_strings submitted during the previous epoch (after the\non-transition culling is complete), in ascending lexographic order by\nVRF key. If the number of beta values incorporated into the TupleHash\ncomputation is greater than or equal to AlphaHighQuality threshold,\nthe alpha is considered "strong", and committee elections are allowed\nbased on the proofs generated with this alpha. If the alpha value is\nweak (insufficient nodes submitted proofs), only validator elections\nare allowed.'),(0,a.kt)("p",null,"Upon receiving a VRFEvent, all eligible nodes MUST wait a minimum of\nProofSubmissionDelay blocks, and then submit a VRFProve transaction,\nwith the Proof field set to the output of\n",(0,a.kt)("inlineCode",{parentName:"p"},"ECVRF_prove(VRFKey_private, alpha_string)"),"."),(0,a.kt)("p",null,"Upon receiving a VRFProve transaction, the scheduler does the following:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Rejects the transaction if less than ProofSubmissionDelay blocks\nhave elapsed since the transition into the current epoch.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Checks to see if the node tentatively eligible to be included in\nthe next election according to the following criteria:"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Not frozen.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Has registered the VRF.ID used to generate the proof prior\nto the transition into the current epoch (May slash).")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Has not already submitted a proof for the current epoch\n(May slash if proof is different).")))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Validates the proof, and if valid, stores the VRF.ID + pi_string\nin the consensus state."))),(0,a.kt)("h3",{id:"vrf-committee-elections"},"VRF Committee Elections"),(0,a.kt)("p",null,"The following changes are made to the committee election process."),(0,a.kt)("p",null,"On epoch transition, as long as the alpha used to generate the proofs\nis considered strong re-validate node eligibility for all nodes that\nsubmitted a VRF proof (Not frozen, VRF.ID has not changed), and cull\nproofs from nodes that are now ineligible."),(0,a.kt)("p",null,"If the alpha value is considered weak, no commitee elections are allowed."),(0,a.kt)("p",null,"For each committee:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Filter the node list based on the current stake/eligibility criteria,\nand additionally filter out nodes that have not submitted a valid\nVRF proof.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"For each eligible (node, commitee kind, committe role) tuple, derive\na sortition string as:"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'`s_n = TupleHash256((chain_context, I2OSP(epoch, 8), runtime_id, I2OSP(kind, 1), I2OSP(role, 1), beta_n), 256, "oasis-core:vrf/committee")`\n')),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Sort s_0 ... s_n in ascending lexographical order.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Select the requisite nodes that produced the sortition strings\nstarting from the head of the sorted list as the committee."))),(0,a.kt)("p",null,"Committee elections MUST be skipped for the genesis and subsequent epoch,\nas the genesis epoch has no VRF proofs, and proofs submitted during the\ngenesis epoch are based on the bootstrap alpha_string."),(0,a.kt)("h3",{id:"vrf-validator-elections"},"VRF Validator Elections"),(0,a.kt)("p",null,"The only place where the beacon is currently used in the validator selection\nprocess is to pick a single node out of multiple eligible nodes controlled by\nthe same entity to become a validator."),(0,a.kt)("p",null,"When this situation occurs the validator is selected as follows:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"For all validator-eligible nodes controlled by the given entity,\nderive a sortition string as:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},' `s_n = TupleHash256((chain_context, I2OSP(epoch, 8), beta_n), 256, "oasis-core:vrf/validator")`\n')),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Sort s_0 ... s_n, in ascending lexographic order.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Select the node that produced the 0th sortition string in the sorted\nlist as the validator."))),(0,a.kt)("p",null,"This is safe to do with beta values generated via the bootstrap alpha string\nas it is up to the entity running the nodes in question as to which ones\nare a validator anyway."),(0,a.kt)("p",null,"As a concession for the transition process, if the number of validators\nthat submit proofs is less than the minimum number of validators configured\nin the scheduler, validator tie-breaks (and only validator tie-breaks)\nwill be done by permuting the node list (as in the current PVSS beacon),\nusing entropy from the block hash."),(0,a.kt)("p",null,"As nodes are required to submit a VRF public key as part of non-genesis\nregistrations, and each node will attempt to submit a VRF proof, this\nbackward compatibility hack should only be triggered on the genesis\nepoch, and can be removed on the next major upgrade."),(0,a.kt)("h3",{id:"timekeeping-changes"},"Timekeeping Changes"),(0,a.kt)("p",null,"Timekeeping will go back to a fixed-interval epoch transition mechanism, with\nall of the beacon related facilities removed. As this is primarily a module\nrename and code removal, the exact details are left unspecified."),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"This is significantly simpler from a design standpoint.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"This is significantly faster and scales significantly better.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"It is possible to go back to fixed-length epochs again."))),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The system loses a way to generate entropy at the consensus layer.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The simple design involves an additional 1-epoch period after network\ninitialization where elections are not available."))),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"I need to implement TupleHash256.")),(0,a.kt)("h2",{id:"references"},"References"))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5da91464.068c028d.js b/assets/js/5da91464.068c028d.js new file mode 100644 index 0000000000..dca16baca9 --- /dev/null +++ b/assets/js/5da91464.068c028d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[108],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>m});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?a(Object(t),!0).forEach((function(n){o(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function s(e,n){if(null==e)return{};var t,r,o=function(e,n){if(null==e)return{};var t,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var d=r.createContext({}),c=function(e){var n=r.useContext(d),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=c(e.components);return r.createElement(d.Provider,{value:n},e.children)},l="mdxType",p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},h=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,d=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),l=c(t),h=o,m=l["".concat(d,".").concat(h)]||l[h]||p[h]||a;return t?r.createElement(m,i(i({ref:n},u),{},{components:t})):r.createElement(m,i({ref:n},u))}));function m(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=h;var s={};for(var d in n)hasOwnProperty.call(n,d)&&(s[d]=n[d]);s.originalType=e,s[l]="string"==typeof e?e:o,i[1]=s;for(var c=2;c<a;c++)i[c]=t[c];return r.createElement.apply(null,i)}return r.createElement.apply(null,t)}h.displayName="MDXCreateElement"},1757:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var r=t(7462),o=(t(7294),t(3905));const a={description:"This page describes how to run an archive node on the Oasis Network."},i="Archive Node",s={unversionedId:"node/run-your-node/archive-node",id:"node/run-your-node/archive-node",title:"Archive Node",description:"This page describes how to run an archive node on the Oasis Network.",source:"@site/docs/node/run-your-node/archive-node.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/archive-node",permalink:"/node/run-your-node/archive-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/archive-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"This page describes how to run an archive node on the Oasis Network."},sidebar:"operators",previous:{title:"Seed Node",permalink:"/node/run-your-node/seed-node"},next:{title:"ParaTime Node",permalink:"/node/run-your-node/paratime-node"}},d={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Archive node status",id:"archive-node-status",level:3},{value:"See also",id:"see-also",level:2}],u={toc:c},l="wrapper";function p(e){let{components:n,...t}=e;return(0,o.kt)(l,(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"archive-node"},"Archive Node"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Archive node support is currently only available in the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.3.14"},"21.3.14")," release for\nuse with the Cobalt (pre Damask upgrade) archived state.")),(0,o.kt)("p",null,"This guide will cover setting up an archive node for the Oasis Network. Node\nstarted in archive mode only serves existing consensus and runtime states.\nThe node has all unneeded consensus and P2P functionality disabled, therefore\nit will not participate in the network. Archive nodes can be used to access\nhistoric state which is pruned in dump-restore network upgrades."),(0,o.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,o.kt)("p",null,"Archive node requires a pre-existing oasis-node state."),(0,o.kt)("h2",{id:"configuration"},"Configuration"),(0,o.kt)("p",null,"Archive mode can be enabled by using the ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.mode")," setting."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This will configure the given node to act as a consensus archive node.")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"# other settings omitted ...\nconsensus:\n tendermint:\n mode: archive\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Keep other settings unchanged from the full-node. For example in order to\nserve archived runtime state, the node needs to have the runtime configured\nand have the state present.")),(0,o.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,o.kt)("p",null,"You can start the node by running the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,o.kt)("h3",{id:"archive-node-status"},"Archive node status"),(0,o.kt)("p",null,"To ensure the node is running in archive mode, run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/node/data/internal.sock\n")),(0,o.kt)("p",null,"Output should report ",(0,o.kt)("inlineCode",{parentName:"p"},"archive")," consensus mode status:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n // other fields omitted ...\n "consensus": {\n "mode": "archive",\n // ...\n')),(0,o.kt)("h2",{id:"see-also"},"See also"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/node/web3#archive-web3-gateway"},"Archive Web3 Gateway")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5ef859b9.642794e7.js b/assets/js/5ef859b9.642794e7.js new file mode 100644 index 0000000000..7fe9d08aec --- /dev/null +++ b/assets/js/5ef859b9.642794e7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7160],{8354:e=>{e.exports=JSON.parse('{"title":"Processes","slug":"core/processes","permalink":"/core/processes","navigation":{"previous":{"title":"Merklized Key-Value Store (MKVS)","permalink":"/core/mkvs"},"next":{"title":"Release Process","permalink":"/core/release-process"}}}')}}]); \ No newline at end of file diff --git a/assets/js/63d4daba.396629ba.js b/assets/js/63d4daba.396629ba.js new file mode 100644 index 0000000000..1dc0d8427c --- /dev/null +++ b/assets/js/63d4daba.396629ba.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7683],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,r,i=function(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=r.createContext({}),s=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=s(e.components);return r.createElement(p.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=s(n),g=i,m=d["".concat(p,".").concat(g)]||d[g]||u[g]||a;return n?r.createElement(m,o(o({ref:t},c),{},{components:n})):r.createElement(m,o({ref:t},c))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=g;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l[d]="string"==typeof e?e:i,o[1]=l;for(var s=2;s<a;s++)o[s]=n[s];return r.createElement.apply(null,o)}return r.createElement.apply(null,n)}g.displayName="MDXCreateElement"},9186:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var r=n(7462),i=(n(7294),n(3905));const a={},o="Exporting Public Key to Entity",l={unversionedId:"oasis-core-ledger/usage/entity",id:"oasis-core-ledger/usage/entity",title:"Exporting Public Key to Entity",description:"Before following the instructions below, make sure your Ledger wallet is",source:"@site/docs/oasis-core-ledger/usage/entity.md",sourceDirName:"oasis-core-ledger/usage",slug:"/oasis-core-ledger/usage/entity",permalink:"/oasis-core-ledger/usage/entity",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/usage/entity.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Obtaining Account Address",permalink:"/oasis-core-ledger/usage/address"},next:{title:"Generating and Signing Transactions",permalink:"/oasis-core-ledger/usage/transactions"}},p={},s=[],c={toc:s},d="wrapper";function u(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"exporting-public-key-to-entity"},"Exporting Public Key to Entity"),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"Before following the instructions below, make sure your Ledger wallet is\nunlocked and the Oasis App is open.")),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"While the Oasis App is available in ",(0,i.kt)("em",{parentName:"p"},"Developer mode"),', opening the App brings\nup the "Pending Ledger review" screen.\nYou need to press both buttons at once to close that screen and transition to\nthe ',(0,i.kt)("em",{parentName:"p"},"ordinary"),' "Oasis Ready" screen where the Oasis App is ready to be used.')),(0,i.kt)("p",null,"Before you will be able to sign anything, you will need to export the public key\nof your Ledger wallet's account and use it to generate an entity."),(0,i.kt)("p",null,"Make sure you set the following environment variables:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"LEDGER_SIGNER_PATH"),": Location of the ",(0,i.kt)("inlineCode",{parentName:"li"},"ledger-signer")," binary.\nSee ",(0,i.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/setup#remembering-path-to-ledger-signer-plugin"},"Setup")," for more details.")),(0,i.kt)("p",null,"To export the public key and generate an entity in the ",(0,i.kt)("inlineCode",{parentName:"p"},"entity"),"\nsubdirectory, run:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'mkdir entity\noasis-node signer export \\\n --signer.dir entity \\\n --signer.backend plugin \\\n --signer.plugin.name ledger \\\n --signer.plugin.path "$LEDGER_SIGNER_PATH"\n')),(0,i.kt)("p",null,"This will create an ",(0,i.kt)("inlineCode",{parentName:"p"},"entity.json")," file in the ",(0,i.kt)("inlineCode",{parentName:"p"},"entity")," directory that contains\nthe public key for a private & public key pair generated on your Ledger wallet."),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"In case you will have more than one Ledger wallet connected, you will need to\nspecify which wallet to use by setting the ",(0,i.kt)("inlineCode",{parentName:"p"},"wallet_id")," configuration key in\nthe ",(0,i.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, i.e."),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre"},'--signer.plugin.config "wallet_id:<LEDGER-WALLET-ID>"\n')),(0,i.kt)("p",{parentName:"admonition"},"where ",(0,i.kt)("inlineCode",{parentName:"p"},"<LEDGER-WALLET-ID>")," is replaced with the ID of your Ledger wallet.\nSee ",(0,i.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/wallets"},"Identifying Wallets")," for more details.")),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"If you want to use different account index for the same Ledger wallet, you\nwill need to specify it by setting the ",(0,i.kt)("inlineCode",{parentName:"p"},"index")," configuration key in the\n",(0,i.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, i.e."),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre"},'--signer.plugin.config "index:<LEDGER-ACCOUNT-INDEX>"\n')),(0,i.kt)("p",{parentName:"admonition"},"where ",(0,i.kt)("inlineCode",{parentName:"p"},"<LEDGER-ACCOUNT-INDEX>")," is replaced with the account index you want to\nuse."),(0,i.kt)("p",{parentName:"admonition"},"If you need to specify multiple configuration keys in the\n",(0,i.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag, you can separate them with a comma (",(0,i.kt)("inlineCode",{parentName:"p"},","),"), e.g."),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre"},'--signer.plugin.config "wallet_id:1fc3be,index:5"\n'))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/6ac8b2ab.0240169b.js b/assets/js/6ac8b2ab.0240169b.js new file mode 100644 index 0000000000..06f2a8993c --- /dev/null +++ b/assets/js/6ac8b2ab.0240169b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4239],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>h});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,i,a=function(e,t){if(null==e)return{};var n,i,a={},o=Object.keys(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i<o.length;i++)n=o[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=i.createContext({}),c=function(e){var t=i.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},u=function(e){var t=c(e.components);return i.createElement(s.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},m=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=c(n),m=a,h=d["".concat(s,".").concat(m)]||d[m]||p[m]||o;return n?i.createElement(h,r(r({ref:t},u),{},{components:n})):i.createElement(h,r({ref:t},u))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:a,r[1]=l;for(var c=2;c<o;c++)r[c]=n[c];return i.createElement.apply(null,r)}return i.createElement.apply(null,n)}m.displayName="MDXCreateElement"},1162:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var i=n(7462),a=(n(7294),n(3905));const o={},r="ADR 0009: Ed25519 Signature Verification Semantics",l={unversionedId:"adrs/0009-ed25519-semantics",id:"adrs/0009-ed25519-semantics",title:"ADR 0009: Ed25519 Signature Verification Semantics",description:"Component",source:"@site/docs/adrs/0009-ed25519-semantics.md",sourceDirName:"adrs",slug:"/adrs/0009-ed25519-semantics",permalink:"/adrs/0009-ed25519-semantics",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0009-ed25519-semantics.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0008: Standard Account Key Generation",permalink:"/adrs/0008-standard-account-key-generation"},next:{title:"ADR 0010: VRF-based Committee Elections",permalink:"/adrs/0010-vrf-elections"}},s={},c=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Reject Non-canonical s",id:"reject-non-canonical-s",level:3},{value:"Reject Small Order A/R",id:"reject-small-order-ar",level:3},{value:"Accept Non-canonical A/R",id:"accept-non-canonical-ar",level:3},{value:"Cofactored Verification Equation",id:"cofactored-verification-equation",level:3},{value:"Accept A/R With Non-zero Torsion",id:"accept-ar-with-non-zero-torsion",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"Future Improvements",id:"future-improvements",level:3},{value:"Recomendations For Future Projects",id:"recomendations-for-future-projects",level:2},{value:"References",id:"references",level:2}],u={toc:c},d="wrapper";function p(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,i.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0009-ed25519-signature-verification-semantics"},"ADR 0009: Ed25519 Signature Verification Semantics"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2021-05-10: Initial version")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Informative"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"In programming, it's often the buts in the specification that kill you."),(0,a.kt)("p",{parentName:"blockquote"},"-- Boris Beizer")),(0,a.kt)("p",null,'For a large host of reasons, mostly historical, there are numerous definitions\nof "Ed25519 signature validation" in the wild, which have the potential to\nbe mutually incompatible. This ADR serves to provide a rough high-level\noverview of the issue, and to document the current definition of "Ed25519\nsignature verification" as used by Oasis Core.'),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("p",null,"The Oasis Core consensus layer (and all of the Go components) currently uses\nthe following Ed25519 verification semantics."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Non-canonical s is rejected (MUST enforce ",(0,a.kt)("inlineCode",{parentName:"li"},"s < L"),")"),(0,a.kt)("li",{parentName:"ul"},"Small order A/R are rejected"),(0,a.kt)("li",{parentName:"ul"},"Non-canonical A/R are accepted"),(0,a.kt)("li",{parentName:"ul"},"The cofactored verification equation MUST be used (",(0,a.kt)("inlineCode",{parentName:"li"},"[8][S]B = [8]R + [8][k]A"),")"),(0,a.kt)("li",{parentName:"ul"},"A/R may have a non-zero torsion component.")),(0,a.kt)("h3",{id:"reject-non-canonical-s"},"Reject Non-canonical s"),(0,a.kt)("p",null,"Ed25519 signatures are trivially malleable unless the scalar component is\nconstrained to ",(0,a.kt)("inlineCode",{parentName:"p"},"0 <= s < L"),", as is possible to create valid signatures\nfrom an existing public key/message/signature tuple by adding L to s."),(0,a.kt)("p",null,"This check is mandated in all recent formulations of Ed25519 including\nbut not limited to RFC 8032 and FIPS 186-5, and most modern implementations\nwill include this check."),(0,a.kt)("p",null,"Note: Only asserting that ",(0,a.kt)("inlineCode",{parentName:"p"},"s[31] & 224 == 0")," as done in older implementations\nis insufficient."),(0,a.kt)("h3",{id:"reject-small-order-ar"},"Reject Small Order A/R"),(0,a.kt)("p",null,"Rejecting small order A is required to make the signature scheme strongly\nbinding (resilience to key/message substitution attacks)."),(0,a.kt)("p",null,"Rejecting (or accepting) small order R is not believed to have a security\nimpact."),(0,a.kt)("h3",{id:"accept-non-canonical-ar"},"Accept Non-canonical A/R"),(0,a.kt)("p",null,"The discrete logarithm of the Ed25519 points that have a valid non-canonical\nencoding and are not small order is unknown, and accepting them is not\nbelieved to have a security impact."),(0,a.kt)("p",null,"Note: RFC 8032 and FIPS 186-5 require rejecting non-canonically encoded\npoints."),(0,a.kt)("h3",{id:"cofactored-verification-equation"},"Cofactored Verification Equation"),(0,a.kt)("p",null,"There are two forms of the Ed25519 verification equation commonly in use,\n",(0,a.kt)("inlineCode",{parentName:"p"},"[S]B = R + [k]A")," (cofactor-less), and ",(0,a.kt)("inlineCode",{parentName:"p"},"[8][S]B = [8]R + [8][k]A"),"\n(cofactored), which are mutually incompatible in that it is possible\nto produce signatures that pass with one and fail with the other."),(0,a.kt)("p",null,"The cofactored verification equation is explicitly required by FIPS 186-5,\nand is the only equation that is compatible with batch signature verification.\nAdditionally, the more modern lattice-reduction based technique for fast\nsignature verification is incompatible with existing implementations unless\ncofactored."),(0,a.kt)("h3",{id:"accept-ar-with-non-zero-torsion"},"Accept A/R With Non-zero Torsion"),(0,a.kt)("p",null,"No other library enforces this, the check is extremely expensive, and\nwith how Oasis Core currently uses Ed25519 signatures, this has no security\nimpact. In the event that Oasis Core does exotic things that, for example,\nrequire that the public key is in the prime-order subgroup, this must be\nchanged."),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("p",null,"The verification semantics in use by Oasis Core provides the following\nproperties:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"SUF-CMA security"),(0,a.kt)("li",{parentName:"ul"},"Non-repudiation (strong binding)"),(0,a.kt)("li",{parentName:"ul"},"Compatibility with batch and lattice reduction based verification.")),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("p",null,'The combination of "reject small order A/R" and "accept non-canonical A/R"\nis difficult to test as it is not easily possible to generate valid\nsignatures that meet both conditions.'),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("h3",{id:"future-improvements"},"Future Improvements"),(0,a.kt)("p",null,"WARNING: Any changes to verification semantics are consensus breaking."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},'Consider switching to the "Algorithm 2" definition, for ease of testing\nand because it is the default behavior provided by curve25519-voi.'),(0,a.kt)("li",{parentName:"ul"},"Consider switching to ZIP-215 semantics, to be inline with other projects,\nmore library support (Give up on strong binding)."),(0,a.kt)("li",{parentName:"ul"},"Switching to ristretto255 (sr25519) eliminates these problems entirely.")),(0,a.kt)("h2",{id:"recomendations-for-future-projects"},"Recomendations For Future Projects"),(0,a.kt)("p",null,"The definition used in Oasis Core is partly historical. New code should\nstrongly consider using one of FIPS 186-5, Algorithm 2, or ZIP-215 semantics."),(0,a.kt)("h2",{id:"references"},"References"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://eprint.iacr.org/2020/1244.pdf"},"Taming the many EdDSAs")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://zips.z.cash/zip-0215"},"Explicitly Defining and Modifying Ed25519 Validation Rules"))))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/6b19e4d7.dec71f3c.js b/assets/js/6b19e4d7.dec71f3c.js new file mode 100644 index 0000000000..64a8a52a8f --- /dev/null +++ b/assets/js/6b19e4d7.dec71f3c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8077],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>h});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){n(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,r,n=function(e,t){if(null==e)return{};var a,r,n={},i=Object.keys(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)a=i[r],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var l=r.createContext({}),p=function(e){var t=r.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},c=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),d=p(a),u=n,h=d["".concat(l,".").concat(u)]||d[u]||m[u]||i;return a?r.createElement(h,o(o({ref:t},c),{},{components:a})):r.createElement(h,o({ref:t},c))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:n,o[1]=s;for(var p=2;p<i;p++)o[p]=a[p];return r.createElement.apply(null,o)}return r.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1564:(e,t,a)=>{a.d(t,{Z:()=>h});var r=a(7294),n=a(6010),i=a(9960),o=a(3438),s=a(3919),l=a(5999);const p={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function c(e){let{href:t,children:a}=e;return r.createElement(i.Z,{href:t,className:(0,n.Z)("card padding--lg",p.cardContainer)},a)}function d(e){let{href:t,icon:a,title:i,description:o}=e;return r.createElement(c,{href:t},r.createElement("h2",{className:(0,n.Z)("text--truncate",p.cardTitle),title:i},a," ",i),o&&r.createElement("p",{className:(0,n.Z)("text--truncate",p.cardDescription),title:o},o))}function m(e){let{item:t}=e;const a=(0,o.Wl)(t);return a?r.createElement(d,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const a=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,o.xz)(t.docId??void 0);return r.createElement(d,{href:t.href,icon:a,title:t.label,description:t.description??n?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(u,{item:t});case"category":return r.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,a)=>{a.d(t,{Z:()=>l});var r=a(7294),n=a(6010),i=a(3438),o=a(1564);function s(e){let{className:t}=e;const a=(0,i.jA)();return r.createElement(l,{items:a.items,className:t})}function l(e){const{items:t,className:a}=e;if(!t)return r.createElement(s,e);const l=(0,i.MN)(t);return r.createElement("section",{className:(0,n.Z)("row",a)},l.map(((e,t)=>r.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},r.createElement(o.Z,{item:e})))))}},7525:(e,t,a)=>{a.d(t,{n:()=>i});var r=a(4477);function n(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&n(t.items)}}function i(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)n(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},7197:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>p,toc:()=>d});var r=a(7462),n=(a(7294),a(3905)),i=a(9268),o=a(7525);const s={},l="Sapphire ParaTime",p={unversionedId:"dapp/sapphire/README",id:"dapp/sapphire/README",title:"Sapphire ParaTime",description:"The Sapphire ParaTime is our official confidential EVM Compatible ParaTime",source:"@site/docs/dapp/sapphire/README.mdx",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/",permalink:"/dapp/sapphire/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Create dApp",permalink:"/dapp/"},next:{title:"Quickstart",permalink:"/dapp/sapphire/quickstart"}},c={},d=[{value:"Web3 Gateway",id:"web3-gateway",level:2},{value:"Mainnet",id:"mainnet",level:3},{value:"Testnet",id:"testnet",level:3},{value:"See also",id:"see-also",level:2}],m={toc:d},u="wrapper";function h(e){let{components:t,...a}=e;return(0,n.kt)(u,(0,r.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"sapphire-paratime"},"Sapphire ParaTime"),(0,n.kt)("p",null,"The Sapphire ParaTime is our official confidential EVM Compatible ParaTime\nproviding a smart contract development environment with EVM compatibility."),(0,n.kt)("p",null,"As the official confidential EVM-compatible ParaTime on the Oasis Network,\nSapphire allows for:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Confidential state, end-to-end encryption, confidential randomness"),(0,n.kt)("li",{parentName:"ul"},"EVM compatibility"),(0,n.kt)("li",{parentName:"ul"},"Easy integration with EVM-based dApps, such as DeFi, NFT, Metaverse and\ncrypto gaming"),(0,n.kt)("li",{parentName:"ul"},"Scalability \u2014 increased throughput of transactions"),(0,n.kt)("li",{parentName:"ul"},"Low-cost \u2014 99%+ lower fees than Ethereum"),(0,n.kt)("li",{parentName:"ul"},"Cross-chain bridge to enable cross-chain interoperability (upcoming)")),(0,n.kt)("p",null,"If you are not bound to EVM and you wish to develop dApps with more\nfine-grained confidentiality, check out the\n",(0,n.kt)("a",{parentName:"p",href:"/dapp/cipher/"},"Cipher ParaTime"),"."),(0,n.kt)("h2",{id:"web3-gateway"},"Web3 Gateway"),(0,n.kt)("p",null,"To get started building on our Sapphire ParaTime, you can use our public Web3\ngateway, fully compatible with Ethereum's Web3 gateway."),(0,n.kt)("h3",{id:"mainnet"},"Mainnet"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"RPC HTTP endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"https://sapphire.oasis.io")),(0,n.kt)("li",{parentName:"ul"},"RPC WebSockets endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"wss://sapphire.oasis.io/ws")),(0,n.kt)("li",{parentName:"ul"},"Chain ID:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Hex: 0x5afe"),(0,n.kt)("li",{parentName:"ul"},"Decimal: 23294"))),(0,n.kt)("li",{parentName:"ul"},"Block explorer: ",(0,n.kt)("a",{parentName:"li",href:"https://explorer.sapphire.oasis.io"},"https://explorer.sapphire.oasis.io"))),(0,n.kt)("button",{class:"button button--primary margin-bottom--md",onClick:()=>{if(!window.ethereum?.request)return alert("Have you installed MetaMask yet? If not, please do so.\n\nComputer: Once it is installed, you will be able to add the ParaTime to your MetaMask.\n\nPhone: Open the website through your MetaMask Browser to add the ParaTime.");window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:"0x5afe",chainName:"Oasis Sapphire",nativeCurrency:{name:"ROSE",symbol:"ROSE",decimals:18},rpcUrls:["https://sapphire.oasis.io/","wss://sapphire.oasis.io/ws"],blockExplorerUrls:["https://explorer.sapphire.oasis.io"]}]})}},"Click here to register Sapphire Mainnet to your MetaMask or Brave Wallet"),(0,n.kt)("h3",{id:"testnet"},"Testnet"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"RPC HTTP endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"https://testnet.sapphire.oasis.dev")),(0,n.kt)("li",{parentName:"ul"},"RPC WebSockets endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"wss://testnet.sapphire.oasis.dev/ws")),(0,n.kt)("li",{parentName:"ul"},"Chain ID:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Hex: 0x5aff"),(0,n.kt)("li",{parentName:"ul"},"Decimal: 23295"))),(0,n.kt)("li",{parentName:"ul"},"Block explorer: ",(0,n.kt)("a",{parentName:"li",href:"https://testnet.explorer.sapphire.oasis.dev"},"https://testnet.explorer.sapphire.oasis.dev"))),(0,n.kt)("button",{class:"button button--primary margin-bottom--md",onClick:()=>{if(!window.ethereum?.request)return alert("Have you installed MetaMask yet? If not, please do so.\n\nComputer: Once it is installed, you will be able to add the ParaTime to your MetaMask.\n\nPhone: Open the website through your MetaMask Browser to add the ParaTime.");window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:"0x5aff",chainName:"Oasis Sapphire Testnet",nativeCurrency:{name:"TEST",symbol:"TEST",decimals:18},rpcUrls:["https://testnet.sapphire.oasis.dev/","wss://testnet.sapphire.oasis.dev/ws"],blockExplorerUrls:["https://testnet.explorer.sapphire.oasis.dev"]}]})}},"Click here to register Sapphire Testnet to your MetaMask or Brave Wallet"),(0,n.kt)("h2",{id:"see-also"},"See also"),(0,n.kt)(i.Z,{items:[(0,o.n)("/general/manage-tokens/how-to-transfer-rose-into-paratime"),(0,o.n)("/node/run-your-node/paratime-node"),(0,o.n)("/node/run-your-node/paratime-client-node"),(0,o.n)("/node/web3"),(0,o.n)("/dapp/emerald/"),(0,o.n)("/dapp/cipher/")],mdxType:"DocCardList"}))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/6ca61699.acffa9e6.js b/assets/js/6ca61699.acffa9e6.js new file mode 100644 index 0000000000..5527ca58ef --- /dev/null +++ b/assets/js/6ca61699.acffa9e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8302],{4033:e=>{e.exports=JSON.parse('{"title":"Prerequisites","description":"This sections lists hardware and software prerequisites for running an Oasis node.","slug":"node/run-your-node/prerequisites","permalink":"/node/run-your-node/prerequisites","navigation":{"previous":{"title":"Run Your Node","permalink":"/node/run-your-node"},"next":{"title":"Hardware Requirements","permalink":"/node/run-your-node/prerequisites/hardware-recommendations"}}}')}}]); \ No newline at end of file diff --git a/assets/js/6d4312e8.d75e76be.js b/assets/js/6d4312e8.d75e76be.js new file mode 100644 index 0000000000..56c44a654d --- /dev/null +++ b/assets/js/6d4312e8.d75e76be.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6584],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>f});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?s(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):s(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function i(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},s=Object.keys(e);for(n=0;n<s.length;n++)a=s[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n<s.length;n++)a=s[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var l=n.createContext({}),c=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,s=e.originalType,l=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),p=c(a),u=r,f=p["".concat(l,".").concat(u)]||p[u]||m[u]||s;return a?n.createElement(f,o(o({ref:t},d),{},{components:a})):n.createElement(f,o({ref:t},d))}));function f(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var s=a.length,o=new Array(s);o[0]=u;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[p]="string"==typeof e?e:r,o[1]=i;for(var c=2;c<s;c++)o[c]=a[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1564:(e,t,a)=>{a.d(t,{Z:()=>f});var n=a(7294),r=a(6010),s=a(9960),o=a(3438),i=a(3919),l=a(5999);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:a}=e;return n.createElement(s.Z,{href:t,className:(0,r.Z)("card padding--lg",c.cardContainer)},a)}function p(e){let{href:t,icon:a,title:s,description:o}=e;return n.createElement(d,{href:t},n.createElement("h2",{className:(0,r.Z)("text--truncate",c.cardTitle),title:s},a," ",s),o&&n.createElement("p",{className:(0,r.Z)("text--truncate",c.cardDescription),title:o},o))}function m(e){let{item:t}=e;const a=(0,o.Wl)(t);return a?n.createElement(p,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const a=(0,i.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,o.xz)(t.docId??void 0);return n.createElement(p,{href:t.href,icon:a,title:t.label,description:t.description??r?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,a)=>{a.d(t,{Z:()=>l});var n=a(7294),r=a(6010),s=a(3438),o=a(1564);function i(e){let{className:t}=e;const a=(0,s.jA)();return n.createElement(l,{items:a.items,className:t})}function l(e){const{items:t,className:a}=e;if(!t)return n.createElement(i,e);const l=(0,s.MN)(t);return n.createElement("section",{className:(0,r.Z)("row",a)},l.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(o.Z,{item:e})))))}},7525:(e,t,a)=>{a.d(t,{n:()=>s});var n=a(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function s(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},8452:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>p,contentTitle:()=>c,default:()=>h,frontMatter:()=>l,metadata:()=>d,toc:()=>m});var n=a(7462),r=(a(7294),a(3905)),s=a(1564),o=a(9268),i=a(7525);const l={},c="Oasis Wallets",d={unversionedId:"general/manage-tokens/oasis-wallets/README",id:"general/manage-tokens/oasis-wallets/README",title:"Oasis Wallets",description:"This document provides an overview of how to use the official Oasis Wallets: a",source:"@site/docs/general/manage-tokens/oasis-wallets/README.mdx",sourceDirName:"general/manage-tokens/oasis-wallets",slug:"/general/manage-tokens/oasis-wallets/",permalink:"/general/manage-tokens/oasis-wallets/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/oasis-wallets/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Staking and Delegating",permalink:"/general/manage-tokens/staking-and-delegating"},next:{title:"Web",permalink:"/general/manage-tokens/oasis-wallets/web"}},p={},m=[{value:"<strong>What are the official Oasis Wallets?</strong>",id:"what-are-the-official-oasis-wallets",level:2},{value:"Where to find the official Oasis Wallets?",id:"where-to-find-the-official-oasis-wallets",level:2},{value:"<strong>Wallet features</strong>",id:"wallet-features",level:2},{value:"See also",id:"see-also",level:2}],u={toc:m},f="wrapper";function h(e){let{components:t,...a}=e;return(0,r.kt)(f,(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"oasis-wallets"},"Oasis Wallets"),(0,r.kt)("p",null,"This document provides an overview of how to use the official Oasis Wallets: a\nnon-custodial web wallet and a non-custodial browser extension that connect to\nthe Oasis Network."),(0,r.kt)("h2",{id:"what-are-the-official-oasis-wallets"},(0,r.kt)("strong",{parentName:"h2"},"What are the official Oasis Wallets?")),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org"},"Oasis Foundation")," supports two first-party non-custodial wallets, a ",(0,r.kt)("a",{parentName:"p",href:"https://wallet.oasis.io"},"web wallet")," named ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-web/"},"Oasis Wallet -Web")," and a browser extension wallet named Oasis Wallet - Browser Extension. Both seamlessly connect to the ",(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network")," and makes it easy to hold, send, and receive ROSE tokens."),(0,r.kt)("p",null,"These products are fully open source, built from the ground up by Oasis community developers, with funding from the Oasis Foundation\u2019s ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community/discussions/13"},"ROSE Bloom Grants Program"),". Both have also gone through multiple internal audits from the Oasis Foundation and ",(0,r.kt)("a",{parentName:"p",href:"https://oasislabs.com"},"Oasis Labs")," teams and are currently going through an external audit as well."),(0,r.kt)("h2",{id:"where-to-find-the-official-oasis-wallets"},"Where to find the official Oasis Wallets?"),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-web/"},"Oasis Wallet - Web")," can be found at ",(0,r.kt)("a",{parentName:"p",href:"https://wallet.oasis.io"},"wallet.oasis.io"),"."),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-ext"},"Oasis Wallet - Browser Extension")," can be found in the ",(0,r.kt)("a",{parentName:"p",href:"https://chrome.google.com/webstore/detail/oasis-wallet/ppdadbejkmjnefldpcdjhnkpbjkikoip"},"Chrome Web Store"),"."),(0,r.kt)("h2",{id:"wallet-features"},(0,r.kt)("strong",{parentName:"h2"},"Wallet features")),(0,r.kt)("p",null,"The Oasis Wallets currently support the following features:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Creating a new wallet (with a user friendly mnemonic recovery phrase)"),(0,r.kt)("li",{parentName:"ul"},"Accessing an existing wallet using a mnemonic recovery phrase, private key, or a ",(0,r.kt)("a",{parentName:"li",href:"https://www.ledger.com"},"Ledger")," device"),(0,r.kt)("li",{parentName:"ul"},"Viewing transaction history"),(0,r.kt)("li",{parentName:"ul"},"Submitting new transactions"),(0,r.kt)("li",{parentName:"ul"},"Managing multiple accounts"),(0,r.kt)("li",{parentName:"ul"},"Toggling between light mode and dark mode (Web variant)"),(0,r.kt)("li",{parentName:"ul"},"Selecting a language for the UI (currently, English and French fort the Web variant, English and Chinese for the Browser Extension variant)"),(0,r.kt)("li",{parentName:"ul"},"Staking and receiving staking rewards"),(0,r.kt)("li",{parentName:"ul"},"Easily switching between different Oasis Wallets that use the same ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0008-standard-account-key-generation"},"ADR 0008")," standard account key generation process")),(0,r.kt)(o.Z,{mdxType:"DocCardList"}),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(s.Z,{item:(0,i.n)("/general/manage-tokens/faq"),mdxType:"DocCard"}))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/6de7ad9b.e01746d2.js b/assets/js/6de7ad9b.e01746d2.js new file mode 100644 index 0000000000..342c2c016e --- /dev/null +++ b/assets/js/6de7ad9b.e01746d2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6984],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>k});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function r(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?l(Object(a),!0).forEach((function(t){o(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):l(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function p(e,t){if(null==e)return{};var a,n,o=function(e,t){if(null==e)return{};var a,n,o={},l=Object.keys(e);for(n=0;n<l.length;n++)a=l[n],t.indexOf(a)>=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n<l.length;n++)a=l[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var i=n.createContext({}),s=function(e){var t=n.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):r(r({},t),e)),a},d=function(e){var t=s(e.components);return n.createElement(i.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,l=e.originalType,i=e.parentName,d=p(e,["components","mdxType","originalType","parentName"]),c=s(a),m=o,k=c["".concat(i,".").concat(m)]||c[m]||u[m]||l;return a?n.createElement(k,r(r({ref:t},d),{},{components:a})):n.createElement(k,r({ref:t},d))}));function k(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=a.length,r=new Array(l);r[0]=m;var p={};for(var i in t)hasOwnProperty.call(t,i)&&(p[i]=t[i]);p.originalType=e,p[c]="string"==typeof e?e:o,r[1]=p;for(var s=2;s<l;s++)r[s]=a[s];return n.createElement.apply(null,r)}return n.createElement.apply(null,a)}m.displayName="MDXCreateElement"},7285:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>u,frontMatter:()=>l,metadata:()=>p,toc:()=>s});var n=a(7462),o=(a(7294),a(3905));const l={},r="Frontend Application",p={unversionedId:"dapp/opl/frontend",id:"dapp/opl/frontend",title:"Frontend Application",description:"We will need a Pinata development API",source:"@site/docs/dapp/opl/frontend.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/frontend",permalink:"/dapp/opl/frontend",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/frontend.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Build",permalink:"/dapp/opl/build"},next:{title:"Emerald ParaTime",permalink:"/dapp/emerald/"}},i={},s=[{value:"VueJS",id:"vuejs",level:3},{value:"Pinata",id:"pinata",level:3},{value:"Start",id:"start",level:3},{value:"MetaMask",id:"metamask",level:3},{value:"Localhost",id:"localhost",level:4},{value:"Example",id:"example",level:2}],d={toc:s},c="wrapper";function u(e){let{components:t,...l}=e;return(0,o.kt)(c,(0,n.Z)({},d,l,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"frontend-application"},"Frontend Application"),(0,o.kt)("p",null,"We will need a ",(0,o.kt)("a",{parentName:"p",href:"https://www.pinata.cloud"},"Pinata")," development API\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.pinata.cloud/docs/getting-started#2-generate-your-api-keys"},"key"),"\nand JWT with the ",(0,o.kt)("inlineCode",{parentName:"p"},"pinFileToIPFS")," permission. Let's obtain that first."),(0,o.kt)("h3",{id:"vuejs"},"VueJS"),(0,o.kt)("p",null,"We will take a shortcut and bypass developing a VueJS app. Instead, we will\nsimply apply a sparse checkout of the complete frontend repo. Inside your\n",(0,o.kt)("inlineCode",{parentName:"p"},"opl-secret-ballot")," directory run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git init .\ngit remote add -f origin https://github.com/oasisprotocol/playground\ngit checkout origin/main opl-secret-ballot/frontend\nmv opl-secret-ballot/frontend/ .\n")),(0,o.kt)("p",null,"Next, update the ",(0,o.kt)("inlineCode",{parentName:"p"},"@oasislabs/secret-ballot-backend")," package name in\n",(0,o.kt)("inlineCode",{parentName:"p"},"frontend/package.json")," to match your ",(0,o.kt)("inlineCode",{parentName:"p"},"backend/package.json")," project name."),(0,o.kt)("p",null,"We recommend using ",(0,o.kt)("a",{parentName:"p",href:"https://pnpm.io"},"pnpm")," to install dependencies, but ",(0,o.kt)("inlineCode",{parentName:"p"},"yarn"),"\nand ",(0,o.kt)("inlineCode",{parentName:"p"},"npm")," will work with some modifications around workspaces."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm install\n")),(0,o.kt)("p",null,"Compile and Hot-Reload for Development"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm run dev\n")),(0,o.kt)("p",null,"Build assets for deployment"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm run build\n")),(0,o.kt)("p",null,"We can now reference the deployed contracts in our frontend Vue app."),(0,o.kt)("p",null,"Modify the ",(0,o.kt)("inlineCode",{parentName:"p"},".env.development")," file with the appropriate addresses:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"VITE_BALLOT_BOX_V1_ADDR=0xFb40591a8df155da291A4B52E4Df9901a95b7C06\n")),(0,o.kt)("p",null,"and"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"VITE_DAO_V1_ADDR=0xFBcb580DD6D64fbF7caF57FB0439502412324179\n")),(0,o.kt)("h3",{id:"pinata"},"Pinata"),(0,o.kt)("p",null,"Additionally, we will need a ",(0,o.kt)("a",{parentName:"p",href:"https://www.pinata.cloud"},"Pinata")," JWT\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.pinata.cloud/reference/datatestauthentication"},"key")," to access the\npinning service with which we store our ballots as JSON."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"VITE_PINATA_JWT=\n")),(0,o.kt)("h3",{id:"start"},"Start"),(0,o.kt)("p",null,"Start Vue app"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"pnpm run dev\n")),(0,o.kt)("h3",{id:"metamask"},"MetaMask"),(0,o.kt)("p",null,"You can use one of the deployed test accounts and associated private key with\n",(0,o.kt)("a",{parentName:"p",href:"https://metamask.io"},"MetaMask"),"."),(0,o.kt)("p",null,"If you have not added a local network to MetaMask already, you can use this\nconfiguration."),(0,o.kt)("h4",{id:"localhost"},"Localhost"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"RPC HTTP endpoint: ",(0,o.kt)("inlineCode",{parentName:"li"},"http://127.0.0.1:8545/")),(0,o.kt)("li",{parentName:"ul"},"Chain ID:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Decimal: 1337")))),(0,o.kt)("h2",{id:"example"},"Example"),(0,o.kt)("p",null,"You should be able to navigate to\n",(0,o.kt)("a",{parentName:"p",href:"http://localhost:5173"},"http://localhost:5173")," and create a new poll."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Create a poll",src:a(3263).Z,width:"2880",height:"1800"})),(0,o.kt)("p",null,"Confirm and sign a transaction to create a new poll (issues a request against\nthe Host contract)."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Confirm new poll",src:a(2291).Z,width:"2880",height:"1800"})),(0,o.kt)("p",null,"Voting on a ballot issues a request to the ",(0,o.kt)("em",{parentName:"p"},"enclave")," contract."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Vote on ballot",src:a(3989).Z,width:"2880",height:"1800"})),(0,o.kt)("p",null,"You should be able to see results from past polls."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"See past proposals",src:a(3212).Z,width:"2880",height:"1800"})),(0,o.kt)("p",null,"If you were able to get to this point, congrats! You have created an OPL dApp!"),(0,o.kt)("admonition",{title:"Example",type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You can try out and download a frontend of the secret ballot Dapp from the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/playground/tree/main/opl-secret-ballot/frontend"},"Oasis Playground repository"),".")))}u.isMDXComponent=!0},2291:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/confirm-new-poll-44de684bfe667f9b7c51358f6e374bc9.png"},3263:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/create-poll-07bde4932eab22772d5d7e193cbc0255.png"},3212:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/past-dao-proposals-fd0f3f96be29751307e0850e034593c3.png"},3989:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/vote-on-ballot-1a35d67b60f5531fd4b91a1633030ee2.png"}}]); \ No newline at end of file diff --git a/assets/js/6ea13540.b571f517.js b/assets/js/6ea13540.b571f517.js new file mode 100644 index 0000000000..e3cde3355f --- /dev/null +++ b/assets/js/6ea13540.b571f517.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1146],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>m});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,i,a=function(e,t){if(null==e)return{};var n,i,a={},r=Object.keys(e);for(i=0;i<r.length;i++)n=r[i],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i<r.length;i++)n=r[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=i.createContext({}),p=function(e){var t=i.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},d=function(e){var t=p(e.components);return i.createElement(s.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},h=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=p(n),h=a,m=u["".concat(s,".").concat(h)]||u[h]||c[h]||r;return n?i.createElement(m,o(o({ref:t},d),{},{components:n})):i.createElement(m,o({ref:t},d))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,o=new Array(r);o[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,o[1]=l;for(var p=2;p<r;p++)o[p]=n[p];return i.createElement.apply(null,o)}return i.createElement.apply(null,n)}h.displayName="MDXCreateElement"},2843:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>l,toc:()=>p});var i=n(7462),a=(n(7294),n(3905));const r={},o="ADR 0001: Multiple Roots Under the Tendermint Application Hash",l={unversionedId:"adrs/0001-tm-multi-root-apphash",id:"adrs/0001-tm-multi-root-apphash",title:"ADR 0001: Multiple Roots Under the Tendermint Application Hash",description:"Component",source:"@site/docs/adrs/0001-tm-multi-root-apphash.md",sourceDirName:"adrs",slug:"/adrs/0001-tm-multi-root-apphash",permalink:"/adrs/0001-tm-multi-root-apphash",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0001-tm-multi-root-apphash.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"Architectural Decision Records",permalink:"/adrs"},next:{title:"ADR 0002: Go Modules Compatible Git Tags",permalink:"/adrs/0002-go-modules-compatible-git-tags"}},s={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Alternatives",id:"alternatives",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],d={toc:p},u="wrapper";function c(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,i.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0001-multiple-roots-under-the-tendermint-application-hash"},"ADR 0001: Multiple Roots Under the Tendermint Application Hash"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2020-08-06: Added consequence for state checkpoints"),(0,a.kt)("li",{parentName:"ul"},"2020-07-28: Initial version")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"Currently the Tendermint ABCI application hash is equal to the consensus state\nroot for a specific height. In order to allow additional uses, like proving to\nlight clients that specific events have been emitted in a block, we should make\nthe application hash be derivable from potentially different kinds of roots."),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("p",null,"The proposed design is to derive the Tendermint ABCI application hash by hashing\nall the different roots as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"AppHash := H(Context || Root_0 || ... || Root_n)\n")),(0,a.kt)("p",null,"Where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"H")," is the SHA-512/256 hash function."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Context")," is the string ",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core/tendermint: roots"),"."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Root_i")," is the fixed-size SHA-512/256 root hash of the specified root.")),(0,a.kt)("p",null,"Currently, the only root would be the existing consensus state root at index 0."),(0,a.kt)("p",null,"To implement this change the following modifications would be required:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Update the ABCI multiplexer's ",(0,a.kt)("inlineCode",{parentName:"p"},"Commit")," method to calculate and return the\napplication hash using the scheme specified above.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Update the consensus API ",(0,a.kt)("inlineCode",{parentName:"p"},"SignedHeader")," response to include the\n",(0,a.kt)("inlineCode",{parentName:"p"},"UntrustedStateRoot")," (the untrusted prefix denotes that the user must verify\nthat the state root corresponds to ",(0,a.kt)("inlineCode",{parentName:"p"},"AppHash")," provided in the signed header in\n",(0,a.kt)("inlineCode",{parentName:"p"},"Meta"),")."),(0,a.kt)("p",{parentName:"li"},"When new roots will be added in the future, both ",(0,a.kt)("inlineCode",{parentName:"p"},"Block")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"SignedHeader"),"\nwill need to include them all."))),(0,a.kt)("h2",{id:"alternatives"},"Alternatives"),(0,a.kt)("p",null,"The proposed design is simple and assumes that the number of additional roots is\nsmall and thus can always be included in signed headers. An alternative scheme\nwould be to Merkelize the roots in a binary Merkle tree (like the one used for\nour MKVS), but this would add complexity and likely require more round trips for\ncommon use cases."),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"This would open the path to including different kinds of provable data (e.g.,\nin addition to state) as part of any consensus-layer block.")),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"As this changes the application hash, this would be a breaking change for the\nconsensus layer.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Since we are simply hashing all the roots together, all of them need to be\nincluded in the signed headers returned to light clients."))),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Consensus state checkpoints will need to contain data for multiple roots.")),(0,a.kt)("h2",{id:"references"},"References"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://github.com/tendermint/tendermint/pull/5134"},"tendermint#5134"))))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/70b0ec1b.61d7589c.js b/assets/js/70b0ec1b.61d7589c.js new file mode 100644 index 0000000000..fb5aadbce4 --- /dev/null +++ b/assets/js/70b0ec1b.61d7589c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4133],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>V});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?o(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):o(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function s(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},o=Object.keys(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var l=n.createContext({}),A=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},c=function(e){var t=A(e.components);return n.createElement(l.Provider,{value:t},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=A(a),u=r,V=m["".concat(l,".").concat(u)]||m[u]||d[u]||o;return a?n.createElement(V,i(i({ref:t},c),{},{components:a})):n.createElement(V,i({ref:t},c))}));function V(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=a.length,i=new Array(o);i[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[m]="string"==typeof e?e:r,i[1]=s;for(var A=2;A<o;A++)i[A]=a[A];return n.createElement.apply(null,i)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1564:(e,t,a)=>{a.d(t,{Z:()=>V});var n=a(7294),r=a(6010),o=a(9960),i=a(3438),s=a(3919),l=a(5999);const A={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function c(e){let{href:t,children:a}=e;return n.createElement(o.Z,{href:t,className:(0,r.Z)("card padding--lg",A.cardContainer)},a)}function m(e){let{href:t,icon:a,title:o,description:i}=e;return n.createElement(c,{href:t},n.createElement("h2",{className:(0,r.Z)("text--truncate",A.cardTitle),title:o},a," ",o),i&&n.createElement("p",{className:(0,r.Z)("text--truncate",A.cardDescription),title:i},i))}function d(e){let{item:t}=e;const a=(0,i.Wl)(t);return a?n.createElement(m,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const a=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return n.createElement(m,{href:t.href,icon:a,title:t.label,description:t.description??r?.description})}function V(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(d,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,a)=>{a.d(t,{Z:()=>l});var n=a(7294),r=a(6010),o=a(3438),i=a(1564);function s(e){let{className:t}=e;const a=(0,o.jA)();return n.createElement(l,{items:a.items,className:t})}function l(e){const{items:t,className:a}=e;if(!t)return n.createElement(s,e);const l=(0,o.MN)(t);return n.createElement("section",{className:(0,r.Z)("row",a)},l.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(i.Z,{item:e})))))}},7525:(e,t,a)=>{a.d(t,{n:()=>o});var n=a(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function o(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},9449:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>V,frontMatter:()=>s,metadata:()=>A,toc:()=>m});var n=a(7462),r=(a(7294),a(3905)),o=a(9268),i=a(7525);const s={},l="How to Transfer ROSE into a ParaTime",A={unversionedId:"general/manage-tokens/how-to-transfer-rose-into-paratime",id:"general/manage-tokens/how-to-transfer-rose-into-paratime",title:"How to Transfer ROSE into a ParaTime",description:"This guide will walk you through transferring ROSE tokens from an Oasis",source:"@site/docs/general/manage-tokens/how-to-transfer-rose-into-paratime.mdx",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/how-to-transfer-rose-into-paratime",permalink:"/general/manage-tokens/how-to-transfer-rose-into-paratime",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/how-to-transfer-rose-into-paratime.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Self-Custody With Ledger Hardware Wallet",permalink:"/general/manage-tokens/holding-rose-tokens/ledger-wallet"},next:{title:"How to Transfer ETH/ERC20 to Emerald ParaTime",permalink:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime"}},c={},m=[{value:"About",id:"about",level:2},{value:"Managing your account with Oasis Wallet Browser Extension",id:"managing-your-account-with-oasis-wallet-browser-extension",level:2},{value:"Importing wallet account",id:"importing-wallet-account",level:3},{value:"Depositing ROSE to a ParaTime",id:"depositing-rose-to-a-paratime",level:3},{value:"Verifying ROSE balance on ParaTime",id:"verifying-rose-balance-on-paratime",level:3},{value:"Wallet Browser Extension",id:"wallet-browser-extension",level:4},{value:"Metamask",id:"metamask",level:4},{value:"Withdrawing ROSE from a ParaTime",id:"withdrawing-rose-from-a-paratime",level:3},{value:"Verifying ParaTime deposits and withdrawals",id:"verifying-paratime-deposits-and-withdrawals",level:3},{value:"See also",id:"see-also",level:2}],d={toc:m},u="wrapper";function V(e){let{components:t,...s}=e;return(0,r.kt)(u,(0,n.Z)({},d,s,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"how-to-transfer-rose-into-a-paratime"},"How to Transfer ROSE into a ParaTime"),(0,r.kt)("p",null,"This guide will walk you through transferring ROSE tokens from an Oasis\nconsensus layer account into an Emerald, Sapphire or Cipher ParaTime using the\nOasis Wallet - Browser Extension."),(0,r.kt)("h2",{id:"about"},"About"),(0,r.kt)("p",null,"Each ParaTime hosts accounts in its own independent chain state, which means\nthat ROSE held at the consensus layer is not the same as the ParaTime's token.\nFortunately, you can easily swap between the two by making ",(0,r.kt)("em",{parentName:"p"},"deposits")," and\n",(0,r.kt)("em",{parentName:"p"},"withdrawals"),". These procedures are formally described in ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0003-consensus-runtime-token-transfer"},"ADR 0003"),"."),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"deposit")," procedure will approve the ParaTime access to the specified\namount of ROSE. Then, a ",(0,r.kt)("inlineCode",{parentName:"p"},"Deposit")," transaction will be executed inside the\nParaTime and tokens will be transferred from your consensus layer account to\nthe ParaTime. If that transaction succeeds, the ParaTime will update the state\nof your provided EVM account to reflect the deposit of tokens. Emerald,\nSapphire and Cipher will give you 1 e/s/cROSE for each consensus ROSE, although\nother ParaTimes may implement different rules."),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"withdraw")," procedure executes the ",(0,r.kt)("inlineCode",{parentName:"p"},"Withdraw")," transaction inside the\nParaTime which transfers the ROSE on the consensus layer from the ParaTime to\nthe provided ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis1")," address. If the transaction succeeds, the ParaTime will\nupdate your EVM account state (usually by burning the tokens inside the\nParaTime)."),(0,r.kt)("p",null,"Currently, the Oasis Wallet Browser Extension is the only graphical user\ninterface for performing deposits/withdrawals to/from ParaTimes. Alternatively,\nyou can use the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account"},"Oasis CLI"),", if you are more keen to using a command line\ninterface."),(0,r.kt)("h2",{id:"managing-your-account-with-oasis-wallet-browser-extension"},"Managing your account with Oasis Wallet Browser Extension"),(0,r.kt)("p",null,"First, install the Oasis Wallet Browser extension. Next, restore your existing\nOasis wallet or create a new by following the\n",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/browser-extension#create-a-new-wallet"},"Oasis Wallet Browser Extension chapter"),"."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet Extension - chrome web store",src:a(2010).Z,width:"1600",height:"1000"})),(0,r.kt)("p",null,"Once done, you will see your balance on the ",(0,r.kt)("strong",{parentName:"p"},"Oasis consensus layer"),". Next, we\nwill import your wallet to be used in the ParaTime."),(0,r.kt)("h3",{id:"importing-wallet-account"},"Importing wallet account"),(0,r.kt)("p",null,"In the top-right corner, click your account icon to open the Account management menu."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Account Management - Importing Accounts",src:a(3419).Z,width:"902",height:"1204"})),(0,r.kt)("p",null,'Click "Import" and select the:'),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},'"Oasis Private Key" to import your existing Oasis private key to be used by\nCipher ParaTime; or'),(0,r.kt)("li",{parentName:"ul"},'"Ethereum-compatible Private Key" to import your existing Ethereum Account to\nbe used by the EVM-compatible Emerald or Sapphire.')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"We assume that you already have your public/private keypair. If you don\u2019t have\none yet, please go and create one. Store your Private Key, because you will\nneed it in the Oasis Wallet Browser Extension.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Importing Ethereum-compatible Account with Private Key",src:a(1679).Z,width:"750",height:"1200"})),(0,r.kt)("p",null,'Fill in the "Account name" that will appear later in the Account Management screen.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Imported Account Name",src:a(2796).Z,width:"750",height:"1200"})),(0,r.kt)("p",null,"Next, paste your Base64-encoded Oasis or hex-encoded Ethereum private key."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"You will need to import ",(0,r.kt)("strong",{parentName:"p"},"the private key and not the mnemonics"),". You can\nderive a private key from the mnemonics with BIP39\u2192BIP44 converter. For example\nby using the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/iancoleman/bip39/releases"},"Ian Cole's tool")," offline.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Entering Ethereum address Private Key (BIP44)",src:a(3763).Z,width:"750",height:"1200"})),(0,r.kt)("p",null,'Your newly imported account will, depending on the account type, appear under\nthe "Oasis Account" or "Ethereum-compatible Account" sections in the Account\nManagement screen. Check that the Oasis or Ethereum address shown at the bottom\nthat it matches the address shown to you when you generated the keypair.'),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"In older versions of the Oasis Wallet Browser Extension there was also another\nbech32-encoded version of the Ethereum address shown in the Ethereum-compatible\nwallet. This address is used in the backend for setting the allowance policy\non the Oasis network. ",(0,r.kt)("strong",{parentName:"p"},"If you can see it, you should immediately update\nyour Wallet Extension! The bech32-encoded address of the Ethereum-compatible\naccount must never be used for transferring ROSE to. The signature schemes are\nincompatible (ECDSA versus ed25519) and those tokens would not be accessible\nanymore!"))),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Account Management - Accounts Overview",src:a(5614).Z,width:"908",height:"1202"})),(0,r.kt)("h3",{id:"depositing-rose-to-a-paratime"},"Depositing ROSE to a ParaTime"),(0,r.kt)("p",null,'Now, you can transfer your ROSE to the ParaTime. Navigate to the "ParaTimes" tab.\nFor the sake of demonstration, we\'ll continue with the Emerald ParaTime, but the\nSapphire or Cipher ParaTimes work just as well.'),(0,r.kt)("p",null,'Under Emerald click on the "To ParaTime" button.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"ParaTimes - Transfer ROSE to Emerald",src:a(439).Z,width:"748",height:"1200"})),(0,r.kt)("p",null,'Fill in the "Amount" of ROSE that you want to transfer to Emerald and, in our\ncase, your Ethereum-compatible address in the "To" field you imported/created\nbefore. Then, click "Next", review and confirm the transaction.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Sending ROSE to Emerald",src:a(8275).Z,width:"748",height:"1198"})),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"At the time of writing, depositing and withdrawing ROSE to and from ParaTimes\nworks for Oasis wallets ",(0,r.kt)("strong",{parentName:"p"},"imported from the private key or the mnemonic only"),".\nSupport for the Ledger hardware wallet is not implemented yet.")),(0,r.kt)("h3",{id:"verifying-rose-balance-on-paratime"},"Verifying ROSE balance on ParaTime"),(0,r.kt)("p",null,"If everything went well, your entered amount of ROSE was sent to the\ndestination address on ParTime. In our case, let's verify that your ROSE safely\narrived at your Emerald Ethereum wallet."),(0,r.kt)("h4",{id:"wallet-browser-extension"},"Wallet Browser Extension"),(0,r.kt)("p",null,'You can check the balance in the Oasis Wallet extension by opening the "Account\nManagement" tab and selecting your destination account to which you\nsent ROSE. Then click on the back arrow and navigate to the "ParaTimes" tab.\nIn the corresponding ParaTime pane, you will notice the available amount of\nyour ROSE.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"ROSE balance in Emerald",src:a(6442).Z,width:"748",height:"1200"})),(0,r.kt)("h4",{id:"metamask"},"Metamask"),(0,r.kt)("p",null,"For EVM-compatible ParaTimes, you can as well verify the balance in\n",(0,r.kt)("a",{parentName:"p",href:"https://metamask.io"},"Metamask")," (or a built-in wallet in the Brave browser).\nFirst, install the extension in your favorite browser and add the Emerald\nMainnet/Testnet by pointing your wallet at the Web3 gateway with parameters\nlisted ",(0,r.kt)("a",{parentName:"p",href:"/dapp/emerald/#web3-gateway"},"here")," (Sapphire\nparameters can be found ",(0,r.kt)("a",{parentName:"p",href:"/dapp/sapphire/#web3-gateway"},"here"),"). Then,\nimport your Ethereum keypair and your balance should immediately be visible."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Brave wallet network configuration requires you to enter Chain's currency decimals for ROSE: 18)")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Metamask - Adding Emerald Mainnet Network Configuration",src:a(2020).Z,width:"1600",height:"1000"})),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Brave Wallet - Received ROSE",src:a(4684).Z,width:"642",height:"802"})),(0,r.kt)("h3",{id:"withdrawing-rose-from-a-paratime"},"Withdrawing ROSE from a ParaTime"),(0,r.kt)("p",null,'You can withdraw your ROSE from the ParaTime back to your Oasis wallet by first\nselecting your ParaTime account in the Account Management screen. Next, switch to\nParaTimes tab and click on the "To Consensus" button near the ParaTime entry.\nFill in the "Amount" and your bech32-encoded Oasis wallet address and confirm\nthe withdrawal. In a few moments you will have your ROSE accessible on the\nconsensus layer.'),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"If you want to transfer ROSE to an exchange and you currently have them\ndeposited on Emerald ParaTime, ",(0,r.kt)("strong",{parentName:"p"},"we strongly recommend that you withdraw ROSE\nto your Oasis wallet first and then perform a regular token transfer to your\nOasis address on the exchange!")," The ParaTime's withdrawal procedure involves a\nnumber of steps as described in the introduction and some exchanges may not\nrecognize this transaction as a valid transaction for funding your account on\nthe exchange.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Advanced users (e.g. those running ParaTime\n",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"compute nodes"),") may need to\nwithdraw ROSE from EVM-compatible ParaTimes stored in their ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis1")," accounts,\nfor example to claim their ParaTime execution rewards. Oasis Wallet Browser\nExtension does not support such withdrawals. Read the\n",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account"},"Oasis CLI Deposit/Withdraw Tokens to/from ParaTime chapter")," to\nlearn how to use Oasis CLI instead.")),(0,r.kt)("h3",{id:"verifying-paratime-deposits-and-withdrawals"},"Verifying ParaTime deposits and withdrawals"),(0,r.kt)("p",null,"To verify and validate your transactions (deposits, withdrawals) on ParaTime\nyou can use the official ",(0,r.kt)("a",{parentName:"p",href:"https://www.oasisscan.com"},"Oasis Scan"),' block\nexplorer. Enter your consensus bech32-encoded address and press Search. Then\nnavigate to Transactions section and press "ParaTime" button next to consensus.\nYou will be able to see all transactions made from both the native or Ethereum\ncompatible address (',(0,r.kt)("inlineCode",{parentName:"p"},"0x"),") you used in Emerald to your consensus (",(0,r.kt)("inlineCode",{parentName:"p"},"oasis1"),")\naddress where you sent your ROSE to."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Search result of oasis1 address - Account details",src:a(1451).Z,width:"3828",height:"2088"})),(0,r.kt)("p",null,"Furthermore, you can click on Tx Hash of any transaction you see on the list.\nYou will find your ",(0,r.kt)("strong",{parentName:"p"},"from")," native or Ethereum-compatible address, your ",(0,r.kt)("strong",{parentName:"p"},"to"),"\ndestination consensus address, and ",(0,r.kt)("strong",{parentName:"p"},"amount")," of ROSE transferred."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Tx Hash - Transaction details",src:a(4564).Z,width:"3826",height:"2392"})),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Be aware that the ",(0,r.kt)("a",{parentName:"p",href:"https://www.oasisscan.com"},"Oasis Scan Blockchain Explorer"),"\nis built for consensus layer. If you want to explore Emerald ParaTime (0x\naddresses, Token Transfers, Contract Calls, etc.), you have to use the\n",(0,r.kt)("a",{parentName:"p",href:"https://explorer.emerald.oasis.dev"},"Emerald Blockchain Explorer"),".")),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(o.Z,{items:[(0,i.n)("/dapp/emerald/writing-dapps-on-emerald"),(0,i.n)("/dapp/sapphire/quickstart"),(0,i.n)("/dapp/cipher/"),(0,i.n)("/general/manage-tokens/cli/account")],mdxType:"DocCardList"}))}V.isMDXComponent=!0},1451:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/oasisscan1-32c1face6545fbbf9d21fc4f1e4ddc2f.png"},4564:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/oasisscan2-85c233753dbb01035bc36849c7b5c6ca.png"},3419:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/accounts1-67bdeddfaab1b76f424c1d413cee99e3.png"},5614:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/accounts2-68f87ae6b9aa0a6f39b9c04c47df05ab.png"},2010:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/chrome_web_store-2ac7085f1a5c5a70358a46177a37f69a.png"},8275:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/deposit-9a48e6aeeededfa9dd09784795f2f2e8.png"},1679:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/import-c480eafa2580a6ab0da6fae21a218a8b.png"},2796:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/import2-31417b4705500f1bcf47eb54fc24d1f9.png"},3763:(e,t,a)=>{a.d(t,{Z:()=>n});const n="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAASwCAMAAACTlz9FAAACDVBMVEX////+/v/8/v/9/f78/P37+/v4+v75+fr4+Pjy9//29vf09vr09vf19fXu9f7z8/bz8/Px8vPv8vfr8v7p8v7w8PDn8P7u7u/m7/3t7e3r7e/k7fzq6+7o6/Pi6/vq6urm6fLg6fnm6Ovn6Ojk5und5vfk5eXg5O/b5Pbh4+fi4+Ph4uLZ4vTc4e7g4ODa3+3d3+PW3/HZ3uze3t7c3NzT3O/Z2+Da2trU2enQ2e3T2OjY2NjW2N3O1+vW1tbT1tvM1enU1NTJ0+jQ0tjS0tLR0dHI0ebO0NfQ0NDI0OPFz+TOzs7LztTEzePKzNPMzMzCy+LCyuHKysrHytHAyeG/yODIyMjFyM+/x9++x9/FxcXCxMzExMTCwsLAwMC9v8i+vr65vcW4u8S7u7u5ubm4uLi0t8C1tbWxtL60tLSxsbGsr7uur6+srKynqreqqqqoqKijp7OiprOmpqahpbKgpLGkpKSeoq+hoaGbn62enp6YnKqcnJyXm6mbm5uUmKeYmJiWlpaQlKOUlJSMkaCRkZGKjp6Ojo6NjY2MjIyLi4uFipuIiIiDh5iFhYWEhIR9gpSCgoJ/f394fY99fX16entzeIt4eHl2dndvdYh0dHVscoVpcIRnbIFgZ3xbYnhYXnVVXHNSWXBOVW5LUmtIT2dDSmQ+RmA7Q143PlozO1cvN1QuNlMtNVIsNFHnphbOAAAdnklEQVR42uzYT2viWhjH8edcFaU4FBelUIQLQzfuXLka6MJFN6WbLrpwIeNChECgwy1FpBRKcROEgFCQWjv9o5m06fMa73M8SUi1vbZDmTt2fp9NnianSYSvYiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeCu16TRSBPAHUKo6vLcUAXx8KlO/CfwWcoc/gCocTIIfnfWlyn3j0C4QwFupza4f3LVyS1V7xmO+JYA3+qsyeAhGeylFi514nrdFv8Kax8yeNr48KdGcGosKvZuaXMkmQ/Xkj8kawceT2b8O7vtlpegVHGbeoffXdpwzeqLISTaJueN+nl5jxXEcixb4yswdMjosagQfjlq15Gv72YYi+j9zv2Pml3MXBzRDtcY3X2mR+FTDN+TeZGERfDhq4/Q+GNs5Rb9l7i3RdnlBfu+c+x6LY4KPRqVK58HD95oi+i1zH9HU55HMXuYX5V7xZXKX6rEdXkNltm+C+4uyojfnXqrX6wVarXUda5NEyeo6TX2i+FimdtQ7bn6iiOxo99zjVoEosapQ7zpVGXVisqMyl7uZ9eE9olVZUqLc7kmvSVSr13eIvsiuYuKUJRKFbavbs7ZXSavWLWa+jddR2T5zT63iC7kXPRku0hRSO4eOe9zIkVaRk2ySsTG9XVgaKtfwgh+9dUVvz/1Ib1s8ZVH2lKfO0xQd271jzf9GIdtjw8lRvKrDwm5zpDeXu+FOL0NVneQeiwGRz3xNdJL44tGXuUGkLA5NLz7iSIPE5pANN/9c7vkb2X5fodDuLU/5R4qIOolbbOMbz1JR+ZOHYHKQUfSTuceV7jsc6qfCY4ccOSMt3efYdTHK/ZRflbtZ3DG5u/6T3Msc//ye0UdylB5yzEnP5r7lc+SmOJ97Rv/zeJ1CLebkSyvJ1pOtdi1zmWBJpNYHQXBXS6fU8xbnLoa3LHxd5hVrleiYuDJl1SjeNxqY/1KJVWPfqg+m+weDgfVC7vp9YevcDW/SN7mH2ZXiR0yXqMHizu1es9gn6gwuZfDl7FWi/ITFlTM9eDGfe08vLVHoC2sX7iT6bUi/yCppmzJ9J1gWldvg8cc/+y8pvyL3fpaoxtrlCtFnHYUVh9zIUXrb1z0rEwe7q0QZm8XXaJVfLyx8VBUpXWc9yv3gM4kod1vvie9tz/TfJCLVkeFk5lH1TMbJ3zJssajN5t5msUWGOdUwK4PFYt1sT4nCy9oEy2IcPPJj8PCSweLcr7NRQN4KibpMPXMsSmGHxReiQ9nc5OKv4RfhKr9MYnHu38Laqmyyj3NPrkt5zF6aUpZtmyUp8wGczD3ty1ih6G77M7kbaxSq6LvOk9Y1b+U12YxJu5SpSLAsrv479/PFuXdMJnE2pUTIo8T6tlzM/JuWY5E3q3q0IPeUKG6fc3iNqqktkbsYmrcCbUWfvMkPZ/9p7rsyuWR4Mqeey30Y7T1m5hY9eW2D8O1SmJ4SlkbhPHj0WoXVF2QX516LCzoyIUe5J7prmb78xIfmrcxls6qxIPeEUT7M3ZnNvRlGeTwt0fhU2a41bZ7L3ZLprmmwWJvPXRwmfulxmlOt8Im4Ltt2eNEmwdJQ2c79o3eU/flH1Z0498PZ3OMUtvS+f9m5u5c2sjCO48+QaIIvpHojFEURQbwQgwsirqwXLohguoRe6KwsUi/cQNmylpZFdqVQ2N5YdwXZhNr6WmI2GvI37pk5mZM06mpNmmSm3w/IFBPOjOU3Z57z5KhEnIJHKkK0ZEa4Y9yPOkRKjcjquHeUTvvRa9H0vDopalfivl38VLw67o/3TfVuejqVY0XyukBKu48o+IcVWcsV8ns3td1ri/uyaCNOVN1H/5koXhm8+nlxz21H5dq4m9VAh4x51zF3XjQq4m5WqpVmq+K+Id1ZdTjvEcdZ8VOi7KrjsETd6gp+YrXNnRYuDqesLxD3ZyKmOZiWUNHUybrWnr9j3Jcd8yNhkevjbs6xJptuDkVibsrTr1+mnlyN+5ZziSltU331VMXda9mkzXL0RUp7nkptiLLg/nCr7h0NfwmNpAuXZ6uWVfe474qYft2OXhaOiKb/fae4H4nxP3EPqxH3nMrj0Ou4pDv0oFfinjID3LxnptxY2jOXWBY6d86zq0YOC3zG6tu+KJw/j9Y57qYcCB3pBl7aPZjuXj58Xdyj94y7vFYjDnpdlF1Tko9Uzu7H5uQfbol76ND7vOyZXoUbpvzvU+d+I/Adqzultru/eWjVNe7Ku5BZGg6KrJt1YYcT7J3KEUy7ZvkecTch3ldfMS/uc6KEdry49xW9FyVrCq2O41zu1KqOu9mQlu0SGSwvW+PnuZwOeNzpNbnfh/9YbY9OChfvpqy6xl15tz68qt6tvxXNOglK9Xev6anzStzfOxPwen/XfeKubxa9dtR31tnjSCi+b5aqlvvqo/5w6ePRl3ErvHBSNDN0Vdxl1RvNGSK/3i/RjVz58y3d9smyQ9ifrKn0ZeF4OWzVM+65ojHmrfCMLamKu+kQ7t4v7i/N5hw9lSv50kEcx0XXuq5UzKvn/dfE3TRwUmqsfMW7D8NmOeK+Ff5kDb7OF7JPu6w6xn31Y7HksTdjGtuhq3HvydUS92E3lG3iWjPnOfbiPmfiLrEPRU9uTG6Ie+S0VHzFs0XPUVS0vtJNDJ+yYs9UAf/qlgLeNM0XROSFPioLZotWxClhvCBHf9cFRlxKxnbyushxMm5GMPpeeEV9RaoOxTCx3aqI+7GUHFZWJvNHRSX7xDJxl9l0rrQzTUKpUx32zahUWqsce6xY2m/Ts6Xvw9M1Szwf3JUvfMtqWzspXO7FLamdmbdDI0tTHVIhMra0EO+WG0VjXVIf4anZh1IlEjPxfji7NBu7e7N2fikekTLrhF/c9r2595cXqXrGPbA2dJ8HfmYN7/z7lLjfpm9qM+f+ihb8zYo9fUTcb5PXdT9/nBJfTdxPRwQoWd7b2wtqny6b/7j/W1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/9Y7OLCZXbKBuVpKLM6O90nI6xxM28EUkxjullbRPqotanBjoDAtQR+HOgYlFFa7JdmkZQ0l1PS34yEEw9KrZNDkkLUJdzHRrPW0QMJ3TakKVljBj2y1z5yGohmx7RlrAjJ2gjsEX15tohbxP2gkKGTRAV6KZ9Yx5xjC3oyF6m141tyep29EoQ3ayXZpp0p4WoEGmm1vOdNo2hTuUryJv463SDMXXYdIel+ZJsE5FI/XaCWmaXntRgAZabOIEO2pPCNBAE/aoNMuMPSBAAw008aPVRfoyaKzOJtbPSZv97WiosJ2UZlmxBWgoe0WaxSbuMAKfOeKOssBnjrijLPCZI+4oC3zmiDvKAp854o6ywGeOuKMs8Jkj7igLfOaIO8oCnznijrLAZ464X2tQEMTM3X7qyIOeqEM8P2cyfdLCvs1kfpCahP8+eGtJrf7MvJU7uvP/bSST+VX8rqXj/s+Blvnjpwfi+OXgoKUnv+8PDn6UmnynftxvpFZ/HfzHzv29tJWtYRx/JYYtHoT0IoRcDF4EPBDBGwVhAkJAwcELGS9kKlYELUWJKAhSBhFFpK0EJSEh4flrz1p5944762xnOjDUpO/zuWjNj73W6so3W7e17co/8F17Owv8KZNuInJ3ngs/OvfrTicn3+ew01n+l3KfA/rRd62Nuf+EuR85jTsArXc/OPdvwPfmfgrU/qXcpbhd+K61MfefMPeuDFRawKWN3B3mbjx3qQL9qZGXpFyrV6ZlKF9dn5+SodxCPX2zuLJejURCM4vrywVR0eyMiMwng87ONoHC7Gwwmz407UZcX5HhkW5Zm+7eJPe5tWoqxulKvVYOJ56NRKJFv6hwzMg/NO1vqyhew9R8fTEvwdrC8cPc3USzuWAHgrGD3Mv11aKEGxfmHlXXV8upP4mTS0bNuzHH14TkLi2gmMp9qwWneyiq+gjvoRTH+QDvei5+9B7eZRB84QrenY54B0yd9eAc5dxjiK1IOFsVOKm7O9ovS1MfNffaM4D+XTz31McenKc1SevjS3QKp386FYzZxZPILtAQ1QFmRArX8J5WJVhbMH6Q+z7Qnw92wI19/rLywkju62049/MSbFySe3rfWrvidON92E5WfO3HHFuTkvs9UB3m7rNSR+LtIdZdEKfWT27Oi1PuQd1NSUr+G1SnEOfegHI1vBsmFc7m07zpIyP3T4NnXsSTN6MkIrUymvu3e6jG6Jiau0urIwOLbtnu1x5i28HassbX3LX23kK4A27srm5EBXiQdO6foNpzEmxcKveoiZjv/TNQFP39Wbye+318TUrurql3mrvWgcvNesMVsikikfv9amuh/gDci9N0j1YKG+7mlX+ZWu7uvdXjtu845U/g+Wjlw1dXZl5zR/twqebuRkWmlpfdYavLy1Ewm97Ew/H6usQWlt0xR8vLRZ+7c1ZfOuwDJ0lwp7VtF0O/PJK7u/+stvVZA06P6XLXc+SSeA1gS+QB+LJXXbl0w+RSawvGD3Pf1Td8uAPXyXvD1b2Tzt252V09abul5MLDhrnn7oDWyaqfEmuDs/q2Vq7dzwMNGV8Tkvsq0JMk91wH+CBOffDyyw5woX9FM7hZjqufeUIvN8j6WpxSTxOK7QGtOX+Q6/1Ic++URGs4TF0OBrNpmo3XL1WxK07NJaPnTyzG1d4HuS+IcwAgGhlTc19LbrfRz0upj8dIHNf70nBt4fhh7q72TlmcYAfWfL6e265oNPdG8rS98LBh7odA953oB+7wAnCZvF939f1dk/E1GbmvuuQaw9xX9XVwzoGKvGgAVZFl4E6GIqCTF28DOJChL8mhBeBGc98VbwW4SCcVzlZ1A8rruT/KQAt9ETkBPiQB9tK5a1DOrUtpZEzNPdfTO6paU6IevBWzx9fcXe3tUtYOuLG7U/pe+SwjuX/LJbNchYcNc2/q5wbdsS1/uyUix+jc40bfI+P836mMee44c/5sAvgSxbmnX+RtbTSWc7kvi+ThAl0Wlaq1mH55cxj20UJHX7xK8rSb7KR0tqqP4fXcz4bXGjMiX3VQPS+XRnIviOej3NcxU7k7DT1t659oaA34mFpb9via+w7QKmbvQEOL/airTuV+NNybZnhYkvs00H/5/Hg22J53/uRxcTD43NfFnYyxcc9dae1J7ldwrQ4g/rxcPb5/7rqGNI5jOP27D3Pi7PgnK72aUsX03ZjzuWtBkg9yD2dzaZ78Re77wyuDWZF2epKNdO49UYvApY45mvuCfjpro6XL3b9+6vSBIPfXxn9KLmszd2BBd+0ZHRnNvS7q2Q8fHqa5l4BvopYH74cVYEsid2zZb7775UDG2ETk3v3yIZKX3G+RcisydYKhZXF2nzFwOS1ygJS+JBaQtjDIXTJyD2f729z30rn3kXKYzv1RVAF4yMpdmmj7+zXvDR0oyD0cP8y9VxIn3AE9+U/JPHAa5F4RdQeUgsOS3Bf8r6o4uF7I9XEh60AkLZzILlCWMTbmuXdlaOTsfrqhtjcWB5+VcX28u75yrbnr6R7O3eDc9jh88trI2X1490b0au7hbP8s9zawqYdubW2Uss7uS8BFZu6HwKIfuKSXE3g42duqHQS5Z46vuTfdc54icYId0LFX/K7Nv3J2bwFTwWFJ7kV3r6gVLf8Gz3KJez9AUz6jLeNsEnM/AfYlpZm8UOeauyr4d0FRavolaGgaWlzs1dzD2f5Z7t9Gksr62n3PjZ6ZewFouJwfxGn4j73NIPfM8TX3aLatOYY7oGOfyzOa4d4eD/emGR6W5J4D+qI+6IXKPlBo43BwwFwH4/1DwpOYew24jdMsl2ckQnJKaQ9yjwpxStfAun+0G8lAuVwQpaVUZaBYLr2S+zuRcLbXct/OzP10+CXGXLmcG8n9cHhJu5iZu1tQ2929G7+fi+Jdae7x2sLxg29EVnSWcAd07G4FOAj3tjkt3hZwGR6muevV8ZoMPPjtFSkBR4OXJT/4oC7jbBJzz3XjV33KBb3jn9ab1fOwy33wpNPk9SgNor/PxWejK1F6q1OMLxbbWbnfa8PBbJm5H7s+MnNfQHzen2uF35lxK3U+Av18du6bgFtCpIPps+vQpcRrC8cPcpdNfTRjB7YGYxfCvdVT83wf2AkPG+a+n1wTfHIf5OPvuaKtb6K+X/A4m8TcZQnA3UFt/8klO61/gX28sncHjagC4Lxert0Dj3EJzY9rO7cY/Sb9tTv4bH3zHMB+Vu4XQK+xPRfMFuae1IPPu5Uwdy2l/3m3ftzTVtK596929v2S1yU79+m+H1W8Xb+U2tYFNPfh2oLxw9zl1D1aztqBvB/7Ntxb5+Fw+6KnDwWHae76J+ueb324082ODzwXZ98PIGNtInOXOmK9iogsdOMbV/oKNBBrV5Mf/VBbkpL/gtiZZOW+CG8lmC0z96gL51NG7i9r+RaN5P7VR6RHZeauTaMm3sxXqIbmnqwtHD/MfereX65m7cClfuMy2NsDqFYk4ca95D79AJUMsIb465sSgCMZa2Oee0fCl6QsXv0RTr9REK/0AOe+cgQsiVNrwulczchA5QbezYKMmD3rw2nWxbtN5X4tXu1Wkwpmq/pEA5XL/uDe+vCvvT4DOvthG07nIC+jueeP/ey9IwnG7KApaskdJip/2fMVrrm7joO1ZY7fjI+ccw9eZO3ACtCf/v+9XWnCuS5JxsbNJJ9rZnTfHtdluGHIJ9+vX5CxNta5/5W56mJRhnKV6oyk5OYXZ+VFVFnyV3Kh6fLSQiSviwqzwWyvmp4ryCuKi1U/TJC7iJRX3KK+V3mpGK4tGD9L9g7oj25KlrnF6szfblyuvFSdk0k0sblPNM397eRaY/5v3H/C5pj7G5mv3/wM/xBvwppj7m8ETs/kyZ25v4l271beDoAvY/2/U/2UzRnO/W2Vi1NiFHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GcLcyRDmToYwdzKEuZMhzJ0MYe5kCHMnQ5g7GfKGzf3B3OkHe/+HvJXf308L0Q80/f53eSu/vf+PEP1A/3n/m7yVX9//IkQ/0C/vf5W38t//sWvvKBICURhGKxhMzMwbzDoSoSJxBwYGZv3vfyPD7KGtEuacNVwuXz2yFmhozbv0MuUo0NCRqXRzZirQzJSz9LOkFmimZin9jHE3w5//MW81W4FGts41MVyZCzQx5xpKV3OcVmljSv/dWnPKdxoYz9TS3Z7Tfud205m9PMAe/c7d5jxj2kupySZouNG45TlPPPOVVEXDTaaaXA8qiKEmOdbX6P87X/UzvtYjSR3Kk4zLGbjFuTywlaf3flyfwNd8rmN/y2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4ZQ8OBAAAAACA/F8bQVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVpX07ZlGdiQIwfLAQ0tgoh0BASCGkSJPCYgshWFgIAQVT+P//yJc5Ce4ns9nrBTeTO/s+RYxzZ2/17jAZXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgN9rmazWCrzVepUsZXYWyUaBH7FJFjIni0SBHzSn4JcK/LDZbGlY2jGBRGZhpcAEVvItakdU/tA7OxlEJZHv8JSKuCwlqIUCE1rIGLYyiE4iI1jcEaGFfInFHTFKJBy+J4OJbWQExzKI0FK+wl4GUUrkS3ygihitJBT+mgOTW0soCkxOfOSOWImP3BEr8ZE7YiU+ckesxEfuiJX4yB2xEh+5I1biI3fESnzkjliJj9wRK/GRO2IlPnJHrMRH7oiV+Mj935Dn7lJXiteQ+0zs9vWx3mf6uo/b/X6vNeuuH4qXkPssVNd775Tqi+q7U+u+uzaKl5D7HBzvD9dcX9N2ky91aav7XvEScg9uqL1tzjd73ekrtt3Ugzr5oVS8htzDK2xXkrpyr25911eU3cxc8XfIPbxLV+5ZTeruKzXb6lDvd9rLi2Krujscyqx/+9FNLIsi6wbtqoV7yapDpcPkst7nNndfV5nCIffQbFtyy9TYSn/UTnq+m2uhzq0brmygrVS1uQ/2qv017V4q9zPN/yef0uzc3yg65B7cx9NJYn062RsL2uTa5/4YKcZyt9HmaXLd3dD7A7kHd+oLfubW5PZ8vLqX3HLv3E4nO49R3R8bl/DxuPvM3Vya4zD50k0xTX+TKpTcg2v8FrVy25h0OF1vLPd+f5+5Gx0eVTNVfcr9pI5Nru2HO/vhhuObDrkHZk+qrT6zX4H8cZdawW2qnb37l5HcL2pssnYeY5mdWkLJPayR3Fu3phs7gbGC+4HCvR/JvVbHJp91+G+O6pB7j9zDGtnMDOczQ96VFdwP5KO52zwzTLbc6/6G3A25h+Y/qj6txltXM7m/CbmH5R1EFmW5s4RPakpW9zci99DsObLN1FjNJ8vzoo79MhTk/ibkHl5jh429s8X7ucFJ7eCR3N+E3MPb2ZG5a3frym/TPuZ2q5q67k/k/i7kPgP18IHozV7Lx9D1YteU3N+F3IOzuB9uOzXHx0Cm5P4u5D4LZXM37TnTQd3ayDlX52oFDweTxXjuz5Nv5P6M3Gcirw51tX0eKssdX+x6K3LH7yI+ckesxEfuiJX4yB2xEh+5I1biI3fESnzkjliJj9wRK/GRO2IlPnJHrMRH7oiV+MgdsRIfuSNW4iN3xEp85I5YSShrBSa2llBWCkxsJaEkCkwskVCWCkxsKcFsFJjURkawm0F8EglnocCkFvI1lnfEJ5ExLO+IzkLGcTiDuCzlG2xnEJVE/oCPVhGNlXyL3hGRWdTOfga/ZSfD8yo6v+Ip9dOCBR4/KlnInCwSvj+DH7KZWexmmaz4ew+82XqVzGgbAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/6z8irhuX6C83JwAAAABJRU5ErkJggg=="},439:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/paratimes-1e42fa05f5490ec7eeebc5608a8c0000.png"},6442:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/paratimes2-0695739c8ea5c7ae9bb51d144ed3a083.png"},4684:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/brave-d5324693f54e8be95d23c517033a1f6c.png"},2020:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/settings-ffbfad31202135351449d6d411667969.png"}}]); \ No newline at end of file diff --git a/assets/js/714fd338.79c436a6.js b/assets/js/714fd338.79c436a6.js new file mode 100644 index 0000000000..27cce7bc0d --- /dev/null +++ b/assets/js/714fd338.79c436a6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[743],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,o=function(e,t){if(null==e)return{};var n,a,o={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),u=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=u(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=u(n),m=o,h=p["".concat(l,".").concat(m)]||p[m]||c[m]||r;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var u=2;u<r;u++)i[u]=n[u];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},9444:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>u});var a=n(7462),o=(n(7294),n(3905));const r={},i="Set up Trusted Execution Environment (TEE)",s={unversionedId:"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",id:"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",title:"Set up Trusted Execution Environment (TEE)",description:"In case the ParaTime you want to run does not require the use of a TEE (e.g.",source:"@site/docs/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee.md",sourceDirName:"node/run-your-node/prerequisites",slug:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",permalink:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"System Configuration",permalink:"/node/run-your-node/prerequisites/system-configuration"},next:{title:"Validator Node",permalink:"/node/run-your-node/validator-node"}},l={},u=[{value:"BIOS Configuration",id:"bios-configuration",level:2},{value:"Ensure Clock Synchronization",id:"ensure-clock-synchronization",level:2},{value:"Install SGX Linux Driver",id:"install-sgx-linux-driver",level:2},{value:"Ubuntu 18.04/16.04",id:"ubuntu-18041604",level:3},{value:"Fedora 34/33",id:"fedora-3433",level:3},{value:"Other Distributions",id:"other-distributions",level:3},{value:"Verification",id:"verification",level:3},{value:"Ensure Proper SGX Device Permissions",id:"ensure-proper-sgx-device-permissions",level:2},{value:"Ensure <code>/dev</code> is NOT Mounted with the <code>noexec</code> Option",id:"ensure-dev-is-not-mounted-with-the-noexec-option",level:2},{value:"Install AESM Service",id:"install-aesm-service",level:2},{value:"Ubuntu 22.04/20.04/18.04",id:"ubuntu-220420041804",level:3},{value:"Docker-enabled System",id:"docker-enabled-system",level:3},{value:"Podman-enabled System",id:"podman-enabled-system",level:3},{value:"Check SGX Setup",id:"check-sgx-setup",level:2},{value:"Install Dependencies",id:"install-dependencies",level:3},{value:"Install Rust",id:"install-rust",level:3},{value:"Build and Install sgxs-tools",id:"build-and-install-sgxs-tools",level:3},{value:"Run <code>sgx-detect</code> Tool",id:"run-sgx-detect-tool",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Missing <code>libsgx-aesm-epid-plugin</code>",id:"missing-libsgx-aesm-epid-plugin",level:3},{value:"Permission Denied When Accessing SGX Kernel Device",id:"permission-denied-when-accessing-sgx-kernel-device",level:3},{value:"Error Opening SGX Kernel Device",id:"error-opening-sgx-kernel-device",level:3},{value:"Unable to Launch Enclaves: Operation not permitted",id:"unable-to-launch-enclaves-operation-not-permitted",level:3},{value:"Unable to Launch Enclaves: Invalid argument",id:"unable-to-launch-enclaves-invalid-argument",level:3}],d={toc:u},p="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(p,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"set-up-trusted-execution-environment-tee"},"Set up Trusted Execution Environment (TEE)"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"In case the ParaTime you want to run does not require the use of a TEE (e.g.\nIntel SGX), you can skip setting up a TEE.")),(0,o.kt)("p",null,"If the ParaTime is configured to run in a TEE (currently only ",(0,o.kt)("a",{parentName:"p",href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html"},"Intel SGX"),"), you\nmust make sure that your system supports running SGX enclaves. This requires\nthat your hardware has SGX support, that SGX support is enabled and that the\nadditional driver and software components are properly installed and running."),(0,o.kt)("h2",{id:"bios-configuration"},"BIOS Configuration"),(0,o.kt)("p",null,"To enable Intel SGX on your hardware, you also need to configure the BIOS.\nFirst, ",(0,o.kt)("strong",{parentName:"p"},"update the BIOS to the latest version with the latest microcode")," and\nthen proceed with BIOS configuration as shown below. Note that some settings may\nnot apply to your BIOS. In that case, configure only the relevant ones. Please\nset the BIOS settings as follows:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"SGX"),": ENABLE"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Hyper-Threading"),": DISABLE"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Intel SpeedStep"),": DISABLE"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"SecureBoot"),": DISABLE (not necessary for recent kernels)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"All Internal Graphics"),": DISABLE"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Turbo Mode"),": DISABLE"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"CPU AES"),": ENABLE")),(0,o.kt)("p",null,"To test if your settings are correct, you may use the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/tools/tree/main/attestation-tool#readme"},"attestation tool"),"\n(",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/tools/releases"},"binary"),") for testing remote attestation against Intel SGX's\ndevelopment server."),(0,o.kt)("h2",{id:"ensure-clock-synchronization"},"Ensure Clock Synchronization"),(0,o.kt)("p",null,"Due to additional sanity checks within runtime enclaves, you should ensure that\nthe node's local clock is synchronized (e.g. using NTP). If it is off by more\nthan half a second you may experience unexpected runtime aborts."),(0,o.kt)("h2",{id:"install-sgx-linux-driver"},"Install SGX Linux Driver"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"In case you are running Linux kernel version 5.11 or higher, the required SGX\ndriver is already included and no additional installation is needed so you may\nskip this section.")),(0,o.kt)("p",null,"On older distributions see below for instructions on how to install the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/intel/linux-sgx-driver"},"legacy (out-of-tree) driver"),"."),(0,o.kt)("h3",{id:"ubuntu-18041604"},"Ubuntu 18.04/16.04"),(0,o.kt)("p",null,"A convenient way to install the SGX Linux driver on Ubuntu 18.04/16.04 systems\nis to use the ",(0,o.kt)("a",{parentName:"p",href:"https://edp.fortanix.com/docs/installation/guide/"},"Fortanix"),"'s\nAPT repository and its ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support"},"DKMS"),"\npackage."),(0,o.kt)("p",null,"First add Fortanix's APT repository to your system:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'echo "deb https://download.fortanix.com/linux/apt xenial main" | sudo tee /etc/apt/sources.list.d/fortanix.list >/dev/null\ncurl -sSL "https://download.fortanix.com/linux/apt/fortanix.gpg" | sudo -E apt-key add -\n')),(0,o.kt)("p",null,"And then install the ",(0,o.kt)("inlineCode",{parentName:"p"},"intel-sgx-dkms")," package:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt update\nsudo apt install intel-sgx-dkms\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Some ",(0,o.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/en-us/azure/confidential-computing/quick-create-portal"},"Azure Confidential Computing instances"),"\nhave the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/intel/SGXDataCenterAttestationPrimitives/tree/master/driver/linux"},"Intel SGX DCAP driver"),"\npre-installed."),(0,o.kt)("p",{parentName:"admonition"},"To determine that, run ",(0,o.kt)("inlineCode",{parentName:"p"},"dmesg | grep -i sgx")," and observe if a line like the\nfollowing is shown:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"[ 4.991649] sgx: intel_sgx: Intel SGX DCAP Driver v1.33\n")),(0,o.kt)("p",{parentName:"admonition"},"If that is the case, you need to blacklist the Intel SGX DCAP driver's module by\nrunning:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},'echo "blacklist intel_sgx" | sudo tee -a /etc/modprobe.d/blacklist-intel_sgx.conf >/dev/null\n'))),(0,o.kt)("h3",{id:"fedora-3433"},"Fedora 34/33"),(0,o.kt)("p",null,"A convenient way to install the SGX Linux driver on Fedora 34/33 systems is to\nuse the Oasis-provided ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sgx-driver-kmod"},"Fedora Package for the Legacy Intel SGX Linux Driver"),"."),(0,o.kt)("h3",{id:"other-distributions"},"Other Distributions"),(0,o.kt)("p",null,"Go to ",(0,o.kt)("a",{parentName:"p",href:"https://01.org/intel-software-guard-extensions/downloads"},"Intel SGX Downloads"),'\npage and find the latest "Intel SGX Linux Release" (',(0,o.kt)("em",{parentName:"p"},"not"),' "Intel SGX DCAP\nRelease") and download the "Intel (R) SGX Installers" for your distribution. The\npackage will have ',(0,o.kt)("inlineCode",{parentName:"p"},"driver")," in the name (e.g., ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx_linux_x64_driver_2.11.0_2d2b795.bin"),")."),(0,o.kt)("h3",{id:"verification"},"Verification"),(0,o.kt)("p",null,"After installing the driver and restarting your system, make sure that the one\nof the SGX devices exists (the exact device name depends on which driver is\nbeing used):"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"/dev/sgx_enclave")," (since Linux kernel 5.11)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"/dev/isgx")," (legacy driver)")),(0,o.kt)("h2",{id:"ensure-proper-sgx-device-permissions"},"Ensure Proper SGX Device Permissions"),(0,o.kt)("p",null,"Make sure that the user that is running the Oasis Node binary has access to the\nSGX device (e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev/sgx_enclave"),"). This can usually be achieved by adding\nthe user into the right group, for example in case the permissions of the SGX\ndevice are as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"crw-rw---- 1 root sgx 10, 125 Oct 28 09:28 /dev/sgx_enclave\n")),(0,o.kt)("p",null,"and the user running Oasis Node is ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis"),", you can do:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo adduser oasis sgx\n")),(0,o.kt)("p",null,"Failure to do so may result in permission denied errors during runtime startup."),(0,o.kt)("h2",{id:"ensure-dev-is-not-mounted-with-the-noexec-option"},"Ensure ",(0,o.kt)("inlineCode",{parentName:"h2"},"/dev")," is NOT Mounted with the ",(0,o.kt)("inlineCode",{parentName:"h2"},"noexec")," Option"),(0,o.kt)("p",null,"Some Linux distributions mount ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev")," with the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexec")," mount option. If that is\nthe case, it will prevent the enclave loader from mapping executable pages."),(0,o.kt)("p",null,"Ensure your ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev")," (i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"devtmpfs"),") is not mounted with the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexec")," option.\nTo check that, use:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cat /proc/mounts | grep devtmpfs\n")),(0,o.kt)("p",null,"To temporarily remove the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexec")," mount option for ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev"),", run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo mount -o remount,exec /dev\n")),(0,o.kt)("p",null,"To permanently remove the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexec")," mount option for ",(0,o.kt)("inlineCode",{parentName:"p"},"/dev"),", add the following to\nthe system's ",(0,o.kt)("inlineCode",{parentName:"p"},"/etc/fstab")," file:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"devtmpfs /dev devtmpfs defaults,exec 0 0\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This is the recommended way to modify mount options for virtual (i.e. API) file\nsystem as described in ",(0,o.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems/"},"systemd's API File Systems"),"\ndocumentation.")),(0,o.kt)("h2",{id:"install-aesm-service"},"Install AESM Service"),(0,o.kt)("p",null,"To allow execution of SGX enclaves, several ",(0,o.kt)("strong",{parentName:"p"},"Architectural Enclaves (AE)")," are\ninvolved (i.e. Launch Enclave, Provisioning Enclave, Provisioning Certificate\nEnclave, Quoting Enclave, Platform Services Enclaves)."),(0,o.kt)("p",null,"Communication between application-spawned SGX enclaves and Intel-provided\nArchitectural Enclaves is through ",(0,o.kt)("strong",{parentName:"p"},"Application Enclave Service Manager\n(AESM)"),". AESM runs as a daemon and provides a socket through which applications\ncan facilitate various SGX services such as launch approval, remote attestation\nquote signing, etc."),(0,o.kt)("h3",{id:"ubuntu-220420041804"},"Ubuntu 22.04/20.04/18.04"),(0,o.kt)("p",null,"A convenient way to install the AESM service on Ubuntu 22.04/20.04/18.04 systems\nis to use the Intel's ",(0,o.kt)("a",{parentName:"p",href:"https://download.01.org/intel-sgx/sgx_repo/"},"official Intel SGX APT repository"),"."),(0,o.kt)("p",null,"First add Intel SGX APT repository to your system:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'echo "deb https://download.01.org/intel-sgx/sgx_repo/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/intel-sgx.list >/dev/null\ncurl -sSL "https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key" | sudo -E apt-key add -\n')),(0,o.kt)("p",null,"And then install the ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-aesm-service"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"libsgx-aesm-launch-plugin")," and\n",(0,o.kt)("inlineCode",{parentName:"p"},"libsgx-aesm-epid-plugin")," packages:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt update\nsudo apt install sgx-aesm-service libsgx-aesm-launch-plugin libsgx-aesm-epid-plugin\n")),(0,o.kt)("p",null,"The AESM service should be up and running. To confirm that, use:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo systemctl status aesmd.service\n")),(0,o.kt)("h3",{id:"docker-enabled-system"},"Docker-enabled System"),(0,o.kt)("p",null,"An easy way to install and run the AESM service on a ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/"},"Docker"),"-enabled\nsystem is to use ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/pkgs/container/aesmd"},"our AESM container image"),"."),(0,o.kt)("p",null,"Executing the following command should (always) pull the latest version of our\nAESM Docker container, map the SGX devices and ",(0,o.kt)("inlineCode",{parentName:"p"},"/var/run/aesmd")," directory and\nensure AESM is running in the background (also automatically started on boot):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker run \\\n --pull always \\\n --detach \\\n --restart always \\\n --device /dev/sgx_enclave \\\n --device /dev/sgx_provision \\\n --volume /var/run/aesmd:/var/run/aesmd \\\n --name aesmd \\\n ghcr.io/oasisprotocol/aesmd:master\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Make sure to use the correct devices based on your ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#verification"},"kernel version"),".\nThe example above assumes the use of the newer driver which uses two devices.\nFor the legacy driver you need to specify ",(0,o.kt)("inlineCode",{parentName:"p"},"--device /dev/isgx")," instead.")),(0,o.kt)("h3",{id:"podman-enabled-system"},"Podman-enabled System"),(0,o.kt)("p",null,"Similarly to Docker-enabled systems, an easy way to install and run the AESM\nservice on a ",(0,o.kt)("a",{parentName:"p",href:"https://podman.io"},"Podman"),"-enabled system is to use\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/pkgs/container/aesmd"},"our AESM container image"),"."),(0,o.kt)("p",null,"First, create the container with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo podman create \\\n --pull always \\\n --device /dev/sgx_enclave \\\n --device /dev/sgx_provision \\\n --volume /var/run/aesmd:/var/run/aesmd:Z \\\n --name aesmd \\\n ghcr.io/oasisprotocol/aesmd:master\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Make sure to use the correct devices based on your ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#verification"},"kernel version"),".\nThe example above assumes the use of the newer driver which uses two devices.\nFor the legacy driver you need to specify ",(0,o.kt)("inlineCode",{parentName:"p"},"--device /dev/isgx")," instead.")),(0,o.kt)("p",null,"Then generate the ",(0,o.kt)("inlineCode",{parentName:"p"},"container-aesmd.service")," systemd unit file for it with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'sudo podman generate systemd --restart-policy=always --time 10 --name aesmd | \\\n sed "/\\[Service\\]/a RuntimeDirectory=aesmd" | \\\n sudo tee /etc/systemd/system/container-aesmd.service\n')),(0,o.kt)("p",null,"Finally, enable and start the ",(0,o.kt)("inlineCode",{parentName:"p"},"container-aesmd.service")," with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo systemctl enable container-aesmd.service\nsudo systemctl start container-aesmd.service\n")),(0,o.kt)("p",null,"The AESM service should be up and running. To confirm that, use:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo systemctl status container-aesmd.service\n")),(0,o.kt)("p",null,"To see the logs of the AESM service, use:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo podman logs -t -f aesmd\n")),(0,o.kt)("h2",{id:"check-sgx-setup"},"Check SGX Setup"),(0,o.kt)("p",null,"In order to make sure that your SGX setup is working, you can use the\n",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect")," tool from the ",(0,o.kt)("a",{parentName:"p",href:"https://lib.rs/crates/sgxs-tools"},"sgxs-tools")," Rust\npackage."),(0,o.kt)("p",null,"There are no pre-built packages for it, so you will need to compile it yourself."),(0,o.kt)("h3",{id:"install-dependencies"},"Install Dependencies"),(0,o.kt)("p",null,"Make sure you have the following installed on your system:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://gcc.gnu.org"},"GCC"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/protocolbuffers/protobuf"},"Protobuf")," compiler."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://www.freedesktop.org/wiki/Software/pkg-config"},"pkg-config"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://www.openssl.org"},"OpenSSL")," development package.")),(0,o.kt)("p",null,"On Fedora, you can install all the above with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo dnf install gcc protobuf-compiler pkg-config openssl-devel\n")),(0,o.kt)("p",null,"On Ubuntu, you can install all the above with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo apt install gcc protobuf-compiler pkg-config libssl-dev\n")),(0,o.kt)("h3",{id:"install-rust"},"Install ",(0,o.kt)("a",{parentName:"h3",href:"https://www.rust-lang.org"},"Rust")),(0,o.kt)("p",null,"We follow ",(0,o.kt)("a",{parentName:"p",href:"https://www.rust-lang.org/tools/install"},"Rust upstream's recommendation"),"\non using ",(0,o.kt)("a",{parentName:"p",href:"https://rustup.rs"},"rustup")," to install and manage Rust versions."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"rustup cannot be installed alongside a distribution packaged Rust version. You\nwill need to remove it (if it's present) before you can start using rustup.")),(0,o.kt)("p",null,"Install rustup by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you want to avoid directly executing a shell script fetched the internet, you\ncan also ",(0,o.kt)("a",{parentName:"p",href:"https://rust-lang.github.io/rustup/installation/other.html"},"download ",(0,o.kt)("inlineCode",{parentName:"a"},"rustup-init")," executable for your platform"),"\nand run it manually. This will run ",(0,o.kt)("inlineCode",{parentName:"p"},"rustup-init")," which will download and install\nthe latest stable version of Rust on your system.")),(0,o.kt)("h3",{id:"build-and-install-sgxs-tools"},"Build and Install sgxs-tools"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cargo install sgxs-tools\n")),(0,o.kt)("h3",{id:"run-sgx-detect-tool"},"Run ",(0,o.kt)("inlineCode",{parentName:"h3"},"sgx-detect")," Tool"),(0,o.kt)("p",null,"After the installation completes, run ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect")," to make sure that everything\nis set up correctly:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo $(which sgx-detect)\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you don't run the ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect")," tool as ",(0,o.kt)("inlineCode",{parentName:"p"},"root"),", it might not have the\nnecessary permissions to access the SGX kernel device.")),(0,o.kt)("p",null,"When everything works, you should get output similar to the following (some\nthings depend on hardware features so your output may differ):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"Detecting SGX, this may take a minute...\n\u2714 SGX instruction set\n \u2714 CPU support\n \u2714 CPU configuration\n \u2714 Enclave attributes\n \u2714 Enclave Page Cache\n SGX features\n \u2714 SGX2 \u2714 EXINFO \u2714 ENCLV \u2714 OVERSUB \u2714 KSS\n Total EPC size: 92.8MiB\n\u2718 Flexible launch control\n \u2714 CPU support\n \uff1f CPU configuration\n \u2718 Able to launch production mode enclave\n\u2714 SGX system software\n \u2714 SGX kernel device (/dev/isgx)\n \u2718 libsgx_enclave_common\n \u2714 AESM service\n \u2714 Able to launch enclaves\n \u2714 Debug mode\n \u2718 Production mode\n \u2714 Production mode (Intel whitelisted)\n")),(0,o.kt)("p",null,"The important part is the checkbox under ",(0,o.kt)("em",{parentName:"p"},"Able to launch enclaves")," in both\n",(0,o.kt)("em",{parentName:"p"},"Debug mode")," and ",(0,o.kt)("em",{parentName:"p"},"Production mode (Intel whitelisted)"),"."),(0,o.kt)("p",null,"In case you encounter errors, see the ",(0,o.kt)("a",{parentName:"p",href:"https://edp.fortanix.com/docs/installation/help/"},"list of common SGX installation issues"),"\nfor help."),(0,o.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,o.kt)("p",null,"See ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/troubleshooting"},"the general troubleshooting section"),", before\nproceeding with ParaTime node-specific troubleshooting."),(0,o.kt)("h3",{id:"missing-libsgx-aesm-epid-plugin"},"Missing ",(0,o.kt)("inlineCode",{parentName:"h3"},"libsgx-aesm-epid-plugin")),(0,o.kt)("p",null,"If you are encountering the following error message in your node's logs:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"failed to initialize TEE: error while getting quote info from AESMD: aesm: error 30\n")),(0,o.kt)("p",null,"Ensure you have all required SGX driver libraries installed as listed in\n",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#install-sgx-linux-driver"},"Install SGX Linux Driver section"),".\nPrevious versions of this guide were missing the ",(0,o.kt)("inlineCode",{parentName:"p"},"libsgx-aesm-epid-plugin"),"."),(0,o.kt)("h3",{id:"permission-denied-when-accessing-sgx-kernel-device"},"Permission Denied When Accessing SGX Kernel Device"),(0,o.kt)("p",null,"If running ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect --verbose")," reports:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"\ud83d\udd6e SGX system software > SGX kernel device\nPermission denied while opening the SGX device (/dev/sgx/enclave, /dev/sgx or\n/dev/isgx). Make sure you have the necessary permissions to create SGX enclaves.\nIf you are running in a container, make sure the device permissions are\ncorrectly set on the container.\n\ndebug: Error opening device: Permission denied (os error 13)\ndebug: cause: Permission denied (os error 13)\n")),(0,o.kt)("p",null,"Ensure you are running the ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect")," tool as ",(0,o.kt)("inlineCode",{parentName:"p"},"root")," via:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sudo $(which sgx-detect) --verbose\n")),(0,o.kt)("h3",{id:"error-opening-sgx-kernel-device"},"Error Opening SGX Kernel Device"),(0,o.kt)("p",null,"If running ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect --verbose")," reports:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'\ud83d\udd6e SGX system software > SGX kernel device\nThe SGX device (/dev/sgx/enclave, /dev/sgx or /dev/isgx) could not be opened:\n"/dev" mounted with `noexec` option.\n\ndebug: Error opening device: "/dev" mounted with `noexec` option\ndebug: cause: "/dev" mounted with `noexec` option\n')),(0,o.kt)("p",null,"Ensure your system's ",(0,o.kt)("a",{parentName:"p",href:"#ensure-dev-is-not-mounted-with-the-noexec-option"},(0,o.kt)("inlineCode",{parentName:"a"},"/dev")," is NOT mounted with the ",(0,o.kt)("inlineCode",{parentName:"a"},"noexec")," mount option"),"."),(0,o.kt)("h3",{id:"unable-to-launch-enclaves-operation-not-permitted"},"Unable to Launch Enclaves: Operation not permitted"),(0,o.kt)("p",null,"If running ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect --verbose")," reports:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"\ud83d\udd6e SGX system software > Able to launch enclaves > Debug mode\nThe enclave could not be launched.\n\ndebug: failed to load report enclave\ndebug: cause: failed to load report enclave\ndebug: cause: Failed to map enclave into memory.\ndebug: cause: Operation not permitted (os error 1)\n")),(0,o.kt)("p",null,"Ensure your system's ",(0,o.kt)("a",{parentName:"p",href:"#ensure-dev-is-not-mounted-with-the-noexec-option"},(0,o.kt)("inlineCode",{parentName:"a"},"/dev")," is NOT mounted with the ",(0,o.kt)("inlineCode",{parentName:"a"},"noexec")," mount option"),"."),(0,o.kt)("h3",{id:"unable-to-launch-enclaves-invalid-argument"},"Unable to Launch Enclaves: Invalid argument"),(0,o.kt)("p",null,"If running ",(0,o.kt)("inlineCode",{parentName:"p"},"sgx-detect --verbose")," reports:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"\ud83d\udd6e SGX system software > Able to launch enclaves > Debug mode\nThe enclave could not be launched.\n\ndebug: failed to load report enclave\ndebug: cause: Failed to call EINIT.\ndebug: cause: I/O ctl failed.\ndebug: cause: Invalid argument (os error 22)\n")),(0,o.kt)("p",null,"This may be related to a bug in the Linux kernel when attempting to run enclaves\non certain hardware configurations. Upgrading the Linux kernel to a version\nequal to or greater than 6.5.0 may solve the issue."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/72e396cc.bc87a11b.js b/assets/js/72e396cc.bc87a11b.js new file mode 100644 index 0000000000..7bbdeeed9b --- /dev/null +++ b/assets/js/72e396cc.bc87a11b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7592],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>m});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?i(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function s(e,n){if(null==e)return{};var t,o,r=function(e,n){if(null==e)return{};var t,o,r={},i=Object.keys(e);for(o=0;o<i.length;o++)t=i[o],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o<i.length;o++)t=i[o],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var d=o.createContext({}),l=function(e){var n=o.useContext(d),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},p=function(e){var n=l(e.components);return o.createElement(d.Provider,{value:n},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},h=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,d=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=l(t),h=r,m=u["".concat(d,".").concat(h)]||u[h]||c[h]||i;return t?o.createElement(m,a(a({ref:n},p),{},{components:t})):o.createElement(m,a({ref:n},p))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,a=new Array(i);a[0]=h;var s={};for(var d in n)hasOwnProperty.call(n,d)&&(s[d]=n[d]);s.originalType=e,s[u]="string"==typeof e?e:r,a[1]=s;for(var l=2;l<i;l++)a[l]=t[l];return o.createElement.apply(null,a)}return o.createElement.apply(null,t)}h.displayName="MDXCreateElement"},6693:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>c,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var o=t(7462),r=(t(7294),t(3905));const i={},a="Sentry Node",s={unversionedId:"node/run-your-node/sentry-node",id:"node/run-your-node/sentry-node",title:"Sentry Node",description:"This guide provides instructions for a deployment using the Sentry node architecture to protect validator nodes from being directly exposed on the public network.",source:"@site/docs/node/run-your-node/sentry-node.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/sentry-node",permalink:"/node/run-your-node/sentry-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/sentry-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"IAS Proxy",permalink:"/node/run-your-node/ias-proxy"},next:{title:"Maintenance",permalink:"/node/run-your-node/maintenance"}},d={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Configuring the Oasis Sentry Node",id:"configuring-the-oasis-sentry-node",level:2},{value:"Initializing Sentry Node",id:"initializing-sentry-node",level:3},{value:"Configuring Sentry Node",id:"configuring-sentry-node",level:3},{value:"Configuring the Oasis Validator Node",id:"configuring-the-oasis-validator-node",level:2},{value:"Initializing Validator Node",id:"initializing-validator-node",level:3},{value:"Configuring the Validator Node",id:"configuring-the-validator-node",level:3}],p={toc:l},u="wrapper";function c(e){let{components:n,...t}=e;return(0,r.kt)(u,(0,o.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"sentry-node"},"Sentry Node"),(0,r.kt)("p",null,"This guide provides instructions for a deployment using the Sentry node architecture to protect validator nodes from being directly exposed on the public network."),(0,r.kt)("p",null,"This guide assumes a setup where an Oasis validator node is only accessible over a private network, with sentry nodes having access to it. The guide does not cover setting this infrastructure up. Knowledge of ",(0,r.kt)("a",{parentName:"p",href:"https://forum.cosmos.network/t/sentry-node-architecture-overview/454"},"Tendermint's Sentry Node architecture")," is assumed as well."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"This is only an example of a Sentry node deployment, and we take no responsibility for mistakes contained therein. Make sure you understand what you are doing.")),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before following this guide, make sure you've read the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Prerequisites")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"Running a Node on the Network")," guides and created your Entity."),(0,r.kt)("h2",{id:"configuring-the-oasis-sentry-node"},"Configuring the Oasis Sentry Node"),(0,r.kt)("h3",{id:"initializing-sentry-node"},"Initializing Sentry Node"),(0,r.kt)("p",null,"Sentry node identity keys can be initialized with:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node identity init --datadir /serverdir/node\n")),(0,r.kt)("h3",{id:"configuring-sentry-node"},"Configuring Sentry Node"),(0,r.kt)("p",null,"An Oasis node can be configured to run as a sentry node by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.sentry.enabled")," flag. The ",(0,r.kt)("inlineCode",{parentName:"p"},"tendermint.sentry.upstream_address")," flag can be used to configure a list of nodes that will be protected by the sentry node."),(0,r.kt)("p",null,"An example of full ",(0,r.kt)("inlineCode",{parentName:"p"},"YAML")," configuration of a sentry node is below."),(0,r.kt)("p",null,"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ external_address }}"),": This is the external IP on which sentry node will be reachable.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ seed_node_address }}"),": This the seed node address of the form ",(0,r.kt)("inlineCode",{parentName:"p"},"ID@IP:port"),". You can find the current Oasis Seed Node address in the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ validator_tendermint_id }}"),": This is the Tendermint ID (address) of the Oasis validator node that will be protected by the sentry node. This address can be obtained by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node identity tendermint show-node-address --datadir /serverdir/node\n")),(0,r.kt)("p",{parentName:"li"},"on the validator node.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ validator_private_address }}"),": This is the (presumably) private address on which validator should be reachable from the sentry node.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ validator_sentry_client_grpc_public_key }}"),": This is the public TLS key of the Oasis validator node that will be protected by the sentry node. This public key can be obtained by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"}," oasis-node identity show-sentry-client-pubkey --datadir /serverdir/node\n")),(0,r.kt)("p",{parentName:"li"},"on the validator node. Note that the above command is only available in ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," from version 20.8.1 onward."))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'##\n# Oasis Sentry Node Configuration\n#\n# This file\'s configurations are derived from the command line args found in the\n# root command of the oasis-node binary. For more information execute:\n#\n# oasis-node --help\n#\n# Settings on the command line that are separated by a dot all belong to the\n# same nested object. So "--foo.bar.baz hello" would translate to:\n#\n# foo:\n# bar:\n# baz: hello\n##\n\n# Set this to where you wish to store node data. The node artifacts\n# should also be located in this directory (for us this is /serverdir/node)\ndatadir: /serverdir/node\n\n# Logging.\n#\n# Per-module log levels are defined below. If you prefer just one unified log\n# level, you can use:\n#\n# log:\n# level: debug\nlog:\n level:\n # Per-module log levels. Longest prefix match will be taken. Fallback to\n # "default", if no match.\n default: debug\n tendermint: warn\n tendermint/context: error\n format: JSON\n # By default logs are output to stdout. If you\'re running this in docker keep\n # the default\n #file: /var/log/oasis-node.log\n\n# Path to the genesis file for the current version of the network.\ngenesis:\n file: /serverdir/etc/genesis.json\n\n# Worker configuration.\nworker:\n sentry:\n # Enable sentry node.\n enabled: true\n # Port used by validator nodes to query sentry node for registry\n # information.\n # IMPORTANT: Only validator nodes protected by the sentry node should have\n # access to this port. This port should not be exposed on the public\n # network.\n control:\n port: 9009\n authorized_pubkey:\n - {{ validator_sentry_client_grpc_public_key }}\n\n# Tendermint backend configuration.\nconsensus:\n tendermint:\n abci:\n prune:\n strategy: keep_n\n # Keep ~1 hour of data since block production is ~1 block every 6 seconds.\n # (3600/6 = 600)\n num_kept: 600\n core:\n listen_address: tcp://0.0.0.0:26656\n external_address: tcp://{{ external_address }}:26656\n \n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n p2p:\n seed:\n - "{{ seed_node_address }}"\n \n sentry:\n upstream_address:\n - "{{ validator_tendermint_id }}@{{ validator_private_address }}:26656"\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Multiple sentry nodes can be provisioned following the above steps.")),(0,r.kt)("h2",{id:"configuring-the-oasis-validator-node"},"Configuring the Oasis Validator Node"),(0,r.kt)("p",null,"In this setup the Oasis validator node should not be exposed directly on the public network. The Oasis validator only needs to be able to connect to its sentry nodes, preferably via a private network."),(0,r.kt)("h3",{id:"initializing-validator-node"},"Initializing Validator Node"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"If your validator node is already registered and running in a non-sentry setup, this step can be skipped as the Oasis validator will update its address in the Registry automatically once we redeploy it with new configuration.")),(0,r.kt)("p",null,"When you are ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#initializing-a-node"},"initializing a validator node"),", you should use the sentry node's external address and Consensus ID in the ",(0,r.kt)("inlineCode",{parentName:"p"},"node.consensus_address")," flag. If you are running multiple sentry nodes, you can specify the ",(0,r.kt)("inlineCode",{parentName:"p"},"node.consensus_address")," flag multiple times."),(0,r.kt)("p",null,"To initialize a validator node with 2 sentry nodes, run the following commands from the ",(0,r.kt)("inlineCode",{parentName:"p"},"/localhostdir/node")," directory:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"export SENTRY1_CONSENSUS_ID=<YOUR_SENTRY1_CONSENSUS_ID_B64>\nexport SENTRY1_STATIC_IP=<YOUR_SENTRY1_STATIC_IP>\nexport SENTRY2_CONSENSUS_ID=<YOUR_SENTRY2_CONSENSUS_ID_B64>\nexport SENTRY2_STATIC_IP=<YOUR_SENTRY2_STATIC_IP>\noasis-node registry node init \\\n --signer.backend file \\\n --signer.dir /localhostdir/entity \\\n --node.consensus_address $SENTRY1_CONSENSUS_ID@$SENTRY1_STATIC_IP:26656 \\\n --node.consensus_address $SENTRY2_CONSENSUS_ID@$SENTRY2_STATIC_IP:26656 \\\n --node.is_self_signed \\\n --node.role validator\n")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"SENTRY_CONSENSUS_ID"),": This is the Consensus ID of the sentry node in base64 format. This ID can be obtained from ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus_pub.pem"),":"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sed -n 2p /serverdir/node/consensus_pub.pem\n")),(0,r.kt)("p",{parentName:"admonition"},"on the sentry node.")),(0,r.kt)("h3",{id:"configuring-the-validator-node"},"Configuring the Validator Node"),(0,r.kt)("p",null,"There are some configuration changes needed for the Oasis validator node to enable proxying through its sentry node. Most of these flags should be familiar from the Tendermint sentry node architecture."),(0,r.kt)("p",null,"Since the validator node will not have an external address, the ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.core.external_address")," flag should be skipped. Similarly, the ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.p2p.seed")," flag can be skipped, as the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," won't be directly connecting to any of the seed nodes."),(0,r.kt)("p",null,"Tendermint Peer Exchange should be disabled on the validator with the ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.p2p.disable_peer_exchange")," flag."),(0,r.kt)("p",null,"Sentry nodes can also be configured as Tendermint Persistent-Peers with the ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.p2p.persistent_peer")," flag."),(0,r.kt)("p",null,"In addition to the familiar Tendermint setup above, the node needs to be configured to query sentry nodes for external addresses every time the validator preforms a re-registration. This is configured with the ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.sentry.address")," flag."),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.sentry.address")," flag is of format: ",(0,r.kt)("inlineCode",{parentName:"p"},"<pubkey>@ip:port")," where:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"<pubkey>"),": Is the sentry node's TLS public key."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ip:port"),": Is the (private) address of the sentry node's control endpoint.")),(0,r.kt)("p",null,"Putting it all together, an example configuration of a validator node in the sentry node architecture is given below."),(0,r.kt)("p",null,"Before using this configuration you should collect the following information to replace the ",(0,r.kt)("inlineCode",{parentName:"p"},"{{ var_name }}")," variables present in the configuration file:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ sentry_node_private_ip }}"),": This is the private IP address of the sentry node over which sentry node should be accessible to the validator.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ sentry_node_grpc_public_key }}"),": This is the sentry node's control endpoint TLS public key. This ID can be obtained by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"}," oasis-node identity show-tls-pubkey --datadir /serverdir/node\n")),(0,r.kt)("p",{parentName:"li"},"on the sentry node. Note that the above command is only available in ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," from version 20.8.1 onward.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ sentry_node_tendermint_id }}"),": This is the Tendermint ID (address) of the sentry node that will be configured as a Persistent Peer. This ID can be obtained by running:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node identity tendermint show-node-address --datadir /serverdir/node\n")),(0,r.kt)("p",{parentName:"li"},"on the sentry node."))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'##\n# Oasis Node Configuration\n#\n# This file\'s configurations are derived from the command line args found in\n# the root command of the oasis-node binary. For more information execute:\n#\n# oasis-node --help\n#\n# Settings on the command line that are separated by a dot all belong to the\n# same nested object. So "--foo.bar.baz hello" would translate to:\n#\n# foo:\n# bar:\n# baz: hello\n##\n\n# Set this to where you wish to store node data. The node artifacts\n# should also be located in this directory (for us this is /serverdir/node)\ndatadir: /serverdir/node\n\n# Logging.\n#\n# Per-module log levels are defined below. If you prefer just one unified log\n# level, you can use:\n#\n# log:\n# level: debug\nlog:\n level:\n # Per-module log levels. Longest prefix match will be taken. Fallback to\n # "default", if no match.\n default: debug\n tendermint: warn\n tendermint/context: error\n format: JSON\n # By default logs are output to stdout. If you\'re running this in docker keep\n # the default\n #file: /var/log/oasis-node.log\n\n# Path to the genesis file for the current version of the network.\ngenesis:\n file: /serverdir/etc/genesis.json\n\n# Worker configuration.\nworker:\n registration:\n # In order for the node to register itself the entity.json of the entity\n # used to provision the node must be available on the node.\n entity: /serverdir/node/entity/entity.json\n sentry:\n address:\n - "{{ sentry_node_grpc_public_key }}@{{ sentry_node_private_ip }}:9009"\n\n# Consensus backend.\nconsensus:\n # Setting this to true will mean that the node you\'re deploying will attempt\n # to register as a validator.\n validator: True\n\n # Tendermint backend configuration.\n tendermint:\n abci:\n prune:\n strategy: keep_n\n # Keep ~7 days of data since block production is ~1 block every 6 seconds.\n # (7*24*3600/6 = 100800)\n num_kept: 100800\n core:\n listen_address: tcp://0.0.0.0:26656\n p2p:\n persistent_peer:\n - "{{ sentry_node_tendermint_id }}@{{ sentry_node_private_ip }}:26656"\n disable_peer_exchange: True\n')))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/72efe815.338559a7.js b/assets/js/72efe815.338559a7.js new file mode 100644 index 0000000000..32f1e8a622 --- /dev/null +++ b/assets/js/72efe815.338559a7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7954],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),d=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=d(e.components);return r.createElement(l.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},y=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=d(n),y=o,m=u["".concat(l,".").concat(y)]||u[y]||c[y]||a;return n?r.createElement(m,i(i({ref:t},p),{},{components:n})):r.createElement(m,i({ref:t},p))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=y;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var d=2;d<a;d++)i[d]=n[d];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}y.displayName="MDXCreateElement"},9950:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var r=n(7462),o=(n(7294),n(3905));const a={},i="IAS Proxy",s={unversionedId:"node/run-your-node/ias-proxy",id:"node/run-your-node/ias-proxy",title:"IAS Proxy",description:"This guide will cover setting up an Intel Attestation Service (IAS)",source:"@site/docs/node/run-your-node/ias-proxy.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/ias-proxy",permalink:"/node/run-your-node/ias-proxy",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/ias-proxy.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Upgrading Key Managers",permalink:"/node/run-your-node/keymanager-node/key-manager-upgrade"},next:{title:"Sentry Node",permalink:"/node/run-your-node/sentry-node"}},l={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Obtaining IAS Service Provider ID (SPID) and API Key",id:"obtaining-ias-service-provider-id-spid-and-api-key",level:3},{value:"Creating a Working Directory",id:"creating-a-working-directory",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the IAS Proxy",id:"starting-the-ias-proxy",level:2},{value:"IAS Proxy Public Key",id:"ias-proxy-public-key",level:2},{value:'Share IAS Proxy address <a id="share-seed-node-address"></a>',id:"share-ias-proxy-address-",level:3}],p={toc:d},u="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"ias-proxy"},"IAS Proxy"),(0,o.kt)("p",null,"This guide will cover setting up an ",(0,o.kt)("a",{parentName:"p",href:"https://software.intel.com/content/www/us/en/develop/download/intel-sgx-intel-epid-provisioning-and-attestation-services.html"},"Intel Attestation Service (IAS)"),"\nProxy node for the Oasis Network. This guide assumes some basic knowledge on the\nuse of command line tools."),(0,o.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,o.kt)("p",null,"Before following this guide, make sure you've followed the\n",(0,o.kt)("a",{parentName:"p",href:"prerequisites"},"Prerequisites")," section and have the Oasis Node binary installed\non your system. The IAS Proxy connects to an Oasis Node, so make sure you have a\nrunning node first. For more details, see the instructions on how to\n",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node#configuration"},"Run a Non-validator Node"),"."),(0,o.kt)("h3",{id:"obtaining-ias-service-provider-id-spid-and-api-key"},"Obtaining IAS Service Provider ID (SPID) and API Key"),(0,o.kt)("p",null,"Running the ",(0,o.kt)("a",{parentName:"p",href:"https://software.intel.com/content/www/us/en/develop/download/intel-sgx-intel-epid-provisioning-and-attestation-services.html"},"Intel Attestation Service (IAS)"),"\nProxy requires access to the IAS API. Go to ",(0,o.kt)("a",{parentName:"p",href:"https://api.portal.trustedservices.intel.com/EPID-attestation"},"IAS Enhanced Privacy ID (EPID) attestation"),"\npage and signup for the ",(0,o.kt)("em",{parentName:"p"},"Production Access"),". As a service provider, you will\nregister your TLS certificate and obtain your Service Provider ID (SPID) and API\nkey. The SPID and API key will be used by the IAS Proxy to communicate with the\nIAS."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Basic understanding of SGX Remote attestation is recommended. See Intel's\n",(0,o.kt)("a",{parentName:"p",href:"https://software.intel.com/content/www/us/en/develop/articles/code-sample-intel-software-guard-extensions-remote-attestation-end-to-end-example.html"},"Remote Attestation End-to-End Example"),"\nfor a short practical introduction.")),(0,o.kt)("h3",{id:"creating-a-working-directory"},"Creating a Working Directory"),(0,o.kt)("p",null,"We will be using the following working directory ",(0,o.kt)("inlineCode",{parentName:"p"},"/node/ias")," (feel free to name\nyour directory however you wish)."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The directory permissions should be ",(0,o.kt)("inlineCode",{parentName:"li"},"rwx------"),".")),(0,o.kt)("p",null,"To create the directory, use the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"mkdir -m700 -p /node/ias\n")),(0,o.kt)("h2",{id:"configuration"},"Configuration"),(0,o.kt)("p",null,"To avoid specifying the IAS Service Provider ID (SPID) and API key in the Oasis\nNode configuration directly, IAS Proxy supports reading the SPID and API key\nfrom environment variables. Make sure you have the following environment\nvariables set:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},'OASIS_IAS_SPID="<your-SPID>"\nOASIS_IAS_APIKEY="<your-API-key>"\n')),(0,o.kt)("p",null,"In order to configure the IAS proxy create the ",(0,o.kt)("inlineCode",{parentName:"p"},"/node/ias/config.yml")," file with\nthe following content:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"datadir: /node/ias\n\nlog:\n level:\n default: info\n format: JSON\n\nias:\n production: true\n\ngrpc:\n port: 8650\n")),(0,o.kt)("h2",{id:"starting-the-ias-proxy"},"Starting the IAS Proxy"),(0,o.kt)("p",null,"You can start the IAS Proxy using the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node ias proxy --config /node/ias/config.yml --address unix:{{ oasis_node_socket }}\n")),(0,o.kt)("p",null,"Before using this configuration you should collect the following information to\nreplace the variables present in the invocation command:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"{{ oasis_node_socket }}"),": Path to a running client Oasis Node socket.")),(0,o.kt)("h2",{id:"ias-proxy-public-key"},"IAS Proxy Public Key"),(0,o.kt)("p",null,"The TLS public key required for connecting to the IAS Proxy can be found in the\nprocess logs where it is output on startup as following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{"caller":"proxy.go:111","level":"info","module":"cmd/ias/proxy","msg":"loaded/generated IAS TLS certificate","public_key":"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=","ts":"2023-06-20T09:43:39.592787275Z"}\n')),(0,o.kt)("p",null,"The relevant item is the ",(0,o.kt)("inlineCode",{parentName:"p"},"public_key")," which in the above case is\n",(0,o.kt)("inlineCode",{parentName:"p"},"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw="),"."),(0,o.kt)("h3",{id:"share-ias-proxy-address-"},"Share IAS Proxy address ",(0,o.kt)("a",{id:"share-seed-node-address"})),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"ParaTime nodes")," can now use your IAS Proxy by specifying it\nin configuration, e.g.:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'ias:\n proxy:\n address:\n - "<IAS_PROXY_PUBLIC_KEY>@<EXTERNAL_IP>:8650"\n')),(0,o.kt)("p",null,"Note that you can list multiple IAS proxy addresses."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/72f44a45.ac36cb64.js b/assets/js/72f44a45.ac36cb64.js new file mode 100644 index 0000000000..24b47861d2 --- /dev/null +++ b/assets/js/72f44a45.ac36cb64.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3724],{3905:(e,t,a)=>{a.d(t,{Zo:()=>h,kt:()=>m});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function s(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){o(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function r(e,t){if(null==e)return{};var a,n,o=function(e,t){if(null==e)return{};var a,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),c=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},h=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,h=r(e,["components","mdxType","originalType","parentName"]),p=c(a),u=o,m=p["".concat(l,".").concat(u)]||p[u]||d[u]||i;return a?n.createElement(m,s(s({ref:t},h),{},{components:a})):n.createElement(m,s({ref:t},h))}));function m(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=a.length,s=new Array(i);s[0]=u;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[p]="string"==typeof e?e:o,s[1]=r;for(var c=2;c<i;c++)s[c]=a[c];return n.createElement.apply(null,s)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},1984:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>r,toc:()=>c});var n=a(7462),o=(a(7294),a(3905));const i={},s="Frequently Asked Questions",r={unversionedId:"general/oasis-network/faq",id:"general/oasis-network/faq",title:"Frequently Asked Questions",description:"This page tries to answer some of the most frequently asked questions about the",source:"@site/docs/general/oasis-network/faq.md",sourceDirName:"general/oasis-network",slug:"/general/oasis-network/faq",permalink:"/general/oasis-network/faq",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/faq.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Token Metrics and Distribution",permalink:"/general/oasis-network/token-metrics-and-distribution"},next:{title:"Overview",permalink:"/general/manage-tokens/"}},l={},c=[{value:"<strong>Overview</strong>",id:"overview",level:2},{value:"<strong>Why Oasis?</strong>",id:"why-oasis",level:3},{value:"<strong>Is the Oasis Protocol Foundation still taking grant applications for projects that are building new dApps?</strong>",id:"is-the-oasis-protocol-foundation-still-taking-grant-applications-for-projects-that-are-building-new-dapps",level:3},{value:"<strong>Architecture</strong>",id:"architecture",level:2},{value:"<strong>What kind of blockchain is the Oasis Network? Does it use sidechains?</strong>",id:"what-kind-of-blockchain-is-the-oasis-network-does-it-use-sidechains",level:3},{value:"<strong>What does the Oasis Network\u2019s architecture look like?</strong>",id:"what-does-the-oasis-networks-architecture-look-like",level:3},{value:"<strong>How is a ParaTime different from a Parachain?</strong>",id:"how-is-a-paratime-different-from-a-parachain",level:3},{value:"<strong>Who will be running all of these ParaTimes? Can anyone run a ParaTime?</strong>",id:"who-will-be-running-all-of-these-paratimes-can-anyone-run-a-paratime",level:3},{value:"<strong>What consensus mechanism are you running? Is it BFT?</strong>",id:"what-consensus-mechanism-are-you-running-is-it-bft",level:3},{value:"<strong>Why doesn\u2019t the Oasis Network do sharding? Does that mean it\u2019s slow?</strong>",id:"why-doesnt-the-oasis-network-do-sharding-does-that-mean-its-slow",level:3},{value:"<strong>How does storage work on the Oasis Network? Do you use IPFS?</strong>",id:"how-does-storage-work-on-the-oasis-network-do-you-use-ipfs",level:3},{value:"<strong>Open Finance & DeFi</strong>",id:"open-finance--defi",level:2},{value:"<strong>Does the Oasis Network have a vision for DeFi? Is it different from the mainstream view of DeFi?</strong>",id:"does-the-oasis-network-have-a-vision-for-defi-is-it-different-from-the-mainstream-view-of-defi",level:3},{value:"<strong>I\u2019ve seen Oasis use both the terms \u201cOpen Finance\u201d and \u201cDeFi\u201d? What\u2019s the difference?</strong>",id:"ive-seen-oasis-use-both-the-terms-open-finance-and-defi-whats-the-difference",level:3},{value:"<strong>Will Oasis provide oracle solutions for use in DeFi applications?</strong>",id:"will-oasis-provide-oracle-solutions-for-use-in-defi-applications",level:3},{value:"<strong>What aspects of DeFi require privacy? How can the Oasis Network\u2019s focus on privacy help with DeFi applications?</strong>",id:"what-aspects-of-defi-require-privacy-how-can-the-oasis-networks-focus-on-privacy-help-with-defi-applications",level:3},{value:"<strong>How does privacy help create a new system of Open Finance?</strong>",id:"how-does-privacy-help-create-a-new-system-of-open-finance",level:3},{value:"<strong>Why would anyone choose to build a DeFi project on Oasis over Ethereum?</strong>",id:"why-would-anyone-choose-to-build-a-defi-project-on-oasis-over-ethereum",level:3},{value:"<strong>Token</strong>",id:"token",level:2},{value:"<strong>How will the Oasis Network\u2019s token be used in the network when it launches?</strong>",id:"how-will-the-oasis-networks-token-be-used-in-the-network-when-it-launches",level:3},{value:"<strong>Privacy</strong>",id:"privacy",level:2},{value:"<strong>How does the Oasis Network achieve privacy and confidentiality? Is it through homomorphic encryption?</strong>",id:"how-does-the-oasis-network-achieve-privacy-and-confidentiality-is-it-through-homomorphic-encryption",level:3},{value:"<strong>Interoperability</strong>",id:"interoperability",level:2},{value:"<strong>Can you run Ethereum smart contracts on the Oasis Network? Or if not directly run smart contracts, could you access a bridge between Ethereum ERC20 assets and Oasis?</strong>",id:"can-you-run-ethereum-smart-contracts-on-the-oasis-network-or-if-not-directly-run-smart-contracts-could-you-access-a-bridge-between-ethereum-erc20-assets-and-oasis",level:3}],h={toc:c},p="wrapper";function d(e){let{components:t,...i}=e;return(0,o.kt)(p,(0,n.Z)({},h,i,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"frequently-asked-questions"},"Frequently Asked Questions"),(0,o.kt)("p",null,"This page tries to answer some of the most frequently asked questions about the\nOasis Network."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This page will constantly be updated with new questions and responses.")),(0,o.kt)("h2",{id:"overview"},(0,o.kt)("strong",{parentName:"h2"},"Overview")),(0,o.kt)("h3",{id:"why-oasis"},(0,o.kt)("strong",{parentName:"h3"},"Why Oasis?")),(0,o.kt)("p",null,"Designed for the next generation of blockchain, the Oasis Network is the first privacy-enabled blockchain platform for open finance and a responsible data economy. Combined with its high throughput and secure architecture, the Oasis Network is able to power private, scalable DeFi, revolutionizing Open Finance and expanding it beyond traders and early adopters to a mass market. Its unique privacy features can not only redefine DeFi, but also create a new type of digital asset called Tokenized Data that can enable users to take control of the data they generate and earn rewards for staking it with applications \u2014 creating the first ever responsible data economy."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"First Privacy-Enabled Blockchain:")," The Oasis Network is the world\u2019s first scalable, privacy-enabled blockchain. ParaTimes on the Oasis Network can leverage confidential computing technology such as secure enclaves to keep data confidential \u2014 unlocking new use cases and applications for blockchain."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Scalable, Private DeFi:")," The Oasis Network\u2019s privacy-first design can expand DeFi beyond traders and early adopters \u2014 unlocking a new mainstream market. Plus its innovative scalability design brings fast speeds and high-throughput to DeFi transactions."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"First to Enable Data Tokenization:")," The Oasis Network can ",(0,o.kt)("strong",{parentName:"p"},"Tokenize Data"),", unlocking game changing use cases for blockchain, and an entirely new ecosystem of apps and projects on the network \u2014 powering the next generation of privacy-first applications."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Rapidly Growing Community:")," The Oasis Network has a thriving community of close to a thousand node operators, developers, enterprise partners, ambassadors, and nearly ten thousand community members engaged in global social channels."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Top-Tier Team:")," The Oasis Team is made up of top talent from around the world with backgrounds from Apple, Google, Amazon, Goldman Sachs, UC Berkeley, Carnegie Mellon, Stanford, Harvard and more \u2014 all committed to growing and expanding the impact of the Oasis Network."),(0,o.kt)("h3",{id:"is-the-oasis-protocol-foundation-still-taking-grant-applications-for-projects-that-are-building-new-dapps"},(0,o.kt)("strong",{parentName:"h3"},"Is the Oasis Protocol Foundation still taking grant applications for projects that are building new dApps?")),(0,o.kt)("p",null,"Yes! We are still taking grant applications. You can apply any time ",(0,o.kt)("a",{parentName:"p",href:"https://medium.com/oasis-protocol-project/oasis-foundation-grant-wishlist-3ad73b723d7"},"here"),"."),(0,o.kt)("h2",{id:"architecture"},(0,o.kt)("strong",{parentName:"h2"},"Architecture")),(0,o.kt)("h3",{id:"what-kind-of-blockchain-is-the-oasis-network-does-it-use-sidechains"},(0,o.kt)("strong",{parentName:"h3"},"What kind of blockchain is the Oasis Network? Does it use sidechains?")),(0,o.kt)("p",null,"The Oasis Network is a Layer 1 blockchain protocol using a BFT, proof-of-stake consensus system. The network\u2019s innovative ParaTime architecture enables us to scale without using sidechains. For more information please refer to our ",(0,o.kt)("a",{parentName:"p",href:"https://docsend.com/view/aq86q2pckrut2yvq"},"platform whitepaper"),"."),(0,o.kt)("h3",{id:"what-does-the-oasis-networks-architecture-look-like"},(0,o.kt)("strong",{parentName:"h3"},"What does the Oasis Network\u2019s architecture look like?")),(0,o.kt)("p",null,"The Oasis Network is a Layer 1, proof-of-stake, decentralized network. It has two main components, the consensus layer and the ParaTime layer."),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"The ",(0,o.kt)("strong",{parentName:"li"},"consensus layer")," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."),(0,o.kt)("li",{parentName:"ol"},"The ",(0,o.kt)("strong",{parentName:"li"},"ParaTime layer")," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state.")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Paratime Communication",src:a(9965).Z,width:"1600",height:"940"})),(0,o.kt)("h3",{id:"how-is-a-paratime-different-from-a-parachain"},(0,o.kt)("strong",{parentName:"h3"},"How is a ParaTime different from a Parachain?")),(0,o.kt)("p",null,"Unlike a Parachain, a ParaTime does not need to do consensus itself, making them simpler to develop and more integrated into the network as a whole. ParaTimes take care of compute and discrepancy detection is used to ensure correctness and integrity of execution, making ParaTimes more efficient than Parachains and other chain designs that rely on sharding."),(0,o.kt)("h3",{id:"who-will-be-running-all-of-these-paratimes-can-anyone-run-a-paratime"},(0,o.kt)("strong",{parentName:"h3"},"Who will be running all of these ParaTimes? Can anyone run a ParaTime?")),(0,o.kt)("p",null,"The network is agnostic in this regard. Anyone can run a ParaTime. It is completely left up to the devs and users to see which ones provide the functionality that they need. Examples of ParaTimes in development include the Oasis Labs Data Sovereignty ParaTime and the ",(0,o.kt)("a",{parentName:"p",href:"https://medium.com/oasis-protocol-project/ethereum-support-on-the-oasis-blockchain-3add9e13556?source=collection_home---4------0-----------------------"},"Second State Virtual Machine"),", an EVM compatible Runtime."),(0,o.kt)("h3",{id:"what-consensus-mechanism-are-you-running-is-it-bft"},(0,o.kt)("strong",{parentName:"h3"},"What consensus mechanism are you running? Is it BFT?")),(0,o.kt)("p",null,"The Oasis Network uses Tendermint as its BFT consensus protocol. Given that the consensus layer uses a BFT protocol, the Oasis Network offers instant finality, meaning that once a block is finalized, it cannot be reverted (at least not for full nodes). A ParaTime commitment goes into a block and as such the ParaTime state is also finalized and cannot be reverted once a block is finalized."),(0,o.kt)("h3",{id:"why-doesnt-the-oasis-network-do-sharding-does-that-mean-its-slow"},(0,o.kt)("strong",{parentName:"h3"},"Why doesn\u2019t the Oasis Network do sharding? Does that mean it\u2019s slow?")),(0,o.kt)("p",null,"The Oasis Network does not use sharding. Instead, Oasis leverages a discrepancy detection model leading up to roothash updates, giving the network the same scalability benefits that sharding offers but with added benefits that come from a design that is much simpler to implement in practice. Sharding is a nice idea in theory but comes with a lot of complexity and costs that make it harder to implement in practice. From a security perspective, the complexity of sharding also makes it harder to audit and inherently more vulnerable to security breaches The Oasis Network\u2019s discrepancy detection-based approach provides the same benefits as sharding through a cleaner, simpler, more efficient implementation. Ultimately, the Oasis Network\u2019s unique scalability mechanism ensures that the network is not only fast (like sharding networks purport to be) but also versatile and secure enough to support a wide range of real-world workloads."),(0,o.kt)("h3",{id:"how-does-storage-work-on-the-oasis-network-do-you-use-ipfs"},(0,o.kt)("strong",{parentName:"h3"},"How does storage work on the Oasis Network? Do you use IPFS?")),(0,o.kt)("p",null,"Storage on the Oasis Network is determined by each ParaTime. There is a clear separation of concerns between the consensus layer and the runtime layer. The ParaTimes that make up the runtime layer have a lot of flexibility in how they choose to manage storage. For instance, the ParaTime being developed by Oasis Labs can support IPFS as its storage solution. Other ParaTime developers could opt to implement different storage mechanisms based on their own unique storage needs."),(0,o.kt)("h2",{id:"open-finance--defi"},(0,o.kt)("strong",{parentName:"h2"},"Open Finance & DeFi")),(0,o.kt)("h3",{id:"does-the-oasis-network-have-a-vision-for-defi-is-it-different-from-the-mainstream-view-of-defi"},(0,o.kt)("strong",{parentName:"h3"},"Does the Oasis Network have a vision for DeFi? Is it different from the mainstream view of DeFi?")),(0,o.kt)("p",null,"The first generation of DeFi dApps has provided the market with a huge number of protocols and primitives that are meant to serve as the foundation for the specific components of a new financial system. Despite the current focus on short-term returns, we at Oasis believe the goal of DeFi applications should be to give rise to a new financial system that removes subjectivity, bias, and inefficiencies by leveraging programmable parameters instead of status, wealth, and geography. Oasis aims to support the next wave of DeFi applications by offering better privacy and scalability features than other Layer 1 networks."),(0,o.kt)("h3",{id:"ive-seen-oasis-use-both-the-terms-open-finance-and-defi-whats-the-difference"},(0,o.kt)("strong",{parentName:"h3"},"I\u2019ve seen Oasis use both the terms \u201cOpen Finance\u201d and \u201cDeFi\u201d? What\u2019s the difference?")),(0,o.kt)("p",null,"The terms \u201cOpen Finance\u201d and \u201cDeFi\u201d are interchangeable. However, we believe that \u201cOpen Finance\u201d better represents the idea that the new financial system should be accessible to everyone who operates within the bounds of specific programmable parameters, regardless of their status, wealth, or geography",(0,o.kt)("strong",{parentName:"p"},".")),(0,o.kt)("h3",{id:"will-oasis-provide-oracle-solutions-for-use-in-defi-applications"},(0,o.kt)("strong",{parentName:"h3"},"Will Oasis provide oracle solutions for use in DeFi applications?")),(0,o.kt)("p",null,"Oasis recently announced a partnership with ",(0,o.kt)("a",{parentName:"p",href:"https://medium.com/oasis-protocol-project/oasis-network-chainlink-integrating-secure-and-reliable-oracles-for-access-to-off-chain-data-5d31e6e4591c?source=collection_home---4------1-----------------------"},"Chainlink")," as the preferred oracle provider of the Oasis Network. This integration is ongoing."),(0,o.kt)("h3",{id:"what-aspects-of-defi-require-privacy-how-can-the-oasis-networks-focus-on-privacy-help-with-defi-applications"},(0,o.kt)("strong",{parentName:"h3"},"What aspects of DeFi require privacy? How can the Oasis Network\u2019s focus on privacy help with DeFi applications?")),(0,o.kt)("p",null,"In the current generation of DeFi, some miners and traders are leveraging the inefficiencies of Ethereum to stack mining fees and interest rates, while preventing many more people from participating in the industry. Privacy can play a strong role in making the network function properly by reducing these inefficiencies. At the application level, privacy is an enabler. For instance, strong privacy guarantees can encourage established institutions to participate in the system because these institutions would be able to protect their interests and relationships. Additionally, privacy features can serve as the foundation for a reputation system, thereby unlocking the full potential of undercollateralized lending. We keep hearing that privacy is the next big thing in DeFi, and we look forward to empowering developers to build the next generation of DeFi applications."),(0,o.kt)("h3",{id:"how-does-privacy-help-create-a-new-system-of-open-finance"},(0,o.kt)("strong",{parentName:"h3"},"How does privacy help create a new system of Open Finance?")),(0,o.kt)("p",null,"Existing financial systems and data systems are not open at all. They are only accessible to a select few. Privacy has a much broader meaning than just keeping something private. Thanks to privacy-preserving computation, users can retain ownership of their information and grant others access to compute on their data without actually revealing (or transferring) their data. This will enable users to accrue data yields by essentially staking their data on the blockchain, unlocking a wide range of new financial opportunities."),(0,o.kt)("p",null,"Open Finance refers to the idea that status, wealth, and geography won't block you from accessing a certain financial product. Adherence to a programmable set of parameters will determine whether someone can participate or not, making new financial opportunities open to more people around the world. For example, services such as lending protocols could offer different interest rates depending on the history of that user. What's game changing for the world of finance is that companies would not have to rely on a centralized score such as FICO - they would be able to build their own models."),(0,o.kt)("h3",{id:"why-would-anyone-choose-to-build-a-defi-project-on-oasis-over-ethereum"},(0,o.kt)("strong",{parentName:"h3"},"Why would anyone choose to build a DeFi project on Oasis over Ethereum?")),(0,o.kt)("p",null,"The network\u2019s cutting-edge scalable features can help unblock DeFi as it works today, fixing the high-transaction fees and slow throughput currently plaguing other Layer 1 networks. Combined, Oasis\u2019 unique ability to provide scalable, private DeFi is expected to make it the leading platform for unlocking the next generation of DeFi markets and use cases."),(0,o.kt)("h2",{id:"token"},(0,o.kt)("strong",{parentName:"h2"},"Token")),(0,o.kt)("h3",{id:"how-will-the-oasis-networks-token-be-used-in-the-network-when-it-launches"},(0,o.kt)("strong",{parentName:"h3"},"How will the Oasis Network\u2019s token be used in the network when it launches?")),(0,o.kt)("p",null,"The ROSE token will be used for transaction fees, staking, and delegation at the consensus layer."),(0,o.kt)("h2",{id:"privacy"},(0,o.kt)("strong",{parentName:"h2"},"Privacy")),(0,o.kt)("h3",{id:"how-does-the-oasis-network-achieve-privacy-and-confidentiality-is-it-through-homomorphic-encryption"},(0,o.kt)("strong",{parentName:"h3"},"How does the Oasis Network achieve privacy and confidentiality? Is it through homomorphic encryption?")),(0,o.kt)("p",null,"There are many ways to achieve confidentiality. Using a trusted execution environments (TEEs) is one way. This is what we do. In effect, we provide end-to-end confidentiality for transactions where state and payload are encrypted at rest, in motion, and, more importantly, in compute. homomorphic encryption is another technique for confidentiality. At this time, anyone can build a ParaTime on the Oasis Network that uses homomorphic encryption to provide confidentiality. We are not prescriptive about what approach developers should take."),(0,o.kt)("p",null,"Something worth noting is that privacy and confidentiality are not equivalent. Privacy implies confidentiality but not the other way around. For privacy, there are techniques such as differential privacy that can be implemented."),(0,o.kt)("h2",{id:"interoperability"},(0,o.kt)("strong",{parentName:"h2"},"Interoperability")),(0,o.kt)("h3",{id:"can-you-run-ethereum-smart-contracts-on-the-oasis-network-or-if-not-directly-run-smart-contracts-could-you-access-a-bridge-between-ethereum-erc20-assets-and-oasis"},(0,o.kt)("strong",{parentName:"h3"},"Can you run Ethereum smart contracts on the Oasis Network? Or if not directly run smart contracts, could you access a bridge between Ethereum ERC20 assets and Oasis?")),(0,o.kt)("p",null,"In short, yes! The Oasis Network supports EVM-compatible ParaTimes which will support a wide range of applications."))}d.isMDXComponent=!0},9965:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/consensus_paratime_communication-9e496f13908c8e30ad6e63e6da9f5fa3.png"}}]); \ No newline at end of file diff --git a/assets/js/7327d54c.6d8f2450.js b/assets/js/7327d54c.6d8f2450.js new file mode 100644 index 0000000000..b72333b0d6 --- /dev/null +++ b/assets/js/7327d54c.6d8f2450.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5524],{3905:(e,t,o)=>{o.d(t,{Zo:()=>c,kt:()=>h});var n=o(7294);function r(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function a(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function i(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?a(Object(o),!0).forEach((function(t){r(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):a(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}function s(e,t){if(null==e)return{};var o,n,r=function(e,t){if(null==e)return{};var o,n,r={},a=Object.keys(e);for(n=0;n<a.length;n++)o=a[n],t.indexOf(o)>=0||(r[o]=e[o]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)o=a[n],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(r[o]=e[o])}return r}var l=n.createContext({}),p=function(e){var t=n.useContext(l),o=t;return e&&(o="function"==typeof e?e(t):i(i({},t),e)),o},c=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var o=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(o),m=r,h=u["".concat(l,".").concat(m)]||u[m]||d[m]||a;return o?n.createElement(h,i(i({ref:t},c),{},{components:o})):n.createElement(h,i({ref:t},c))}));function h(e,t){var o=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=o.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:r,i[1]=s;for(var p=2;p<a;p++)i[p]=o[p];return n.createElement.apply(null,i)}return n.createElement.apply(null,o)}m.displayName="MDXCreateElement"},398:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var n=o(7462),r=(o(7294),o(3905));const a={},i="Network Governance",s={unversionedId:"get-involved/network-governance",id:"get-involved/network-governance",title:"Network Governance",description:"If you have a general question on how to use and deploy our software, please",source:"@site/docs/get-involved/network-governance.md",sourceDirName:"get-involved",slug:"/get-involved/network-governance",permalink:"/get-involved/network-governance",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/network-governance.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"Develop Oasis Core",permalink:"/get-involved/oasis-core"},next:{title:"Delegation Policy",permalink:"/get-involved/delegation-policy"}},l={},p=[{value:"Governance Model Overview",id:"governance-model-overview",level:3},{value:"Decision Making Process",id:"decision-making-process",level:3},{value:"Minor Feature Requests",id:"minor-feature-requests",level:3},{value:"Major Feature Requests",id:"major-feature-requests",level:3},{value:"Urgent Bug Fixes",id:"urgent-bug-fixes",level:3},{value:"Contributing to the Network",id:"contributing-to-the-network",level:3}],c={toc:p},u="wrapper";function d(e){let{components:t,...o}=e;return(0,r.kt)(u,(0,n.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"network-governance"},"Network Governance"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"If you have a general question on how to use and deploy our software, please\nread our ",(0,r.kt)("a",{parentName:"p",href:"/node/"},"Run a Node")," section or join our\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/"},"community Discord"),"."),(0,r.kt)("p",{parentName:"admonition"},"All community members are welcome and encouraged to commit code, documentation\nand enhancement proposals to the platform. Contribution guidelines can be found\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/oasis-core"},"here"),".")),(0,r.kt)("h3",{id:"governance-model-overview"},"Governance Model Overview"),(0,r.kt)("p",null,"The Oasis Protocol Foundation proposes a representative democracy governance\nmodel based on a combination of off-chain and on-chain processes for the\ncontinued development of the Oasis Network. The Oasis Protocol Foundation will\nbe tasked with guiding the long-term development of the platform and\ncoordinating the community of development and network operations, with input\ncollected from community members and changes to the network being voted on by\nnode operators, with voting power based proportionally on staked and delegated\ntokens. We propose this model because we think it will provide a balanced voice\nto all engaged community members -- from developers of all sizes, to node\nowners, to token holders -- while at the same time still facilitating the swift\ndeployment of network updates, new features, critical bug fixes."),(0,r.kt)("p",null,"In order for the community to balance distributed ownership and participation\nwith speed and quality of platform development, we propose a hybrid model of\noff- and on-chain mechanisms, organized around the following key components:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Minor Feature Requests"),(0,r.kt)("li",{parentName:"ol"},"Major Feature Requests"),(0,r.kt)("li",{parentName:"ol"},"Bug Fixes")),(0,r.kt)("h3",{id:"decision-making-process"},"Decision Making Process"),(0,r.kt)("p",null,"Moving forward, our proposed process for reviewing and approving major protocol\nupdates is:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Proposals.")," for features and roadmap updates can come from anyone in the\ncommunity in the form of issues\n(",(0,r.kt)("a",{parentName:"p",href:"/get-involved/network-governance#minor-feature-requests"},"for minor features"),") or\n",(0,r.kt)("a",{parentName:"p",href:"../../adrs"},"Architectural Decision Records")," (ADRs,\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/network-governance#major-feature-requests"},"for major features"),").")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Review and discussion of the proposals.")," Decisions about the future of the\nproject are made through discussion with all members of the community, from\nthe newest user to the most experienced. All non-sensitive project management\ndiscussion takes place in the Oasis Protocol GitHub via issues\n(",(0,r.kt)("a",{parentName:"p",href:"/get-involved/network-governance#minor-feature-requests"},"for minor features"),") and ADRs\n(",(0,r.kt)("a",{parentName:"p",href:"/get-involved/network-governance#major-feature-requests"},"for major features"),").")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Decision making process.")," In order to ensure that the project is not\nbogged down by endless discussion and continual voting, the project operates\na policy of lazy consensus. This allows the majority of decisions to be made\nwithout resorting to a formal vote."),(0,r.kt)("p",{parentName:"li"},"In general, as long as nobody explicitly opposes a proposal or patch, it is\nrecognised as having the support of the community. For lazy consensus to be\neffective, it is necessary to allow at least 72 hours before assuming that\nthere are no objections to the proposal. This requirement ensures that\neveryone is given enough time to read, digest and respond to the proposal."),(0,r.kt)("p",{parentName:"li"},"In case consensus is not reached through discussion, the\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/master/GOVERNANCE.md#committers"},"project committers"),"\nmay vote to either accept the proposal or reject it. Votes are cast using\ncomments in the proposal pull request. The proposal is accepted by a simple\nmajority vote.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Final vote for approval.")," Once built, the community votes to approve each\nupgrade and the corresponding features that are included in the proposal.\nThis voting process may initially be done off-chain but will eventually\nbecome an on-chain process. Entities holding stake will vote to approve\nchanges, with each entity's voting power being proportional to their share of\ntokens staked relative to the total tokens staked.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Upgrade.")," Node operators autonomously upgrade their system to run the new\nversion of the software."))),(0,r.kt)("h3",{id:"minor-feature-requests"},"Minor Feature Requests"),(0,r.kt)("p",null,"To request new functionality, there are two primary approaches that will be\nmost effective at receiving input and making progress."),(0,r.kt)("p",null,"If the feature is small - a change to a single piece of functionality, or an\naddition that can be expressed clearly and succinctly in a few sentences,\nthen the most appropriate place to\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/issues/new?template=feature_request.md"},"propose it is as a new feature request"),"\nin the Oasis Core repository."),(0,r.kt)("h3",{id:"major-feature-requests"},"Major Feature Requests"),(0,r.kt)("p",null,"If the feature is more complicated, involves protocol changes, or has potential\nsafety or performance implications, then consider\n",(0,r.kt)("a",{parentName:"p",href:"../../adrs"},"proposing an Architectural Decision Record (ADR)")," and submit it as\na pull request to the Oasis Core repository. This will allow a structured\nreview and commenting of the proposed changes. You should aim to get the ADR\naccepted and merged before starting on implementation. Please keep in mind that\nthe project's committers still have the final word on what is accepted into the\nproject."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"We recommend that major protocol updates including a need to hard fork, roadmap\nand feature planning be conducted with recommendations from the Oasis Protocol\nFoundation and its technical advisory committee.")),(0,r.kt)("h3",{id:"urgent-bug-fixes"},"Urgent Bug Fixes"),(0,r.kt)("p",null,"Urgent bug fixes will primarily be coordinated off-chain to optimize for speed\nin addressing any issues that are critical to the immediate health of the\nnetwork. The Oasis Network community as a whole is collectively responsible for\nidentifying and addressing bugs. As bugs are identified, the Oasis Protocol\nFoundation can serve as a line of first defense to triage these bugs and\ncoordinate security patches for quick release."),(0,r.kt)("p",null,"Bugs are a reality for any software project. We can't fix what we don't know\nabout!"),(0,r.kt)("p",null,"If you believe a bug report presents a security risk, please follow\n",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Responsible_disclosure"},"responsible disclosure"),"\nand report it by following the\n",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/security"},"security disclosure information")," instead\nof filing a public issue or posting it to a public forum."),(0,r.kt)("p",null,"We will get back to you promptly."),(0,r.kt)("p",null,"Otherwise, please, first search between\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/issues"},"existing issues in our repository"),"\nand if the issue is not reported yet,\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/issues/new?template=bug_report.md"},"file a new one"),"."),(0,r.kt)("h3",{id:"contributing-to-the-network"},"Contributing to the Network"),(0,r.kt)("p",null,"If you are interested in contributing to the Oasis Network's codebase or\ndocumentation, please\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/oasis-core"},"review our contribution guidelines here."),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/736ce571.b372baff.js b/assets/js/736ce571.b372baff.js new file mode 100644 index 0000000000..e74e31a450 --- /dev/null +++ b/assets/js/736ce571.b372baff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3336],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},i=Object.keys(e);for(a=0;a<i.length;a++)n=i[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a<i.length;a++)n=i[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},d=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},u="mdxType",l={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),u=m(n),c=r,h=u["".concat(p,".").concat(c)]||u[c]||l[c]||i;return n?a.createElement(h,o(o({ref:t},d),{},{components:n})):a.createElement(h,o({ref:t},d))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=c;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[u]="string"==typeof e?e:r,o[1]=s;for(var m=2;m<i;m++)o[m]=n[m];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},2505:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>l,frontMatter:()=>i,metadata:()=>s,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const i={},o="Hardware Requirements",s={unversionedId:"node/run-your-node/prerequisites/hardware-recommendations",id:"node/run-your-node/prerequisites/hardware-recommendations",title:"Hardware Requirements",description:"The Oasis Network is composed of multiple classes of nodes and services such",source:"@site/docs/node/run-your-node/prerequisites/hardware-recommendations.md",sourceDirName:"node/run-your-node/prerequisites",slug:"/node/run-your-node/prerequisites/hardware-recommendations",permalink:"/node/run-your-node/prerequisites/hardware-recommendations",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/hardware-recommendations.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Prerequisites",permalink:"/node/run-your-node/prerequisites"},next:{title:"Stake Requirements",permalink:"/node/run-your-node/prerequisites/stake-requirements"}},p={},m=[{value:"CPU",id:"suggested-minimum-configurations",level:3},{value:"Memory",id:"memory",level:3},{value:"Storage",id:"storage",level:3},{value:"Network",id:"network",level:3}],d={toc:m},u="wrapper";function l(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"hardware-requirements"},"Hardware Requirements"),(0,r.kt)("p",null,"The Oasis Network is composed of multiple classes of nodes and services such\nas:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Consensus validator or non-validator node"),(0,r.kt)("li",{parentName:"ul"},"Sapphire ParaTime compute or client node"),(0,r.kt)("li",{parentName:"ul"},"Emerald ParaTime compute or client node"),(0,r.kt)("li",{parentName:"ul"},"Cipher ParaTime compute or client node")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Hardware requirements for running the Oasis Web3 gateway can be found\n",(0,r.kt)("a",{parentName:"p",href:"/node/web3#hardware"},"here"),".")),(0,r.kt)("p",null,"This page describes the ",(0,r.kt)("strong",{parentName:"p"},"minimum")," and ",(0,r.kt)("strong",{parentName:"p"},"recommended")," system hardware\nrequirements for running different types of nodes on the Oasis Network. If you\nare running more than one ParaTime on a single node, you will require more\nresources."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"If you configure a system with slower resources than the recommended values, you\nrun the risk of being underprovisioned, causing proposer node timeouts and\nsynchronization delays. This could result in losing stake and not participating\nin committees."),(0,r.kt)("p",{parentName:"admonition"},"If you run out of memory or storage, the Oasis node process will be forcefully\nkilled. This could lead to state corruption, losing stake and not participating\nin committees.")),(0,r.kt)("h3",{id:"suggested-minimum-configurations"},"CPU"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Consensus validator or non-validator node:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 2.0 GHz x86-64 CPU with ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," support"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs with\n",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," and ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2"},"AVX2")," support"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Emerald ParaTime compute node and all ParaTime client nodes:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 2.0 GHz x86-64 CPU with ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," support"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 2.0 GHz x86-64 CPU with 4 cores/vCPUs with\n",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," and ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2"},"AVX2")," support"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Sapphire and Cipher ParaTime compute node:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 2.0 GHz x86-64 CPU with ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," and ",(0,r.kt)("a",{parentName:"li",href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html"},"Intel SGX")," support"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs with\n",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set"),", ",(0,r.kt)("a",{parentName:"li",href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html"},"Intel SGX")," and ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2"},"AVX2")," support")))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"During regular workload your node will operate with the minimal CPU resources.\nHowever, if put under heavy load it might require more cores/vCPUs (e.g. an\nEmerald ParaTime client node behind a public Emerald Web3 gateway)."),(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/AES_instruction_set"},"AES instruction set")," support is required by ",(0,r.kt)("a",{parentName:"p",href:"https://sites.google.com/view/deoxyscipher"},"Deoxys-II-256-128"),", a\nMisuse-Resistant Authenticated Encryption (MRAE) algorithm, which is used for\nencrypting ParaTime's state."),(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2"},"Advanced Vector Extensions 2 (AVX2)")," support enables faster Ed25519\nsignature verification which in turn makes a node sync faster."),(0,r.kt)("p",{parentName:"admonition"},"The ",(0,r.kt)("a",{parentName:"p",href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html"},"Intel SGX")," support is required if you want to run Paratime compute nodes\nthat use a trusted execution environment (TEE).")),(0,r.kt)("h3",{id:"memory"},"Memory"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Consensus validator or non-validator node:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 6 GB of ECC RAM"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 8 GB of ECC RAM"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Each Emerald, Sapphire, Cipher compute or client node:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 12 GB of ECC RAM"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 20 GB of ECC RAM")))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"During regular workload your node will operate with less than the minimum amount\nof memory. However, at certain time points, it will absolutely require more\nmemory. Examples of such more resource intensive time points are the initial\nstate sync, BadgerDB migration when upgrading a node to a new major version of\nthe Oasis Core, generating storage checkpoints with BadgerDB, periodic BadgerDB\ncompactions...")),(0,r.kt)("h3",{id:"storage"},"Storage"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Consensus validator or non-validator node:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 400 GB of SSD or NVMe fast storage"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 700 GB of SSD or NVMe fast storage"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Emerald ParaTime compute or client node (in addition to the consensus storage requirements):"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 400 GB of SSD or NVMe fast storage"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 700 GB of SSD or NVMe fast storage"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Sapphire and Cipher ParaTime compute or client node (in addition to the consensus storage requirements):"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 200 GB of SSD or NVMe fast storage"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 300 GB of SSD or NVMe fast storage")))),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Consensus and ParaTime state is stored in an embedded ",(0,r.kt)("a",{parentName:"p",href:"https://dgraph.io/docs/badger/"},"BadgerDB")," database which\nwas ",(0,r.kt)("a",{parentName:"p",href:"https://dgraph.io/docs/badger/design/"},"designed to run on SSDs"),". Hence, we ",(0,r.kt)("strong",{parentName:"p"},"strongly discourage"),"\ntrying to run a node that stores data ",(0,r.kt)("strong",{parentName:"p"},"on classical HDDs"),".")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The consensus layer and ParaTimes accumulate state over time. The speed at which\nthe state grows depends on the number of transactions on the network and\nParaTimes."),(0,r.kt)("p",{parentName:"admonition"},"For example, a consensus non-validator node on the Mainnet accumulated:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"280 GB of consensus state in ~1 year between Apr 28, 2021 and Apr 11, 2022 (since the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt upgrade"),")"),(0,r.kt)("li",{parentName:"ul"},"32 GB of consensus state in ~1 month since the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/damask-upgrade"},"Damask upgrade"))),(0,r.kt)("p",{parentName:"admonition"},"For example, an Emerald client node on the Mainnet additionally accumulated:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"260 GB of Emerald ParaTime state in ~5 months between Nov 18, 2021 and Apr 11, 2022 (since the ",(0,r.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/oasis-emerald-evm-paratime-is-live-on-mainnet-13afe953a4c9"},"Emerald Mainnet launch"),")"),(0,r.kt)("li",{parentName:"ul"},"25 GB of Emerald ParaTime state in ~1 month since the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/damask-upgrade"},"Damask upgrade")))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Dump & restore upgrades (e.g. ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/damask-upgrade"},"Damask upgrade"),", ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt upgrade"),") include state\nwipes which will free the node storage. Historical state can be accessed by\nrunning a separate archive node.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"You can configure your node ",(0,r.kt)("em",{parentName:"p"},"not to")," keep a complete state from the genesis\nonward. This will reduce the amount of storage required for the consensus and\nParaTime state."),(0,r.kt)("p",{parentName:"admonition"},"To enable pruning of the consensus state set the\n",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.abci.prune.strategy")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.abci.prune.num_kept")," parameters appropriately in your\n",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#configuring-the-oasis-node"},"node's configuration"),"."),(0,r.kt)("p",{parentName:"admonition"},"To enable pruning of the ParaTime state set the\n",(0,r.kt)("inlineCode",{parentName:"p"},"runtime.history.pruner.strategy")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"runtime.history.pruner.num_kept"),"\nparameters appropriately in your ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#configuring-the-oasis-node"},"node's configuration"),".")),(0,r.kt)("h3",{id:"network"},"Network"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Consensus validator node and all ParaTime compute nodes:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Minimum: 200 Mbps internet connection with low latency"),(0,r.kt)("li",{parentName:"ul"},"Recommended: 1 Gbps internet connection with low latency")))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"During regular workload your node will receive much less network traffic.\nHowever, at certain time points when huge bursts of transactions arrive, you\nneed to assure that it doesn't timeout.")))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/74cc02ce.043628bc.js b/assets/js/74cc02ce.043628bc.js new file mode 100644 index 0000000000..091b3d36d9 --- /dev/null +++ b/assets/js/74cc02ce.043628bc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3565],{3905:(e,t,r)=>{r.d(t,{Zo:()=>d,kt:()=>f});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},d=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=l(r),u=o,f=p["".concat(c,".").concat(u)]||p[u]||m[u]||a;return r?n.createElement(f,i(i({ref:t},d),{},{components:r})):n.createElement(f,i({ref:t},d))}));function f(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var l=2;l<a;l++)i[l]=r[l];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},1564:(e,t,r)=>{r.d(t,{Z:()=>f});var n=r(7294),o=r(6010),a=r(9960),i=r(3438),s=r(3919),c=r(5999);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:r}=e;return n.createElement(a.Z,{href:t,className:(0,o.Z)("card padding--lg",l.cardContainer)},r)}function p(e){let{href:t,icon:r,title:a,description:i}=e;return n.createElement(d,{href:t},n.createElement("h2",{className:(0,o.Z)("text--truncate",l.cardTitle),title:a},r," ",a),i&&n.createElement("p",{className:(0,o.Z)("text--truncate",l.cardDescription),title:i},i))}function m(e){let{item:t}=e;const r=(0,i.Wl)(t);return r?n.createElement(p,{href:r,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,c.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const r=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",o=(0,i.xz)(t.docId??void 0);return n.createElement(p,{href:t.href,icon:r,title:t.label,description:t.description??o?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,r)=>{r.d(t,{Z:()=>c});var n=r(7294),o=r(6010),a=r(3438),i=r(1564);function s(e){let{className:t}=e;const r=(0,a.jA)();return n.createElement(c,{items:r.items,className:t})}function c(e){const{items:t,className:r}=e;if(!t)return n.createElement(s,e);const c=(0,a.MN)(t);return n.createElement("section",{className:(0,o.Z)("row",r)},c.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(i.Z,{item:e})))))}},7525:(e,t,r)=>{r.d(t,{n:()=>a});var n=r(4477);function o(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&o(t.items)}}function a(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)o(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},4707:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>f,frontMatter:()=>s,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905)),a=r(9268),i=r(7525);const s={},c="Use Oasis",l={unversionedId:"general/README",id:"general/README",title:"Use Oasis",description:"This chapter provides general overview of the Oasis Network and introduces",source:"@site/docs/general/README.mdx",sourceDirName:"general",slug:"/general/",permalink:"/general/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",next:{title:"Oasis Network",permalink:"/general/oasis-network/"}},d={},p=[],m={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"use-oasis"},"Use Oasis"),(0,o.kt)("p",null,"This chapter provides general overview of the Oasis Network and introduces\nbasic tools for you to get started."),(0,o.kt)(a.Z,{items:[(0,i.n)("/general/oasis-network/"),(0,i.n)("/general/manage-tokens/")],mdxType:"DocCardList"}))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7671072d.ea95b17c.js b/assets/js/7671072d.ea95b17c.js new file mode 100644 index 0000000000..d3664efab6 --- /dev/null +++ b/assets/js/7671072d.ea95b17c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[594],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>f});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?a(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function d(e,n){if(null==e)return{};var t,o,r=function(e,n){if(null==e)return{};var t,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)t=a[o],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)t=a[o],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=o.createContext({}),s=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=s(e.components);return o.createElement(l.Provider,{value:n},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},m=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=d(e,["components","mdxType","originalType","parentName"]),c=s(t),m=r,f=c["".concat(l,".").concat(m)]||c[m]||p[m]||a;return t?o.createElement(f,i(i({ref:n},u),{},{components:t})):o.createElement(f,i({ref:n},u))}));function f(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var a=t.length,i=new Array(a);i[0]=m;var d={};for(var l in n)hasOwnProperty.call(n,l)&&(d[l]=n[l]);d.originalType=e,d[c]="string"==typeof e?e:r,i[1]=d;for(var s=2;s<a;s++)i[s]=t[s];return o.createElement.apply(null,i)}return o.createElement.apply(null,t)}m.displayName="MDXCreateElement"},5194:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>d,toc:()=>s});var o=t(7462),r=(t(7294),t(3905));const a={},i="Non-validator Node",d={unversionedId:"node/run-your-node/non-validator-node",id:"node/run-your-node/non-validator-node",title:"Non-validator Node",description:"These instructions are for setting up a non-validator node. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a ParaTime node instead, see the instructions for running a ParaTime node.",source:"@site/docs/node/run-your-node/non-validator-node.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/non-validator-node",permalink:"/node/run-your-node/non-validator-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/non-validator-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Validator Node",permalink:"/node/run-your-node/validator-node"},next:{title:"Seed Node",permalink:"/node/run-your-node/seed-node"}},l={},s=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Creating a Working Directory",id:"creating-a-working-directory",level:3},{value:"Copying the Genesis File",id:"copying-the-genesis-file",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Checking Node Status",id:"checking-node-status",level:2}],u={toc:s},c="wrapper";function p(e){let{components:n,...t}=e;return(0,r.kt)(c,(0,o.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"non-validator-node"},"Non-validator Node"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"These instructions are for setting up a ",(0,r.kt)("em",{parentName:"p"},"non-validator")," node. If you want to run a ",(0,r.kt)("em",{parentName:"p"},"validator")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"instructions for running a validator node"),". Similarly, if you want to run a ",(0,r.kt)("em",{parentName:"p"},"ParaTime")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"instructions for running a ParaTime node"),".")),(0,r.kt)("p",null,"This guide will cover setting up your non-validator node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools."),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,r.kt)("a",{parentName:"p",href:"prerequisites"},"Prerequisites")," section and have the Oasis Node binary installed on your systems."),(0,r.kt)("h3",{id:"creating-a-working-directory"},"Creating a Working Directory"),(0,r.kt)("p",null,"We will be creating the following directory structure inside a chosen top-level ",(0,r.kt)("inlineCode",{parentName:"p"},"/node")," (feel free to name your directories however you wish) directory:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"etc"),": This will store the node configuration and genesis file.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"data"),": This will store the data directory needed by the running ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary, including the complete blockchain state."),(0,r.kt)("p",{parentName:"li"},"The directory permissions should be ",(0,r.kt)("inlineCode",{parentName:"p"},"rwx------"),"."))),(0,r.kt)("p",null,"To create the directory structure, use the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"mkdir -m700 -p /node/{etc,data}\n")),(0,r.kt)("h3",{id:"copying-the-genesis-file"},"Copying the Genesis File"),(0,r.kt)("p",null,"The latest genesis file can be found in ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),". You should download the latest ",(0,r.kt)("inlineCode",{parentName:"p"},"genesis.json")," file and copy it to the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc")," directory we just created."),(0,r.kt)("h2",{id:"configuration"},"Configuration"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"This will configure the given node to only follow the consensus layer.")),(0,r.kt)("p",null,"In order to configure the node create the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc/config.yml")," file with the following content:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'datadir: /node/data\n\nlog:\n level:\n default: info\n tendermint: info\n tendermint/context: error\n format: JSON\n\ngenesis:\n file: /node/etc/genesis.json\n\nconsensus:\n tendermint:\n p2p:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n seed:\n - "{{ seed_node_address }}"\n\n')),(0,r.kt)("p",null,"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"{{ seed_node_address }}"),": The seed node address in the form ",(0,r.kt)("inlineCode",{parentName:"p"},"ID@IP:port"),"."),(0,r.kt)("p",{parentName:"li"},"You can find the current Oasis Seed Node address in the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),"."))),(0,r.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,r.kt)("p",null,"You can start the node by running the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,r.kt)("h2",{id:"checking-node-status"},"Checking Node Status"),(0,r.kt)("p",null,"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/node/data/internal.sock\n")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/767aa429.f443a6cd.js b/assets/js/767aa429.f443a6cd.js new file mode 100644 index 0000000000..04ee94e01c --- /dev/null +++ b/assets/js/767aa429.f443a6cd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8862],{3905:(e,a,n)=>{n.d(a,{Zo:()=>p,kt:()=>k});var t=n(7294);function r(e,a,n){return a in e?Object.defineProperty(e,a,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[a]=n,e}function l(e,a){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);a&&(t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.push.apply(n,t)}return n}function o(e){for(var a=1;a<arguments.length;a++){var n=null!=arguments[a]?arguments[a]:{};a%2?l(Object(n),!0).forEach((function(a){r(e,a,n[a])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(n,a))}))}return e}function i(e,a){if(null==e)return{};var n,t,r=function(e,a){if(null==e)return{};var n,t,r={},l=Object.keys(e);for(t=0;t<l.length;t++)n=l[t],a.indexOf(n)>=0||(r[n]=e[n]);return r}(e,a);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)n=l[t],a.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=t.createContext({}),c=function(e){var a=t.useContext(s),n=a;return e&&(n="function"==typeof e?e(a):o(o({},a),e)),n},p=function(e){var a=c(e.components);return t.createElement(s.Provider,{value:a},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var a=e.children;return t.createElement(t.Fragment,{},a)}},m=t.forwardRef((function(e,a){var n=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=c(n),m=r,k=d["".concat(s,".").concat(m)]||d[m]||u[m]||l;return n?t.createElement(k,o(o({ref:a},p),{},{components:n})):t.createElement(k,o({ref:a},p))}));function k(e,a){var n=arguments,r=a&&a.mdxType;if("string"==typeof e||r){var l=n.length,o=new Array(l);o[0]=m;var i={};for(var s in a)hasOwnProperty.call(a,s)&&(i[s]=a[s]);i.originalType=e,i[d]="string"==typeof e?e:r,o[1]=i;for(var c=2;c<l;c++)o[c]=n[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,n)}m.displayName="MDXCreateElement"},2066:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var t=n(7462),r=(n(7294),n(3905));const l={title:"Wallet",description:"Manage accounts in your CLI wallet"},o="Managing Accounts in Your Wallet",i={unversionedId:"general/manage-tokens/cli/wallet",id:"general/manage-tokens/cli/wallet",title:"Wallet",description:"Manage accounts in your CLI wallet",source:"@site/docs/general/manage-tokens/cli/wallet.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/wallet",permalink:"/general/manage-tokens/cli/wallet",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/wallet.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Wallet",description:"Manage accounts in your CLI wallet"},sidebar:"general",previous:{title:"ParaTime",permalink:"/general/manage-tokens/cli/paratime"},next:{title:"Account",permalink:"/general/manage-tokens/cli/account"}},s={},c=[{value:"Create an Account",id:"create",level:2},{value:"Import an Existing Keypair or a Mnemonic",id:"import",level:2},{value:"List Accounts Stored in Your Wallet",id:"list",level:2},{value:"Show Account Configuration Details",id:"show",level:2},{value:"Export the Account's Secret",id:"export",level:2},{value:"Renaming the Account",id:"rename",level:2},{value:"Deleting an Account",id:"remove",level:2},{value:"Set Default Account",id:"set-default",level:2},{value:"Advanced",id:"advanced",level:2},{value:"Remote Signer for <code>oasis-node</code>",id:"remote-signer",level:3},{value:"Test Accounts",id:"test-accounts",level:3}],p={toc:c},d="wrapper";function u(e){let{components:a,...n}=e;return(0,r.kt)(d,(0,t.Z)({},p,n,{components:a,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"managing-accounts-in-your-wallet"},"Managing Accounts in Your Wallet"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet")," command is used to manage accounts in your wallet. The wallet\ncan contain file-based accounts which are stored along your Oasis CLI\nconfiguration, or a reference to an account stored on your hardware wallet."),(0,r.kt)("p",null,"The following encryption algorithms and derivation paths are supported by the\nOasis CLI for your accounts:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ed25519-adr8"),": ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/EdDSA"},"Ed25519")," keypair using the ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0008-standard-account-key-generation"},"ADR-8")," derivation path in order\nto obtain a private key from the mnemonic. This is the default setting\nsuitable for accounts on the Oasis consensus layer and Cipher."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"secp256k1-bip44"),": ",(0,r.kt)("a",{parentName:"li",href:"https://en.bitcoin.it/wiki/Secp256k1"},"Secp256k1")," Ethereum-compatible keypair using ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki"},"BIP-44"),"\nwith ETH coin type to derive a private key. This setting is\nused for accounts living on EVM-compatible ParaTimes such as Sapphire or\nEmerald. The same account can be imported into Metamask and other Ethereum\nwallets."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ed25519-legacy"),": ",(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/EdDSA"},"Ed25519")," keypair using a legacy 5-component derivation\npath. This is the preferred setting for Oasis accounts stored on a hardware\nwallet like Ledger. It is called legacy, because it was first implemented\nbefore the ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0008-standard-account-key-generation"},"ADR-8")," was standardized."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"sr25519-adr8"),": ",(0,r.kt)("a",{parentName:"li",href:"https://wiki.polkadot.network/docs/learn-cryptography"},"Sr25519")," keypair using the ",(0,r.kt)("a",{parentName:"li",href:"/adrs/0008-standard-account-key-generation"},"ADR-8")," derivation path. This is\nan alternative signature scheme for signing ParaTime transactions."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ed25519-raw"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"secp256k1-raw")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"sr25519-raw"),": Respective Ed25519,\nSecp256k1 and Sr25519 keypairs imported directly from Base32 or Hex-encoded\nprivate keys. No key derivation is involved.")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For compatibility with Ethereum, each ",(0,r.kt)("inlineCode",{parentName:"p"},"secp256k1")," account corresponds to two\naddresses:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"20-byte hex-encoded Ethereum-compatible address, e.g.\n",(0,r.kt)("inlineCode",{parentName:"li"},"0xDCbF59bbcC0B297F1729adB23d7a5D721B481BA9")),(0,r.kt)("li",{parentName:"ul"},"Bech32-encoded Oasis native address, e.g.\n",(0,r.kt)("inlineCode",{parentName:"li"},"oasis1qq3agel5x07pxz08ns3d2y7sjrr3xf9paquhhhzl"),".")),(0,r.kt)("p",{parentName:"admonition"},"There exists a ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/types/address.go#L135-L142"},"mapping")," from the Ethereum address\nto the native Oasis address as in the example above, but ",(0,r.kt)("strong",{parentName:"p"},"there is no reverse\nmapping"),".")),(0,r.kt)("h2",{id:"create"},"Create an Account"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet create <name>")," command is used add a new account into your Oasis\nCLI wallet by:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"generating a new mnemonic and storing it into a file-based wallet, or"),(0,r.kt)("li",{parentName:"ul"},"creating a reference to an account stored on your hardware wallet.")),(0,r.kt)("p",null,"By default, a password-encrypted file-based wallet will be used for storing the\nprivate key. You will have to enter the password for this account each time to\naccess use it for signing the transactions (e.g. to send tokens). The account\naddress is public and can be accessed without entering the passphrase."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet create oscar\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"? Choose a new passphrase: \n? Repeat passphrase:\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The first account you create or import will become your ",(0,r.kt)("strong",{parentName:"p"},"default account"),".\nThis means it will automatically be selected as a source for sending funds or\ncalling smart contracts unless specified otherwise by using ",(0,r.kt)("inlineCode",{parentName:"p"},"--account <name>"),"\nflag. You can always ",(0,r.kt)("a",{parentName:"p",href:"#set-default"},"change the default account")," later.")),(0,r.kt)("p",null,"To use your hardware wallet, add ",(0,r.kt)("inlineCode",{parentName:"p"},"--kind ledger")," parameter and Oasis CLI will\nstore a reference to an account on your hardware wallet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet create logan --kind ledger\n")),(0,r.kt)("p",null,"A specific account kind (",(0,r.kt)("inlineCode",{parentName:"p"},"ed25519-adr8"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"secp256k1-bip44"),") and the derivation\npath number can be passed with ",(0,r.kt)("inlineCode",{parentName:"p"},"--file.algorithm")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"--file.number")," or\n",(0,r.kt)("inlineCode",{parentName:"p"},"--ledger.algorithm")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"--ledger.number")," respectively. For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet create lenny --kind ledger --ledger.algorithm secp256k1-bip44 --ledger.number 3\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"When creating a hardware wallet account, Oasis CLI will:"),(0,r.kt)("ol",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ol"},"obtain the public key of the account from your hardware wallet,"),(0,r.kt)("li",{parentName:"ol"},"compute the corresponding native address, and"),(0,r.kt)("li",{parentName:"ol"},"store the Oasis native address into the Oasis CLI.")),(0,r.kt)("p",{parentName:"admonition"},"If you try to open the same account with a different Ledger device or\nreset your Ledger with a new mnemonic, Oasis CLI will abort because the address\nof the account obtained from the new device will not match the one stored in\nyour config."),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre"},"oasis wallet show logan\nError: address mismatch after loading account (expected: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl got: oasis1qzdyu09x7hs5nqa0sjgy5jtmz3j5f99ccq0aezjk)\n"))),(0,r.kt)("h2",{id:"import"},"Import an Existing Keypair or a Mnemonic"),(0,r.kt)("p",null,"If you already have a mnemonic or a raw private key, you can import it\nas a new account by invoking ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet import"),". You will be asked\ninteractively to select an account kind (",(0,r.kt)("inlineCode",{parentName:"p"},"mnemonic")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"private key"),"),\nencryption algorithm (",(0,r.kt)("inlineCode",{parentName:"p"},"ed25519")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"secp256k1"),") and then provide either the\nmnemonic with the derivation number, or the raw private key in the corresponding\nformat."),(0,r.kt)("p",null,"Importing an account with a mnemonic looks like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet import eugene\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"? Kind: mnemonic\n? Algorithm: secp256k1-bip44\n? Key number: 0\n? Mnemonic: [Enter 2 empty lines to finish]man ankle mystery favorite tone number ice west spare marriage control lucky life together neither\n\n? Mnemonic: \nman ankle mystery favorite tone number ice west spare marriage control lucky life together neither\n? Choose a new passphrase: \n? Repeat passphrase:\n")),(0,r.kt)("p",null,"Let's make another Secp256k1 account and entering a hex-encoded raw private key:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet import emma\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis wallet import emma\n? Kind: private key\n? Algorithm: secp256k1-raw\n? Private key (hex-encoded): [Enter 2 empty lines to finish]4811ebbe4f29f32a758f6f7bad39deb97ea67f07350637e31c75795dc679262a\n\n? Private key (hex-encoded): \n4811ebbe4f29f32a758f6f7bad39deb97ea67f07350637e31c75795dc679262a\n? Choose a new passphrase: \n? Repeat passphrase:\n")),(0,r.kt)("h2",{id:"list"},"List Accounts Stored in Your Wallet"),(0,r.kt)("p",null,"You can list all available accounts in your wallet with ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet list"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh \neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz \nlenny ledger (secp256k1-bip44:3) oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall \nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl \noscar (*) file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e \n")),(0,r.kt)("p",null,"Above, you can see the native Oasis addresses of all local accounts. The\n",(0,r.kt)("a",{parentName:"p",href:"#set-default"},"default account")," has a special ",(0,r.kt)("inlineCode",{parentName:"p"},"(*)")," sign next to its name."),(0,r.kt)("h2",{id:"show"},"Show Account Configuration Details"),(0,r.kt)("p",null,"To verify whether an account exists in your wallet, use ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet show <name>"),".\nThis will print the account's native address and the public key which requires\nentering your account's password."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet show oscar\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Unlock your account.\n? Passphrase:\nName: oscar\nPublic Key: Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=\nNative address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n")),(0,r.kt)("p",null,"For ",(0,r.kt)("inlineCode",{parentName:"p"},"secp256k1")," accounts Ethereum's hex-encoded address will also be printed."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet show eugene\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Unlock your account.\n? Passphrase: \nName: eugene\nPublic Key: ArEjDxsPfDvfeLlity4mjGzy8E/nI4umiC8vYQh+eh/c\nEthereum address: 0xBd16C6bF701a01DF1B5C11B14860b6bDbE776669\nNative address: oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\n")),(0,r.kt)("p",null,"Showing an account stored on your hardware wallet will require connecting it to\nyour computer:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet show logan\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Name: logan\nPublic Key: l+cuboPsOeuY1+kYlROrpmKgiiELmXSw9xl0WEg8cWE=\nNative address: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\n")),(0,r.kt)("h2",{id:"export"},"Export the Account's Secret"),(0,r.kt)("p",null,"You can obtain the secret material of a file-based account such as the mnemonic\nor the private key by running ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet export <name>"),"."),(0,r.kt)("p",null,"For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet export oscar\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase: \nName: oscar\nPublic Key: Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=\nNative address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\nExport:\npromote easily runway junior saddle gold flip believe wet example amount believe habit mixed pistol lemon increase moon rail mail fiction miss clip asset\n")),(0,r.kt)("p",null,"The same goes for Secp256k1 accounts:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet export eugene\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase: \nName: eugene\nPublic Key: ArEjDxsPfDvfeLlity4mjGzy8E/nI4umiC8vYQh+eh/c\nEthereum address: 0xBd16C6bF701a01DF1B5C11B14860b6bDbE776669\nNative address: oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\nExport:\nman ankle mystery favorite tone number ice west spare marriage control lucky life together neither\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet export emma\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase: \nName: emma\nPublic Key: Az8B2UpSUET0E3n9XMzr+HBvviQKcRvz6C6bJtRFWNYG\nEthereum address: 0xeEbE22411f579682F6f9D68f4C19B3581bCb576b\nNative address: oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\nExport:\n4811ebbe4f29f32a758f6f7bad39deb97ea67f07350637e31c75795dc679262a\n")),(0,r.kt)("p",null,"Trying to export an account stored on your hardware wallet will only\nexport its public key:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet export lenny\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"WARNING: Exporting the account will expose secret key material!\nName: lenny\nPublic Key: AhhT2TUkEZ7rMasLBvHcsGj4SUO7Iw36ELEpL0evZDV1\nEthereum address: 0x95e5e3C1BDD92cd4A0c14c62480DB5867946281D\nNative address: oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\nExport:\n")),(0,r.kt)("h2",{id:"rename"},"Renaming the Account"),(0,r.kt)("p",null,"To rename an account, run ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet rename <old_name> <new_name>"),"."),(0,r.kt)("p",null,"For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet rename lenny lester\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh \neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz \nlester ledger (secp256k1-bip44:3) oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall \nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl \noscar (*) file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e \n")),(0,r.kt)("h2",{id:"remove"},"Deleting an Account"),(0,r.kt)("p",null,"To irreversibly delete the account from your wallet use ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet remove <name>"),".\nFor file-based accounts this will delete the file containing the private key\nfrom your disk. For hardware wallet accounts this will delete the Oasis CLI\nreference, but the private keys will remain intact on your hardware wallet."),(0,r.kt)("p",null,"For example, let's delete ",(0,r.kt)("inlineCode",{parentName:"p"},"lenny")," account:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh \neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz \nlenny ledger (secp256k1-bip44:3) oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall \nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl \noscar (*) file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e \n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet remove lenny\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"WARNING: Removing the account will ERASE secret key material!\nWARNING: THIS ACTION IS IRREVERSIBLE!\n? Enter 'I really want to remove account lenny' (without quotes) to confirm removal: I really want to remove account lenny\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"oasis wallet list\nACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\noscar (*) file (ed25519-raw) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n")),(0,r.kt)("h2",{id:"set-default"},"Set Default Account"),(0,r.kt)("p",null,"To change your default account, use ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet set-default <name>")," and the\nname of the desired default account."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh \neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz \nlenny ledger (secp256k1-bip44:3) oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall \nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl \noscar (*) file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e \n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet set-default lenny\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \nemma file (secp256k1-raw) oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh \neugene file (secp256k1-bip44:0) oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz \nlenny (*) ledger (secp256k1-bip44:3) oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall \nlogan ledger (ed25519-legacy:0) oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl \noscar file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e \n")),(0,r.kt)("h2",{id:"advanced"},"Advanced"),(0,r.kt)("h3",{id:"remote-signer"},"Remote Signer for ",(0,r.kt)("inlineCode",{parentName:"h3"},"oasis-node")),(0,r.kt)("p",null,"You can bind the account in your Oasis CLI wallet with a local instance of\n",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node"),". To do this, use\n",(0,r.kt)("inlineCode",{parentName:"p"},"wallet remote-signer <account_name> <socket_path>"),", pick the account you wish\nto expose and provide a path to the new unix socket:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet remote-signer oscar /datadir/oasis-oscar.socket\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Unlock your account.\n? Passphrase: \nAddress: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\nNode Args:\n --signer.backend=remote \\\n --signer.remote.address=unix:/datadir/oasis-oscar.socket\n\n*** REMOTE SIGNER READY ***\n")),(0,r.kt)("h3",{id:"test-accounts"},"Test Accounts"),(0,r.kt)("p",null,"Oasis CLI comes with the following hardcoded test accounts:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:alice"),": Ed25519 test account by Oasis core tests"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:bob"),": Ed25519 test account by Oasis core tests"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:charlie"),": Secp256k1 test account"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:cory"),": Ed25519 account used by ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-net-runner")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:dave"),": Secp256k1 test account"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:erin"),": Sr25519 test account"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"test:frank"),": Sr25519 test account")),(0,r.kt)("admonition",{title:"Do not use these accounts on public networks",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Private keys for these accounts are well-known. Do not fund them on public\nnetworks, because anyone can drain them!")),(0,r.kt)("p",null,"We suggest that you use these accounts for Localnet development or for\nreproducibility when you report bugs to the Oasis core team. You can access the\nprivate key of a test account the same way as you would for ordinary accounts\nby running ",(0,r.kt)("inlineCode",{parentName:"p"},"wallet export"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7687a514.c7ce56ca.js b/assets/js/7687a514.c7ce56ca.js new file mode 100644 index 0000000000..833b0c4fd7 --- /dev/null +++ b/assets/js/7687a514.c7ce56ca.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6476],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,a,n=function(e,t){if(null==e)return{};var r,a,n={},i=Object.keys(e);for(a=0;a<i.length;a++)r=i[a],t.indexOf(r)>=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a<i.length;a++)r=i[a],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var s=a.createContext({}),l=function(e){var t=a.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},p=function(e){var t=l(e.components);return a.createElement(s.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=l(r),u=n,f=d["".concat(s,".").concat(u)]||d[u]||m[u]||i;return r?a.createElement(f,o(o({ref:t},p),{},{components:r})):a.createElement(f,o({ref:t},p))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=r.length,o=new Array(i);o[0]=u;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c[d]="string"==typeof e?e:n,o[1]=c;for(var l=2;l<i;l++)o[l]=r[l];return a.createElement.apply(null,o)}return a.createElement.apply(null,r)}u.displayName="MDXCreateElement"},1564:(e,t,r)=>{r.d(t,{Z:()=>f});var a=r(7294),n=r(6010),i=r(9960),o=r(3438),c=r(3919),s=r(5999);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function p(e){let{href:t,children:r}=e;return a.createElement(i.Z,{href:t,className:(0,n.Z)("card padding--lg",l.cardContainer)},r)}function d(e){let{href:t,icon:r,title:i,description:o}=e;return a.createElement(p,{href:t},a.createElement("h2",{className:(0,n.Z)("text--truncate",l.cardTitle),title:i},r," ",i),o&&a.createElement("p",{className:(0,n.Z)("text--truncate",l.cardDescription),title:o},o))}function m(e){let{item:t}=e;const r=(0,o.Wl)(t);return r?a.createElement(d,{href:r,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,s.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const r=(0,c.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,o.xz)(t.docId??void 0);return a.createElement(d,{href:t.href,icon:r,title:t.label,description:t.description??n?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(u,{item:t});case"category":return a.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,r)=>{r.d(t,{Z:()=>s});var a=r(7294),n=r(6010),i=r(3438),o=r(1564);function c(e){let{className:t}=e;const r=(0,i.jA)();return a.createElement(s,{items:r.items,className:t})}function s(e){const{items:t,className:r}=e;if(!t)return a.createElement(c,e);const s=(0,i.MN)(t);return a.createElement("section",{className:(0,n.Z)("row",r)},s.map(((e,t)=>a.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},a.createElement(o.Z,{item:e})))))}},7525:(e,t,r)=>{r.d(t,{n:()=>i});var a=r(4477);function n(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&n(t.items)}}function i(e){const t=(0,a.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)n(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},7922:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>p,toc:()=>m});var a=r(7462),n=(r(7294),r(3905)),i=r(1564),o=r(9268),c=r(7525);const s={},l="Cipher ParaTime",p={unversionedId:"dapp/cipher/README",id:"dapp/cipher/README",title:"Cipher ParaTime",description:"The Cipher ParaTime is a Confidential ParaTime for executing Wasm smart contracts.",source:"@site/docs/dapp/cipher/README.mdx",sourceDirName:"dapp/cipher",slug:"/dapp/cipher/",permalink:"/dapp/cipher/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/cipher/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Integrating BAND oracle smart contract",permalink:"/dapp/emerald/integrating-band-oracle-smart-contract"},next:{title:"Prerequisites",permalink:"/dapp/cipher/prerequisites"}},d={},m=[{value:"Smart Contracts Development",id:"smart-contracts-development",level:2},{value:"See also",id:"see-also",level:2}],u={toc:m},f="wrapper";function h(e){let{components:t,...r}=e;return(0,n.kt)(f,(0,a.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"cipher-paratime"},"Cipher ParaTime"),(0,n.kt)("p",null,"The Cipher ParaTime is a Confidential ParaTime for executing Wasm smart contracts."),(0,n.kt)("p",null,"As the officially supported ParaTime by the Oasis Protocol Foundation, Cipher\nallows for:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Flexibility \u2014 Developer can define which data to store in a public\nand which data in the (more expensive) confidential storage"),(0,n.kt)("li",{parentName:"ul"},"Security \u2014 Rust language primarily used for writing Wasm smart contracts is\nknown for its strict memory management and was developed specifically to\navoid memory leaks"),(0,n.kt)("li",{parentName:"ul"},"Scalability \u2014 increased throughput of transactions"),(0,n.kt)("li",{parentName:"ul"},"Low-cost \u2014 99%+ lower fees than Ethereum"),(0,n.kt)("li",{parentName:"ul"},"Cross-chain bridge to enable cross-chain interoperability (upcoming)")),(0,n.kt)("p",null,"If you're looking for EVM-compatible ParaTimes, check out the\n",(0,n.kt)("a",{parentName:"p",href:"/dapp/emerald/"},"Emerald")," and the confidential\n",(0,n.kt)("a",{parentName:"p",href:"/dapp/sapphire/"},"Sapphire")," paratimes."),(0,n.kt)("h2",{id:"smart-contracts-development"},"Smart Contracts Development"),(0,n.kt)("p",null,"The Cipher ParaTime implements the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/contract-sdk"},"Oasis Contract SDK")," API. To learn how to\nwrite a confidential smart contract in Rust and deploy it on the Oasis Cipher\nParaTime, read the related Oasis Contract SDK chapters:"),(0,n.kt)(i.Z,{item:(0,c.n)("/dapp/cipher/prerequisites"),mdxType:"DocCard"}),(0,n.kt)(i.Z,{item:(0,c.n)("/dapp/cipher/hello-world"),mdxType:"DocCard"}),(0,n.kt)(i.Z,{item:(0,c.n)("/dapp/cipher/confidential-smart-contract"),mdxType:"DocCard"}),(0,n.kt)("h2",{id:"see-also"},"See also"),(0,n.kt)(o.Z,{items:[(0,c.n)("/general/manage-tokens/how-to-transfer-rose-into-paratime"),(0,c.n)("/node/run-your-node/paratime-node"),(0,c.n)("/node/run-your-node/paratime-client-node"),(0,c.n)("/dapp/emerald/"),(0,c.n)("/dapp/sapphire/")],mdxType:"DocCardList"}))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/777245c5.058378d4.js b/assets/js/777245c5.058378d4.js new file mode 100644 index 0000000000..a812b6bbd6 --- /dev/null +++ b/assets/js/777245c5.058378d4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5732],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>v});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function p(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var i=o.createContext({}),l=function(e){var t=o.useContext(i),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},c=function(e){var t=l(e.components);return o.createElement(i.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,i=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=l(n),m=r,v=u["".concat(i,".").concat(m)]||u[m]||d[m]||a;return n?o.createElement(v,s(s({ref:t},c),{},{components:n})):o.createElement(v,s({ref:t},c))}));function v(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,s=new Array(a);s[0]=m;var p={};for(var i in t)hasOwnProperty.call(t,i)&&(p[i]=t[i]);p.originalType=e,p[u]="string"==typeof e?e:r,s[1]=p;for(var l=2;l<a;l++)s[l]=n[l];return o.createElement.apply(null,s)}return o.createElement.apply(null,n)}m.displayName="MDXCreateElement"},9047:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>p,toc:()=>l});var o=n(7462),r=(n(7294),n(3905));const a={},s="Governance",p={unversionedId:"core/consensus/services/governance",id:"core/consensus/services/governance",title:"Governance",description:"The governance service is responsible for providing an on-chain governance",source:"@site/docs/core/consensus/services/governance.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/governance",permalink:"/core/consensus/services/governance",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/governance.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Committee Scheduler",permalink:"/core/consensus/services/scheduler"},next:{title:"Root Hash",permalink:"/core/consensus/services/roothash"}},i={},l=[{value:"Methods",id:"methods",level:2},{value:"Submit Proposal",id:"submit-proposal",level:3},{value:"Vote",id:"vote",level:3},{value:"Events",id:"events",level:2},{value:"Proposal Submitted Event",id:"proposal-submitted-event",level:3},{value:"Proposal Finalized Event",id:"proposal-finalized-event",level:3},{value:"Proposal Executed Event",id:"proposal-executed-event",level:3},{value:"Vote Event",id:"vote-event",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:2},{value:"Test Vectors",id:"test-vectors",level:2}],c={toc:l},u="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,o.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"governance"},"Governance"),(0,r.kt)("p",null,"The governance service is responsible for providing an on-chain governance\nmechanism."),(0,r.kt)("p",null,"The service interface definition lives in ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/governance/api"},(0,r.kt)("inlineCode",{parentName:"a"},"go/governance/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/governance/api?tab=doc"},"consensus service API documentation")," and the ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0006-consensus-governance"},"governance ADR\nspecification"),"."),(0,r.kt)("h2",{id:"methods"},"Methods"),(0,r.kt)("p",null,"The following sections describe the methods supported by the consensus\ngovernance service."),(0,r.kt)("h3",{id:"submit-proposal"},"Submit Proposal"),(0,r.kt)("p",null,"Proposal submission enables a new consensus layer governance proposal to be\ncreated."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Method name:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"governance.SubmitProposal\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'// ProposalContent is a consensus layer governance proposal content.\ntype ProposalContent struct {\n Upgrade *UpgradeProposal `json:"upgrade,omitempty"`\n CancelUpgrade *CancelUpgradeProposal `json:"cancel_upgrade,omitempty"`\n}\n\n// UpgradeProposal is an upgrade proposal.\ntype UpgradeProposal struct {\n upgrade.Descriptor\n}\n\n// CancelUpgradeProposal is an upgrade cancellation proposal.\ntype CancelUpgradeProposal struct {\n // ProposalID is the identifier of the pending upgrade proposal.\n ProposalID uint64 `json:"proposal_id"`\n}\n')),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Fields:")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"upgrade")," (optional) specifies an upgrade proposal."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"cancel_upgrade")," (optional) specifies an upgrade cancellation proposal.")),(0,r.kt)("p",null,"Exactly one of the proposal kind fields needs to be non-nil, otherwise the\nproposal is considered malformed."),(0,r.kt)("h3",{id:"vote"},"Vote"),(0,r.kt)("p",null,"Voting for submitted consensus layer governance proposals."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Method name:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"governance.CastVote\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalVote struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Vote is the vote.\n Vote Vote `json:"vote"`\n}\n')),(0,r.kt)("h2",{id:"events"},"Events"),(0,r.kt)("h3",{id:"proposal-submitted-event"},"Proposal Submitted Event"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalSubmittedEvent {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Submitter is the staking account address of the submitter.\n Submitter staking.Address `json:"submitter"`\n}\n')),(0,r.kt)("p",null,"Emitted for every submitted proposal."),(0,r.kt)("h3",{id:"proposal-finalized-event"},"Proposal Finalized Event"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalFinalizedEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // State is the new proposal state.\n State ProposalState `json:"state"`\n}\n')),(0,r.kt)("p",null,"Emitted when a proposal is finalized."),(0,r.kt)("h3",{id:"proposal-executed-event"},"Proposal Executed Event"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalExecutedEvent {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n}\n')),(0,r.kt)("p",null,"Emitted when a passed proposal is executed."),(0,r.kt)("h3",{id:"vote-event"},"Vote Event"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type VoteEvent {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Submitter is the staking account address of the vote submitter.\n Submitter staking.Address `json:"submitter"`\n // Vote is the cast vote.\n Vote Vote `json:"vote"`\n}\n')),(0,r.kt)("p",null,"Emitted when a vote is cast."),(0,r.kt)("h2",{id:"consensus-parameters"},"Consensus Parameters"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"gas_costs")," (transaction.Costs) are the governance transaction gas costs.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"min_proposal_deposit")," (base units) specifies the number of base units that\nare deposited when creating a new proposal.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"voting_period")," (epochs) specifies the number of epochs after which the voting\nfor a proposal is closed and the votes are tallied.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"quorum")," (uint8: ","[","0,100","]",") specifies the minimum percentage of voting power\nthat needs to be cast on a proposal for the result to be valid.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"threshold")," (uint8: ","[","0,100","]",") specifies the minimum percentage of ",(0,r.kt)("inlineCode",{parentName:"p"},"VoteYes"),"\nvotes in order for a proposal to be accepted.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," (epochs) specifies the minimum number of epochs\nbetween the current epoch and the proposed upgrade epoch for the upgrade\nproposal to be valid. Additionally specifies the minimum number of epochs\nbetween two consecutive pending upgrades.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"upgrade_cancel_min_epoch_diff")," (epochs) specifies the minimum number of\nepochs between the current epoch and the proposed upgrade epoch for the\nupgrade cancellation proposal to be valid."))),(0,r.kt)("h2",{id:"test-vectors"},"Test Vectors"),(0,r.kt)("p",null,"To generate test vectors for various governance ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/transactions"},"transactions"),", run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make -C go governance/gen_vectors\n")),(0,r.kt)("p",null,"For more information about the structure of the test vectors see the section\non ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/test-vectors"},"Transaction Test Vectors"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/79102774.bb2a36ad.js b/assets/js/79102774.bb2a36ad.js new file mode 100644 index 0000000000..1725bc7453 --- /dev/null +++ b/assets/js/79102774.bb2a36ad.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9541],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var i=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function r(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,i,o=function(e,t){if(null==e)return{};var n,i,o={},a=Object.keys(e);for(i=0;i<a.length;i++)n=a[i],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i<a.length;i++)n=a[i],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=i.createContext({}),d=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},p=function(e){var t=d(e.components);return i.createElement(l.Provider,{value:t},e.children)},c="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},u=i.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=d(n),u=o,m=c["".concat(l,".").concat(u)]||c[u]||h[u]||a;return n?i.createElement(m,r(r({ref:t},p),{},{components:n})):i.createElement(m,r({ref:t},p))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,r=new Array(a);r[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:o,r[1]=s;for(var d=2;d<a;d++)r[d]=n[d];return i.createElement.apply(null,r)}return i.createElement.apply(null,n)}u.displayName="MDXCreateElement"},1564:(e,t,n)=>{n.d(t,{Z:()=>m});var i=n(7294),o=n(6010),a=n(9960),r=n(3438),s=n(3919),l=n(5999);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function p(e){let{href:t,children:n}=e;return i.createElement(a.Z,{href:t,className:(0,o.Z)("card padding--lg",d.cardContainer)},n)}function c(e){let{href:t,icon:n,title:a,description:r}=e;return i.createElement(p,{href:t},i.createElement("h2",{className:(0,o.Z)("text--truncate",d.cardTitle),title:a},n," ",a),r&&i.createElement("p",{className:(0,o.Z)("text--truncate",d.cardDescription),title:r},r))}function h(e){let{item:t}=e;const n=(0,r.Wl)(t);return n?i.createElement(c,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",o=(0,r.xz)(t.docId??void 0);return i.createElement(c,{href:t.href,icon:n,title:t.label,description:t.description??o?.description})}function m(e){let{item:t}=e;switch(t.type){case"link":return i.createElement(u,{item:t});case"category":return i.createElement(h,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},7525:(e,t,n)=>{n.d(t,{n:()=>a});var i=n(4477);function o(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&o(t.items)}}function a(e){const t=(0,i.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)o(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},9890:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>d,toc:()=>c});var i=n(7462),o=(n(7294),n(3905)),a=n(1564),r=n(7525);const s={},l="Validator Node",d={unversionedId:"node/run-your-node/validator-node",id:"node/run-your-node/validator-node",title:"Validator Node",description:"This guide will walk you through the process of setting up your validator node",source:"@site/docs/node/run-your-node/validator-node.mdx",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/validator-node",permalink:"/node/run-your-node/validator-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/validator-node.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Set up Trusted Execution Environment (TEE)",permalink:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"},next:{title:"Non-validator Node",permalink:"/node/run-your-node/non-validator-node"}},p={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Physical Machines",id:"physical-machines",level:2},{value:"Creating Your Entity on the <code>localhost</code>",id:"creating-your-entity-on-the-localhost",level:2},{value:"Creating a Working Directory",id:"creating-a-working-directory",level:3},{value:"Copying the Genesis File",id:"copying-the-genesis-file",level:3},{value:"Initializing an Entity",id:"initializing-an-entity",level:3},{value:"Using a Ledger-based Signer",id:"using-a-ledger-based-signer",level:4},{value:"Using a File-based Signer",id:"using-a-file-based-signer",level:4},{value:"Initializing a Node",id:"initializing-a-node",level:3},{value:"Adding the Node to the Entity Descriptor",id:"adding-the-node-to-the-entity-descriptor",level:3},{value:"Running an Oasis Node on the <code>server</code>",id:"running-an-oasis-node-on-the-server",level:2},{value:"Setting up the Oasis Node's Working Directory",id:"setting-up-the-oasis-nodes-working-directory",level:3},{value:"Setting Up the the <code>/serverdir</code> Directory",id:"setting-up-the-the-serverdir-directory",level:4},{value:"Copying the Node Artifacts from <code>/localhostdir</code>",id:"copying-the-node-artifacts-from-localhostdir",level:4},{value:"Copying the Public Entity Artifacts from <code>/localhostdir</code>",id:"copying-the-public-entity-artifacts-from-localhostdir",level:4},{value:"Copying the Genesis File to the server",id:"copying-the-genesis-file-to-the-server",level:4},{value:"Configuring the Oasis Node",id:"configuring-the-oasis-node",level:4},{value:"Ensuring Proper Permissions",id:"ensuring-proper-permissions",level:4},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:3},{value:"Verifying the Connection to the Network",id:"verifying-the-connection-to-the-network",level:3},{value:"Staking and Registering",id:"staking-and-registering",level:2},{value:"Check that your node is synced",id:"check-that-your-node-is-synced",level:3},{value:"Generating a Staking (Escrow) Transaction on the <code>localhost</code>",id:"generating-a-staking-escrow-transaction-on-the-localhost",level:3},{value:"Generating Entity Registration Transaction",id:"generating-entity-registration-transaction",level:3},{value:"Submitting Your Transactions on the <code>server</code>",id:"submitting-your-transactions-on-the-server",level:3},{value:"Checking that Your Node is Properly Registered",id:"checking-that-your-node-is-properly-registered",level:3},{value:"Oasis Metadata Registry",id:"oasis-metadata-registry",level:2}],h={toc:c},u="wrapper";function m(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,i.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"validator-node"},"Validator Node"),(0,o.kt)("p",null,"This guide will walk you through the process of setting up your ",(0,o.kt)("strong",{parentName:"p"},"validator node"),"\nfor the Oasis Network on either the Mainnet or the Testnet. It is designed for\nindividuals who have a basic understanding of command line tools."),(0,o.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,o.kt)("p",null,"Before proceeding with this guide, ensure that you have completed the steps\noutlined in the ",(0,o.kt)("a",{parentName:"p",href:"prerequisites/"},"Prerequisites")," section so that:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"your system meets the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/hardware-recommendations"},"hardware requirements"),","),(0,o.kt)("li",{parentName:"ul"},"you have the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node binary")," installed on your systems,"),(0,o.kt)("li",{parentName:"ul"},"you understand what are ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/stake-requirements"},"Stake requirements")," to become a validator on the\nOasis Network.")),(0,o.kt)("h2",{id:"physical-machines"},"Physical Machines"),(0,o.kt)("p",null,"You will be using two separate physical machines for deployment: your local\nsystem, referred to as ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),", and a remote ",(0,o.kt)("inlineCode",{parentName:"p"},"server")," which will function\nas an Oasis node. The reason for this is to ensure protection of the keys used\nto setup your node."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Localhost:")," On the localhost, you will ",(0,o.kt)("a",{parentName:"p",href:"#creating-your-entity"},"create your entity")," which is\nessential for deploying nodes on the network. To ensure the security of these\nprivate keys, we strongly recommend to isolate the localhost from any network or\ninternet connectivity. Once the keys have been generated, it is highly\nrecommended to use ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Hardware_security_module"},"Hardware Security Modules (HSM)")," for secure storage\nsuch as the ",(0,o.kt)("a",{parentName:"p",href:"../../../general/manage-tokens/holding-rose-tokens/ledger-wallet"},"Ledger wallet"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Server:")," After the entity has been created, proceed to ",(0,o.kt)("a",{parentName:"p",href:"./#running-an-oasis-node-on-the-server"},"set up the server in\norder to start the Oasis node"),". The server needs to meet the hardware\nrequirements and have an acces to the internet."),(0,o.kt)("h2",{id:"creating-your-entity-on-the-localhost"},"Creating Your Entity on the ",(0,o.kt)("inlineCode",{parentName:"h2"},"localhost")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"Everything in this section should be done on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost")," as there are\nsensitive items that will be created.")),(0,o.kt)("p",null,"During the entity initialization process, you will generate essential components\nsuch as keys and other crucial artifacts that are necessary for the deployment\nof nodes on the network. This guide has been designed with a particular file\nstructure in mind. Nonetheless, feel free to reorganize and rename directories\nas needed to accommodate your preferences."),(0,o.kt)("h3",{id:"creating-a-working-directory"},"Creating a Working Directory"),(0,o.kt)("p",null,"Begin by creating a directory named ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir"),". This location will be used\nto store generated artifacts. It is important that you securely store the\ngenerated artifacts."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"mkdir /localhostdir\n")),(0,o.kt)("p",null,"Within the ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir"),", create the following subdirectories and set their\npermissions to ",(0,o.kt)("inlineCode",{parentName:"p"},"rwx------"),":"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"entity"),": This will store your entity. The private contents in this\ndirectory are safest if used on a machine kept disconnected from the internet.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"node"),": This will store a node's identity. The private contents of this\ndirectory will be used on the node itself."))),(0,o.kt)("p",null,"To create the directory structure, use the following commands:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd /localhostdir\nmkdir -m700 -p {entity,node}\n")),(0,o.kt)("h3",{id:"copying-the-genesis-file"},"Copying the Genesis File"),(0,o.kt)("p",null,"To continue, download the most recent ",(0,o.kt)("inlineCode",{parentName:"p"},"genesis.json")," file from the\n",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," section and save it to your ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir")," working\ndirectory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd /localhostdir\n# replace RELEASE_DATE with actual Mainnet consensus dump date, e.g. 2022-11-04\ncurl -L -o genesis.json https://github.com/oasisprotocol/mainnet-artifacts/releases/download/RELEASE_DATE/genesis.json\n")),(0,o.kt)("p",null,"Then, set the environment variable that points to its path as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"GENESIS_FILE_PATH=/localhostdir/genesis.json\n")),(0,o.kt)("h3",{id:"initializing-an-entity"},"Initializing an Entity"),(0,o.kt)("p",null,"An entity is critical to operating nodes on the network as it controls the stake attached to a given individual or organization on the network. We highly recommend using an HSM or ",(0,o.kt)("a",{parentName:"p",href:"../../../oasis-core-ledger"},"Ledger")," device to protect your entity private key."),(0,o.kt)("h4",{id:"using-a-ledger-based-signer"},"Using a Ledger-based Signer"),(0,o.kt)("p",null,"The Ledger-based signer stores your private keys on your Ledger wallet. It is implemented as an Oasis Core signer plugin."),(0,o.kt)("p",null,"You will need to set it up as described in the ",(0,o.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/setup"},"Setup")," section of our ",(0,o.kt)("a",{parentName:"p",href:"../../../oasis-core-ledger"},"Oasis Core Ledger docs"),"."),(0,o.kt)("p",null,"As the entity's private key is stored on your Ledger wallet, you only need to export the entity's public key as described in ",(0,o.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/entity"},"Exporting Public Key to Entity")," section of our ",(0,o.kt)("a",{parentName:"p",href:"../../../oasis-core-ledger"},"Oasis Core Ledger docs"),"."),(0,o.kt)("p",null,"This will create 1 file in ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity"),":"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"entity.json"),": The entity descriptor. This is the JSON of the unsigned information to be sent to the registry application on the network.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"There will be no signed entity descriptor, i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"entity_genesis.json"),", created yet. It will get created when you'll update the entity descriptor with your signed node descriptor as described in the ",(0,o.kt)("a",{parentName:"p",href:"#adding-the-node-to-the-entity-descriptor"},"Adding the Node to the Entity Descriptor")," section.")),(0,o.kt)("h4",{id:"using-a-file-based-signer"},"Using a File-based Signer"),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"We strongly suggest that you do not use any entity that is generated with the file-based signer on the Mainnet."),(0,o.kt)("p",{parentName:"admonition"},"When using the file-based signer the use of an ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Air_gap_(networking)"},"offline/air-gapped machine")," for this purpose is highly recommended. Gaining access to the entity private key can compromise your tokens.")),(0,o.kt)("p",null,"To initialize an entity simply run the following from ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry entity init\n")),(0,o.kt)("p",null,"This will generate three files in ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity"),":"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"entity.pem"),": The private key of the entity. ",(0,o.kt)("strong",{parentName:"li"},"NEVER SHARE THIS AS IT CAN BE USED TO TRANSFER STAKE.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"entity.json"),": The entity descriptor. This is the JSON of the unsigned information to be sent to the registry application on the network."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"entity_genesis.json"),": This JSON object contains the entity descriptor that has been signed with entity's private key, i.e. ",(0,o.kt)("inlineCode",{parentName:"li"},"entity.pem"),". This is meant to be shared for inclusion in the Genesis block.")),(0,o.kt)("h3",{id:"initializing-a-node"},"Initializing a Node"),(0,o.kt)("p",null,"A node registers itself to the network when the node starts up. However, in order to validate itself, the entity signs a public key associated with the node. This allows the node registration to happen without the uploading entity's private key to the internet."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"To get the ",(0,o.kt)("inlineCode",{parentName:"p"},"$ENTITY_ID")," needed below check the value of the ",(0,o.kt)("inlineCode",{parentName:"p"},"id")," field in ",(0,o.kt)("inlineCode",{parentName:"p"},"entity.json"),", e.g. with the following content in ",(0,o.kt)("inlineCode",{parentName:"p"},"entity.json"),":"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},'{"v":1,"id":"2D5nSE3uFGvp2UkUY3w8OSjnCCYmQX/3JpJ77+aJGUQ="}\n')),(0,o.kt)("p",{parentName:"admonition"},"the entity ID is ",(0,o.kt)("inlineCode",{parentName:"p"},"2D5nSE3uFGvp2UkUY3w8OSjnCCYmQX/3JpJ77+aJGUQ="),".")),(0,o.kt)("p",null,"To initialize a validator node, take note of the static IP of the server where your node will run, and issue the following commands from the ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/node")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"ENTITY_ID=<YOUR-ENTITY-ID>\nSTATIC_IP=<YOUR-STATIC-IP>\noasis-node registry node init \\\n --node.entity_id $ENTITY_ID \\\n --node.consensus_address $STATIC_IP:26656 \\\n --node.role validator\n")),(0,o.kt)("p",null,"This command will create a validator node's identity so that it can be a self-signed node (this is what allows self-registration)."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"There are more options for node initialization that you can explore by running:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry node init --help\n")),(0,o.kt)("p",{parentName:"admonition"},"The options shown above are just the minimum.")),(0,o.kt)("p",null,"The command will generate the following files:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"consensus.pem"),": The node's consensus private key. ",(0,o.kt)("strong",{parentName:"li"},"DO NOT SHARE")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"consensus_pub.pem"),": The node's consensus public key."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"identity.pem"),": The node's identity private key. ",(0,o.kt)("strong",{parentName:"li"},"DO NOT SHARE")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"identity_pub.pem"),": The node's identity public key."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"node_genesis.json"),": The node's details if you wish to include this node in the genesis file of the network."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"p2p.pem"),": The node's private key for libp2p. ",(0,o.kt)("strong",{parentName:"li"},"DO NOT SHARE")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"p2p_pub.pem"),": The node's public key for libp2p."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"sentry_client_tls_identity.pem"),": The node's TLS private key for communicating with sentry nodes. ",(0,o.kt)("strong",{parentName:"li"},"DO NOT SHARE")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"sentry_client_tls_identity_cert.pem"),": The node's TLS certificate for communicating with sentry nodes.")),(0,o.kt)("h3",{id:"adding-the-node-to-the-entity-descriptor"},"Adding the Node to the Entity Descriptor"),(0,o.kt)("p",null,"Once the node has been initialized, we need to add it to the entity descriptor so that it can properly register itself when the node starts up. The instructions differ based on what kind of signer was used to generate the entity."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"If using the plugin-based signer,")," execute the following command in the ",(0,o.kt)("inlineCode",{parentName:"li"},"/localhostdir/entity")," directory (again this assumes the use of the Ledger signer plugin in which case you will need to then confirm the signing operation on the Ledger device):")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'oasis-node registry entity update \\\n --signer.backend plugin \\\n --signer.plugin.name ledger \\\n --signer.plugin.path "$LEDGER_SIGNER_PATH" \\\n --signer.plugin.config "wallet_id:$LEDGER_WALLET_ID,index:$LEDGER_INDEX" \\\n --entity.node.descriptor /localhostdir/node/node_genesis.json\n')),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"If using the file-based signer"),", execute the following command in the ",(0,o.kt)("inlineCode",{parentName:"li"},"/localhostdir/entity")," directory:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry entity update \\\n --entity.node.descriptor /localhostdir/node/node_genesis.json\n")),(0,o.kt)("p",null,"This will update the entity descriptor in ",(0,o.kt)("inlineCode",{parentName:"p"},"entity.json")," and subsequently the ",(0,o.kt)("inlineCode",{parentName:"p"},"entity_genesis.json")," file that contains the signed entity descriptor payload."),(0,o.kt)("h2",{id:"running-an-oasis-node-on-the-server"},"Running an Oasis Node on the ",(0,o.kt)("inlineCode",{parentName:"h2"},"server")),(0,o.kt)("h3",{id:"setting-up-the-oasis-nodes-working-directory"},"Setting up the Oasis Node's Working Directory"),(0,o.kt)("p",null,"Before we run the node on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server")," we need to ensure that we have a place to store necessary files for the node."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We will reference the working directory on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server")," as ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir")," throughout the documentation.")),(0,o.kt)("h4",{id:"setting-up-the-the-serverdir-directory"},"Setting Up the the ",(0,o.kt)("inlineCode",{parentName:"h4"},"/serverdir")," Directory"),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir")," directory we will create the following subdirectories:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"etc/")," - this is to store the configuration"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"node/")," - this is to store the node's data"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"node/entity/")," - this is to store the public components of the node's entity")),(0,o.kt)("p",null,"You can make this directory structure by executing the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"mkdir -m700 -p /serverdir/{etc,node,node/entity}\n")),(0,o.kt)("h4",{id:"copying-the-node-artifacts-from-localhostdir"},"Copying the Node Artifacts from ",(0,o.kt)("inlineCode",{parentName:"h4"},"/localhostdir")),(0,o.kt)("p",null,"In order for the node registration to work properly, as defined in ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity.json"),", you must copy the node's artifacts you generated in the ",(0,o.kt)("a",{parentName:"p",href:"#initializing-a-node"},"Initializing a Node")," section. To do so, upload the following files from ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/node")," to ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," over a secure channel (e.g. SSH):"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"consensus.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"consensus_pub.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"identity.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"identity_pub.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"p2p.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"p2p_pub.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"sentry_client_tls_identity.pem")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"sentry_client_tls_identity_cert.pem"))),(0,o.kt)("p",null,"After copying, make sure that all these files have ",(0,o.kt)("inlineCode",{parentName:"p"},"0600")," permissions, i.e. only their owner has ",(0,o.kt)("inlineCode",{parentName:"p"},"read")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"write")," permissions."),(0,o.kt)("p",null,"To do so, run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"chmod -R 600 /serverdir/node/*.pem\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"You may have noticed that some of these files were listed as ",(0,o.kt)("strong",{parentName:"p"},"DO NOT SHARE")," in the ",(0,o.kt)("a",{parentName:"p",href:"#initializing-a-node"},"Initializing a Node")," section."),(0,o.kt)("p",{parentName:"admonition"},"In the future, these keys should be generated and referenced from an HSM. However, until HSM support is implemented, these keys should be kept as secure as possible on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),".")),(0,o.kt)("h4",{id:"copying-the-public-entity-artifacts-from-localhostdir"},"Copying the Public Entity Artifacts from ",(0,o.kt)("inlineCode",{parentName:"h4"},"/localhostdir")),(0,o.kt)("p",null,"We will also need to have the public entity artifacts from the ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir")," present on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),". Copy the ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity/entity.json")," file on ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost")," to ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node/entity/entity.json")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),"."),(0,o.kt)("h4",{id:"copying-the-genesis-file-to-the-server"},"Copying the Genesis File to the server"),(0,o.kt)("p",null,"The latest Genesis file can be found in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),". You should download the latest ",(0,o.kt)("inlineCode",{parentName:"p"},"genesis.json")," file and copy it to ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/etc/genesis.json")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),"."),(0,o.kt)("h4",{id:"configuring-the-oasis-node"},"Configuring the Oasis Node"),(0,o.kt)("p",null,"There are a variety of options available when running an Oasis node. The following YAML file is a basic configuration for a validator node on the network."),(0,o.kt)("p",null,"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"{{ external_address }}"),": The external IP you used when registering this node.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"If you are using a ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/sentry-node"},"Sentry Node"),", you should use the public IP of that machine.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"{{ seed_node_address }}"),": The seed node address in the form ",(0,o.kt)("inlineCode",{parentName:"p"},"ID@IP:port"),"."),(0,o.kt)("p",{parentName:"li"},"You can find the current Oasis Seed Node address in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),"."))),(0,o.kt)("p",null,"To use this configuration, save it in the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/etc/config.yml")," file and pass it to the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," command as an argument to the ",(0,o.kt)("inlineCode",{parentName:"p"},"--config")," flag."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'##\n# Oasis Node Configuration\n#\n# This file\'s contents are derived from the command line arguments found in the\n# root command of the oasis-node binary. For more information, execute:\n#\n# oasis-node --help\n#\n# Settings on the command line that are separated by a dot all belong to the\n# same nested object. For example, "--foo.bar.baz hello" would translate to:\n#\n# foo:\n# bar:\n# baz: hello\n##\n\n# Set this to where you wish to store node data. The node\'s artifacts\n# should also be located in this directory.\ndatadir: /serverdir/node\n\n# Logging.\n#\n# Per-module log levels are defined below. If you prefer just one unified log\n# level, you can use:\n#\n# log:\n# level: debug\nlog:\n level:\n # Per-module log levels. Longest prefix match will be taken. Fallback to\n # "default", if no match.\n default: debug\n tendermint: warn\n tendermint/context: error\n format: JSON\n # By default logs are output to stdout. If you would like to output logs to\n # a file, you can use:\n #\n # file: /var/log/oasis-node.log\n\n# Genesis.\ngenesis:\n # Path to the genesis file for the current version of the network.\n file: /serverdir/etc/genesis.json\n\n# Worker configuration.\nworker:\n registration:\n # In order for the node to register itself, the entity.json of the entity\n # used to provision the node must be available on the node.\n entity: /serverdir/node/entity/entity.json\n\n# Consensus backend.\nconsensus:\n # Setting this to true will mean that the node you\'re deploying will attempt\n # to register as a validator.\n validator: true\n\n # Tendermint backend configuration.\n tendermint:\n core:\n listen_address: tcp://0.0.0.0:26656\n\n # The external IP that is used when registering this node to the network.\n # NOTE: If you are using the Sentry node setup, this option should be\n # omitted.\n external_address: tcp://{{ external_address }}:26656\n\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n p2p:\n seed:\n - "{{ seed_node_address }}"\n')),(0,o.kt)("h4",{id:"ensuring-proper-permissions"},"Ensuring Proper Permissions"),(0,o.kt)("p",null,"Only the owner of the process that runs the Oasis node should have access to the files in the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," directory. The ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary ensures that the files used by the node are as least privileged as possible so that you don't accidentally shoot yourself in the foot while operating a node."),(0,o.kt)("p",null,"To ensure proper permissions are set, we suggest running the following to remove all non-owner read/write/execute permissions:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"chmod -R go-r,go-w,go-x /serverdir\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Just so it's clear, the following permissions are expected by the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"700")," for the ",(0,o.kt)("inlineCode",{parentName:"li"},"/serverdir/node")," directory"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"700")," for the ",(0,o.kt)("inlineCode",{parentName:"li"},"/serverdir/node/entity")," directory"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"600")," for all ",(0,o.kt)("inlineCode",{parentName:"li"},"*.pem")," files"))),(0,o.kt)("h3",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,o.kt)("p",null,"You can start the node by running the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /serverdir/etc/config.yml\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The Oasis node is configured to run in the foreground by default."),(0,o.kt)("p",{parentName:"admonition"},"We recommend you configure and use it with a process manager like ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/systemd/systemd"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org"},"Supervisor"),".")),(0,o.kt)("h3",{id:"verifying-the-connection-to-the-network"},"Verifying the Connection to the Network"),(0,o.kt)("p",null,"As part of the starting the server process, the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary will, by default, setup an internal unix socket in the ",(0,o.kt)("inlineCode",{parentName:"p"},"datadir")," of the Node. This socket can be used to communicate to the node and query details about the network."),(0,o.kt)("p",null,"Run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry entity list -a unix:/serverdir/node/internal.sock\n")),(0,o.kt)("p",null,"If this command fails, you'll receive a non-zero exit code and there's a high likelihood that you are not connected to the network. However, if it does work properly it should respond with output like the following but with potentially many more values:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"CVzqFIADD2Ed0khGBNf4Rvh7vSNtrL1ULTkWYQszDpc=\nC5z1jB+FHB/QgtTITr6NKWpUs9QHwD11CG3v8tmuJ0g=\nDPbZomOIleFrvcJBZPl7y/wEB1w9Q569vAbb6Krl9fE=\nDVobZ8bWlOv2J6oHO0uITr5FPO5rIY2irdPNhByprHk=\nD2hqhJcmZnBmhw9TodOdoFPAjmRkpRatANCNHxIDHgA=\n")),(0,o.kt)("p",null,"Once you get to a node that's connected you can move on to the next section as your node is not yet registered as a validator on the Oasis Network."),(0,o.kt)("h2",{id:"staking-and-registering"},"Staking and Registering"),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This step is not necessary if your entity was fully staked at genesis.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"If you've submitted staking or registry transactions before, your nonce is likely different than the nonce used in the examples. If you're uncertain, please check your account nonce by using ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"this guide"),".")),(0,o.kt)("p",null,"Once you have been funded, you can complete the process of connecting your node to the network by registering both your entity and your node, as described below."),(0,o.kt)("h3",{id:"check-that-your-node-is-synced"},"Check that your node is synced"),(0,o.kt)("p",null,"Before you can make any transactions you'll have to make sure that your node is synced. To do so call this command on the server:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control is-synced -a unix:/serverdir/node/internal.sock\n")),(0,o.kt)("p",null,"If your node is synced, the above command should output:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"node completed initial syncing\n")),(0,o.kt)("p",null,"If your node is not yet synced, you will need to wait before you can move forward."),(0,o.kt)("h3",{id:"generating-a-staking-escrow-transaction-on-the-localhost"},"Generating a Staking (Escrow) Transaction on the ",(0,o.kt)("inlineCode",{parentName:"h3"},"localhost")),(0,o.kt)("p",null,"Your entity's private key should be disconnected from the internet on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),". Therefore, you need to generate the following transaction on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),"."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"The entity's private key is used to authorize transactions on your staking account."),(0,o.kt)("p",{parentName:"admonition"},"Hence it should never be present on the online ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),".")),(0,o.kt)("p",null,"The current minimum stake required to register an entity and register a node as a validator is 200 tokens. So, we will generate an escrow transaction that escrows 200 tokens on your own entity."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},'The Oasis node\'s staking application calls the operation of staking tokens "escrow."')),(0,o.kt)("p",null,"Before generating the escrow transaction, you need to set the following environment variables:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"GENESIS_FILE_PATH"),": Path to the Genesis file on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),", i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/genesis.json"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"ENTITY_DIR_PATH"),": Path to entity's artifacts directory on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),","),(0,o.kt)("p",{parentName:"li"},"i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity/"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"OUTPUT_TX_FILE_PATH"),": Path to the file containing the outputted signed transaction."),(0,o.kt)("p",{parentName:"li"},"For this guide, we will use ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/signed-escrow.tx"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"ACCOUNT_ADDRESS"),": Your staking account address."),(0,o.kt)("p",{parentName:"li"},"To obtain your staking account address from your Entity's ID, see ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#from-public-key"},"Obtaining Account Address From Entity's ID"),"."))),(0,o.kt)("p",null,"Then execute the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node stake account gen_escrow \\\n --genesis.file $GENESIS_FILE_PATH \\\n --signer.backend file \\\n --signer.dir $ENTITY_DIR_PATH \\\n --stake.escrow.account $ACCOUNT_ADDRESS \\\n --stake.amount 200000000000 \\\n --transaction.file $OUTPUT_TX_FILE_PATH \\\n --transaction.fee.gas 2269 \\\n --transaction.fee.amount 2000 \\\n --transaction.nonce 0\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The option ",(0,o.kt)("inlineCode",{parentName:"p"},"--stake.amount")," looks like a very large number, but this is actually just an equivalent to 200 tokens on the Oasis consensus layer as each unit value used to track the account balance is 1x10^-9 tokens."),(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--transactions.fee.gas")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"--transaction.fee.amount")," options depend on the network configuration, see ",(0,o.kt)("a",{parentName:"p",href:"/core/oasis-node/cli#common-transaction-flags"},"Common Transaction Flags")," for details.")),(0,o.kt)("h3",{id:"generating-entity-registration-transaction"},"Generating Entity Registration Transaction"),(0,o.kt)("p",null,"Before you can run your node successfully, you'll need to register your entity so that your node registers properly. You could do this process ",(0,o.kt)("em",{parentName:"p"},"after")," you submit the escrow transaction, however, to save steps we prepare everything before hand."),(0,o.kt)("p",null,"Before generating the register transaction, you need to set the following environment variables:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"GENESIS_FILE_PATH"),": Path to the Genesis file on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),", i.e."),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/genesis.json"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"ENTITY_DIR_PATH"),": Path to entity's artifacts directory on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost"),","),(0,o.kt)("p",{parentName:"li"},"i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/entity/"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"OUTPUT_REGISTER_TX_FILE_PATH"),": Path to the file containing the outputted signed transaction."),(0,o.kt)("p",{parentName:"li"},"For this guide, we will use ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/signed-register.tx"),"."))),(0,o.kt)("p",null,"Then execute the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry entity gen_register \\\n --genesis.file $GENESIS_FILE_PATH \\\n --signer.backend file \\\n --signer.dir $ENTITY_DIR_PATH \\\n --transaction.file $OUTPUT_REGISTER_TX_FILE_PATH \\\n --transaction.fee.gas 2460 \\\n --transaction.fee.amount 1000 \\\n --transaction.nonce 1\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--transactions.fee.gas")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"--transaction.fee.amount")," options depend on the network configuration, see ",(0,o.kt)("a",{parentName:"p",href:"/core/oasis-node/cli#common-transaction-flags"},"Common Transaction Flags")," for details.")),(0,o.kt)("h3",{id:"submitting-your-transactions-on-the-server"},"Submitting Your Transactions on the ",(0,o.kt)("inlineCode",{parentName:"h3"},"server")),(0,o.kt)("p",null,"To complete the staking process we need to copy the generated escrow and registry transactions from your offline ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost")," to the ",(0,o.kt)("inlineCode",{parentName:"p"},"server")," and submit them."),(0,o.kt)("p",null,"To do so, follow these steps:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Copy the file ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/signed-escrow.tx")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost")," to"),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/signed-escrow.tx")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Copy the file ",(0,o.kt)("inlineCode",{parentName:"p"},"/localhostdir/signed-register.tx")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"localhost")," to"),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/signed-register.tx")," on the ",(0,o.kt)("inlineCode",{parentName:"p"},"server"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Submit both transactions via ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node consensus submit_tx")," sub-command:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node consensus submit_tx \\\n --transaction.file /serverdir/signed-escrow.tx \\\n -a unix:/serverdir/node/internal.sock\noasis-node consensus submit_tx \\\n --transaction.file /serverdir/signed-register.tx \\\n -a unix:/serverdir/node/internal.sock\n")))),(0,o.kt)("h3",{id:"checking-that-your-node-is-properly-registered"},"Checking that Your Node is Properly Registered"),(0,o.kt)("p",null,"To ensure that your node is properly connected as a validator on the network, you can run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/serverdir/node/internal.sock\n")),(0,o.kt)("p",null,"If your node is registered and a validator, the above command should output (some fields omitted for clarity):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-javascript"},'{\n "software_version": "20.10",\n "identity": {\n ...\n },\n "consensus": {\n "consensus_version": "1.0.0",\n "backend": "tendermint",\n "features": 3,\n "node_peers": [\n ...\n ],\n "latest_height": 55899,\n "latest_hash": "AR34gxwWz1LS5rMDa6E0L1/ThW9E38ySIbRRlRG/shg=",\n "latest_time": "2020-08-10T11:38:26+02:00",\n "latest_state_root": {\n "ns": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "version": 55898,\n "hash": "h2+8ZryxseOKpuSho1nVSImLF/irVsTF5xryc3I9cRk="\n },\n "genesis_height": 1,\n "genesis_hash": "+SIAMCUeZtWuYPg/Ke+zwPRhNRripRgUq1d5Al9ImNA=",\n "is_validator": true\n },\n "registration": {\n ...\n }\n}\n')),(0,o.kt)("p",null,"Pay attention to the ",(0,o.kt)("inlineCode",{parentName:"p"},"is_validator")," field which should have the value of ",(0,o.kt)("inlineCode",{parentName:"p"},"true"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Nodes are only elected into the validator set at epoch transitions, so you may need to wait for up to an epoch before being considered.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Note that in order to be elected in the validator set you need to have enough stake to be in the top K entities (where K is a network-specific parameter specified by the ",(0,o.kt)("inlineCode",{parentName:"p"},"scheduler.max_validators")," field in the genesis document).")),(0,o.kt)("p",null,"Congratulations, if you made it this far, you've properly connected your node\nto the network and became a validator on the Oasis Network."),(0,o.kt)("h2",{id:"oasis-metadata-registry"},"Oasis Metadata Registry"),(0,o.kt)("p",null,"For the final touch, you can add some metadata about your entity to the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/metadata-registry"},"Metadata Registry"),". The Metadata Registry is the same for the Mainnet and\nthe Testnet. The metadata consists of your entity name, email, Keybase handle,\nTwitter handle, etc. This information is also used by third party applications.\nFor example ",(0,o.kt)("a",{parentName:"p",href:"https://www.oasisscan.com/validators"},"Oasis Scan")," fetches your image from Keybase and uses it as the node\noperator's avatar."),(0,o.kt)("h1",{id:"see-also"},"See also"),(0,o.kt)(a.Z,{item:(0,r.n)("/core/oasis-node/cli"),mdxType:"DocCard"}),(0,o.kt)(a.Z,{item:(0,r.n)("/general/manage-tokens/cli/"),mdxType:"DocCard"}))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7b1f3817.31e1bfa3.js b/assets/js/7b1f3817.31e1bfa3.js new file mode 100644 index 0000000000..a5d629421a --- /dev/null +++ b/assets/js/7b1f3817.31e1bfa3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8713],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>c});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},i=Object.keys(e);for(a=0;a<i.length;a++)n=i[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a<i.length;a++)n=i[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),s=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},d=function(e){var t=s(e.components);return a.createElement(p.Provider,{value:t},e.children)},m="mdxType",k={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),m=s(n),u=r,c=m["".concat(p,".").concat(u)]||m[u]||k[u]||i;return n?a.createElement(c,o(o({ref:t},d),{},{components:n})):a.createElement(c,o({ref:t},d))}));function c(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l[m]="string"==typeof e?e:r,o[1]=l;for(var s=2;s<i;s++)o[s]=n[s];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}u.displayName="MDXCreateElement"},3286:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>k,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const i={},o="ADR 0002: Go Modules Compatible Git Tags",l={unversionedId:"adrs/0002-go-modules-compatible-git-tags",id:"adrs/0002-go-modules-compatible-git-tags",title:"ADR 0002: Go Modules Compatible Git Tags",description:"Component",source:"@site/docs/adrs/0002-go-modules-compatible-git-tags.md",sourceDirName:"adrs",slug:"/adrs/0002-go-modules-compatible-git-tags",permalink:"/adrs/0002-go-modules-compatible-git-tags",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0002-go-modules-compatible-git-tags.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0001: Multiple Roots Under the Tendermint Application Hash",permalink:"/adrs/0001-tm-multi-root-apphash"},next:{title:"ADR 0003: Consensus/Runtime Token Transfer",permalink:"/adrs/0003-consensus-runtime-token-transfer"}},p={},s=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Alternatives",id:"alternatives",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}],d={toc:s},m="wrapper";function k(e){let{components:t,...n}=e;return(0,r.kt)(m,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"adr-0002-go-modules-compatible-git-tags"},"ADR 0002: Go Modules Compatible Git Tags"),(0,r.kt)("h2",{id:"component"},"Component"),(0,r.kt)("p",null,"Oasis Core"),(0,r.kt)("h2",{id:"changelog"},"Changelog"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2020-09-04: Initial version")),(0,r.kt)("h2",{id:"status"},"Status"),(0,r.kt)("p",null,"Accepted"),(0,r.kt)("h2",{id:"context"},"Context"),(0,r.kt)("p",null,"Projects that depend on ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/mod/github.com/oasisprotocol/oasis-core/go"},"Oasis Core's Go module"),", i.e.\n",(0,r.kt)("inlineCode",{parentName:"p"},"github.com/oasisprotocol/oasis-core/go"),", need a way to depend on its particular\nversion."),(0,r.kt)("p",null,"Go Modules only allow ",(0,r.kt)("a",{parentName:"p",href:"https://semver.org/spec/v2.0.0.html"},"Semantic Versioning 2.0.0")," for\n",(0,r.kt)("a",{parentName:"p",href:"https://golang.org/ref/mod#versions"},"versioning of the modules")," which makes it hard to work\nwith ",(0,r.kt)("a",{parentName:"p",href:"/core/versioning"},"Oasis Core's CalVer (calendar versioning) scheme"),"."),(0,r.kt)("p",null,"The currently used scheme for Go Modules compatible Git tags is:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"go/v0.YY.MINOR[.MICRO]\n")),(0,r.kt)("p",null,"where:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"YY")," represents the short year (e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"19"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"20"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"21"),", ...),")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"MINOR")," represents the minor version starting with zero (e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"2"),",\n",(0,r.kt)("inlineCode",{parentName:"p"},"3"),", ...),")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"MICRO"),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,r.kt)("inlineCode",{parentName:"p"},"0"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"2"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"3"),", ...)."),(0,r.kt)("p",{parentName:"li"},"If the ",(0,r.kt)("inlineCode",{parentName:"p"},"MICRO")," version is ",(0,r.kt)("inlineCode",{parentName:"p"},"0"),", it is omitted."))),(0,r.kt)("p",null,"It turns out this only works for Oasis Core versions with the ",(0,r.kt)("inlineCode",{parentName:"p"},"MICRO")," version\nof ",(0,r.kt)("inlineCode",{parentName:"p"},"0")," since the Go Modules compatible Git tag omits the ",(0,r.kt)("inlineCode",{parentName:"p"},".MICRO")," part and is\nthus compatible with ",(0,r.kt)("a",{parentName:"p",href:"https://golang.org/ref/mod#versions"},"Go Modules versioning requirements"),"."),(0,r.kt)("h2",{id:"decision"},"Decision"),(0,r.kt)("p",null,"The proposed design is to tag Oasis Core releases with the following Go Modules\ncompatible Git tags (in addition to the ordinary Git tags):"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"go/v0.YY0MINOR.MICRO\n")),(0,r.kt)("p",null,"where:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"YY")," represents the short year (e.g. ",(0,r.kt)("inlineCode",{parentName:"li"},"19"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"20"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"21"),", ...),"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"0MINOR")," represents the zero-padded minor version starting with zero (e.g.\n",(0,r.kt)("inlineCode",{parentName:"li"},"00"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"01"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"02"),", ..., ",(0,r.kt)("inlineCode",{parentName:"li"},"10"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"11"),", ...),"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"MICRO"),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,r.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"2"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"3"),", ...).")),(0,r.kt)("p",null,"Here are some examples of how the ordinary and the corresponding Go Modules\ncompatible Git tags would look like:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:"center"},"Version"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Ordinary Git tag"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Go Modules compatible Git tag"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.9"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.9")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2009.0"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.9.1"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.9.1")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2009.1"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.9.2"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.9.2")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2009.2"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.10"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.10")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2010.0"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.10.1"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.10.1")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2010.1"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"20.10.2"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v20.10.2")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2010.2"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"..."),(0,r.kt)("td",{parentName:"tr",align:"center"},"..."),(0,r.kt)("td",{parentName:"tr",align:"center"},"...")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.0"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.0")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2100.0"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.0.1"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.0.1")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2100.1"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.0.2"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.0.2")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2100.2"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.1"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.1")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2101.0"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.1.1"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.1.1")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2101.1"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"21.1.2"),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"v21.1.2")),(0,r.kt)("td",{parentName:"tr",align:"center"},(0,r.kt)("inlineCode",{parentName:"td"},"go/v0.2101.2"))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"..."),(0,r.kt)("td",{parentName:"tr",align:"center"},"..."),(0,r.kt)("td",{parentName:"tr",align:"center"},"...")))),(0,r.kt)("p",null,"Using such a scheme makes the version of the Oasis Core Go module fully\ncompatible with the ",(0,r.kt)("a",{parentName:"p",href:"https://golang.org/ref/mod#versions"},"Go Modules versioning requirements")," and thus\nenables users to use the familiar Go tools to check for new module versions,\ni.e. ",(0,r.kt)("inlineCode",{parentName:"p"},"go list -m -u all"),", or to obtain and require a module, i.e.\n",(0,r.kt)("inlineCode",{parentName:"p"},"go get github.com/oasisprotocol/oasis-core/go@latest"),"."),(0,r.kt)("h2",{id:"alternatives"},"Alternatives"),(0,r.kt)("p",null,"An alternative scheme would be to use the following Go Modules compatible Git\ntags:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"go/v0.YY.MINOR-MICRO\n")),(0,r.kt)("p",null,"where:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"YY")," represents the short year (e.g. ",(0,r.kt)("inlineCode",{parentName:"li"},"19"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"20"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"21"),", ...),"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"MINOR")," represents the minor version starting with zero (e.g. ",(0,r.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"2"),",\n",(0,r.kt)("inlineCode",{parentName:"li"},"3"),", ...),"),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"MICRO"),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,r.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"2"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"3"),", ...).")),(0,r.kt)("p",null,"Using the ",(0,r.kt)("inlineCode",{parentName:"p"},"-MICRO")," suffix would make Go treat all such versions as a\n",(0,r.kt)("a",{parentName:"p",href:"https://golang.org/ref/mod#glos-pre-release-version"},"Go Modules pre-release version"),"."),(0,r.kt)("p",null,"The consequence of that would be that all Go tools would treat such versions as\npre-releases."),(0,r.kt)("p",null,"For example, let's say the Oasis Core Go module would have the following Go\nversion tags:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"go/v0.20.9")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"go/v0.20.10-0")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"go/v0.20.10-1"))),(0,r.kt)("p",null,"and a module that depends on the Oasis Core Go module would currently require\nversion ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.20.9"),"."),(0,r.kt)("p",null,"One downside would be that the ",(0,r.kt)("inlineCode",{parentName:"p"},"go list -m -u all")," command would not notify a\nuser that an update, i.e. version ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.20.10-1"),", is available."),(0,r.kt)("p",null,"The second downside would be that using the\n",(0,r.kt)("inlineCode",{parentName:"p"},"go get github.com/oasisprotocol/oasis-core/go@latest")," command would treat\nversion ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.20.9")," as the latest version and download and require this version of\nthe Oasis Core Go module instead of the real latest version, ",(0,r.kt)("inlineCode",{parentName:"p"},"v0.20.10-1")," in\nthis example."),(0,r.kt)("h2",{id:"consequences"},"Consequences"),(0,r.kt)("h3",{id:"positive"},"Positive"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"This allow users to depend on a bugfix/patch release of the Oasis Core Go\nmodule in a ",(0,r.kt)("a",{parentName:"li",href:"https://golang.org/ref/mod#versions"},"Go Modules versioning requirements")," compatible way,\ni.e. without having to resort to pinning the requirement to a particular\nOasis Core commit.")),(0,r.kt)("h3",{id:"negative"},"Negative"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The connection between an ordinary Git tag and a Go Modules compatible Git tag\nis not very obvious."),(0,r.kt)("p",{parentName:"li"},"For example, it might not be immediately obvious that ",(0,r.kt)("inlineCode",{parentName:"p"},"v21.0")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"go/v0.2100.0")," refer to the same thing.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Using a zero-padded minor version fixed to two characters would limit the\nnumber of releases in a year to 100 releases."))),(0,r.kt)("h2",{id:"references"},"References"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://github.com/dgraph-io/badger"},"BadgerDB")," uses a ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/dgraph-io/badger/releases"},"similar scheme for tagging Go Modules compatible Git tags"),"\nfor their CalVer versioning scheme.")))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7bee5ea1.4271d180.js b/assets/js/7bee5ea1.4271d180.js new file mode 100644 index 0000000000..6e23d3b75c --- /dev/null +++ b/assets/js/7bee5ea1.4271d180.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3154],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},r=Object.keys(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=o.createContext({}),c=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=c(e.components);return o.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},g=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=c(n),g=a,m=d["".concat(l,".").concat(g)]||d[g]||u[g]||r;return n?o.createElement(m,s(s({ref:t},p),{},{components:n})):o.createElement(m,s({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,s=new Array(r);s[0]=g;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[d]="string"==typeof e?e:a,s[1]=i;for(var c=2;c<r;c++)s[c]=n[c];return o.createElement.apply(null,s)}return o.createElement.apply(null,n)}g.displayName="MDXCreateElement"},8616:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var o=n(7462),a=(n(7294),n(3905));const r={},s="Terminology",i={unversionedId:"general/manage-tokens/terminology",id:"general/manage-tokens/terminology",title:"Terminology",description:"Account",source:"@site/docs/general/manage-tokens/terminology.md",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/terminology",permalink:"/general/manage-tokens/terminology",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/terminology.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Overview",permalink:"/general/manage-tokens/"},next:{title:"Staking and Delegating",permalink:"/general/manage-tokens/staking-and-delegating"}},l={},c=[{value:"Account",id:"account",level:2},{value:"Address",id:"address",level:2},{value:"Delegation",id:"delegation",level:2},{value:"Staking",id:"staking",level:2},{value:"Rewards",id:"rewards",level:2},{value:"Commission",id:"commission",level:2},{value:"Slashing",id:"slashing",level:2}],p={toc:c},d="wrapper";function u(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"terminology"},"Terminology"),(0,a.kt)("h2",{id:"account"},"Account"),(0,a.kt)("p",null,"A staking ",(0,a.kt)("strong",{parentName:"p"},"account")," is an entry in the staking ledger."),(0,a.kt)("p",null,"It has two (sub)accounts:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"General account")),(0,a.kt)("p",{parentName:"li"},"It is used to keep the funds that are freely available to the account owner\nto transfer, delegate/stake, pay gas fees, etc.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Escrow account")),(0,a.kt)("p",{parentName:"li"},"It is used to keep the funds needed for specific consensus-layer operations\n(e.g. registering and running nodes, staking and delegation of tokens, ...)."),(0,a.kt)("p",{parentName:"li"},"To simplify accounting, each escrow results in the source account being\nissued shares which can be converted back into staking tokens during the\nreclaim escrow operation. Reclaiming escrow does not complete immediately,\nbut may be subject to a debonding period during which the tokens still remain\nescrowed."))),(0,a.kt)("h2",{id:"address"},"Address"),(0,a.kt)("p",null,"A staking account ",(0,a.kt)("strong",{parentName:"p"},"address")," is represented by a truncated hash of a\ncorresponding entity's public key, prefixed by a 1 byte address version."),(0,a.kt)("p",null,"It uses ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32"},"Bech32 encoding")," for text serialization with ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis")," as its human\nreadable part (HRP) prefix."),(0,a.kt)("h2",{id:"delegation"},"Delegation"),(0,a.kt)("p",null,"You can ",(0,a.kt)("strong",{parentName:"p"},"delegate")," your tokens by submitting an ",(0,a.kt)("strong",{parentName:"p"},"escrow")," transaction that\ndeposits a specific number of tokens into someone else\u2019s escrow account (as\nopposed to ",(0,a.kt)("strong",{parentName:"p"},"staking")," tokens, which usually refers to depositing tokens into\nyour own escrow account)."),(0,a.kt)("p",null,"In other words, delegating your tokens is equivalent to staking your tokens in\nsomeone else's validator node. Delegating your tokens can give you the\nopportunity to participate in the Oasis Network's proof-of-stake consensus\nsystem and earn rewards via someone else's validator node."),(0,a.kt)("h2",{id:"staking"},"Staking"),(0,a.kt)("p",null,"You can stake your tokens by submitting an ",(0,a.kt)("strong",{parentName:"p"},"escrow")," transaction that deposits\na specific number of tokens into your escrow account."),(0,a.kt)("h2",{id:"rewards"},"Rewards"),(0,a.kt)("p",null,"By delegating your tokens to someone else's node, you can earn a portion of the\nrewards earned by that node through its participation in the Oasis Network."),(0,a.kt)("h2",{id:"commission"},"Commission"),(0,a.kt)("p",null,"Node operators collect ",(0,a.kt)("strong",{parentName:"p"},"commissions")," when their node earns a\n",(0,a.kt)("strong",{parentName:"p"},"staking reward")," for delegators. A validator node earns a staking reward for\nparticipating in the consensus protocol each epoch. The ",(0,a.kt)("strong",{parentName:"p"},"commission rate")," is\na fraction of the staking reward."),(0,a.kt)("p",null,"For example, if our validator node earns a reward of 0.007 tokens, 0.0035\ntokens are added to the escrow pool (increasing the value of our escrow pool\nshares uniformly), and 0.0035 tokens are given to us (issuing us new shares as\nif we manually deposited them)."),(0,a.kt)("h2",{id:"slashing"},"Slashing"),(0,a.kt)("p",null,"A portion of your delegated tokens can be ",(0,a.kt)("strong",{parentName:"p"},"slashed")," (seized) by the network,\nif the node that you delegated your tokens to gets slashed, e.g. as a penalty\nfor equivocating in the protocol by signing diverging blocks for the same\nheight."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7ca72da4.e6358fdb.js b/assets/js/7ca72da4.e6358fdb.js new file mode 100644 index 0000000000..f78bef50bf --- /dev/null +++ b/assets/js/7ca72da4.e6358fdb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9634],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),p=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},l="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),l=p(r),f=i,g=l["".concat(s,".").concat(f)]||l[f]||d[f]||o;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=r.length,a=new Array(o);a[0]=f;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c[l]="string"==typeof e?e:i,a[1]=c;for(var p=2;p<o;p++)a[p]=r[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},3652:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>p});var n=r(7462),i=(r(7294),r(3905));const o={},a="Big Integer Quantities",c={unversionedId:"core/bigint",id:"core/bigint",title:"Big Integer Quantities",description:"Arbitrary-precision positive integer quantities are represented by the",source:"@site/docs/core/bigint.md",sourceDirName:"core",slug:"/core/bigint",permalink:"/core/bigint",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/bigint.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{}},s={},p=[{value:"Encoding",id:"encoding",level:2}],u={toc:p},l="wrapper";function d(e){let{components:t,...r}=e;return(0,i.kt)(l,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"big-integer-quantities"},"Big Integer Quantities"),(0,i.kt)("p",null,"Arbitrary-precision positive integer quantities are represented by the\n",(0,i.kt)("inlineCode",{parentName:"p"},"quantity.Quantity")," type."),(0,i.kt)("h2",{id:"encoding"},"Encoding"),(0,i.kt)("p",null,"When encoded it uses the big-endian byte order."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/7da689db.2c312011.js b/assets/js/7da689db.2c312011.js new file mode 100644 index 0000000000..b7ed912024 --- /dev/null +++ b/assets/js/7da689db.2c312011.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[36],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>h});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function i(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?o(Object(a),!0).forEach((function(t){n(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):o(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function l(e,t){if(null==e)return{};var a,r,n=function(e,t){if(null==e)return{};var a,r,n={},o=Object.keys(e);for(r=0;r<o.length;r++)a=o[r],t.indexOf(a)>=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)a=o[r],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var s=r.createContext({}),u=function(e){var t=r.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},d=function(e){var t=u(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},c=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=u(a),c=n,h=p["".concat(s,".").concat(c)]||p[c]||m[c]||o;return a?r.createElement(h,i(i({ref:t},d),{},{components:a})):r.createElement(h,i({ref:t},d))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,i=new Array(o);i[0]=c;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:n,i[1]=l;for(var u=2;u<o;u++)i[u]=a[u];return r.createElement.apply(null,i)}return r.createElement.apply(null,a)}c.displayName="MDXCreateElement"},5162:(e,t,a)=>{a.d(t,{Z:()=>i});var r=a(7294),n=a(6010);const o={tabItem:"tabItem_Ymn6"};function i(e){let{children:t,hidden:a,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,n.Z)(o.tabItem,i),hidden:a},t)}},4866:(e,t,a)=>{a.d(t,{Z:()=>N});var r=a(7462),n=a(7294),o=a(6010),i=a(2466),l=a(6550),s=a(1980),u=a(7392),d=a(12);function p(e){return function(e){return n.Children.map(e,(e=>{if(!e||(0,n.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return e;throw new Error(`Docusaurus error: Bad <Tabs> child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:t,label:a,attributes:r,default:n}}=e;return{value:t,label:a,attributes:r,default:n}}))}function m(e){const{values:t,children:a}=e;return(0,n.useMemo)((()=>{const e=t??p(a);return function(e){const t=(0,u.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[t,a])}function c(e){let{value:t,tabValues:a}=e;return a.some((e=>e.value===t))}function h(e){let{queryString:t=!1,groupId:a}=e;const r=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:a}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!a)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return a??null}({queryString:t,groupId:a});return[(0,s._X)(o),(0,n.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function v(e){const{defaultValue:t,queryString:a=!1,groupId:r}=e,o=m(e),[i,l]=(0,n.useState)((()=>function(e){let{defaultValue:t,tabValues:a}=e;if(0===a.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(t){if(!c({value:t,tabValues:a}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${a.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=a.find((e=>e.default))??a[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[s,u]=h({queryString:a,groupId:r}),[p,v]=function(e){let{groupId:t}=e;const a=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,d.Nk)(a);return[r,(0,n.useCallback)((e=>{a&&o.set(e)}),[a,o])]}({groupId:r}),f=(()=>{const e=s??p;return c({value:e,tabValues:o})?e:null})();(0,n.useLayoutEffect)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,n.useCallback)((e=>{if(!c({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),u(e),v(e)}),[u,v,o]),tabValues:o}}var f=a(2389);const k={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function b(e){let{className:t,block:a,selectedValue:l,selectValue:s,tabValues:u}=e;const d=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,a=d.indexOf(t),r=u[a].value;r!==l&&(p(t),s(r))},c=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const a=d.indexOf(e.currentTarget)+1;t=d[a]??d[0];break}case"ArrowLeft":{const a=d.indexOf(e.currentTarget)-1;t=d[a]??d[d.length-1];break}}t?.focus()};return n.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":a},t)},u.map((e=>{let{value:t,label:a,attributes:i}=e;return n.createElement("li",(0,r.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>d.push(e),onKeyDown:c,onClick:m},i,{className:(0,o.Z)("tabs__item",k.tabItem,i?.className,{"tabs__item--active":l===t})}),a??t)})))}function g(e){let{lazy:t,children:a,selectedValue:r}=e;const o=(Array.isArray(a)?a:[a]).filter(Boolean);if(t){const e=o.find((e=>e.props.value===r));return e?(0,n.cloneElement)(e,{className:"margin-top--md"}):null}return n.createElement("div",{className:"margin-top--md"},o.map(((e,t)=>(0,n.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function y(e){const t=v(e);return n.createElement("div",{className:(0,o.Z)("tabs-container",k.tabList)},n.createElement(b,(0,r.Z)({},e,t)),n.createElement(g,(0,r.Z)({},e,t)))}function N(e){const t=(0,f.Z)();return n.createElement(y,(0,r.Z)({key:String(t)},e))}},9231:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>u,toc:()=>p});var r=a(7462),n=(a(7294),a(3905)),o=a(4866),i=a(5162);const l={},s="ParaTime Node",u={unversionedId:"get-involved/run-node/paratime-node",id:"get-involved/run-node/paratime-node",title:"ParaTime Node",description:"This guide provides an overview of the requirements to become a compute node for",source:"@site/docs/get-involved/run-node/paratime-node.mdx",sourceDirName:"get-involved/run-node",slug:"/get-involved/run-node/paratime-node",permalink:"/get-involved/run-node/paratime-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/run-node/paratime-node.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"Consensus Validator Node",permalink:"/get-involved/run-node/validator-node"},next:{title:"Develop Oasis Core",permalink:"/get-involved/oasis-core"}},d={},p=[{value:"About Oasis Network",id:"about-oasis-network",level:2},{value:"Operating ParaTimes",id:"operating-paratimes",level:2},{value:"Cipher ParaTime",id:"cipher-paratime",level:3},{value:"Overview",id:"overview",level:3},{value:"Features",id:"features",level:3},{value:"Mainnet Requirements",id:"mainnet-requirements",level:3},{value:"Rewards",id:"rewards",level:3},{value:"Emerald ParaTime",id:"emerald-paratime",level:3},{value:"Overview",id:"overview-1",level:3},{value:"Features",id:"features-1",level:3},{value:"Mainnet Requirements",id:"mainnet-requirements-1",level:3}],m={toc:p},c="wrapper";function h(e){let{components:t,...l}=e;return(0,n.kt)(c,(0,r.Z)({},m,l,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"paratime-node"},"ParaTime Node"),(0,n.kt)("p",null,"This guide provides an overview of the requirements to become a compute node for\na ParaTime connected to the Oasis Network."),(0,n.kt)("h2",{id:"about-oasis-network"},"About Oasis Network"),(0,n.kt)("p",null,"The Oasis Network has two main components, the consensus layer and the ParaTime\nLayer."),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"consensus layer")," is a scalable, high-throughput, secure,\nproof-of-stake consensus run by a decentralized set of validator nodes."),(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"ParaTime layer")," hosts many parallel runtimes (ParaTimes), each\nrepresenting a replicated compute environment with shared state.")),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Oasis architectural design including ParaTime and consensus layers",src:a(4128).Z,width:"1523",height:"718"})),(0,n.kt)("h2",{id:"operating-paratimes"},"Operating ParaTimes"),(0,n.kt)("p",null,"Operating a ParaTime requires the participation of node operators who\ncontribute nodes to the committee in exchange for rewards.\nParaTimes can be operated by anyone, and have their own reward system,\nparticipation requirements, and structure."),(0,n.kt)("p",null,"As a node operator you can participate in any number of ParaTimes.\nWhile there are a number of ParaTimes under development, below are a few key\nParaTimes that you can get involved in today.\nFor operational documentation on running a ParaTime, please see the section on\n",(0,n.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"running a ParaTime node for node operators"),"."),(0,n.kt)(o.Z,{mdxType:"Tabs"},(0,n.kt)(i.Z,{value:"Cipher ParaTime",mdxType:"TabItem"},(0,n.kt)("h3",{id:"cipher-paratime"},"Cipher ParaTime"),(0,n.kt)("p",null,"An Oasis Foundation developed ParaTime that will enable WebAssembly-based\nconfidential smart contracts."),(0,n.kt)("h3",{id:"overview"},"Overview"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Leading Developer:")," ",(0,n.kt)("a",{parentName:"li",href:"http://oasisprotocol.org"},"Oasis Protocol Foundation")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Status:")," Deployed on Mainnet and Testnet"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Testnet Launch Date:")," June 2021"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Mainnet Launch Date:")," October 2021"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Discord Channel:")," ",(0,n.kt)("a",{parentName:"li",href:"/get-involved/"},"#cipher-paratime")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Requires SGX"),": Yes"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Parameters:"),(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/node/mainnet/#cipher-paratime"},"Mainnet")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/node/testnet/#cipher-paratime"},"Testnet"))))),(0,n.kt)("h3",{id:"features"},"Features"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Fully decentralized with node operators distributed across the world."),(0,n.kt)("li",{parentName:"ul"},"Oasis ",(0,n.kt)("strong",{parentName:"li"},"ROSE")," tokens are the native token used in the ParaTime for gas fees."),(0,n.kt)("li",{parentName:"ul"},"Support for WebAssembly smart contracts."),(0,n.kt)("li",{parentName:"ul"},"Support for confidential compute.")),(0,n.kt)("h3",{id:"mainnet-requirements"},"Mainnet Requirements"),(0,n.kt)("p",null,"For your Cipher ParaTime node to be eligible to be elected into the Cipher\ncommittee on Mainnet, your entity needs to:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Have a validator in the ",(0,n.kt)("strong",{parentName:"li"},"validator set"),".")),(0,n.kt)("h3",{id:"rewards"},"Rewards"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"The ParaTime will release tokens on-chain to reward nodes for participation."),(0,n.kt)("li",{parentName:"ul"},"The reward program is 2 years long, and tokens will be released per epoch."),(0,n.kt)("li",{parentName:"ul"},"The reward will be 10","~","20 ROSE tokens per entity per epoch, where the Oasis\nProtocol Foundation will make the final decision on the reward size upon th\nCipher's Mainnet launch."),(0,n.kt)("li",{parentName:"ul"},"Incentivized Testnet with ROSE tokens delegated by the Oasis Protocol\nFoundation to Testnet participants based on performance (rewards can be found\n",(0,n.kt)("a",{parentName:"li",href:"https://oasis-foundation.medium.com/oasis-cipher-paratime-c9f40ae64946"},"here"),")."))),(0,n.kt)(i.Z,{value:"Emerald ParaTime",mdxType:"TabItem"},(0,n.kt)("h3",{id:"emerald-paratime"},"Emerald ParaTime"),(0,n.kt)("p",null,"An EVM-compatible Oasis Foundation developed ParaTime that enables the use of\nEVM smart contracts on the Oasis network."),(0,n.kt)("h3",{id:"overview-1"},"Overview"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Leading Developer:")," ",(0,n.kt)("a",{parentName:"li",href:"http://oasisprotocol.org"},"Oasis Protocol Foundation"),", with contributions from\ncommunity developers"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Status:")," Deployed on Mainnet and Testnet"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Testnet Launch Date:")," October 2021"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Mainnet Launch Date:")," November 2021"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Discord Channel:")," ",(0,n.kt)("a",{parentName:"li",href:"/get-involved/"},"#emerald-paratime")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Requires SGX:")," No"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Parameters:"),(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/node/mainnet/#emerald-paratime"},"Mainnet")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/node/testnet/#emerald-paratime"},"Testnet"))))),(0,n.kt)("h3",{id:"features-1"},"Features"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Fully decentralized with node operators distributed across the world."),(0,n.kt)("li",{parentName:"ul"},"Oasis ",(0,n.kt)("strong",{parentName:"li"},"ROSE")," tokens are the native token used in the ParaTime for gas fees.")),(0,n.kt)("h3",{id:"mainnet-requirements-1"},"Mainnet Requirements"),(0,n.kt)("p",null,"For your Emerald ParaTime node to be eligible to be elected into the Emerald\ncommittee on Mainnet, your entity needs to:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Have a validator in the ",(0,n.kt)("strong",{parentName:"li"},"validator set"),"."),(0,n.kt)("li",{parentName:"ul"},"Have at least ",(0,n.kt)("strong",{parentName:"li"},"5,000,000.00 ROSE staked/delegated")," to it.")))))}h.isMDXComponent=!0},4128:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"}}]); \ No newline at end of file diff --git a/assets/js/7f0ce295.5c887430.js b/assets/js/7f0ce295.5c887430.js new file mode 100644 index 0000000000..5e9c2b0d00 --- /dev/null +++ b/assets/js/7f0ce295.5c887430.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[766],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,r,i=function(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),d=p(n),u=i,g=d["".concat(s,".").concat(u)]||d[u]||m[u]||a;return n?r.createElement(g,o(o({ref:t},c),{},{components:n})):r.createElement(g,o({ref:t},c))}));function g(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,o=new Array(a);o[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[d]="string"==typeof e?e:i,o[1]=l;for(var p=2;p<a;p++)o[p]=n[p];return r.createElement.apply(null,o)}return r.createElement.apply(null,n)}u.displayName="MDXCreateElement"},6134:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>m,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var r=n(7462),i=(n(7294),n(3905));const a={},o="Versioning",l={unversionedId:"oasis-core-ledger/versioning",id:"oasis-core-ledger/versioning",title:"Versioning",description:"Oasis Core Ledger uses [Semantic Versioning 2.0.0] with the following format:",source:"@site/docs/oasis-core-ledger/versioning.md",sourceDirName:"oasis-core-ledger",slug:"/oasis-core-ledger/versioning",permalink:"/oasis-core-ledger/versioning",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/versioning.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Identifying Wallets",permalink:"/oasis-core-ledger/usage/wallets"},next:{title:"Release Process",permalink:"/oasis-core-ledger/release-process"}},s={},p=[],c={toc:p},d="wrapper";function m(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"versioning"},"Versioning"),(0,i.kt)("p",null,"Oasis Core Ledger uses ",(0,i.kt)("a",{parentName:"p",href:"https://semver.org/spec/v2.0.0.html"},"Semantic Versioning 2.0.0")," with the following format:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-text"},"MAJOR.MINOR.PATCH[-MODIFIER]\n")),(0,i.kt)("p",null,"where:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MAJOR")," represents the major version starting with zero (e.g. ",(0,i.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"2"),",\n",(0,i.kt)("inlineCode",{parentName:"li"},"3"),", ...),"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MINOR")," represents the minor version starting with zero (e.g. ",(0,i.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"2"),",\n",(0,i.kt)("inlineCode",{parentName:"li"},"3"),", ...),"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"PATCH"),' represents the final number in the version (sometimes referred\nto as the "micro" segment) (e.g. ',(0,i.kt)("inlineCode",{parentName:"li"},"0"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"1"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"2"),", ",(0,i.kt)("inlineCode",{parentName:"li"},"3"),", ...)."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"MODIFIER")," represents (optional) build metadata, e.g. ",(0,i.kt)("inlineCode",{parentName:"li"},"git8c01382"),".")),(0,i.kt)("p",null,"When a backwards incompatible release is made, the ",(0,i.kt)("inlineCode",{parentName:"p"},"MAJOR")," version should be\nbumped."),(0,i.kt)("p",null,"When a regularly scheduled release is made, the ",(0,i.kt)("inlineCode",{parentName:"p"},"MINOR")," version should be\nbumped."),(0,i.kt)("p",null,"If there are fixes and (backwards compatible) changes that we want to back-port\nfrom an upcoming release, then the ",(0,i.kt)("inlineCode",{parentName:"p"},"PATCH")," version should be bumped."),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"MODIFIER")," should be used to denote a build from an untagged (and\npotentially unclean) git source. It should be of the form:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-text"},"gitCOMMIT_SHA[+dirty]\n")),(0,i.kt)("p",null,"where:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"COMMIT_SHA")," represents the current commit\u2019s abbreviated SHA.")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"+dirty")," part is optional and is only present if there are uncommitted\nchanges in the working directory."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8199fa7c.8f626e20.js b/assets/js/8199fa7c.8f626e20.js new file mode 100644 index 0000000000..0547b05121 --- /dev/null +++ b/assets/js/8199fa7c.8f626e20.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5784],{4830:e=>{e.exports=JSON.parse('{"title":"Build Environment Setup and Building","slug":"core/development-setup/build-environment-setup-and-building","permalink":"/core/development-setup/build-environment-setup-and-building","navigation":{"previous":{"title":"Development Setup","permalink":"/core/development-setup"},"next":{"title":"Prerequisites","permalink":"/core/development-setup/prerequisites"}}}')}}]); \ No newline at end of file diff --git a/assets/js/8443.4217f133.js b/assets/js/8443.4217f133.js new file mode 100644 index 0000000000..cfc42efb24 --- /dev/null +++ b/assets/js/8443.4217f133.js @@ -0,0 +1,2 @@ +/*! For license information please see 8443.4217f133.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8443],{8443:(t,e,n)=>{"use strict";t.exports=n(295)},1228:(t,e,n)=>{"use strict";var i=n(2856),s={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none",opacity:"1"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:"0"},defaultClasses:{root:"algolia-autocomplete",prefix:"aa",noPrefix:!1,dropdownMenu:"dropdown-menu",input:"input",hint:"hint",suggestions:"suggestions",suggestion:"suggestion",cursor:"cursor",dataset:"dataset",empty:"empty"},appendTo:{wrapper:{position:"absolute",zIndex:"100",display:"none"},input:{},inputWithNoHint:{},dropdown:{display:"block"}}};i.isMsie()&&i.mixin(s.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),i.isMsie()&&i.isMsie()<=7&&i.mixin(s.input,{marginTop:"-1px"}),t.exports=s},9050:(t,e,n)=>{"use strict";var i="aaDataset",s="aaValue",r="aaDatum",o=n(2856),a=n(4910),u=n(3561),c=n(1228),l=n(514);function h(t){var e;(t=t||{}).templates=t.templates||{},t.source||o.error("missing source"),t.name&&(e=t.name,!/^[_a-zA-Z0-9-]+$/.test(e))&&o.error("invalid dataset name: "+t.name),this.query=null,this._isEmpty=!0,this.highlight=!!t.highlight,this.name=void 0===t.name||null===t.name?o.getUniqueId():t.name,this.source=t.source,this.displayFn=function(t){return t=t||"value",o.isFunction(t)?t:e;function e(e){return e[t]}}(t.display||t.displayKey),this.debounce=t.debounce,this.cache=!1!==t.cache,this.templates=function(t,e){return{empty:t.empty&&o.templatify(t.empty),header:t.header&&o.templatify(t.header),footer:t.footer&&o.templatify(t.footer),suggestion:t.suggestion||n};function n(t){return"<p>"+e(t)+"</p>"}}(t.templates,this.displayFn),this.css=o.mixin({},c,t.appendTo?c.appendTo:{}),this.cssClasses=t.cssClasses=o.mixin({},c.defaultClasses,t.cssClasses||{}),this.cssClasses.prefix=t.cssClasses.formattedPrefix||o.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix);var n=o.className(this.cssClasses.prefix,this.cssClasses.dataset);this.$el=t.$menu&&t.$menu.find(n+"-"+this.name).length>0?a.element(t.$menu.find(n+"-"+this.name)[0]):a.element(u.dataset.replace("%CLASS%",this.name).replace("%PREFIX%",this.cssClasses.prefix).replace("%DATASET%",this.cssClasses.dataset)),this.$menu=t.$menu,this.clearCachedSuggestions()}h.extractDatasetName=function(t){return a.element(t).data(i)},h.extractValue=function(t){return a.element(t).data(s)},h.extractDatum=function(t){var e=a.element(t).data(r);return"string"==typeof e&&(e=JSON.parse(e)),e},o.mixin(h.prototype,l,{_render:function(t,e){if(this.$el){var n,c=this,l=[].slice.call(arguments,2);if(this.$el.empty(),n=e&&e.length,this._isEmpty=!n,!n&&this.templates.empty)this.$el.html(function(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!0}].concat(e),c.templates.empty.apply(this,e)}.apply(this,l)).prepend(c.templates.header?h.apply(this,l):null).append(c.templates.footer?p.apply(this,l):null);else if(n)this.$el.html(function(){var t,n,l=[].slice.call(arguments,0),h=this,p=u.suggestions.replace("%PREFIX%",this.cssClasses.prefix).replace("%SUGGESTIONS%",this.cssClasses.suggestions);return t=a.element(p).css(this.css.suggestions),n=o.map(e,f),t.append.apply(t,n),t;function f(t){var e,n=u.suggestion.replace("%PREFIX%",h.cssClasses.prefix).replace("%SUGGESTION%",h.cssClasses.suggestion);return(e=a.element(n).attr({role:"option",id:["option",Math.floor(1e8*Math.random())].join("-")}).append(c.templates.suggestion.apply(this,[t].concat(l)))).data(i,c.name),e.data(s,c.displayFn(t)||void 0),e.data(r,JSON.stringify(t)),e.children().each((function(){a.element(this).css(h.css.suggestionChild)})),e}}.apply(this,l)).prepend(c.templates.header?h.apply(this,l):null).append(c.templates.footer?p.apply(this,l):null);else if(e&&!Array.isArray(e))throw new TypeError("suggestions must be an array");this.$menu&&this.$menu.addClass(this.cssClasses.prefix+(n?"with":"without")+"-"+this.name).removeClass(this.cssClasses.prefix+(n?"without":"with")+"-"+this.name),this.trigger("rendered",t)}function h(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!n}].concat(e),c.templates.header.apply(this,e)}function p(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!n}].concat(e),c.templates.footer.apply(this,e)}},getRoot:function(){return this.$el},update:function(t){function e(e){if(!this.canceled&&t===this.query){var n=[].slice.call(arguments,1);this.cacheSuggestions(t,e,n),this._render.apply(this,[t,e].concat(n))}}if(this.query=t,this.canceled=!1,this.shouldFetchFromCache(t))e.apply(this,[this.cachedSuggestions].concat(this.cachedRenderExtraArgs));else{var n=this,i=function(){n.canceled||n.source(t,e.bind(n))};if(this.debounce){clearTimeout(this.debounceTimeout),this.debounceTimeout=setTimeout((function(){n.debounceTimeout=null,i()}),this.debounce)}else i()}},cacheSuggestions:function(t,e,n){this.cachedQuery=t,this.cachedSuggestions=e,this.cachedRenderExtraArgs=n},shouldFetchFromCache:function(t){return this.cache&&this.cachedQuery===t&&this.cachedSuggestions&&this.cachedSuggestions.length},clearCachedSuggestions:function(){delete this.cachedQuery,delete this.cachedSuggestions,delete this.cachedRenderExtraArgs},cancel:function(){this.canceled=!0},clear:function(){this.$el&&(this.cancel(),this.$el.empty(),this.trigger("rendered",""))},isEmpty:function(){return this._isEmpty},destroy:function(){this.clearCachedSuggestions(),this.$el=null}}),t.exports=h},3354:(t,e,n)=>{"use strict";var i=n(2856),s=n(4910),r=n(514),o=n(9050),a=n(1228);function u(t){var e,n,r,o=this;(t=t||{}).menu||i.error("menu is required"),i.isArray(t.datasets)||i.isObject(t.datasets)||i.error("1 or more datasets required"),t.datasets||i.error("datasets is required"),this.isOpen=!1,this.isEmpty=!0,this.minLength=t.minLength||0,this.templates={},this.appendTo=t.appendTo||!1,this.css=i.mixin({},a,t.appendTo?a.appendTo:{}),this.cssClasses=t.cssClasses=i.mixin({},a.defaultClasses,t.cssClasses||{}),this.cssClasses.prefix=t.cssClasses.formattedPrefix||i.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix),e=i.bind(this._onSuggestionClick,this),n=i.bind(this._onSuggestionMouseEnter,this),r=i.bind(this._onSuggestionMouseLeave,this);var c=i.className(this.cssClasses.prefix,this.cssClasses.suggestion);this.$menu=s.element(t.menu).on("mouseenter.aa",c,n).on("mouseleave.aa",c,r).on("click.aa",c,e),this.$container=t.appendTo?t.wrapper:this.$menu,t.templates&&t.templates.header&&(this.templates.header=i.templatify(t.templates.header),this.$menu.prepend(this.templates.header())),t.templates&&t.templates.empty&&(this.templates.empty=i.templatify(t.templates.empty),this.$empty=s.element('<div class="'+i.className(this.cssClasses.prefix,this.cssClasses.empty,!0)+'"></div>'),this.$menu.append(this.$empty),this.$empty.hide()),this.datasets=i.map(t.datasets,(function(e){return function(t,e,n){return new u.Dataset(i.mixin({$menu:t,cssClasses:n},e))}(o.$menu,e,t.cssClasses)})),i.each(this.datasets,(function(t){var e=t.getRoot();e&&0===e.parent().length&&o.$menu.append(e),t.onSync("rendered",o._onRendered,o)})),t.templates&&t.templates.footer&&(this.templates.footer=i.templatify(t.templates.footer),this.$menu.append(this.templates.footer()));var l=this;s.element(window).resize((function(){l._redraw()}))}i.mixin(u.prototype,r,{_onSuggestionClick:function(t){this.trigger("suggestionClicked",s.element(t.currentTarget))},_onSuggestionMouseEnter:function(t){var e=s.element(t.currentTarget);if(!e.hasClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0))){this._removeCursor();var n=this;setTimeout((function(){n._setCursor(e,!1)}),0)}},_onSuggestionMouseLeave:function(t){if(t.relatedTarget&&s.element(t.relatedTarget).closest("."+i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).length>0)return;this._removeCursor(),this.trigger("cursorRemoved")},_onRendered:function(t,e){if(this.isEmpty=i.every(this.datasets,(function(t){return t.isEmpty()})),this.isEmpty)if(e.length>=this.minLength&&this.trigger("empty"),this.$empty)if(e.length<this.minLength)this._hide();else{var n=this.templates.empty({query:this.datasets[0]&&this.datasets[0].query});this.$empty.html(n),this.$empty.show(),this._show()}else i.any(this.datasets,(function(t){return t.templates&&t.templates.empty}))?e.length<this.minLength?this._hide():this._show():this._hide();else this.isOpen&&(this.$empty&&(this.$empty.empty(),this.$empty.hide()),e.length>=this.minLength?this._show():this._hide());this.trigger("datasetRendered")},_hide:function(){this.$container.hide()},_show:function(){this.$container.css("display","block"),this._redraw(),this.trigger("shown")},_redraw:function(){this.isOpen&&this.appendTo&&this.trigger("redrawn")},_getSuggestions:function(){return this.$menu.find(i.className(this.cssClasses.prefix,this.cssClasses.suggestion))},_getCursor:function(){return this.$menu.find(i.className(this.cssClasses.prefix,this.cssClasses.cursor)).first()},_setCursor:function(t,e){t.first().addClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).attr("aria-selected","true"),this.trigger("cursorMoved",e)},_removeCursor:function(){this._getCursor().removeClass(i.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).removeAttr("aria-selected")},_moveCursor:function(t){var e,n,i,s;this.isOpen&&(n=this._getCursor(),e=this._getSuggestions(),this._removeCursor(),-1!==(i=((i=e.index(n)+t)+1)%(e.length+1)-1)?(i<-1&&(i=e.length-1),this._setCursor(s=e.eq(i),!0),this._ensureVisible(s)):this.trigger("cursorRemoved"))},_ensureVisible:function(t){var e,n,i,s;n=(e=t.position().top)+t.height()+parseInt(t.css("margin-top"),10)+parseInt(t.css("margin-bottom"),10),i=this.$menu.scrollTop(),s=this.$menu.height()+parseInt(this.$menu.css("padding-top"),10)+parseInt(this.$menu.css("padding-bottom"),10),e<0?this.$menu.scrollTop(i+e):s<n&&this.$menu.scrollTop(i+(n-s))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,this.isEmpty||this._show(),this.trigger("opened"))},setLanguageDirection:function(t){this.$menu.css("ltr"===t?this.css.ltr:this.css.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(t){var e=null;return t.length&&(e={raw:o.extractDatum(t),value:o.extractValue(t),datasetName:o.extractDatasetName(t)}),e},getCurrentCursor:function(){return this._getCursor().first()},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},cursorTopSuggestion:function(){this._setCursor(this._getSuggestions().first(),!1)},update:function(t){i.each(this.datasets,(function(e){e.update(t)}))},empty:function(){i.each(this.datasets,(function(t){t.clear()})),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){this.$menu.off(".aa"),this.$menu=null,i.each(this.datasets,(function(t){t.destroy()}))}}),u.Dataset=o,t.exports=u},50:(t,e,n)=>{"use strict";var i=n(2856),s=n(4910);function r(t){t&&t.el||i.error("EventBus initialized without el"),this.$el=s.element(t.el)}i.mixin(r.prototype,{trigger:function(t,e,n,s){var r=i.Event("autocomplete:"+t);return this.$el.trigger(r,[e,n,s]),r}}),t.exports=r},514:(t,e,n)=>{"use strict";var i=n(624),s=/\s+/;function r(t,e,n,i){var r;if(!n)return this;for(e=e.split(s),n=i?function(t,e){return t.bind?t.bind(e):function(){t.apply(e,[].slice.call(arguments,0))}}(n,i):n,this._callbacks=this._callbacks||{};r=e.shift();)this._callbacks[r]=this._callbacks[r]||{sync:[],async:[]},this._callbacks[r][t].push(n);return this}function o(t,e,n){return function(){for(var i,s=0,r=t.length;!i&&s<r;s+=1)i=!1===t[s].apply(e,n);return!i}}t.exports={onSync:function(t,e,n){return r.call(this,"sync",t,e,n)},onAsync:function(t,e,n){return r.call(this,"async",t,e,n)},off:function(t){var e;if(!this._callbacks)return this;t=t.split(s);for(;e=t.shift();)delete this._callbacks[e];return this},trigger:function(t){var e,n,r,a,u;if(!this._callbacks)return this;t=t.split(s),r=[].slice.call(arguments,1);for(;(e=t.shift())&&(n=this._callbacks[e]);)a=o(n.sync,this,[e].concat(r)),u=o(n.async,this,[e].concat(r)),a()&&i(u);return this}}},3561:t=>{"use strict";t.exports={wrapper:'<span class="%ROOT%"></span>',dropdown:'<span class="%PREFIX%%DROPDOWN_MENU%"></span>',dataset:'<div class="%PREFIX%%DATASET%-%CLASS%"></div>',suggestions:'<span class="%PREFIX%%SUGGESTIONS%"></span>',suggestion:'<div class="%PREFIX%%SUGGESTION%"></div>'}},2534:(t,e,n)=>{"use strict";var i;i={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"};var s=n(2856),r=n(4910),o=n(514);function a(t){var e,n,o,a,u,c=this;(t=t||{}).input||s.error("input is missing"),e=s.bind(this._onBlur,this),n=s.bind(this._onFocus,this),o=s.bind(this._onKeydown,this),a=s.bind(this._onInput,this),this.$hint=r.element(t.hint),this.$input=r.element(t.input).on("blur.aa",e).on("focus.aa",n).on("keydown.aa",o),0===this.$hint.length&&(this.setHint=this.getHint=this.clearHint=this.clearHintIfInvalid=s.noop),s.isMsie()?this.$input.on("keydown.aa keypress.aa cut.aa paste.aa",(function(t){i[t.which||t.keyCode]||s.defer(s.bind(c._onInput,c,t))})):this.$input.on("input.aa",a),this.query=this.$input.val(),this.$overflowHelper=(u=this.$input,r.element('<pre aria-hidden="true"></pre>').css({position:"absolute",visibility:"hidden",whiteSpace:"pre",fontFamily:u.css("font-family"),fontSize:u.css("font-size"),fontStyle:u.css("font-style"),fontVariant:u.css("font-variant"),fontWeight:u.css("font-weight"),wordSpacing:u.css("word-spacing"),letterSpacing:u.css("letter-spacing"),textIndent:u.css("text-indent"),textRendering:u.css("text-rendering"),textTransform:u.css("text-transform")}).insertAfter(u))}function u(t){return t.altKey||t.ctrlKey||t.metaKey||t.shiftKey}a.normalizeQuery=function(t){return(t||"").replace(/^\s*/g,"").replace(/\s{2,}/g," ")},s.mixin(a.prototype,o,{_onBlur:function(){this.resetInputValue(),this.$input.removeAttr("aria-activedescendant"),this.trigger("blurred")},_onFocus:function(){this.trigger("focused")},_onKeydown:function(t){var e=i[t.which||t.keyCode];this._managePreventDefault(e,t),e&&this._shouldTrigger(e,t)&&this.trigger(e+"Keyed",t)},_onInput:function(){this._checkInputValue()},_managePreventDefault:function(t,e){var n,i,s;switch(t){case"tab":i=this.getHint(),s=this.getInputValue(),n=i&&i!==s&&!u(e);break;case"up":case"down":n=!u(e);break;default:n=!1}n&&e.preventDefault()},_shouldTrigger:function(t,e){var n;if("tab"===t)n=!u(e);else n=!0;return n},_checkInputValue:function(){var t,e,n,i,s;t=this.getInputValue(),i=t,s=this.query,n=!(!(e=a.normalizeQuery(i)===a.normalizeQuery(s))||!this.query)&&this.query.length!==t.length,this.query=t,e?n&&this.trigger("whitespaceChanged",this.query):this.trigger("queryChanged",this.query)},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(t){this.query=t},getInputValue:function(){return this.$input.val()},setInputValue:function(t,e){void 0===t&&(t=this.query),this.$input.val(t),e?this.clearHint():this._checkInputValue()},expand:function(){this.$input.attr("aria-expanded","true")},collapse:function(){this.$input.attr("aria-expanded","false")},setActiveDescendant:function(t){this.$input.attr("aria-activedescendant",t)},removeActiveDescendant:function(){this.$input.removeAttr("aria-activedescendant")},resetInputValue:function(){this.setInputValue(this.query,!0)},getHint:function(){return this.$hint.val()},setHint:function(t){this.$hint.val(t)},clearHint:function(){this.setHint("")},clearHintIfInvalid:function(){var t,e,n;n=(t=this.getInputValue())!==(e=this.getHint())&&0===e.indexOf(t),""!==t&&n&&!this.hasOverflow()||this.clearHint()},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},hasOverflow:function(){var t=this.$input.width()-2;return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>=t},isCursorAtEnd:function(){var t,e,n;return t=this.$input.val().length,e=this.$input[0].selectionStart,s.isNumber(e)?e===t:!document.selection||((n=document.selection.createRange()).moveStart("character",-t),t===n.text.length)},destroy:function(){this.$hint.off(".aa"),this.$input.off(".aa"),this.$hint=this.$input=this.$overflowHelper=null}}),t.exports=a},6549:(t,e,n)=>{"use strict";var i="aaAttrs",s=n(2856),r=n(4910),o=n(50),a=n(2534),u=n(3354),c=n(3561),l=n(1228);function h(t){var e,n;if((t=t||{}).input||s.error("missing input"),this.isActivated=!1,this.debug=!!t.debug,this.autoselect=!!t.autoselect,this.autoselectOnBlur=!!t.autoselectOnBlur,this.openOnFocus=!!t.openOnFocus,this.minLength=s.isNumber(t.minLength)?t.minLength:1,this.autoWidth=void 0===t.autoWidth||!!t.autoWidth,this.clearOnSelected=!!t.clearOnSelected,this.tabAutocomplete=void 0===t.tabAutocomplete||!!t.tabAutocomplete,t.hint=!!t.hint,t.hint&&t.appendTo)throw new Error("[autocomplete.js] hint and appendTo options can't be used at the same time");this.css=t.css=s.mixin({},l,t.appendTo?l.appendTo:{}),this.cssClasses=t.cssClasses=s.mixin({},l.defaultClasses,t.cssClasses||{}),this.cssClasses.prefix=t.cssClasses.formattedPrefix=s.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix),this.listboxId=t.listboxId=[this.cssClasses.root,"listbox",s.getUniqueId()].join("-");var a=function(t){var e,n,o,a;e=r.element(t.input),n=r.element(c.wrapper.replace("%ROOT%",t.cssClasses.root)).css(t.css.wrapper),t.appendTo||"block"!==e.css("display")||"table"!==e.parent().css("display")||n.css("display","table-cell");var u=c.dropdown.replace("%PREFIX%",t.cssClasses.prefix).replace("%DROPDOWN_MENU%",t.cssClasses.dropdownMenu);o=r.element(u).css(t.css.dropdown).attr({role:"listbox",id:t.listboxId}),t.templates&&t.templates.dropdownMenu&&o.html(s.templatify(t.templates.dropdownMenu)());a=e.clone().css(t.css.hint).css(function(t){return{backgroundAttachment:t.css("background-attachment"),backgroundClip:t.css("background-clip"),backgroundColor:t.css("background-color"),backgroundImage:t.css("background-image"),backgroundOrigin:t.css("background-origin"),backgroundPosition:t.css("background-position"),backgroundRepeat:t.css("background-repeat"),backgroundSize:t.css("background-size")}}(e)),a.val("").addClass(s.className(t.cssClasses.prefix,t.cssClasses.hint,!0)).removeAttr("id name placeholder required").prop("readonly",!0).attr({"aria-hidden":"true",autocomplete:"off",spellcheck:"false",tabindex:-1}),a.removeData&&a.removeData();e.data(i,{"aria-autocomplete":e.attr("aria-autocomplete"),"aria-expanded":e.attr("aria-expanded"),"aria-owns":e.attr("aria-owns"),autocomplete:e.attr("autocomplete"),dir:e.attr("dir"),role:e.attr("role"),spellcheck:e.attr("spellcheck"),style:e.attr("style"),type:e.attr("type")}),e.addClass(s.className(t.cssClasses.prefix,t.cssClasses.input,!0)).attr({autocomplete:"off",spellcheck:!1,role:"combobox","aria-autocomplete":t.datasets&&t.datasets[0]&&t.datasets[0].displayKey?"both":"list","aria-expanded":"false","aria-label":t.ariaLabel,"aria-owns":t.listboxId}).css(t.hint?t.css.input:t.css.inputWithNoHint);try{e.attr("dir")||e.attr("dir","auto")}catch(l){}return n=t.appendTo?n.appendTo(r.element(t.appendTo).eq(0)).eq(0):e.wrap(n).parent(),n.prepend(t.hint?a:null).append(o),{wrapper:n,input:e,hint:a,menu:o}}(t);this.$node=a.wrapper;var u=this.$input=a.input;e=a.menu,n=a.hint,t.dropdownMenuContainer&&r.element(t.dropdownMenuContainer).css("position","relative").append(e.css("top","0")),u.on("blur.aa",(function(t){var n=document.activeElement;s.isMsie()&&(e[0]===n||e[0].contains(n))&&(t.preventDefault(),t.stopImmediatePropagation(),s.defer((function(){u.focus()})))})),e.on("mousedown.aa",(function(t){t.preventDefault()})),this.eventBus=t.eventBus||new o({el:u}),this.dropdown=new h.Dropdown({appendTo:t.appendTo,wrapper:this.$node,menu:e,datasets:t.datasets,templates:t.templates,cssClasses:t.cssClasses,minLength:this.minLength}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onSync("shown",this._onShown,this).onSync("empty",this._onEmpty,this).onSync("redrawn",this._onRedrawn,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new h.Input({input:u,hint:n}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._bindKeyboardShortcuts(t),this._setLanguageDirection()}s.mixin(h.prototype,{_bindKeyboardShortcuts:function(t){if(t.keyboardShortcuts){var e=this.$input,n=[];s.each(t.keyboardShortcuts,(function(t){"string"==typeof t&&(t=t.toUpperCase().charCodeAt(0)),n.push(t)})),r.element(document).keydown((function(t){var i=t.target||t.srcElement,s=i.tagName;if(!i.isContentEditable&&"INPUT"!==s&&"SELECT"!==s&&"TEXTAREA"!==s){var r=t.which||t.keyCode;-1!==n.indexOf(r)&&(e.focus(),t.stopPropagation(),t.preventDefault())}}))}},_onSuggestionClicked:function(t,e){var n;(n=this.dropdown.getDatumForSuggestion(e))&&this._select(n,{selectionMethod:"click"})},_onCursorMoved:function(t,e){var n=this.dropdown.getDatumForCursor(),i=this.dropdown.getCurrentCursor().attr("id");this.input.setActiveDescendant(i),n&&(e&&this.input.setInputValue(n.value,!0),this.eventBus.trigger("cursorchanged",n.raw,n.datasetName))},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint(),this.eventBus.trigger("cursorremoved")},_onDatasetRendered:function(){this._updateHint(),this.eventBus.trigger("updated")},_onOpened:function(){this._updateHint(),this.input.expand(),this.eventBus.trigger("opened")},_onEmpty:function(){this.eventBus.trigger("empty")},_onRedrawn:function(){this.$node.css("top","0px"),this.$node.css("left","0px");var t=this.$input[0].getBoundingClientRect();this.autoWidth&&this.$node.css("width",t.width+"px");var e=this.$node[0].getBoundingClientRect(),n=t.bottom-e.top;this.$node.css("top",n+"px");var i=t.left-e.left;this.$node.css("left",i+"px"),this.eventBus.trigger("redrawn")},_onShown:function(){this.eventBus.trigger("shown"),this.autoselect&&this.dropdown.cursorTopSuggestion()},_onClosed:function(){this.input.clearHint(),this.input.removeActiveDescendant(),this.input.collapse(),this.eventBus.trigger("closed")},_onFocused:function(){if(this.isActivated=!0,this.openOnFocus){var t=this.input.getQuery();t.length>=this.minLength?this.dropdown.update(t):this.dropdown.empty(),this.dropdown.open()}},_onBlurred:function(){var t,e;t=this.dropdown.getDatumForCursor(),e=this.dropdown.getDatumForTopSuggestion();var n={selectionMethod:"blur"};this.debug||(this.autoselectOnBlur&&t?this._select(t,n):this.autoselectOnBlur&&e?this._select(e,n):(this.isActivated=!1,this.dropdown.empty(),this.dropdown.close()))},_onEnterKeyed:function(t,e){var n,i;n=this.dropdown.getDatumForCursor(),i=this.dropdown.getDatumForTopSuggestion();var s={selectionMethod:"enterKey"};n?(this._select(n,s),e.preventDefault()):this.autoselect&&i&&(this._select(i,s),e.preventDefault())},_onTabKeyed:function(t,e){if(this.tabAutocomplete){var n;(n=this.dropdown.getDatumForCursor())?(this._select(n,{selectionMethod:"tabKey"}),e.preventDefault()):this._autocomplete(!0)}else this.dropdown.close()},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(t,e){this.input.clearHintIfInvalid(),e.length>=this.minLength?this.dropdown.update(e):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var t=this.input.getLanguageDirection();this.dir!==t&&(this.dir=t,this.$node.css("direction",t),this.dropdown.setLanguageDirection(t))},_updateHint:function(){var t,e,n,i,r;(t=this.dropdown.getDatumForTopSuggestion())&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(e=this.input.getInputValue(),n=a.normalizeQuery(e),i=s.escapeRegExChars(n),(r=new RegExp("^(?:"+i+")(.+$)","i").exec(t.value))?this.input.setHint(e+r[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(t){var e,n,i,s;e=this.input.getHint(),n=this.input.getQuery(),i=t||this.input.isCursorAtEnd(),e&&n!==e&&i&&((s=this.dropdown.getDatumForTopSuggestion())&&this.input.setInputValue(s.value),this.eventBus.trigger("autocompleted",s.raw,s.datasetName))},_select:function(t,e){void 0!==t.value&&this.input.setQuery(t.value),this.clearOnSelected?this.setVal(""):this.input.setInputValue(t.value,!0),this._setLanguageDirection(),!1===this.eventBus.trigger("selected",t.raw,t.datasetName,e).isDefaultPrevented()&&(this.dropdown.close(),s.defer(s.bind(this.dropdown.empty,this.dropdown)))},open:function(){if(!this.isActivated){var t=this.input.getInputValue();t.length>=this.minLength?this.dropdown.update(t):this.dropdown.empty()}this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(t){t=s.toStr(t),this.isActivated?this.input.setInputValue(t):(this.input.setQuery(t),this.input.setInputValue(t,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),function(t,e){var n=t.find(s.className(e.prefix,e.input));s.each(n.data(i),(function(t,e){void 0===t?n.removeAttr(e):n.attr(e,t)})),n.detach().removeClass(s.className(e.prefix,e.input,!0)).insertAfter(t),n.removeData&&n.removeData(i);t.remove()}(this.$node,this.cssClasses),this.$node=null},getWrapper:function(){return this.dropdown.$container[0]}}),h.Dropdown=u,h.Input=a,h.sources=n(8840),t.exports=h},4910:t=>{"use strict";t.exports={element:null}},6177:t=>{"use strict";t.exports=function(t){var e=t.match(/Algolia for JavaScript \((\d+\.)(\d+\.)(\d+)\)/)||t.match(/Algolia for vanilla JavaScript (\d+\.)(\d+\.)(\d+)/);if(e)return[e[1],e[2],e[3]]}},2856:(t,e,n)=>{"use strict";var i,s=n(8820),r=n(4910);function o(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}t.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(t){if(void 0===t&&(t=navigator.userAgent),/(msie|trident)/i.test(t)){var e=t.match(/(msie |rv:)(\d+(.\d+)?)/i);if(e)return e[2]}return!1},escapeRegExChars:function(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(t){return"number"==typeof t},toStr:function(t){return null==t?"":t+""},cloneDeep:function(t){var e=this.mixin({},t),n=this;return this.each(e,(function(t,i){t&&(n.isArray(t)?e[i]=[].concat(t):n.isObject(t)&&(e[i]=n.cloneDeep(t)))})),e},error:function(t){throw new Error(t)},every:function(t,e){var n=!0;return t?(this.each(t,(function(i,s){n&&(n=e.call(null,i,s,t)&&n)})),!!n):n},any:function(t,e){var n=!1;return t?(this.each(t,(function(i,s){if(e.call(null,i,s,t))return n=!0,!1})),n):n},getUniqueId:(i=0,function(){return i++}),templatify:function(t){if(this.isFunction(t))return t;var e=r.element(t);return"SCRIPT"===e.prop("tagName")?function(){return e.text()}:function(){return String(t)}},defer:function(t){setTimeout(t,0)},noop:function(){},formatPrefix:function(t,e){return e?"":t+"-"},className:function(t,e,n){return n?t+e:"."+s(t+e,{isIdentifier:!0})},escapeHighlightedString:function(t,e,n){e=e||"<em>";var i=document.createElement("div");i.appendChild(document.createTextNode(e)),n=n||"</em>";var s=document.createElement("div");s.appendChild(document.createTextNode(n));var r=document.createElement("div");return r.appendChild(document.createTextNode(t)),r.innerHTML.replace(RegExp(o(i.innerHTML),"g"),e).replace(RegExp(o(s.innerHTML),"g"),n)}}},9983:(t,e,n)=>{"use strict";var i=n(2856),s=n(533),r=n(6177);var o,a,u=(o=[],a=window.Promise.resolve(),function(t,e){return function(n,s){(function(t,e){return window.Promise.resolve().then((function(){return o.length&&(a=t.search(o),o=[]),a})).then((function(t){if(t)return t.results[e]}))})(t.as,o.push({indexName:t.indexName,query:n,params:e})-1).then((function(t){t&&s(t.hits,t)})).catch((function(t){i.error(t.message)}))}});t.exports=function(t,e){var n=r(t.as._ua);if(n&&n[0]>=3&&n[1]>20){var i="autocomplete.js "+s;-1===t.as._ua.indexOf(i)&&(t.as._ua+="; "+i)}return u(t,e)}},8840:(t,e,n)=>{"use strict";t.exports={hits:n(9983),popularIn:n(4445)}},4445:(t,e,n)=>{"use strict";var i=n(2856),s=n(533),r=n(6177);t.exports=function(t,e,n,o){var a=r(t.as._ua);if(a&&a[0]>=3&&a[1]>20&&((e=e||{}).additionalUA="autocomplete.js "+s),!n.source)return i.error("Missing 'source' key");var u=i.isFunction(n.source)?n.source:function(t){return t[n.source]};if(!n.index)return i.error("Missing 'index' key");var c=n.index;return o=o||{},function(a,l){t.search(a,e,(function(t,a){if(t)i.error(t.message);else{if(a.hits.length>0){var h=a.hits[0],p=i.mixin({hitsPerPage:0},n);delete p.source,delete p.index;var f=r(c.as._ua);return f&&f[0]>=3&&f[1]>20&&(e.additionalUA="autocomplete.js "+s),void c.search(u(h),p,(function(t,e){if(t)i.error(t.message);else{var n=[];if(o.includeAll){var s=o.allTitle||"All departments";n.push(i.mixin({facet:{value:s,count:e.nbHits}},i.cloneDeep(h)))}i.each(e.facets,(function(t,e){i.each(t,(function(t,s){n.push(i.mixin({facet:{facet:e,value:s,count:t}},i.cloneDeep(h)))}))}));for(var r=1;r<a.hits.length;++r)n.push(a.hits[r]);l(n,a)}}))}l([])}}))}}},295:(t,e,n)=>{"use strict";var i=n(6990);n(4910).element=i;var s=n(2856);s.isArray=i.isArray,s.isFunction=i.isFunction,s.isObject=i.isPlainObject,s.bind=i.proxy,s.each=function(t,e){i.each(t,(function(t,n){return e(n,t)}))},s.map=i.map,s.mixin=i.extend,s.Event=i.Event;var r="aaAutocomplete",o=n(6549),a=n(50);function u(t,e,n,u){n=s.isArray(n)?n:[].slice.call(arguments,2);var c=i(t).each((function(t,s){var c=i(s),l=new a({el:c}),h=u||new o({input:c,eventBus:l,dropdownMenuContainer:e.dropdownMenuContainer,hint:void 0===e.hint||!!e.hint,minLength:e.minLength,autoselect:e.autoselect,autoselectOnBlur:e.autoselectOnBlur,tabAutocomplete:e.tabAutocomplete,openOnFocus:e.openOnFocus,templates:e.templates,debug:e.debug,clearOnSelected:e.clearOnSelected,cssClasses:e.cssClasses,datasets:n,keyboardShortcuts:e.keyboardShortcuts,appendTo:e.appendTo,autoWidth:e.autoWidth,ariaLabel:e.ariaLabel||s.getAttribute("aria-label")});c.data(r,h)}));return c.autocomplete={},s.each(["open","close","getVal","setVal","destroy","getWrapper"],(function(t){c.autocomplete[t]=function(){var e,n=arguments;return c.each((function(s,o){var a=i(o).data(r);e=a[t].apply(a,n)})),e}})),c}u.sources=o.sources,u.escapeHighlightedString=s.escapeHighlightedString;var c="autocomplete"in window,l=window.autocomplete;u.noConflict=function(){return c?window.autocomplete=l:delete window.autocomplete,u},t.exports=u},533:t=>{t.exports="0.38.1"},6990:t=>{var e;e=window,t.exports=function(t){var e,n,i=function(){var e,n,i,s,r,o,a=[],u=a.concat,c=a.filter,l=a.slice,h=t.document,p={},f={},d={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},g=/^\s*<(\w+|!)[^>]*>/,m=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,y=/^(?:body|html)$/i,w=/([A-Z])/g,b=["val","css","html","text","data","width","height","offset"],C=["after","prepend","before","append"],x=h.createElement("table"),_=h.createElement("tr"),S={tr:h.createElement("tbody"),tbody:x,thead:x,tfoot:x,td:_,th:_,"*":h.createElement("div")},E=/complete|loaded|interactive/,A=/^[\w-]*$/,$={},T=$.toString,O={},D=h.createElement("div"),N={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},k=Array.isArray||function(t){return t instanceof Array};function I(t){return null==t?String(t):$[T.call(t)]||"object"}function P(t){return"function"==I(t)}function L(t){return null!=t&&t==t.window}function M(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function F(t){return"object"==I(t)}function R(t){return F(t)&&!L(t)&&Object.getPrototypeOf(t)==Object.prototype}function q(t){var e=!!t&&"length"in t&&t.length,n=i.type(t);return"function"!=n&&!L(t)&&("array"==n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function V(t){return c.call(t,(function(t){return null!=t}))}function H(t){return t.length>0?i.fn.concat.apply([],t):t}function B(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function K(t){return t in f?f[t]:f[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function j(t,e){return"number"!=typeof e||d[B(t)]?e:e+"px"}function z(t){var e,n;return p[t]||(e=h.createElement(t),h.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),p[t]=n),p[t]}function U(t){return"children"in t?l.call(t.children):i.map(t.childNodes,(function(t){if(1==t.nodeType)return t}))}function Q(t,e){var n,i=t?t.length:0;for(n=0;n<i;n++)this[n]=t[n];this.length=i,this.selector=e||""}function W(t,i,s){for(n in i)s&&(R(i[n])||k(i[n]))?(R(i[n])&&!R(t[n])&&(t[n]={}),k(i[n])&&!k(t[n])&&(t[n]=[]),W(t[n],i[n],s)):i[n]!==e&&(t[n]=i[n])}function Z(t,e){return null==e?i(t):i(t).filter(e)}function X(t,e,n,i){return P(e)?e.call(t,n,i):e}function G(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function J(t,n){var i=t.className||"",s=i&&i.baseVal!==e;if(n===e)return s?i.baseVal:i;s?i.baseVal=n:t.className=n}function Y(t){try{return t?"true"==t||"false"!=t&&("null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?i.parseJSON(t):t):t}catch(e){return t}}function tt(t,e){e(t);for(var n=0,i=t.childNodes.length;n<i;n++)tt(t.childNodes[n],e)}return O.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var i,s=t.parentNode,r=!s;return r&&(s=D).appendChild(t),i=~O.qsa(s,e).indexOf(t),r&&D.removeChild(t),i},r=function(t){return t.replace(/-+(.)?/g,(function(t,e){return e?e.toUpperCase():""}))},o=function(t){return c.call(t,(function(e,n){return t.indexOf(e)==n}))},O.fragment=function(t,n,s){var r,o,a;return m.test(t)&&(r=i(h.createElement(RegExp.$1))),r||(t.replace&&(t=t.replace(v,"<$1></$2>")),n===e&&(n=g.test(t)&&RegExp.$1),n in S||(n="*"),(a=S[n]).innerHTML=""+t,r=i.each(l.call(a.childNodes),(function(){a.removeChild(this)}))),R(s)&&(o=i(r),i.each(s,(function(t,e){b.indexOf(t)>-1?o[t](e):o.attr(t,e)}))),r},O.Z=function(t,e){return new Q(t,e)},O.isZ=function(t){return t instanceof O.Z},O.init=function(t,n){var s;if(!t)return O.Z();if("string"==typeof t)if("<"==(t=t.trim())[0]&&g.test(t))s=O.fragment(t,RegExp.$1,n),t=null;else{if(n!==e)return i(n).find(t);s=O.qsa(h,t)}else{if(P(t))return i(h).ready(t);if(O.isZ(t))return t;if(k(t))s=V(t);else if(F(t))s=[t],t=null;else if(g.test(t))s=O.fragment(t.trim(),RegExp.$1,n),t=null;else{if(n!==e)return i(n).find(t);s=O.qsa(h,t)}}return O.Z(s,t)},(i=function(t,e){return O.init(t,e)}).extend=function(t){var e,n=l.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach((function(n){W(t,n,e)})),t},O.qsa=function(t,e){var n,i="#"==e[0],s=!i&&"."==e[0],r=i||s?e.slice(1):e,o=A.test(r);return t.getElementById&&o&&i?(n=t.getElementById(r))?[n]:[]:1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType?[]:l.call(o&&!i&&t.getElementsByClassName?s?t.getElementsByClassName(r):t.getElementsByTagName(e):t.querySelectorAll(e))},i.contains=h.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},i.type=I,i.isFunction=P,i.isWindow=L,i.isArray=k,i.isPlainObject=R,i.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},i.isNumeric=function(t){var e=Number(t),n=typeof t;return null!=t&&"boolean"!=n&&("string"!=n||t.length)&&!isNaN(e)&&isFinite(e)||!1},i.inArray=function(t,e,n){return a.indexOf.call(e,t,n)},i.camelCase=r,i.trim=function(t){return null==t?"":String.prototype.trim.call(t)},i.uuid=0,i.support={},i.expr={},i.noop=function(){},i.map=function(t,e){var n,i,s,r=[];if(q(t))for(i=0;i<t.length;i++)null!=(n=e(t[i],i))&&r.push(n);else for(s in t)null!=(n=e(t[s],s))&&r.push(n);return H(r)},i.each=function(t,e){var n,i;if(q(t)){for(n=0;n<t.length;n++)if(!1===e.call(t[n],n,t[n]))return t}else for(i in t)if(!1===e.call(t[i],i,t[i]))return t;return t},i.grep=function(t,e){return c.call(t,e)},t.JSON&&(i.parseJSON=JSON.parse),i.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),(function(t,e){$["[object "+e+"]"]=e.toLowerCase()})),i.fn={constructor:O.Z,length:0,forEach:a.forEach,reduce:a.reduce,push:a.push,sort:a.sort,splice:a.splice,indexOf:a.indexOf,concat:function(){var t,e,n=[];for(t=0;t<arguments.length;t++)e=arguments[t],n[t]=O.isZ(e)?e.toArray():e;return u.apply(O.isZ(this)?this.toArray():this,n)},map:function(t){return i(i.map(this,(function(e,n){return t.call(e,n,e)})))},slice:function(){return i(l.apply(this,arguments))},ready:function(t){return E.test(h.readyState)&&h.body?t(i):h.addEventListener("DOMContentLoaded",(function(){t(i)}),!1),this},get:function(t){return t===e?l.call(this):this[t>=0?t:t+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each((function(){null!=this.parentNode&&this.parentNode.removeChild(this)}))},each:function(t){return a.every.call(this,(function(e,n){return!1!==t.call(e,n,e)})),this},filter:function(t){return P(t)?this.not(this.not(t)):i(c.call(this,(function(e){return O.matches(e,t)})))},add:function(t,e){return i(o(this.concat(i(t,e))))},is:function(t){return this.length>0&&O.matches(this[0],t)},not:function(t){var n=[];if(P(t)&&t.call!==e)this.each((function(e){t.call(this,e)||n.push(this)}));else{var s="string"==typeof t?this.filter(t):q(t)&&P(t.item)?l.call(t):i(t);this.forEach((function(t){s.indexOf(t)<0&&n.push(t)}))}return i(n)},has:function(t){return this.filter((function(){return F(t)?i.contains(this,t):i(this).find(t).size()}))},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!F(t)?t:i(t)},last:function(){var t=this[this.length-1];return t&&!F(t)?t:i(t)},find:function(t){var e=this;return t?"object"==typeof t?i(t).filter((function(){var t=this;return a.some.call(e,(function(e){return i.contains(e,t)}))})):1==this.length?i(O.qsa(this[0],t)):this.map((function(){return O.qsa(this,t)})):i()},closest:function(t,e){var n=[],s="object"==typeof t&&i(t);return this.each((function(i,r){for(;r&&!(s?s.indexOf(r)>=0:O.matches(r,t));)r=r!==e&&!M(r)&&r.parentNode;r&&n.indexOf(r)<0&&n.push(r)})),i(n)},parents:function(t){for(var e=[],n=this;n.length>0;)n=i.map(n,(function(t){if((t=t.parentNode)&&!M(t)&&e.indexOf(t)<0)return e.push(t),t}));return Z(e,t)},parent:function(t){return Z(o(this.pluck("parentNode")),t)},children:function(t){return Z(this.map((function(){return U(this)})),t)},contents:function(){return this.map((function(){return this.contentDocument||l.call(this.childNodes)}))},siblings:function(t){return Z(this.map((function(t,e){return c.call(U(e.parentNode),(function(t){return t!==e}))})),t)},empty:function(){return this.each((function(){this.innerHTML=""}))},pluck:function(t){return i.map(this,(function(e){return e[t]}))},show:function(){return this.each((function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=z(this.nodeName))}))},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=P(t);if(this[0]&&!e)var n=i(t).get(0),s=n.parentNode||this.length>1;return this.each((function(r){i(this).wrapAll(e?t.call(this,r):s?n.cloneNode(!0):n)}))},wrapAll:function(t){if(this[0]){var e;for(i(this[0]).before(t=i(t));(e=t.children()).length;)t=e.first();i(t).append(this)}return this},wrapInner:function(t){var e=P(t);return this.each((function(n){var s=i(this),r=s.contents(),o=e?t.call(this,n):t;r.length?r.wrapAll(o):s.append(o)}))},unwrap:function(){return this.parent().each((function(){i(this).replaceWith(i(this).children())})),this},clone:function(){return this.map((function(){return this.cloneNode(!0)}))},hide:function(){return this.css("display","none")},toggle:function(t){return this.each((function(){var n=i(this);(t===e?"none"==n.css("display"):t)?n.show():n.hide()}))},prev:function(t){return i(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return i(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each((function(e){var n=this.innerHTML;i(this).empty().append(X(this,t,e,n))})):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each((function(e){var n=X(this,t,e,this.textContent);this.textContent=null==n?"":""+n})):0 in this?this.pluck("textContent").join(""):null},attr:function(t,i){var s;return"string"!=typeof t||1 in arguments?this.each((function(e){if(1===this.nodeType)if(F(t))for(n in t)G(this,n,t[n]);else G(this,t,X(this,i,e,this.getAttribute(t)))})):0 in this&&1==this[0].nodeType&&null!=(s=this[0].getAttribute(t))?s:e},removeAttr:function(t){return this.each((function(){1===this.nodeType&&t.split(" ").forEach((function(t){G(this,t)}),this)}))},prop:function(t,e){return t=N[t]||t,1 in arguments?this.each((function(n){this[t]=X(this,e,n,this[t])})):this[0]&&this[0][t]},removeProp:function(t){return t=N[t]||t,this.each((function(){delete this[t]}))},data:function(t,n){var i="data-"+t.replace(w,"-$1").toLowerCase(),s=1 in arguments?this.attr(i,n):this.attr(i);return null!==s?Y(s):e},val:function(t){return 0 in arguments?(null==t&&(t=""),this.each((function(e){this.value=X(this,t,e,this.value)}))):this[0]&&(this[0].multiple?i(this[0]).find("option").filter((function(){return this.selected})).pluck("value"):this[0].value)},offset:function(e){if(e)return this.each((function(t){var n=i(this),s=X(this,e,t,n.offset()),r=n.offsetParent().offset(),o={top:s.top-r.top,left:s.left-r.left};"static"==n.css("position")&&(o.position="relative"),n.css(o)}));if(!this.length)return null;if(h.documentElement!==this[0]&&!i.contains(h.documentElement,this[0]))return{top:0,left:0};var n=this[0].getBoundingClientRect();return{left:n.left+t.pageXOffset,top:n.top+t.pageYOffset,width:Math.round(n.width),height:Math.round(n.height)}},css:function(t,e){if(arguments.length<2){var s=this[0];if("string"==typeof t){if(!s)return;return s.style[r(t)]||getComputedStyle(s,"").getPropertyValue(t)}if(k(t)){if(!s)return;var o={},a=getComputedStyle(s,"");return i.each(t,(function(t,e){o[e]=s.style[r(e)]||a.getPropertyValue(e)})),o}}var u="";if("string"==I(t))e||0===e?u=B(t)+":"+j(t,e):this.each((function(){this.style.removeProperty(B(t))}));else for(n in t)t[n]||0===t[n]?u+=B(n)+":"+j(n,t[n])+";":this.each((function(){this.style.removeProperty(B(n))}));return this.each((function(){this.style.cssText+=";"+u}))},index:function(t){return t?this.indexOf(i(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return!!t&&a.some.call(this,(function(t){return this.test(J(t))}),K(t))},addClass:function(t){return t?this.each((function(e){if("className"in this){s=[];var n=J(this);X(this,t,e,n).split(/\s+/g).forEach((function(t){i(this).hasClass(t)||s.push(t)}),this),s.length&&J(this,n+(n?" ":"")+s.join(" "))}})):this},removeClass:function(t){return this.each((function(n){if("className"in this){if(t===e)return J(this,"");s=J(this),X(this,t,n,s).split(/\s+/g).forEach((function(t){s=s.replace(K(t)," ")})),J(this,s.trim())}}))},toggleClass:function(t,n){return t?this.each((function(s){var r=i(this);X(this,t,s,J(this)).split(/\s+/g).forEach((function(t){(n===e?!r.hasClass(t):n)?r.addClass(t):r.removeClass(t)}))})):this},scrollTop:function(t){if(this.length){var n="scrollTop"in this[0];return t===e?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=t}:function(){this.scrollTo(this.scrollX,t)})}},scrollLeft:function(t){if(this.length){var n="scrollLeft"in this[0];return t===e?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=t}:function(){this.scrollTo(t,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),n=this.offset(),s=y.test(e[0].nodeName)?{top:0,left:0}:e.offset();return n.top-=parseFloat(i(t).css("margin-top"))||0,n.left-=parseFloat(i(t).css("margin-left"))||0,s.top+=parseFloat(i(e[0]).css("border-top-width"))||0,s.left+=parseFloat(i(e[0]).css("border-left-width"))||0,{top:n.top-s.top,left:n.left-s.left}}},offsetParent:function(){return this.map((function(){for(var t=this.offsetParent||h.body;t&&!y.test(t.nodeName)&&"static"==i(t).css("position");)t=t.offsetParent;return t}))}},i.fn.detach=i.fn.remove,["width","height"].forEach((function(t){var n=t.replace(/./,(function(t){return t[0].toUpperCase()}));i.fn[t]=function(s){var r,o=this[0];return s===e?L(o)?o["inner"+n]:M(o)?o.documentElement["scroll"+n]:(r=this.offset())&&r[t]:this.each((function(e){(o=i(this)).css(t,X(this,s,e,o[t]()))}))}})),C.forEach((function(n,s){var r=s%2;i.fn[n]=function(){var n,o,a=i.map(arguments,(function(t){var s=[];return"array"==(n=I(t))?(t.forEach((function(t){return t.nodeType!==e?s.push(t):i.zepto.isZ(t)?s=s.concat(t.get()):void(s=s.concat(O.fragment(t)))})),s):"object"==n||null==t?t:O.fragment(t)})),u=this.length>1;return a.length<1?this:this.each((function(e,n){o=r?n:n.parentNode,n=0==s?n.nextSibling:1==s?n.firstChild:2==s?n:null;var c=i.contains(h.documentElement,o);a.forEach((function(e){if(u)e=e.cloneNode(!0);else if(!o)return i(e).remove();o.insertBefore(e,n),c&&tt(e,(function(e){if(!(null==e.nodeName||"SCRIPT"!==e.nodeName.toUpperCase()||e.type&&"text/javascript"!==e.type||e.src)){var n=e.ownerDocument?e.ownerDocument.defaultView:t;n.eval.call(n,e.innerHTML)}}))}))}))},i.fn[r?n+"To":"insert"+(s?"Before":"After")]=function(t){return i(t)[n](this),this}})),O.Z.prototype=Q.prototype=i.fn,O.uniq=o,O.deserializeValue=Y,i.zepto=O,i}();return function(e){var n,i=1,s=Array.prototype.slice,r=e.isFunction,o=function(t){return"string"==typeof t},a={},u={},c="onfocusin"in t,l={focus:"focusin",blur:"focusout"},h={mouseenter:"mouseover",mouseleave:"mouseout"};function p(t){return t._zid||(t._zid=i++)}function f(t,e,n,i){if((e=d(e)).ns)var s=g(e.ns);return(a[p(t)]||[]).filter((function(t){return t&&(!e.e||t.e==e.e)&&(!e.ns||s.test(t.ns))&&(!n||p(t.fn)===p(n))&&(!i||t.sel==i)}))}function d(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function g(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!c&&t.e in l||!!e}function v(t){return h[t]||c&&l[t]||t}function y(t,i,s,r,o,u,c){var l=p(t),f=a[l]||(a[l]=[]);i.split(/\s/).forEach((function(i){if("ready"==i)return e(document).ready(s);var a=d(i);a.fn=s,a.sel=o,a.e in h&&(s=function(t){var n=t.relatedTarget;if(!n||n!==this&&!e.contains(this,n))return a.fn.apply(this,arguments)}),a.del=u;var l=u||s;a.proxy=function(e){if(!(e=S(e)).isImmediatePropagationStopped()){try{var i=Object.getOwnPropertyDescriptor(e,"data");i&&!i.writable||(e.data=r)}catch(e){}var s=l.apply(t,e._args==n?[e]:[e].concat(e._args));return!1===s&&(e.preventDefault(),e.stopPropagation()),s}},a.i=f.length,f.push(a),"addEventListener"in t&&t.addEventListener(v(a.e),a.proxy,m(a,c))}))}function w(t,e,n,i,s){var r=p(t);(e||"").split(/\s/).forEach((function(e){f(t,e,n,i).forEach((function(e){delete a[r][e.i],"removeEventListener"in t&&t.removeEventListener(v(e.e),e.proxy,m(e,s))}))}))}u.click=u.mousedown=u.mouseup=u.mousemove="MouseEvents",e.event={add:y,remove:w},e.proxy=function(t,n){var i=2 in arguments&&s.call(arguments,2);if(r(t)){var a=function(){return t.apply(n,i?i.concat(s.call(arguments)):arguments)};return a._zid=p(t),a}if(o(n))return i?(i.unshift(t[n],t),e.proxy.apply(null,i)):e.proxy(t[n],t);throw new TypeError("expected function")},e.fn.bind=function(t,e,n){return this.on(t,e,n)},e.fn.unbind=function(t,e){return this.off(t,e)},e.fn.one=function(t,e,n,i){return this.on(t,e,n,i,1)};var b=function(){return!0},C=function(){return!1},x=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,_={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};function S(t,i){if(i||!t.isDefaultPrevented){i||(i=t),e.each(_,(function(e,n){var s=i[e];t[e]=function(){return this[n]=b,s&&s.apply(i,arguments)},t[n]=C}));try{t.timeStamp||(t.timeStamp=Date.now())}catch(s){}(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?!1===i.returnValue:i.getPreventDefault&&i.getPreventDefault())&&(t.isDefaultPrevented=b)}return t}function E(t){var e,i={originalEvent:t};for(e in t)x.test(e)||t[e]===n||(i[e]=t[e]);return S(i,t)}e.fn.delegate=function(t,e,n){return this.on(e,t,n)},e.fn.undelegate=function(t,e,n){return this.off(e,t,n)},e.fn.live=function(t,n){return e(document.body).delegate(this.selector,t,n),this},e.fn.die=function(t,n){return e(document.body).undelegate(this.selector,t,n),this},e.fn.on=function(t,i,a,u,c){var l,h,p=this;return t&&!o(t)?(e.each(t,(function(t,e){p.on(t,i,a,e,c)})),p):(o(i)||r(u)||!1===u||(u=a,a=i,i=n),u!==n&&!1!==a||(u=a,a=n),!1===u&&(u=C),p.each((function(n,r){c&&(l=function(t){return w(r,t.type,u),u.apply(this,arguments)}),i&&(h=function(t){var n,o=e(t.target).closest(i,r).get(0);if(o&&o!==r)return n=e.extend(E(t),{currentTarget:o,liveFired:r}),(l||u).apply(o,[n].concat(s.call(arguments,1)))}),y(r,t,u,a,i,h||l)})))},e.fn.off=function(t,i,s){var a=this;return t&&!o(t)?(e.each(t,(function(t,e){a.off(t,i,e)})),a):(o(i)||r(s)||!1===s||(s=i,i=n),!1===s&&(s=C),a.each((function(){w(this,t,s,i)})))},e.fn.trigger=function(t,n){return(t=o(t)||e.isPlainObject(t)?e.Event(t):S(t))._args=n,this.each((function(){t.type in l&&"function"==typeof this[t.type]?this[t.type]():"dispatchEvent"in this?this.dispatchEvent(t):e(this).triggerHandler(t,n)}))},e.fn.triggerHandler=function(t,n){var i,s;return this.each((function(r,a){(i=E(o(t)?e.Event(t):t))._args=n,i.target=a,e.each(f(a,t.type||t),(function(t,e){if(s=e.proxy(i),i.isImmediatePropagationStopped())return!1}))})),s},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach((function(t){e.fn[t]=function(e){return 0 in arguments?this.bind(t,e):this.trigger(t)}})),e.Event=function(t,e){o(t)||(t=(e=t).type);var n=document.createEvent(u[t]||"Events"),i=!0;if(e)for(var s in e)"bubbles"==s?i=!!e[s]:n[s]=e[s];return n.initEvent(t,i,!0),S(n)}}(i),n=[],i.fn.remove=function(){return this.each((function(){this.parentNode&&("IMG"===this.tagName&&(n.push(this),this.src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=",e&&clearTimeout(e),e=setTimeout((function(){n=[]}),6e4)),this.parentNode.removeChild(this))}))},function(t){var e={},n=t.fn.data,i=t.camelCase,s=t.expando="Zepto"+ +new Date,r=[];function o(r,o){var u=r[s],c=u&&e[u];if(void 0===o)return c||a(r);if(c){if(o in c)return c[o];var l=i(o);if(l in c)return c[l]}return n.call(t(r),o)}function a(n,r,o){var a=n[s]||(n[s]=++t.uuid),c=e[a]||(e[a]=u(n));return void 0!==r&&(c[i(r)]=o),c}function u(e){var n={};return t.each(e.attributes||r,(function(e,s){0==s.name.indexOf("data-")&&(n[i(s.name.replace("data-",""))]=t.zepto.deserializeValue(s.value))})),n}t.fn.data=function(e,n){return void 0===n?t.isPlainObject(e)?this.each((function(n,i){t.each(e,(function(t,e){a(i,t,e)}))})):0 in this?o(this[0],e):void 0:this.each((function(){a(this,e,n)}))},t.data=function(e,n,i){return t(e).data(n,i)},t.hasData=function(n){var i=n[s],r=i&&e[i];return!!r&&!t.isEmptyObject(r)},t.fn.removeData=function(n){return"string"==typeof n&&(n=n.split(/\s+/)),this.each((function(){var r=this[s],o=r&&e[r];o&&t.each(n||o,(function(t){delete o[n?i(this):t]}))}))},["remove","empty"].forEach((function(e){var n=t.fn[e];t.fn[e]=function(){var t=this.find("*");return"remove"===e&&(t=t.add(this)),t.removeData(),n.call(this)}}))}(i),i}(e)},8820:t=>{"use strict";var e={}.hasOwnProperty,n=/[ -,\.\/:-@\[-\^`\{-~]/,i=/[ -,\.\/:-@\[\]\^`\{-~]/,s=/(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g,r=function t(r,o){"single"!=(o=function(t,n){if(!t)return n;var i={};for(var s in n)i[s]=e.call(t,s)?t[s]:n[s];return i}(o,t.options)).quotes&&"double"!=o.quotes&&(o.quotes="single");for(var a="double"==o.quotes?'"':"'",u=o.isIdentifier,c=r.charAt(0),l="",h=0,p=r.length;h<p;){var f=r.charAt(h++),d=f.charCodeAt(),g=void 0;if(d<32||d>126){if(d>=55296&&d<=56319&&h<p){var m=r.charCodeAt(h++);56320==(64512&m)?d=((1023&d)<<10)+(1023&m)+65536:h--}g="\\"+d.toString(16).toUpperCase()+" "}else g=o.escapeEverything?n.test(f)?"\\"+f:"\\"+d.toString(16).toUpperCase()+" ":/[\t\n\f\r\x0B]/.test(f)?"\\"+d.toString(16).toUpperCase()+" ":"\\"==f||!u&&('"'==f&&a==f||"'"==f&&a==f)||u&&i.test(f)?"\\"+f:f;l+=g}return u&&(/^-[-\d]/.test(l)?l="\\-"+l.slice(1):/\d/.test(c)&&(l="\\3"+c+" "+l.slice(1))),l=l.replace(s,(function(t,e,n){return e&&e.length%2?t:(e||"")+n})),!u&&o.wrap?a+l+a:l};r.options={escapeEverything:!1,isIdentifier:!1,quotes:"single",wrap:!1},r.version="3.0.0",t.exports=r},624:(t,e,n)=>{"use strict";var i,s,r,o=[n(5525),n(4785),n(8291),n(2709),n(2506),n(9176)],a=-1,u=[],c=!1;function l(){i&&s&&(i=!1,s.length?u=s.concat(u):a=-1,u.length&&h())}function h(){if(!i){c=!1,i=!0;for(var t=u.length,e=setTimeout(l);t;){for(s=u,u=[];s&&++a<t;)s[a].run();a=-1,t=u.length}s=null,a=-1,i=!1,clearTimeout(e)}}for(var p=-1,f=o.length;++p<f;)if(o[p]&&o[p].test&&o[p].test()){r=o[p].install(h);break}function d(t,e){this.fun=t,this.array=e}d.prototype.run=function(){var t=this.fun,e=this.array;switch(e.length){case 0:return t();case 1:return t(e[0]);case 2:return t(e[0],e[1]);case 3:return t(e[0],e[1],e[2]);default:return t.apply(null,e)}},t.exports=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];u.push(new d(t,e)),c||i||(c=!0,r())}},2709:(t,e,n)=>{"use strict";e.test=function(){return!n.g.setImmediate&&void 0!==n.g.MessageChannel},e.install=function(t){var e=new n.g.MessageChannel;return e.port1.onmessage=t,function(){e.port2.postMessage(0)}}},8291:(t,e,n)=>{"use strict";var i=n.g.MutationObserver||n.g.WebKitMutationObserver;e.test=function(){return i},e.install=function(t){var e=0,s=new i(t),r=n.g.document.createTextNode("");return s.observe(r,{characterData:!0}),function(){r.data=e=++e%2}}},4785:(t,e,n)=>{"use strict";e.test=function(){return"function"==typeof n.g.queueMicrotask},e.install=function(t){return function(){n.g.queueMicrotask(t)}}},2506:(t,e,n)=>{"use strict";e.test=function(){return"document"in n.g&&"onreadystatechange"in n.g.document.createElement("script")},e.install=function(t){return function(){var e=n.g.document.createElement("script");return e.onreadystatechange=function(){t(),e.onreadystatechange=null,e.parentNode.removeChild(e),e=null},n.g.document.documentElement.appendChild(e),t}}},9176:(t,e)=>{"use strict";e.test=function(){return!0},e.install=function(t){return function(){setTimeout(t,0)}}}}]); \ No newline at end of file diff --git a/assets/js/8443.4217f133.js.LICENSE.txt b/assets/js/8443.4217f133.js.LICENSE.txt new file mode 100644 index 0000000000..4f7ccd8a76 --- /dev/null +++ b/assets/js/8443.4217f133.js.LICENSE.txt @@ -0,0 +1 @@ +/*! https://mths.be/cssesc v3.0.0 by @mathias */ diff --git a/assets/js/85011861.0bf72b19.js b/assets/js/85011861.0bf72b19.js new file mode 100644 index 0000000000..162991f980 --- /dev/null +++ b/assets/js/85011861.0bf72b19.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8194],{3905:(n,e,t)=>{t.d(e,{Zo:()=>p,kt:()=>g});var a=t(7294);function r(n,e,t){return e in n?Object.defineProperty(n,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):n[e]=t,n}function o(n,e){var t=Object.keys(n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(n);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),t.push.apply(t,a)}return t}function s(n){for(var e=1;e<arguments.length;e++){var t=null!=arguments[e]?arguments[e]:{};e%2?o(Object(t),!0).forEach((function(e){r(n,e,t[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(e){Object.defineProperty(n,e,Object.getOwnPropertyDescriptor(t,e))}))}return n}function i(n,e){if(null==n)return{};var t,a,r=function(n,e){if(null==n)return{};var t,a,r={},o=Object.keys(n);for(a=0;a<o.length;a++)t=o[a],e.indexOf(t)>=0||(r[t]=n[t]);return r}(n,e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(n);for(a=0;a<o.length;a++)t=o[a],e.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(n,t)&&(r[t]=n[t])}return r}var l=a.createContext({}),c=function(n){var e=a.useContext(l),t=e;return n&&(t="function"==typeof n?n(e):s(s({},e),n)),t},p=function(n){var e=c(n.components);return a.createElement(l.Provider,{value:e},n.children)},d="mdxType",m={inlineCode:"code",wrapper:function(n){var e=n.children;return a.createElement(a.Fragment,{},e)}},u=a.forwardRef((function(n,e){var t=n.components,r=n.mdxType,o=n.originalType,l=n.parentName,p=i(n,["components","mdxType","originalType","parentName"]),d=c(t),u=r,g=d["".concat(l,".").concat(u)]||d[u]||m[u]||o;return t?a.createElement(g,s(s({ref:e},p),{},{components:t})):a.createElement(g,s({ref:e},p))}));function g(n,e){var t=arguments,r=e&&e.mdxType;if("string"==typeof n||r){var o=t.length,s=new Array(o);s[0]=u;var i={};for(var l in e)hasOwnProperty.call(e,l)&&(i[l]=e[l]);i.originalType=n,i[d]="string"==typeof n?n:r,s[1]=i;for(var c=2;c<o;c++)s[c]=t[c];return a.createElement.apply(null,s)}return a.createElement.apply(null,t)}u.displayName="MDXCreateElement"},9996:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>l,contentTitle:()=>s,default:()=>m,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const o={title:"Transaction",description:"Using CLI to submit or decode a transaction"},s="Transaction Tools",i={unversionedId:"general/manage-tokens/cli/transaction",id:"general/manage-tokens/cli/transaction",title:"Transaction",description:"Using CLI to submit or decode a transaction",source:"@site/docs/general/manage-tokens/cli/transaction.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/transaction",permalink:"/general/manage-tokens/cli/transaction",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/transaction.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Transaction",description:"Using CLI to submit or decode a transaction"},sidebar:"general",previous:{title:"Account",permalink:"/general/manage-tokens/cli/account"},next:{title:"Address book",permalink:"/general/manage-tokens/cli/addressbook"}},l={},c=[{value:"Decode, Verify and Show a Transaction",id:"show",level:2},{value:"Sign a Transaction",id:"sign",level:2},{value:"Submit a Transaction",id:"submit",level:2}],p={toc:c},d="wrapper";function m(n){let{components:e,...t}=n;return(0,r.kt)(d,(0,a.Z)({},p,t,{components:e,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"transaction-tools"},"Transaction Tools"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"transaction")," command offers convenient tools for processing raw\nconsensus or ParaTime transactions stored in a JSON file:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"decoding and displaying the transaction,"),(0,r.kt)("li",{parentName:"ul"},"verifying transaction's signature,"),(0,r.kt)("li",{parentName:"ul"},"signing the transaction,"),(0,r.kt)("li",{parentName:"ul"},"broadcasting the transaction.")),(0,r.kt)("h2",{id:"show"},"Decode, Verify and Show a Transaction"),(0,r.kt)("p",null,"To show the transaction, invoke ",(0,r.kt)("inlineCode",{parentName:"p"},"transaction show <filename.json>")," and provide\na filename containing a previously generated transaction by ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," or the\nOasis CLI's ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#output-file"},(0,r.kt)("inlineCode",{parentName:"a"},"--output-file"))," parameter."),(0,r.kt)("p",null,"For example, let's take the following transaction transferring ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0 TEST")," from\n",(0,r.kt)("inlineCode",{parentName:"p"},"test:alice")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"test:bob")," on Testnet consensus layer and store it to\n",(0,r.kt)("inlineCode",{parentName:"p"},"testtx.json"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="testtx.json"',title:'"testtx.json"'},'{\n "untrusted_raw_value": "pGNmZWWiY2dhcwFmYW1vdW50QGRib2R5omJ0b1UAyND0Wds45cwxynfmbSxEVty+tQJmYW1vdW50RDuaygBlbm9uY2UBZm1ldGhvZHBzdGFraW5nLlRyYW5zZmVy",\n "signature": {\n "public_key": "NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=",\n "signature": "k51gq/PyDHCjm2vEMMpePnnTOaFUddRadfrP8UmgzMz1G0JDr+1lRH9lsg04+2krpmMYs7TOgX55+RVJ5a+LDw=="\n }\n}\n')),(0,r.kt)("p",null,"We can decode and verify the transaction as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis transaction show testtx.json --network testnet\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Hash: bd312d0faf8b7399b8b92b07cb6b40b418995875551341fa8540503322c5b70a\nSigner: NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: k51gq/PyDHCjm2vEMMpePnnTOaFUddRadfrP8UmgzMz1G0JDr+1lRH9lsg04+2krpmMYs7TOgX55+RVJ5a+LDw==)\nContent:\n Method: staking.Transfer\n Body:\n To: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 1.0 TEST\n Nonce: 1\n Fee:\n Amount: 0.0 TEST\n Gas limit: 1\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\n")),(0,r.kt)("p",null,"Since the signature also includes the ",(0,r.kt)("a",{parentName:"p",href:"/core/crypto#chain-domain-separation"},"chain domain separation context"),", it\nwill be invalid on other networks such as Mainnet and Oasis CLI will mark it as\n",(0,r.kt)("inlineCode",{parentName:"p"},"[INVALID SIGNATURE]"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis transaction show testtx.json --network mainnet\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Hash: bd312d0faf8b7399b8b92b07cb6b40b418995875551341fa8540503322c5b70a\nSigner: NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: k51gq/PyDHCjm2vEMMpePnnTOaFUddRadfrP8UmgzMz1G0JDr+1lRH9lsg04+2krpmMYs7TOgX55+RVJ5a+LDw==)\n [INVALID SIGNATURE]\nContent:\n Method: staking.Transfer\n Body:\n To: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 1.0 ROSE\n Nonce: 1\n Fee:\n Amount: 0.0 ROSE\n Gas limit: 1\n (gas price: 0.0 ROSE per gas unit)\n\nNetwork: mainnet\nParaTime: none (consensus layer)\n")),(0,r.kt)("p",null,"A similar approach is suitable for ParaTime transactions. Take the following\ntransaction which transfers ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0 TEST")," from ",(0,r.kt)("inlineCode",{parentName:"p"},"test:alice")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"test:bob")," inside\nSapphire ParaTime on Testnet and save it as ",(0,r.kt)("inlineCode",{parentName:"p"},"testtx2.json"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="testtx2.json"',title:'"testtx2.json"'},'{\n "Body": "o2F2AWJhaaJic2mBomVub25jZQFsYWRkcmVzc19zcGVjoWlzaWduYXR1cmWhZ2VkMjU1MTlYIDXD8zVt2FNk/roDVLVFraEJ0b2zi/XWEmgX24xyz9aRY2ZlZaJjZ2FzAWZhbW91bnSCQEBkY2FsbKJkYm9keaJidG9VAMjQ9FnbOOXMMcp35m0sRFbcvrUCZmFtb3VudIJIDeC2s6dkAABAZm1ldGhvZHFhY2NvdW50cy5UcmFuc2Zlcg==",\n "AuthProofs": [\n {\n "signature": "mxOARaaRkHrHiUObGO2KbUXZhmbIS2h3hsRM+3Y/DzvMtbVdwcZm2EZ7oP7dR5XHKkrQnjMwZnkT0mdZUsLIBw=="\n }\n ]\n}\n')),(0,r.kt)("p",null,"Oasis CLI will be able to verify the transaction only for the exact network and\nParaTime combination since both are included inside the chain domain separation\ncontext of a ParaTime transaction signature."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis transaction show testtx2.json --network testnet --paratime sapphire\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Hash: 3013be1ba6e1ef17921382f01b53f519174b2f35753d1fc37ad11bfc382f51f5\nSigner(s):\n 1. NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: mxOARaaRkHrHiUObGO2KbUXZhmbIS2h3hsRM+3Y/DzvMtbVdwcZm2EZ7oP7dR5XHKkrQnjMwZnkT0mdZUsLIBw==)\nContent:\n Format: plain\n Method: accounts.Transfer\n Body:\n To: test:bob (oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx)\n Amount: 1.0 TEST\n Authorized signer(s):\n 1. NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE= (ed25519)\n Nonce: 1\n Fee:\n Amount: 0.0 TEST\n Gas limit: 1\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\n")),(0,r.kt)("h2",{id:"sign"},"Sign a Transaction"),(0,r.kt)("p",null,"To sign a ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#unsigned"},"previously unsigned transaction")," transaction or to append\nanother signature to the transaction (",(0,r.kt)("em",{parentName:"p"},"multisig"),"), run\n",(0,r.kt)("inlineCode",{parentName:"p"},"transaction sign <filename.json>"),"."),(0,r.kt)("p",null,"For example, let's transfer ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0 TEST")," from ",(0,r.kt)("inlineCode",{parentName:"p"},"test:alice")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"test:bob")," on\nTestnet consensus layer, but don't sign it and store it to\n",(0,r.kt)("inlineCode",{parentName:"p"},"testtx_unsigned.json"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="testtx_unsigned.json"',title:'"testtx_unsigned.json"'},'{\n "nonce": 32,\n "fee": {\n "amount": "0",\n "gas": 1265\n },\n "method": "staking.Transfer",\n "body": "omJ0b1UAyND0Wds45cwxynfmbSxEVty+tQJmYW1vdW50RDuaygA="\n}\n')),(0,r.kt)("p",null,"Comparing this transaction to ",(0,r.kt)("a",{parentName:"p",href:"#show"},(0,r.kt)("inlineCode",{parentName:"a"},"testtx.json"))," which was signed, we can\nnotice that the transaction is not wrapped inside the ",(0,r.kt)("inlineCode",{parentName:"p"},"untrusted_raw_value"),"\nenvelope with the ",(0,r.kt)("inlineCode",{parentName:"p"},"signature")," field."),(0,r.kt)("p",null,"Decoding unsigned transaction gives us similar output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis transaction show testtx_unsigned.json --network testnet\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Method: staking.Transfer\nBody:\n To: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 1.0 TEST\nNonce: 32\nFee:\n Amount: 0.0 TEST\n Gas limit: 1265\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\n")),(0,r.kt)("p",null,"Finally, let's sign the transaction:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis transaction sign testtx_unsigned.json --network testnet --account test:alice\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nMethod: staking.Transfer\nBody:\n To: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 1.0 TEST\nNonce: 39\nFee:\n Amount: 0.0 TEST\n Gas limit: 1265\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: test:alice\n")),(0,r.kt)("p",null,"We can also use ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#output-file"},(0,r.kt)("inlineCode",{parentName:"a"},"--output-file"))," here and store the\nsigned transaction back to another file instead of showing it."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#npa"},"Network and Account")," selectors are available for the ",(0,r.kt)("inlineCode",{parentName:"p"},"transaction sign"),"\ncommand.")),(0,r.kt)("h2",{id:"submit"},"Submit a Transaction"),(0,r.kt)("p",null,"Invoking ",(0,r.kt)("inlineCode",{parentName:"p"},"transaction submit <filename.json>")," will broadcast the consensus or\nParaTime transaction to the selected network or ParaTime. If the transaction\nhasn't been signed yet, Oasis CLI will first sign it with the selected account\nin your wallet and then broadcast it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis tx submit testtx.json --network testnet --no-paratime\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Broadcasting transaction...\nTransaction executed successfully.\nTransaction hash: a81a1dcd203bba01761a55527f2c44251278110a247e63a12f064bf41e07f13a\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis tx submit testtx2.json --network testnet --paratime sapphire\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Broadcasting transaction...\nTransaction included in block successfully.\nRound: 946461\nTransaction hash: 25f0b2a92b6171969e9cd41d047bc20b4e2307c3a329ddef41af73df69d95b5d\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/859.cfff1c0d.js b/assets/js/859.cfff1c0d.js new file mode 100644 index 0000000000..4a09470397 --- /dev/null +++ b/assets/js/859.cfff1c0d.js @@ -0,0 +1,2 @@ +/*! For license information please see 859.cfff1c0d.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[859],{3905:(e,t,r)=>{"use strict";r.d(t,{Zo:()=>u,kt:()=>p});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},f="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),h=a,p=f["".concat(s,".").concat(h)]||f[h]||d[h]||i;return r?n.createElement(p,o(o({ref:t},u),{},{components:r})):n.createElement(p,o({ref:t},u))}));function p(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[f]="string"==typeof e?e:a,o[1]=l;for(var c=2;c<i;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}h.displayName="MDXCreateElement"},1262:(e,t,r)=>{"use strict";r.d(t,{Z:()=>i});var n=r(7294),a=r(2389);function i(e){let{children:t,fallback:r}=e;return(0,a.Z)()?n.createElement(n.Fragment,null,t?.()):r??null}},3262:e=>{var t;self,t=function(){return function(){var e={8847:function(e,t,r){"use strict";var n=r(1828),a={"X,X div":'direction:ltr;font-family:"Open Sans",verdana,arial,sans-serif;margin:0;padding:0;',"X input,X button":'font-family:"Open Sans",verdana,arial,sans-serif;',"X input:focus,X button:focus":"outline:none;","X a":"text-decoration:none;","X a:hover":"text-decoration:none;","X .crisp":"shape-rendering:crispEdges;","X .user-select-none":"-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;","X svg":"overflow:hidden;","X svg a":"fill:#447adb;","X svg a:hover":"fill:#3c6dc5;","X .main-svg":"position:absolute;top:0;left:0;pointer-events:none;","X .main-svg .draglayer":"pointer-events:all;","X .cursor-default":"cursor:default;","X .cursor-pointer":"cursor:pointer;","X .cursor-crosshair":"cursor:crosshair;","X .cursor-move":"cursor:move;","X .cursor-col-resize":"cursor:col-resize;","X .cursor-row-resize":"cursor:row-resize;","X .cursor-ns-resize":"cursor:ns-resize;","X .cursor-ew-resize":"cursor:ew-resize;","X .cursor-sw-resize":"cursor:sw-resize;","X .cursor-s-resize":"cursor:s-resize;","X .cursor-se-resize":"cursor:se-resize;","X .cursor-w-resize":"cursor:w-resize;","X .cursor-e-resize":"cursor:e-resize;","X .cursor-nw-resize":"cursor:nw-resize;","X .cursor-n-resize":"cursor:n-resize;","X .cursor-ne-resize":"cursor:ne-resize;","X .cursor-grab":"cursor:-webkit-grab;cursor:grab;","X .modebar":"position:absolute;top:2px;right:2px;","X .ease-bg":"-webkit-transition:background-color .3s ease 0s;-moz-transition:background-color .3s ease 0s;-ms-transition:background-color .3s ease 0s;-o-transition:background-color .3s ease 0s;transition:background-color .3s ease 0s;","X .modebar--hover>:not(.watermark)":"opacity:0;-webkit-transition:opacity .3s ease 0s;-moz-transition:opacity .3s ease 0s;-ms-transition:opacity .3s ease 0s;-o-transition:opacity .3s ease 0s;transition:opacity .3s ease 0s;","X:hover .modebar--hover .modebar-group":"opacity:1;","X .modebar-group":"float:left;display:inline-block;box-sizing:border-box;padding-left:8px;position:relative;vertical-align:middle;white-space:nowrap;","X .modebar-btn":"position:relative;font-size:16px;padding:3px 4px;height:22px;cursor:pointer;line-height:normal;box-sizing:border-box;","X .modebar-btn svg":"position:relative;top:2px;","X .modebar.vertical":"display:flex;flex-direction:column;flex-wrap:wrap;align-content:flex-end;max-height:100%;","X .modebar.vertical svg":"top:-1px;","X .modebar.vertical .modebar-group":"display:block;float:none;padding-left:0px;padding-bottom:8px;","X .modebar.vertical .modebar-group .modebar-btn":"display:block;text-align:center;","X [data-title]:before,X [data-title]:after":"position:absolute;-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-o-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);display:none;opacity:0;z-index:1001;pointer-events:none;top:110%;right:50%;","X [data-title]:hover:before,X [data-title]:hover:after":"display:block;opacity:1;","X [data-title]:before":'content:"";position:absolute;background:rgba(0,0,0,0);border:6px solid rgba(0,0,0,0);z-index:1002;margin-top:-12px;border-bottom-color:#69738a;margin-right:-6px;',"X [data-title]:after":"content:attr(data-title);background:#69738a;color:#fff;padding:8px 10px;font-size:12px;line-height:12px;white-space:nowrap;margin-right:-18px;border-radius:2px;","X .vertical [data-title]:before,X .vertical [data-title]:after":"top:0%;right:200%;","X .vertical [data-title]:before":"border:6px solid rgba(0,0,0,0);border-left-color:#69738a;margin-top:8px;margin-right:-30px;",Y:'font-family:"Open Sans",verdana,arial,sans-serif;position:fixed;top:50px;right:20px;z-index:10000;font-size:10pt;max-width:180px;',"Y p":"margin:0;","Y .notifier-note":"min-width:180px;max-width:250px;border:1px solid #fff;z-index:3000;margin:0;background-color:#8c97af;background-color:rgba(140,151,175,.9);color:#fff;padding:10px;overflow-wrap:break-word;word-wrap:break-word;-ms-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;","Y .notifier-close":"color:#fff;opacity:.8;float:right;padding:0 5px;background:none;border:none;font-size:20px;font-weight:bold;line-height:20px;","Y .notifier-close:hover":"color:#444;text-decoration:none;cursor:pointer;"};for(var i in a){var o=i.replace(/^,/," ,").replace(/X/g,".js-plotly-plot .plotly").replace(/Y/g,".plotly-notifier");n.addStyleRule(o,a[i])}},8222:function(e,t,r){"use strict";e.exports=r(2887)},7206:function(e,t,r){"use strict";e.exports=r(822)},9509:function(e,t,r){"use strict";e.exports=r(2201)},9548:function(e,t,r){"use strict";e.exports=r(8729)},1039:function(e,t,r){"use strict";e.exports=r(4382)},4296:function(e,t,r){"use strict";e.exports=r(3102)},2576:function(e,t,r){"use strict";var n=r(9548);n.register([r(7206),r(4201),r(8222),r(1039),r(4296),r(6398),r(9509)]),e.exports=n},4201:function(e,t,r){"use strict";e.exports=r(8810)},6398:function(e,t,r){"use strict";e.exports=r(2275)},2884:function(e){"use strict";e.exports=[{path:"",backoff:0},{path:"M-2.4,-3V3L0.6,0Z",backoff:.6},{path:"M-3.7,-2.5V2.5L1.3,0Z",backoff:1.3},{path:"M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z",backoff:1.55},{path:"M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z",backoff:1.6},{path:"M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z",backoff:2},{path:"M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z",backoff:0,noRotate:!0},{path:"M2,2V-2H-2V2Z",backoff:0,noRotate:!0}]},215:function(e,t,r){"use strict";var n=r(2884),a=r(1940),i=r(5555),o=r(4467).templatedArray;r(4695),e.exports=o("annotation",{visible:{valType:"boolean",dflt:!0,editType:"calc+arraydraw"},text:{valType:"string",editType:"calc+arraydraw"},textangle:{valType:"angle",dflt:0,editType:"calc+arraydraw"},font:a({editType:"calc+arraydraw",colorEditType:"arraydraw"}),width:{valType:"number",min:1,dflt:null,editType:"calc+arraydraw"},height:{valType:"number",min:1,dflt:null,editType:"calc+arraydraw"},opacity:{valType:"number",min:0,max:1,dflt:1,editType:"arraydraw"},align:{valType:"enumerated",values:["left","center","right"],dflt:"center",editType:"arraydraw"},valign:{valType:"enumerated",values:["top","middle","bottom"],dflt:"middle",editType:"arraydraw"},bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"arraydraw"},bordercolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"arraydraw"},borderpad:{valType:"number",min:0,dflt:1,editType:"calc+arraydraw"},borderwidth:{valType:"number",min:0,dflt:1,editType:"calc+arraydraw"},showarrow:{valType:"boolean",dflt:!0,editType:"calc+arraydraw"},arrowcolor:{valType:"color",editType:"arraydraw"},arrowhead:{valType:"integer",min:0,max:n.length,dflt:1,editType:"arraydraw"},startarrowhead:{valType:"integer",min:0,max:n.length,dflt:1,editType:"arraydraw"},arrowside:{valType:"flaglist",flags:["end","start"],extras:["none"],dflt:"end",editType:"arraydraw"},arrowsize:{valType:"number",min:.3,dflt:1,editType:"calc+arraydraw"},startarrowsize:{valType:"number",min:.3,dflt:1,editType:"calc+arraydraw"},arrowwidth:{valType:"number",min:.1,editType:"calc+arraydraw"},standoff:{valType:"number",min:0,dflt:0,editType:"calc+arraydraw"},startstandoff:{valType:"number",min:0,dflt:0,editType:"calc+arraydraw"},ax:{valType:"any",editType:"calc+arraydraw"},ay:{valType:"any",editType:"calc+arraydraw"},axref:{valType:"enumerated",dflt:"pixel",values:["pixel",i.idRegex.x.toString()],editType:"calc"},ayref:{valType:"enumerated",dflt:"pixel",values:["pixel",i.idRegex.y.toString()],editType:"calc"},xref:{valType:"enumerated",values:["paper",i.idRegex.x.toString()],editType:"calc"},x:{valType:"any",editType:"calc+arraydraw"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto",editType:"calc+arraydraw"},xshift:{valType:"number",dflt:0,editType:"calc+arraydraw"},yref:{valType:"enumerated",values:["paper",i.idRegex.y.toString()],editType:"calc"},y:{valType:"any",editType:"calc+arraydraw"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"auto",editType:"calc+arraydraw"},yshift:{valType:"number",dflt:0,editType:"calc+arraydraw"},clicktoshow:{valType:"enumerated",values:[!1,"onoff","onout"],dflt:!1,editType:"arraydraw"},xclick:{valType:"any",editType:"arraydraw"},yclick:{valType:"any",editType:"arraydraw"},hovertext:{valType:"string",editType:"arraydraw"},hoverlabel:{bgcolor:{valType:"color",editType:"arraydraw"},bordercolor:{valType:"color",editType:"arraydraw"},font:a({editType:"arraydraw"}),editType:"arraydraw"},captureevents:{valType:"boolean",editType:"arraydraw"},editType:"calc",_deprecated:{ref:{valType:"string",editType:"calc"}}})},3749:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(2605).draw;function o(e){var t=e._fullLayout;n.filterVisible(t.annotations).forEach((function(t){var r=a.getFromId(e,t.xref),n=a.getFromId(e,t.yref),i=a.getRefType(t.xref),o=a.getRefType(t.yref);t._extremes={},"range"===i&&l(t,r),"range"===o&&l(t,n)}))}function l(e,t){var r,n=t._id,i=n.charAt(0),o=e[i],l=e["a"+i],s=e[i+"ref"],c=e["a"+i+"ref"],u=e["_"+i+"padplus"],f=e["_"+i+"padminus"],d={x:1,y:-1}[i]*e[i+"shift"],h=3*e.arrowsize*e.arrowwidth||0,p=h+d,v=h-d,y=3*e.startarrowsize*e.arrowwidth||0,g=y+d,m=y-d;if(c===s){var x=a.findExtremes(t,[t.r2c(o)],{ppadplus:p,ppadminus:v}),b=a.findExtremes(t,[t.r2c(l)],{ppadplus:Math.max(u,g),ppadminus:Math.max(f,m)});r={min:[x.min[0],b.min[0]],max:[x.max[0],b.max[0]]}}else g=l?g+l:g,m=l?m-l:m,r=a.findExtremes(t,[t.r2c(o)],{ppadplus:Math.max(u,p,g),ppadminus:Math.max(f,v,m)});e._extremes[n]=r}e.exports=function(e){var t=e._fullLayout;if(n.filterVisible(t.annotations).length&&e._fullData.length)return n.syncOrAsync([i,o],e)}},4317:function(e,t,r){"use strict";var n=r(1828),a=r(3972),i=r(4467).arrayEditor;function o(e,t){var r,n,a,i,o,s,c,u=e._fullLayout.annotations,f=[],d=[],h=[],p=(t||[]).length;for(r=0;r<u.length;r++)if(i=(a=u[r]).clicktoshow){for(n=0;n<p;n++)if(s=(o=t[n]).xaxis,c=o.yaxis,s._id===a.xref&&c._id===a.yref&&s.d2r(o.x)===l(a._xclick,s)&&c.d2r(o.y)===l(a._yclick,c)){(a.visible?"onout"===i?d:h:f).push(r);break}n===p&&a.visible&&"onout"===i&&d.push(r)}return{on:f,off:d,explicitOff:h}}function l(e,t){return"log"===t.type?t.l2r(e):t.d2r(e)}e.exports={hasClickToShow:function(e,t){var r=o(e,t);return r.on.length>0||r.explicitOff.length>0},onClick:function(e,t){var r,l,s=o(e,t),c=s.on,u=s.off.concat(s.explicitOff),f={},d=e._fullLayout.annotations;if(c.length||u.length){for(r=0;r<c.length;r++)(l=i(e.layout,"annotations",d[c[r]])).modifyItem("visible",!0),n.extendFlat(f,l.getUpdateObj());for(r=0;r<u.length;r++)(l=i(e.layout,"annotations",d[u[r]])).modifyItem("visible",!1),n.extendFlat(f,l.getUpdateObj());return a.call("update",e,{},f)}}}},5625:function(e,t,r){"use strict";var n=r(1828),a=r(7901);e.exports=function(e,t,r,i){i("opacity");var o=i("bgcolor"),l=i("bordercolor"),s=a.opacity(l);i("borderpad");var c=i("borderwidth"),u=i("showarrow");if(i("text",u?" ":r._dfltTitle.annotation),i("textangle"),n.coerceFont(i,"font",r.font),i("width"),i("align"),i("height")&&i("valign"),u){var f,d,h=i("arrowside");-1!==h.indexOf("end")&&(f=i("arrowhead"),d=i("arrowsize")),-1!==h.indexOf("start")&&(i("startarrowhead",f),i("startarrowsize",d)),i("arrowcolor",s?t.bordercolor:a.defaultLine),i("arrowwidth",2*(s&&c||1)),i("standoff"),i("startstandoff")}var p=i("hovertext"),v=r.hoverlabel||{};if(p){var y=i("hoverlabel.bgcolor",v.bgcolor||(a.opacity(o)?a.rgb(o):a.defaultLine)),g=i("hoverlabel.bordercolor",v.bordercolor||a.contrast(y));n.coerceFont(i,"hoverlabel.font",{family:v.font.family,size:v.font.size,color:v.font.color||g})}i("captureevents",!!p)}},4128:function(e,t,r){"use strict";var n=r(2770),a=r(8163);e.exports=function(e,t,r,i){t=t||{};var o="log"===r&&"linear"===t.type,l="linear"===r&&"log"===t.type;if(o||l)for(var s,c,u=e._fullLayout.annotations,f=t._id.charAt(0),d=0;d<u.length;d++)s=u[d],c="annotations["+d+"].",s[f+"ref"]===t._id&&h(f),s["a"+f+"ref"]===t._id&&h("a"+f);function h(e){var r=s[e],l=null;l=o?a(r,t.range):Math.pow(10,r),n(l)||(l=null),i(c+e,l)}}},4046:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(5501),o=r(5625),l=r(215);function s(e,t,r){function i(r,a){return n.coerce(e,t,l,r,a)}var s=i("visible"),c=i("clicktoshow");if(s||c){o(e,t,r,i);for(var u=t.showarrow,f=["x","y"],d=[-10,-30],h={_fullLayout:r},p=0;p<2;p++){var v=f[p],y=a.coerceRef(e,t,h,v,"","paper");if("paper"!==y&&a.getFromId(h,y)._annIndices.push(t._index),a.coercePosition(t,h,i,y,v,.5),u){var g="a"+v,m=a.coerceRef(e,t,h,g,"pixel",["pixel","paper"]);"pixel"!==m&&m!==y&&(m=t[g]="pixel");var x="pixel"===m?d[p]:.4;a.coercePosition(t,h,i,m,g,x)}i(v+"anchor"),i(v+"shift")}if(n.noneOrAll(e,t,["x","y"]),u&&n.noneOrAll(e,t,["ax","ay"]),c){var b=i("xclick"),_=i("yclick");t._xclick=void 0===b?t.x:a.cleanPosition(b,h,t.xref),t._yclick=void 0===_?t.y:a.cleanPosition(_,h,t.yref)}}}e.exports=function(e,t){i(e,t,{name:"annotations",handleItemDefaults:s})}},2605:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(4875),o=r(1828),l=o.strTranslate,s=r(9298),c=r(7901),u=r(1424),f=r(211),d=r(3893),h=r(6964),p=r(8569),v=r(4467).arrayEditor,y=r(3011);function g(e,t){var r=e._fullLayout.annotations[t]||{},n=s.getFromId(e,r.xref),a=s.getFromId(e,r.yref);n&&n.setScale(),a&&a.setScale(),x(e,r,t,!1,n,a)}function m(e,t,r,n,a){var i=a[r],o=a[r+"ref"],l=-1!==r.indexOf("y"),c="domain"===s.getRefType(o),u=l?n.h:n.w;return e?c?i+(l?-t:t)/e._length:e.p2r(e.r2p(i)+t):i+(l?-t:t)/u}function x(e,t,r,i,g,x){var b,_,w=e._fullLayout,T=e._fullLayout._size,M=e._context.edits;i?(b="annotation-"+i,_=i+".annotations"):(b="annotation",_="annotations");var k=v(e.layout,_,t),A=k.modifyBase,L=k.modifyItem,S=k.getUpdateObj;w._infolayer.selectAll("."+b+'[data-index="'+r+'"]').remove();var O="clip"+w._uid+"_ann"+r;if(t._input&&!1!==t.visible){var D={x:{},y:{}},C=+t.textangle||0,P=w._infolayer.append("g").classed(b,!0).attr("data-index",String(r)).style("opacity",t.opacity),I=P.append("g").classed("annotation-text-g",!0),R=M[t.showarrow?"annotationTail":"annotationPosition"],z=t.captureevents||M.annotationText||R,N=I.append("g").style("pointer-events",z?"all":null).call(h,"pointer").on("click",(function(){e._dragging=!1,e.emit("plotly_clickannotation",Z(n.event))}));t.hovertext&&N.on("mouseover",(function(){var r=t.hoverlabel,n=r.font,a=this.getBoundingClientRect(),i=e.getBoundingClientRect();f.loneHover({x0:a.left-i.left,x1:a.right-i.left,y:(a.top+a.bottom)/2-i.top,text:t.hovertext,color:r.bgcolor,borderColor:r.bordercolor,fontFamily:n.family,fontSize:n.size,fontColor:n.color},{container:w._hoverlayer.node(),outerContainer:w._paper.node(),gd:e})})).on("mouseout",(function(){f.loneUnhover(w._hoverlayer.node())}));var E=t.borderwidth,F=t.borderpad,H=E+F,j=N.append("rect").attr("class","bg").style("stroke-width",E+"px").call(c.stroke,t.bordercolor).call(c.fill,t.bgcolor),B=t.width||t.height,Y=w._topclips.selectAll("#"+O).data(B?[0]:[]);Y.enter().append("clipPath").classed("annclip",!0).attr("id",O).append("rect"),Y.exit().remove();var U=t.font,V=w._meta?o.templateString(t.text,w._meta):t.text,q=N.append("text").classed("annotation-text",!0).text(V);M.annotationText?q.call(d.makeEditable,{delegate:N,gd:e}).call(G).on("edit",(function(r){t.text=r,this.call(G),L("text",r),g&&g.autorange&&A(g._name+".autorange",!0),x&&x.autorange&&A(x._name+".autorange",!0),a.call("_guiRelayout",e,S())})):q.call(G)}else n.selectAll("#"+O).remove();function Z(e){var n={index:r,annotation:t._input,fullAnnotation:t,event:e};return i&&(n.subplotId=i),n}function G(r){return r.call(u.font,U).attr({"text-anchor":{left:"start",right:"end"}[t.align]||"middle"}),d.convertToTspans(r,e,W),r}function W(){var r=q.selectAll("a");1===r.size()&&r.text()===q.text()&&N.insert("a",":first-child").attr({"xlink:xlink:href":r.attr("xlink:href"),"xlink:xlink:show":r.attr("xlink:show")}).style({cursor:"pointer"}).node().appendChild(j.node());var n=N.select(".annotation-text-math-group"),f=!n.empty(),v=u.bBox((f?n:q).node()),b=v.width,_=v.height,k=t.width||b,z=t.height||_,F=Math.round(k+2*H),U=Math.round(z+2*H);function V(e,t){return"auto"===t&&(t=e<1/3?"left":e>2/3?"right":"center"),{center:0,middle:0,left:.5,bottom:-.5,right:-.5,top:.5}[t]}for(var G=!1,W=["x","y"],X=0;X<W.length;X++){var J,K,Q,$,ee,te=W[X],re=t[te+"ref"]||te,ne=t["a"+te+"ref"],ae={x:g,y:x}[te],ie=(C+("x"===te?0:-90))*Math.PI/180,oe=F*Math.cos(ie),le=U*Math.sin(ie),se=Math.abs(oe)+Math.abs(le),ce=t[te+"anchor"],ue=t[te+"shift"]*("x"===te?1:-1),fe=D[te],de=s.getRefType(re);if(ae&&"domain"!==de){var he=ae.r2fraction(t[te]);(he<0||he>1)&&(ne===re?((he=ae.r2fraction(t["a"+te]))<0||he>1)&&(G=!0):G=!0),J=ae._offset+ae.r2p(t[te]),$=.5}else{var pe="domain"===de;"x"===te?(Q=t[te],J=pe?ae._offset+ae._length*Q:J=T.l+T.w*Q):(Q=1-t[te],J=pe?ae._offset+ae._length*Q:J=T.t+T.h*Q),$=t.showarrow?.5:Q}if(t.showarrow){fe.head=J;var ve=t["a"+te];if(ee=oe*V(.5,t.xanchor)-le*V(.5,t.yanchor),ne===re){var ye=s.getRefType(ne);"domain"===ye?("y"===te&&(ve=1-ve),fe.tail=ae._offset+ae._length*ve):"paper"===ye?"y"===te?(ve=1-ve,fe.tail=T.t+T.h*ve):fe.tail=T.l+T.w*ve:fe.tail=ae._offset+ae.r2p(ve),K=ee}else fe.tail=J+ve,K=ee+ve;fe.text=fe.tail+ee;var ge=w["x"===te?"width":"height"];if("paper"===re&&(fe.head=o.constrain(fe.head,1,ge-1)),"pixel"===ne){var me=-Math.max(fe.tail-3,fe.text),xe=Math.min(fe.tail+3,fe.text)-ge;me>0?(fe.tail+=me,fe.text+=me):xe>0&&(fe.tail-=xe,fe.text-=xe)}fe.tail+=ue,fe.head+=ue}else K=ee=se*V($,ce),fe.text=J+ee;fe.text+=ue,ee+=ue,K+=ue,t["_"+te+"padplus"]=se/2+K,t["_"+te+"padminus"]=se/2-K,t["_"+te+"size"]=se,t["_"+te+"shift"]=ee}if(G)N.remove();else{var be=0,_e=0;if("left"!==t.align&&(be=(k-b)*("center"===t.align?.5:1)),"top"!==t.valign&&(_e=(z-_)*("middle"===t.valign?.5:1)),f)n.select("svg").attr({x:H+be-1,y:H+_e}).call(u.setClipUrl,B?O:null,e);else{var we=H+_e-v.top,Te=H+be-v.left;q.call(d.positionText,Te,we).call(u.setClipUrl,B?O:null,e)}Y.select("rect").call(u.setRect,H,H,k,z),j.call(u.setRect,E/2,E/2,F-E,U-E),N.call(u.setTranslate,Math.round(D.x.text-F/2),Math.round(D.y.text-U/2)),I.attr({transform:"rotate("+C+","+D.x.text+","+D.y.text+")"});var Me,ke=function(r,n){P.selectAll(".annotation-arrow-g").remove();var s=D.x.head,f=D.y.head,d=D.x.tail+r,h=D.y.tail+n,v=D.x.text+r,b=D.y.text+n,_=o.rotationXYMatrix(C,v,b),w=o.apply2DTransform(_),k=o.apply2DTransform2(_),O=+j.attr("width"),R=+j.attr("height"),z=v-.5*O,E=z+O,F=b-.5*R,H=F+R,B=[[z,F,z,H],[z,H,E,H],[E,H,E,F],[E,F,z,F]].map(k);if(!B.reduce((function(e,t){return e^!!o.segmentsIntersect(s,f,s+1e6,f+1e6,t[0],t[1],t[2],t[3])}),!1)){B.forEach((function(e){var t=o.segmentsIntersect(d,h,s,f,e[0],e[1],e[2],e[3]);t&&(d=t.x,h=t.y)}));var Y=t.arrowwidth,U=t.arrowcolor,V=t.arrowside,q=P.append("g").style({opacity:c.opacity(U)}).classed("annotation-arrow-g",!0),Z=q.append("path").attr("d","M"+d+","+h+"L"+s+","+f).style("stroke-width",Y+"px").call(c.stroke,c.rgb(U));if(y(Z,V,t),M.annotationPosition&&Z.node().parentNode&&!i){var G=s,W=f;if(t.standoff){var X=Math.sqrt(Math.pow(s-d,2)+Math.pow(f-h,2));G+=t.standoff*(d-s)/X,W+=t.standoff*(h-f)/X}var J,K,Q=q.append("path").classed("annotation-arrow",!0).classed("anndrag",!0).classed("cursor-move",!0).attr({d:"M3,3H-3V-3H3ZM0,0L"+(d-G)+","+(h-W),transform:l(G,W)}).style("stroke-width",Y+6+"px").call(c.stroke,"rgba(0,0,0,0)").call(c.fill,"rgba(0,0,0,0)");p.init({element:Q.node(),gd:e,prepFn:function(){var e=u.getTranslate(N);J=e.x,K=e.y,g&&g.autorange&&A(g._name+".autorange",!0),x&&x.autorange&&A(x._name+".autorange",!0)},moveFn:function(e,r){var n=w(J,K),a=n[0]+e,i=n[1]+r;N.call(u.setTranslate,a,i),L("x",m(g,e,"x",T,t)),L("y",m(x,r,"y",T,t)),t.axref===t.xref&&L("ax",m(g,e,"ax",T,t)),t.ayref===t.yref&&L("ay",m(x,r,"ay",T,t)),q.attr("transform",l(e,r)),I.attr({transform:"rotate("+C+","+a+","+i+")"})},doneFn:function(){a.call("_guiRelayout",e,S());var t=document.querySelector(".js-notes-box-panel");t&&t.redraw(t.selectedObj)}})}}};t.showarrow&&ke(0,0),R&&p.init({element:N.node(),gd:e,prepFn:function(){Me=I.attr("transform")},moveFn:function(e,r){var n="pointer";if(t.showarrow)t.axref===t.xref?L("ax",m(g,e,"ax",T,t)):L("ax",t.ax+e),t.ayref===t.yref?L("ay",m(x,r,"ay",T.w,t)):L("ay",t.ay+r),ke(e,r);else{if(i)return;var a,o;if(g)a=m(g,e,"x",T,t);else{var s=t._xsize/T.w,c=t.x+(t._xshift-t.xshift)/T.w-s/2;a=p.align(c+e/T.w,s,0,1,t.xanchor)}if(x)o=m(x,r,"y",T,t);else{var u=t._ysize/T.h,f=t.y-(t._yshift+t.yshift)/T.h-u/2;o=p.align(f-r/T.h,u,0,1,t.yanchor)}L("x",a),L("y",o),g&&x||(n=p.getCursor(g?.5:a,x?.5:o,t.xanchor,t.yanchor))}I.attr({transform:l(e,r)+Me}),h(N,n)},clickFn:function(r,n){t.captureevents&&e.emit("plotly_clickannotation",Z(n))},doneFn:function(){h(N),a.call("_guiRelayout",e,S());var t=document.querySelector(".js-notes-box-panel");t&&t.redraw(t.selectedObj)}})}}}e.exports={draw:function(e){var t=e._fullLayout;t._infolayer.selectAll(".annotation").remove();for(var r=0;r<t.annotations.length;r++)t.annotations[r].visible&&g(e,r);return i.previousPromises(e)},drawOne:g,drawRaw:x}},3011:function(e,t,r){"use strict";var n=r(9898),a=r(7901),i=r(2884),o=r(1828),l=o.strScale,s=o.strRotate,c=o.strTranslate;e.exports=function(e,t,r){var o,u,f,d,h=e.node(),p=i[r.arrowhead||0],v=i[r.startarrowhead||0],y=(r.arrowwidth||1)*(r.arrowsize||1),g=(r.arrowwidth||1)*(r.startarrowsize||1),m=t.indexOf("start")>=0,x=t.indexOf("end")>=0,b=p.backoff*y+r.standoff,_=v.backoff*g+r.startstandoff;if("line"===h.nodeName){o={x:+e.attr("x1"),y:+e.attr("y1")},u={x:+e.attr("x2"),y:+e.attr("y2")};var w=o.x-u.x,T=o.y-u.y;if(d=(f=Math.atan2(T,w))+Math.PI,b&&_&&b+_>Math.sqrt(w*w+T*T))return void R();if(b){if(b*b>w*w+T*T)return void R();var M=b*Math.cos(f),k=b*Math.sin(f);u.x+=M,u.y+=k,e.attr({x2:u.x,y2:u.y})}if(_){if(_*_>w*w+T*T)return void R();var A=_*Math.cos(f),L=_*Math.sin(f);o.x-=A,o.y-=L,e.attr({x1:o.x,y1:o.y})}}else if("path"===h.nodeName){var S=h.getTotalLength(),O="";if(S<b+_)return void R();var D=h.getPointAtLength(0),C=h.getPointAtLength(.1);f=Math.atan2(D.y-C.y,D.x-C.x),o=h.getPointAtLength(Math.min(_,S)),O="0px,"+_+"px,";var P=h.getPointAtLength(S),I=h.getPointAtLength(S-.1);d=Math.atan2(P.y-I.y,P.x-I.x),u=h.getPointAtLength(Math.max(0,S-b)),O+=S-(O?_+b:b)+"px,"+S+"px",e.style("stroke-dasharray",O)}function R(){e.style("stroke-dasharray","0px,100px")}function z(t,i,o,u){t.path&&(t.noRotate&&(o=0),n.select(h.parentNode).append("path").attr({class:e.attr("class"),d:t.path,transform:c(i.x,i.y)+s(180*o/Math.PI)+l(u)}).style({fill:a.rgb(r.arrowcolor),"stroke-width":0}))}m&&z(v,o,f,g),x&&z(p,u,d,y)}},2745:function(e,t,r){"use strict";var n=r(2605),a=r(4317);e.exports={moduleType:"component",name:"annotations",layoutAttributes:r(215),supplyLayoutDefaults:r(4046),includeBasePlot:r(6325)("annotations"),calcAutorange:r(3749),draw:n.draw,drawOne:n.drawOne,drawRaw:n.drawRaw,hasClickToShow:a.hasClickToShow,onClick:a.onClick,convertCoords:r(4128)}},6997:function(e,t,r){"use strict";var n=r(215),a=r(962).overrideAll,i=r(4467).templatedArray;e.exports=a(i("annotation",{visible:n.visible,x:{valType:"any"},y:{valType:"any"},z:{valType:"any"},ax:{valType:"number"},ay:{valType:"number"},xanchor:n.xanchor,xshift:n.xshift,yanchor:n.yanchor,yshift:n.yshift,text:n.text,textangle:n.textangle,font:n.font,width:n.width,height:n.height,opacity:n.opacity,align:n.align,valign:n.valign,bgcolor:n.bgcolor,bordercolor:n.bordercolor,borderpad:n.borderpad,borderwidth:n.borderwidth,showarrow:n.showarrow,arrowcolor:n.arrowcolor,arrowhead:n.arrowhead,startarrowhead:n.startarrowhead,arrowside:n.arrowside,arrowsize:n.arrowsize,startarrowsize:n.startarrowsize,arrowwidth:n.arrowwidth,standoff:n.standoff,startstandoff:n.startstandoff,hovertext:n.hovertext,hoverlabel:n.hoverlabel,captureevents:n.captureevents}),"calc","from-root")},5485:function(e,t,r){"use strict";var n=r(1828),a=r(9298);function i(e,t){var r=t.fullSceneLayout.domain,i=t.fullLayout._size,o={pdata:null,type:"linear",autorange:!1,range:[-1/0,1/0]};e._xa={},n.extendFlat(e._xa,o),a.setConvert(e._xa),e._xa._offset=i.l+r.x[0]*i.w,e._xa.l2p=function(){return.5*(1+e._pdata[0]/e._pdata[3])*i.w*(r.x[1]-r.x[0])},e._ya={},n.extendFlat(e._ya,o),a.setConvert(e._ya),e._ya._offset=i.t+(1-r.y[1])*i.h,e._ya.l2p=function(){return.5*(1-e._pdata[1]/e._pdata[3])*i.h*(r.y[1]-r.y[0])}}e.exports=function(e){for(var t=e.fullSceneLayout.annotations,r=0;r<t.length;r++)i(t[r],e);e.fullLayout._infolayer.selectAll(".annotation-"+e.id).remove()}},226:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(5501),o=r(5625),l=r(6997);function s(e,t,r,i){function s(r,a){return n.coerce(e,t,l,r,a)}function c(e){var n=e+"axis",i={_fullLayout:{}};return i._fullLayout[n]=r[n],a.coercePosition(t,i,s,e,e,.5)}s("visible")&&(o(e,t,i.fullLayout,s),c("x"),c("y"),c("z"),n.noneOrAll(e,t,["x","y","z"]),t.xref="x",t.yref="y",t.zref="z",s("xanchor"),s("yanchor"),s("xshift"),s("yshift"),t.showarrow&&(t.axref="pixel",t.ayref="pixel",s("ax",-10),s("ay",-30),n.noneOrAll(e,t,["ax","ay"])))}e.exports=function(e,t,r){i(e,t,{name:"annotations",handleItemDefaults:s,fullLayout:r.fullLayout})}},2188:function(e,t,r){"use strict";var n=r(2605).drawRaw,a=r(3538),i=["x","y","z"];e.exports=function(e){for(var t=e.fullSceneLayout,r=e.dataScale,o=t.annotations,l=0;l<o.length;l++){for(var s=o[l],c=!1,u=0;u<3;u++){var f=i[u],d=s[f],h=t[f+"axis"].r2fraction(d);if(h<0||h>1){c=!0;break}}c?e.fullLayout._infolayer.select(".annotation-"+e.id+'[data-index="'+l+'"]').remove():(s._pdata=a(e.glplot.cameraParams,[t.xaxis.r2l(s.x)*r[0],t.yaxis.r2l(s.y)*r[1],t.zaxis.r2l(s.z)*r[2]]),n(e.graphDiv,s,l,e.id,s._xa,s._ya))}}},2468:function(e,t,r){"use strict";var n=r(3972),a=r(1828);e.exports={moduleType:"component",name:"annotations3d",schema:{subplots:{scene:{annotations:r(6997)}}},layoutAttributes:r(6997),handleDefaults:r(226),includeBasePlot:function(e,t){var r=n.subplotsRegistry.gl3d;if(r)for(var i=r.attrRegex,o=Object.keys(e),l=0;l<o.length;l++){var s=o[l];i.test(s)&&(e[s].annotations||[]).length&&(a.pushUnique(t._basePlotModules,r),a.pushUnique(t._subplots.gl3d,s))}},convert:r(5485),draw:r(2188)}},7561:function(e,t,r){"use strict";e.exports=r(3489),r(4338),r(3961),r(8751),r(6825),r(7715),r(9384),r(3805),r(8874),r(3290),r(9108),r(5422),r(4320),r(1320),r(1367),r(1457)},2201:function(e,t,r){"use strict";var n=r(7561),a=r(1828),i=r(606),o=i.EPOCHJD,l=i.ONEDAY,s={valType:"enumerated",values:a.sortObjectKeys(n.calendars),editType:"calc",dflt:"gregorian"},c=function(e,t,r,n){var i={};return i[r]=s,a.coerce(e,t,i,r,n)},u="##",f={d:{0:"dd","-":"d"},e:{0:"d","-":"d"},a:{0:"D","-":"D"},A:{0:"DD","-":"DD"},j:{0:"oo","-":"o"},W:{0:"ww","-":"w"},m:{0:"mm","-":"m"},b:{0:"M","-":"M"},B:{0:"MM","-":"MM"},y:{0:"yy","-":"yy"},Y:{0:"yyyy","-":"yyyy"},U:u,w:u,c:{0:"D M d %X yyyy","-":"D M d %X yyyy"},x:{0:"mm/dd/yyyy","-":"mm/dd/yyyy"}},d={};function h(e){var t=d[e];return t||(t=d[e]=n.instance(e))}function p(e){return a.extendFlat({},s,{description:e})}function v(e){return"Sets the calendar system to use with `"+e+"` date data."}var y={xcalendar:p(v("x"))},g=a.extendFlat({},y,{ycalendar:p(v("y"))}),m=a.extendFlat({},g,{zcalendar:p(v("z"))}),x=p(["Sets the calendar system to use for `range` and `tick0`","if this is a date axis. This does not set the calendar for","interpreting data on this axis, that's specified in the trace","or via the global `layout.calendar`"].join(" "));e.exports={moduleType:"component",name:"calendars",schema:{traces:{scatter:g,bar:g,box:g,heatmap:g,contour:g,histogram:g,histogram2d:g,histogram2dcontour:g,scatter3d:m,surface:m,mesh3d:m,scattergl:g,ohlc:y,candlestick:y},layout:{calendar:p(["Sets the default calendar system to use for interpreting and","displaying dates throughout the plot."].join(" "))},subplots:{xaxis:{calendar:x},yaxis:{calendar:x},scene:{xaxis:{calendar:x},yaxis:{calendar:x},zaxis:{calendar:x}},polar:{radialaxis:{calendar:x}}},transforms:{filter:{valuecalendar:p(["WARNING: All transforms are deprecated and may be removed from the API in next major version.","Sets the calendar system to use for `value`, if it is a date."].join(" ")),targetcalendar:p(["WARNING: All transforms are deprecated and may be removed from the API in next major version.","Sets the calendar system to use for `target`, if it is an","array of dates. If `target` is a string (eg *x*) we use the","corresponding trace attribute (eg `xcalendar`) if it exists,","even if `targetcalendar` is provided."].join(" "))}}},layoutAttributes:s,handleDefaults:c,handleTraceDefaults:function(e,t,r,n){for(var a=0;a<r.length;a++)c(e,t,r[a]+"calendar",n.calendar)},CANONICAL_SUNDAY:{chinese:"2000-01-02",coptic:"2000-01-03",discworld:"2000-01-03",ethiopian:"2000-01-05",hebrew:"5000-01-01",islamic:"1000-01-02",julian:"2000-01-03",mayan:"5000-01-01",nanakshahi:"1000-01-05",nepali:"2000-01-05",persian:"1000-01-01",jalali:"1000-01-01",taiwan:"1000-01-04",thai:"2000-01-04",ummalqura:"1400-01-06"},CANONICAL_TICK:{chinese:"2000-01-01",coptic:"2000-01-01",discworld:"2000-01-01",ethiopian:"2000-01-01",hebrew:"5000-01-01",islamic:"1000-01-01",julian:"2000-01-01",mayan:"5000-01-01",nanakshahi:"1000-01-01",nepali:"2000-01-01",persian:"1000-01-01",jalali:"1000-01-01",taiwan:"1000-01-01",thai:"2000-01-01",ummalqura:"1400-01-01"},DFLTRANGE:{chinese:["2000-01-01","2001-01-01"],coptic:["1700-01-01","1701-01-01"],discworld:["1800-01-01","1801-01-01"],ethiopian:["2000-01-01","2001-01-01"],hebrew:["5700-01-01","5701-01-01"],islamic:["1400-01-01","1401-01-01"],julian:["2000-01-01","2001-01-01"],mayan:["5200-01-01","5201-01-01"],nanakshahi:["0500-01-01","0501-01-01"],nepali:["2000-01-01","2001-01-01"],persian:["1400-01-01","1401-01-01"],jalali:["1400-01-01","1401-01-01"],taiwan:["0100-01-01","0101-01-01"],thai:["2500-01-01","2501-01-01"],ummalqura:["1400-01-01","1401-01-01"]},getCal:h,worldCalFmt:function(e,t,r){for(var n,a,i,s,c,d=Math.floor((t+.05)/l)+o,p=h(r).fromJD(d),v=0;-1!==(v=e.indexOf("%",v));)"0"===(n=e.charAt(v+1))||"-"===n||"_"===n?(i=3,a=e.charAt(v+2),"_"===n&&(n="-")):(a=n,n="0",i=2),(s=f[a])?(c=s===u?u:p.formatDate(s[n]),e=e.substr(0,v)+c+e.substr(v+i),v+=c.length):v+=i;return e}}},2399:function(e,t){"use strict";t.defaults=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],t.defaultLine="#444",t.lightLine="#eee",t.background="#fff",t.borderLine="#BEC8D9",t.lightFraction=1e3/11},7901:function(e,t,r){"use strict";var n=r(4267),a=r(2770),i=r(3627).isTypedArray,o=e.exports={},l=r(2399);o.defaults=l.defaults;var s=o.defaultLine=l.defaultLine;o.lightLine=l.lightLine;var c=o.background=l.background;function u(e){if(a(e)||"string"!=typeof e)return e;var t=e.trim();if("rgb"!==t.substr(0,3))return e;var r=t.match(/^rgba?\s*\(([^()]*)\)$/);if(!r)return e;var n=r[1].trim().split(/\s*[\s,]\s*/),i="a"===t.charAt(3)&&4===n.length;if(!i&&3!==n.length)return e;for(var o=0;o<n.length;o++){if(!n[o].length)return e;if(n[o]=Number(n[o]),!(n[o]>=0))return e;if(3===o)n[o]>1&&(n[o]=1);else if(n[o]>=1)return e}var l=Math.round(255*n[0])+", "+Math.round(255*n[1])+", "+Math.round(255*n[2]);return i?"rgba("+l+", "+n[3]+")":"rgb("+l+")"}o.tinyRGB=function(e){var t=e.toRgb();return"rgb("+Math.round(t.r)+", "+Math.round(t.g)+", "+Math.round(t.b)+")"},o.rgb=function(e){return o.tinyRGB(n(e))},o.opacity=function(e){return e?n(e).getAlpha():0},o.addOpacity=function(e,t){var r=n(e).toRgb();return"rgba("+Math.round(r.r)+", "+Math.round(r.g)+", "+Math.round(r.b)+", "+t+")"},o.combine=function(e,t){var r=n(e).toRgb();if(1===r.a)return n(e).toRgbString();var a=n(t||c).toRgb(),i=1===a.a?a:{r:255*(1-a.a)+a.r*a.a,g:255*(1-a.a)+a.g*a.a,b:255*(1-a.a)+a.b*a.a},o={r:i.r*(1-r.a)+r.r*r.a,g:i.g*(1-r.a)+r.g*r.a,b:i.b*(1-r.a)+r.b*r.a};return n(o).toRgbString()},o.contrast=function(e,t,r){var a=n(e);return 1!==a.getAlpha()&&(a=n(o.combine(e,c))),(a.isDark()?t?a.lighten(t):c:r?a.darken(r):s).toString()},o.stroke=function(e,t){var r=n(t);e.style({stroke:o.tinyRGB(r),"stroke-opacity":r.getAlpha()})},o.fill=function(e,t){var r=n(t);e.style({fill:o.tinyRGB(r),"fill-opacity":r.getAlpha()})},o.clean=function(e){if(e&&"object"==typeof e){var t,r,n,a,l=Object.keys(e);for(t=0;t<l.length;t++)if(a=e[n=l[t]],"color"===n.substr(n.length-5))if(Array.isArray(a))for(r=0;r<a.length;r++)a[r]=u(a[r]);else e[n]=u(a);else if("colorscale"===n.substr(n.length-10)&&Array.isArray(a))for(r=0;r<a.length;r++)Array.isArray(a[r])&&(a[r][1]=u(a[r][1]));else if(Array.isArray(a)){var s=a[0];if(!Array.isArray(s)&&s&&"object"==typeof s)for(r=0;r<a.length;r++)o.clean(a[r])}else a&&"object"==typeof a&&!i(a)&&o.clean(a)}}},3583:function(e,t,r){"use strict";var n=r(3838),a=r(1940),i=r(1426).extendFlat,o=r(962).overrideAll;e.exports=o({orientation:{valType:"enumerated",values:["h","v"],dflt:"v"},thicknessmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"pixels"},thickness:{valType:"number",min:0,dflt:30},lenmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"fraction"},len:{valType:"number",min:0,dflt:1},x:{valType:"number"},xref:{valType:"enumerated",dflt:"paper",values:["container","paper"],editType:"layoutstyle"},xanchor:{valType:"enumerated",values:["left","center","right"]},xpad:{valType:"number",min:0,dflt:10},y:{valType:"number"},yref:{valType:"enumerated",dflt:"paper",values:["container","paper"],editType:"layoutstyle"},yanchor:{valType:"enumerated",values:["top","middle","bottom"]},ypad:{valType:"number",min:0,dflt:10},outlinecolor:n.linecolor,outlinewidth:n.linewidth,bordercolor:n.linecolor,borderwidth:{valType:"number",min:0,dflt:0},bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)"},tickmode:n.minor.tickmode,nticks:n.nticks,tick0:n.tick0,dtick:n.dtick,tickvals:n.tickvals,ticktext:n.ticktext,ticks:i({},n.ticks,{dflt:""}),ticklabeloverflow:i({},n.ticklabeloverflow,{}),ticklabelposition:{valType:"enumerated",values:["outside","inside","outside top","inside top","outside left","inside left","outside right","inside right","outside bottom","inside bottom"],dflt:"outside"},ticklen:n.ticklen,tickwidth:n.tickwidth,tickcolor:n.tickcolor,ticklabelstep:n.ticklabelstep,showticklabels:n.showticklabels,labelalias:n.labelalias,tickfont:a({}),tickangle:n.tickangle,tickformat:n.tickformat,tickformatstops:n.tickformatstops,tickprefix:n.tickprefix,showtickprefix:n.showtickprefix,ticksuffix:n.ticksuffix,showticksuffix:n.showticksuffix,separatethousands:n.separatethousands,exponentformat:n.exponentformat,minexponent:n.minexponent,showexponent:n.showexponent,title:{text:{valType:"string"},font:a({}),side:{valType:"enumerated",values:["right","top","bottom"]}},_deprecated:{title:{valType:"string"},titlefont:a({}),titleside:{valType:"enumerated",values:["right","top","bottom"],dflt:"top"}}},"colorbars","from-root")},939:function(e){"use strict";e.exports={cn:{colorbar:"colorbar",cbbg:"cbbg",cbfill:"cbfill",cbfills:"cbfills",cbline:"cbline",cblines:"cblines",cbaxis:"cbaxis",cbtitleunshift:"cbtitleunshift",cbtitle:"cbtitle",cboutline:"cboutline",crisp:"crisp",jsPlaceholder:"js-placeholder"}}},2499:function(e,t,r){"use strict";var n=r(1828),a=r(4467),i=r(6218),o=r(8701),l=r(6115),s=r(9426),c=r(3583);e.exports=function(e,t,r){var u=a.newContainer(t,"colorbar"),f=e.colorbar||{};function d(e,t){return n.coerce(f,u,c,e,t)}var h=r.margin||{t:0,b:0,l:0,r:0},p=r.width-h.l-h.r,v=r.height-h.t-h.b,y="v"===d("orientation"),g=d("thicknessmode");d("thickness","fraction"===g?30/(y?p:v):30);var m=d("lenmode");d("len","fraction"===m?1:y?v:p);var x,b,_,w="paper"===d("yref"),T="paper"===d("xref"),M="left";y?(_="middle",M=T?"left":"right",x=T?1.02:1,b=.5):(_=w?"bottom":"top",M="center",x=.5,b=w?1.02:1),n.coerce(f,u,{x:{valType:"number",min:T?-2:0,max:T?3:1,dflt:x}},"x"),n.coerce(f,u,{y:{valType:"number",min:w?-2:0,max:w?3:1,dflt:b}},"y"),d("xanchor",M),d("xpad"),d("yanchor",_),d("ypad"),n.noneOrAll(f,u,["x","y"]),d("outlinecolor"),d("outlinewidth"),d("bordercolor"),d("borderwidth"),d("bgcolor");var k=n.coerce(f,u,{ticklabelposition:{valType:"enumerated",dflt:"outside",values:y?["outside","inside","outside top","inside top","outside bottom","inside bottom"]:["outside","inside","outside left","inside left","outside right","inside right"]}},"ticklabelposition");d("ticklabeloverflow",-1!==k.indexOf("inside")?"hide past domain":"hide past div"),i(f,u,d,"linear");var A=r.font,L={outerTicks:!1,font:A};-1!==k.indexOf("inside")&&(L.bgColor="black"),s(f,u,d,"linear",L),l(f,u,d,"linear",L),o(f,u,d,"linear",L),d("title.text",r._dfltTitle.colorbar);var S=u.showticklabels?u.tickfont:A,O=n.extendFlat({},S,{color:A.color,size:n.bigFont(S.size)});n.coerceFont(d,"title.font",O),d("title.side",y?"top":"right")}},8981:function(e,t,r){"use strict";var n=r(9898),a=r(4267),i=r(4875),o=r(3972),l=r(9298),s=r(8569),c=r(1828),u=c.strTranslate,f=r(1426).extendFlat,d=r(6964),h=r(1424),p=r(7901),v=r(2998),y=r(3893),g=r(2869).flipScale,m=r(1453),x=r(2830),b=r(3838),_=r(8783),w=_.LINE_SPACING,T=_.FROM_TL,M=_.FROM_BR,k=r(939).cn;e.exports={draw:function(e){var t=e._fullLayout._infolayer.selectAll("g."+k.colorbar).data(function(e){var t,r,n,a,i=e._fullLayout,o=e.calcdata,l=[];function s(e){return f(e,{_fillcolor:null,_line:{color:null,width:null,dash:null},_levels:{start:null,end:null,size:null},_filllevels:null,_fillgradient:null,_zrange:null})}function c(){"function"==typeof a.calc?a.calc(e,n,t):(t._fillgradient=r.reversescale?g(r.colorscale):r.colorscale,t._zrange=[r[a.min],r[a.max]])}for(var u=0;u<o.length;u++){var d=o[u],h=(n=d[0].trace)._module.colorbar;if(!0===n.visible&&h)for(var p=Array.isArray(h),v=p?h:[h],y=0;y<v.length;y++){var m=(a=v[y]).container;(r=m?n[m]:n)&&r.showscale&&((t=s(r.colorbar))._id="cb"+n.uid+(p&&m?"-"+m:""),t._traceIndex=n.index,t._propPrefix=(m?m+".":"")+"colorbar.",t._meta=n._meta,c(),l.push(t))}}for(var x in i._colorAxes)if((r=i[x]).showscale){var b=i._colorAxes[x];(t=s(r.colorbar))._id="cb"+x,t._propPrefix=x+".colorbar.",t._meta=i._meta,a={min:"cmin",max:"cmax"},"heatmap"!==b[0]&&(n=b[1],a.calc=n._module.colorbar.calc),c(),l.push(t)}return l}(e),(function(e){return e._id}));t.enter().append("g").attr("class",(function(e){return e._id})).classed(k.colorbar,!0),t.each((function(t){var r=n.select(this);c.ensureSingle(r,"rect",k.cbbg),c.ensureSingle(r,"g",k.cbfills),c.ensureSingle(r,"g",k.cblines),c.ensureSingle(r,"g",k.cbaxis,(function(e){e.classed(k.crisp,!0)})),c.ensureSingle(r,"g",k.cbtitleunshift,(function(e){e.append("g").classed(k.cbtitle,!0)})),c.ensureSingle(r,"rect",k.cboutline);var g=function(e,t,r){var o="v"===t.orientation,s=t.len,d=t.lenmode,g=t.thickness,_=t.thicknessmode,A=t.outlinewidth,L=t.borderwidth,S=t.bgcolor,O=t.xanchor,D=t.yanchor,C=t.xpad,P=t.ypad,I=t.x,R=o?t.y:1-t.y,z="paper"===t.yref,N="paper"===t.xref,E=r._fullLayout,F=E._size,H=t._fillcolor,j=t._line,B=t.title,Y=B.side,U=t._zrange||n.extent(("function"==typeof H?H:j.color).domain()),V="function"==typeof j.color?j.color:function(){return j.color},q="function"==typeof H?H:function(){return H},Z=t._levels,G=function(e,t,r){var n,a,i=t._levels,o=[],l=[],s=i.end+i.size/100,c=i.size,u=1.001*r[0]-.001*r[1],f=1.001*r[1]-.001*r[0];for(a=0;a<1e5&&(n=i.start+a*c,!(c>0?n>=s:n<=s));a++)n>u&&n<f&&o.push(n);if(t._fillgradient)l=[0];else if("function"==typeof t._fillcolor){var d=t._filllevels;if(d)for(s=d.end+d.size/100,c=d.size,a=0;a<1e5&&(n=d.start+a*c,!(c>0?n>=s:n<=s));a++)n>r[0]&&n<r[1]&&l.push(n);else(l=o.map((function(e){return e-i.size/2}))).push(l[l.length-1]+i.size)}else t._fillcolor&&"string"==typeof t._fillcolor&&(l=[0]);return i.size<0&&(o.reverse(),l.reverse()),{line:o,fill:l}}(0,t,U),W=G.fill,X=G.line,J=Math.round(g*("fraction"===_?o?F.w:F.h:1)),K=J/(o?F.w:F.h),Q=Math.round(s*("fraction"===d?o?F.h:F.w:1)),$=Q/(o?F.h:F.w),ee=N?F.w:r._fullLayout.width,te=z?F.h:r._fullLayout.height,re=Math.round(o?I*ee+C:R*te+P),ne={center:.5,right:1}[O]||0,ae={top:1,middle:.5}[D]||0,ie=o?I-ne*K:R-ae*K,oe=o?R-ae*$:I-ne*$,le=Math.round(o?te*(1-oe):ee*oe);t._lenFrac=$,t._thickFrac=K,t._uFrac=ie,t._vFrac=oe;var se=t._axis=function(e,t,r){var n=e._fullLayout,a="v"===t.orientation,i={type:"linear",range:r,tickmode:t.tickmode,nticks:t.nticks,tick0:t.tick0,dtick:t.dtick,tickvals:t.tickvals,ticktext:t.ticktext,ticks:t.ticks,ticklen:t.ticklen,tickwidth:t.tickwidth,tickcolor:t.tickcolor,showticklabels:t.showticklabels,labelalias:t.labelalias,ticklabelposition:t.ticklabelposition,ticklabeloverflow:t.ticklabeloverflow,ticklabelstep:t.ticklabelstep,tickfont:t.tickfont,tickangle:t.tickangle,tickformat:t.tickformat,exponentformat:t.exponentformat,minexponent:t.minexponent,separatethousands:t.separatethousands,showexponent:t.showexponent,showtickprefix:t.showtickprefix,tickprefix:t.tickprefix,showticksuffix:t.showticksuffix,ticksuffix:t.ticksuffix,title:t.title,showline:!0,anchor:"free",side:a?"right":"bottom",position:1},o=a?"y":"x",l={type:"linear",_id:o+t._id},s={letter:o,font:n.font,noHover:!0,noTickson:!0,noTicklabelmode:!0,calendar:n.calendar};function u(e,t){return c.coerce(i,l,b,e,t)}return m(i,l,u,s,n),x(i,l,u,s),l}(r,t,U);se.position=K+(o?I+C/F.w:R+P/F.h);var ce=-1!==["top","bottom"].indexOf(Y);if(o&&ce&&(se.title.side=Y,se.titlex=I+C/F.w,se.titley=oe+("top"===B.side?$-P/F.h:P/F.h)),o||ce||(se.title.side=Y,se.titley=R+P/F.h,se.titlex=oe+C/F.w),j.color&&"auto"===t.tickmode){se.tickmode="linear",se.tick0=Z.start;var ue=Z.size,fe=c.constrain(Q/50,4,15)+1,de=(U[1]-U[0])/((t.nticks||fe)*ue);if(de>1){var he=Math.pow(10,Math.floor(Math.log(de)/Math.LN10));ue*=he*c.roundUp(de/he,[2,5,10]),(Math.abs(Z.start)/Z.size+1e-6)%1<2e-6&&(se.tick0=0)}se.dtick=ue}se.domain=o?[oe+P/F.h,oe+$-P/F.h]:[oe+C/F.w,oe+$-C/F.w],se.setScale(),e.attr("transform",u(Math.round(F.l),Math.round(F.t)));var pe,ve=e.select("."+k.cbtitleunshift).attr("transform",u(-Math.round(F.l),-Math.round(F.t))),ye=se.ticklabelposition,ge=se.title.font.size,me=e.select("."+k.cbaxis),xe=0,be=0;function _e(n,a){var i={propContainer:se,propName:t._propPrefix+"title",traceIndex:t._traceIndex,_meta:t._meta,placeholder:E._dfltTitle.colorbar,containerGroup:e.select("."+k.cbtitle)},o="h"===n.charAt(0)?n.substr(1):"h"+n;e.selectAll("."+o+",."+o+"-math-group").remove(),v.draw(r,n,f(i,a||{}))}function we(){var e,t;(o&&ce||!o&&!ce)&&("top"===Y&&(e=C+F.l+ee*I,t=P+F.t+te*(1-oe-$)+3+.75*ge),"bottom"===Y&&(e=C+F.l+ee*I,t=P+F.t+te*(1-oe)-3-.25*ge),"right"===Y&&(t=P+F.t+te*R+3+.75*ge,e=C+F.l+ee*oe),_e(se._id+"title",{attributes:{x:e,y:t,"text-anchor":o?"start":"middle"}}))}function Te(){if(o&&!ce||!o&&ce){var e,a,i=se.position||0,l=se._offset+se._length/2;if("right"===Y)a=l,e=F.l+ee*i+10+ge*(se.showticklabels?1:.5);else if(e=l,"bottom"===Y&&(a=F.t+te*i+10+(-1===ye.indexOf("inside")?se.tickfont.size:0)+("intside"!==se.ticks&&t.ticklen||0)),"top"===Y){var s=B.text.split("<br>").length;a=F.t+te*i+10-J-w*ge*s}_e((o?"h":"v")+se._id+"title",{avoid:{selection:n.select(r).selectAll("g."+se._id+"tick"),side:Y,offsetTop:o?0:F.t,offsetLeft:o?F.l:0,maxShift:o?E.width:E.height},attributes:{x:e,y:a,"text-anchor":"middle"},transform:{rotate:o?-90:0,offset:0}})}}function Me(){if(!o&&!ce||o&&ce){var i,s=e.select("."+k.cbtitle),f=s.select("text"),d=[-A/2,A/2],p=s.select(".h"+se._id+"title-math-group").node(),v=15.6;if(f.node()&&(v=parseInt(f.node().style.fontSize,10)*w),p?(i=h.bBox(p),be=i.width,(xe=i.height)>v&&(d[1]-=(xe-v)/2)):f.node()&&!f.classed(k.jsPlaceholder)&&(i=h.bBox(f.node()),be=i.width,xe=i.height),o){if(xe){if(xe+=5,"top"===Y)se.domain[1]-=xe/F.h,d[1]*=-1;else{se.domain[0]+=xe/F.h;var g=y.lineCount(f);d[1]+=(1-g)*v}s.attr("transform",u(d[0],d[1])),se.setScale()}}else be&&("right"===Y&&(se.domain[0]+=(be+ge/2)/F.w),s.attr("transform",u(d[0],d[1])),se.setScale())}e.selectAll("."+k.cbfills+",."+k.cblines).attr("transform",o?u(0,Math.round(F.h*(1-se.domain[1]))):u(Math.round(F.w*se.domain[0]),0)),me.attr("transform",o?u(0,Math.round(-F.t)):u(Math.round(-F.l),0));var m=e.select("."+k.cbfills).selectAll("rect."+k.cbfill).attr("style","").data(W);m.enter().append("rect").classed(k.cbfill,!0).style("stroke","none"),m.exit().remove();var x=U.map(se.c2p).map(Math.round).sort((function(e,t){return e-t}));m.each((function(e,i){var l=[0===i?U[0]:(W[i]+W[i-1])/2,i===W.length-1?U[1]:(W[i]+W[i+1])/2].map(se.c2p).map(Math.round);o&&(l[1]=c.constrain(l[1]+(l[1]>l[0])?1:-1,x[0],x[1]));var s=n.select(this).attr(o?"x":"y",re).attr(o?"y":"x",n.min(l)).attr(o?"width":"height",Math.max(J,2)).attr(o?"height":"width",Math.max(n.max(l)-n.min(l),2));if(t._fillgradient)h.gradient(s,r,t._id,o?"vertical":"horizontalreversed",t._fillgradient,"fill");else{var u=q(e).replace("e-","");s.attr("fill",a(u).toHexString())}}));var b=e.select("."+k.cblines).selectAll("path."+k.cbline).data(j.color&&j.width?X:[]);b.enter().append("path").classed(k.cbline,!0),b.exit().remove(),b.each((function(e){var t=re,r=Math.round(se.c2p(e))+j.width/2%1;n.select(this).attr("d","M"+(o?t+","+r:r+","+t)+(o?"h":"v")+J).call(h.lineGroupStyle,j.width,V(e),j.dash)})),me.selectAll("g."+se._id+"tick,path").remove();var _=re+J+(A||0)/2-("outside"===t.ticks?1:0),T=l.calcTicks(se),M=l.getTickSigns(se)[2];return l.drawTicks(r,se,{vals:"inside"===se.ticks?l.clipEnds(se,T):T,layer:me,path:l.makeTickPath(se,_,M),transFn:l.makeTransTickFn(se)}),l.drawLabels(r,se,{vals:T,layer:me,transFn:l.makeTransTickLabelFn(se),labelFns:l.makeLabelFns(se,_)})}function ke(){var n,l=J+A/2;-1===ye.indexOf("inside")&&(n=h.bBox(me.node()),l+=o?n.width:n.height),pe=ve.select("text");var c=0,f=o&&"top"===Y,v=!o&&"right"===Y,y=0;if(pe.node()&&!pe.classed(k.jsPlaceholder)){var m,x=ve.select(".h"+se._id+"title-math-group").node();x&&(o&&ce||!o&&!ce)?(c=(n=h.bBox(x)).width,m=n.height):(c=(n=h.bBox(ve.node())).right-F.l-(o?re:le),m=n.bottom-F.t-(o?le:re),o||"top"!==Y||(l+=n.height,y=n.height)),v&&(pe.attr("transform",u(c/2+ge/2,0)),c*=2),l=Math.max(l,o?c:m)}var b=2*(o?C:P)+l+L+A/2,w=0;!o&&B.text&&"bottom"===D&&R<=0&&(b+=w=b/2,y+=w),E._hColorbarMoveTitle=w,E._hColorbarMoveCBTitle=y;var H=L+A,j=(o?re:le)-H/2-(o?C:0),U=(o?le:re)-(o?Q:P+y-w);e.select("."+k.cbbg).attr("x",j).attr("y",U).attr(o?"width":"height",Math.max(b-w,2)).attr(o?"height":"width",Math.max(Q+H,2)).call(p.fill,S).call(p.stroke,t.bordercolor).style("stroke-width",L);var V=v?Math.max(c-10,0):0;e.selectAll("."+k.cboutline).attr("x",(o?re:le+C)+V).attr("y",(o?le+P-Q:re)+(f?xe:0)).attr(o?"width":"height",Math.max(J,2)).attr(o?"height":"width",Math.max(Q-(o?2*P+xe:2*C+V),2)).call(p.stroke,t.outlinecolor).style({fill:"none","stroke-width":A});var q=o?ne*b:0,Z=o?0:(1-ae)*b-y;if(q=N?F.l-q:-q,Z=z?F.t-Z:-Z,e.attr("transform",u(q,Z)),!o&&(L||a(S).getAlpha()&&!a.equals(E.paper_bgcolor,S))){var G=me.selectAll("text"),W=G[0].length,X=e.select("."+k.cbbg).node(),K=h.bBox(X),$=h.getTranslate(e),ee=2;G.each((function(e,t){var r=0,n=W-1;if(t===r||t===n){var a,i=h.bBox(this),o=h.getTranslate(this);if(t===n){var l=i.right+o.x;(a=K.right+$.x+le-L-ee+I-l)>0&&(a=0)}else if(t===r){var s=i.left+o.x;(a=K.left+$.x+le+L+ee-s)<0&&(a=0)}a&&(W<3?this.setAttribute("transform","translate("+a+",0) "+this.getAttribute("transform")):this.setAttribute("visibility","hidden"))}}))}var te={},ie=T[O],oe=M[O],ue=T[D],fe=M[D],de=b-J;o?("pixels"===d?(te.y=R,te.t=Q*ue,te.b=Q*fe):(te.t=te.b=0,te.yt=R+s*ue,te.yb=R-s*fe),"pixels"===_?(te.x=I,te.l=b*ie,te.r=b*oe):(te.l=de*ie,te.r=de*oe,te.xl=I-g*ie,te.xr=I+g*oe)):("pixels"===d?(te.x=I,te.l=Q*ie,te.r=Q*oe):(te.l=te.r=0,te.xl=I+s*ie,te.xr=I-s*oe),"pixels"===_?(te.y=1-R,te.t=b*ue,te.b=b*fe):(te.t=de*ue,te.b=de*fe,te.yt=R-g*ue,te.yb=R+g*fe));var he=t.y<.5?"b":"t",be=t.x<.5?"l":"r";r._fullLayout._reservedMargin[t._id]={};var _e={r:E.width-j-q,l:j+te.r,b:E.height-U-Z,t:U+te.b};N&&z?i.autoMargin(r,t._id,te):N?r._fullLayout._reservedMargin[t._id][he]=_e[he]:z||o?r._fullLayout._reservedMargin[t._id][be]=_e[be]:r._fullLayout._reservedMargin[t._id][he]=_e[he]}return c.syncOrAsync([i.previousPromises,we,Me,Te,i.previousPromises,ke],r)}(r,t,e);g&&g.then&&(e._promises||[]).push(g),e._context.edits.colorbarPosition&&function(e,t,r){var n,a,i,l="v"===t.orientation,c=r._fullLayout,f=c._size;s.init({element:e.node(),gd:r,prepFn:function(){n=e.attr("transform"),d(e)},moveFn:function(r,o){e.attr("transform",n+u(r,o)),a=s.align((l?t._uFrac:t._vFrac)+r/f.w,l?t._thickFrac:t._lenFrac,0,1,t.xanchor),i=s.align((l?t._vFrac:1-t._uFrac)-o/f.h,l?t._lenFrac:t._thickFrac,0,1,t.yanchor);var c=s.getCursor(a,i,t.xanchor,t.yanchor);d(e,c)},doneFn:function(){if(d(e),void 0!==a&&void 0!==i){var n={};n[t._propPrefix+"x"]=a,n[t._propPrefix+"y"]=i,void 0!==t._traceIndex?o.call("_guiRestyle",r,n,t._traceIndex):o.call("_guiRelayout",r,n)}}})}(r,t,e)})),t.exit().each((function(t){i.autoMargin(e,t._id)})).remove(),t.order()}}},6228:function(e,t,r){"use strict";var n=r(1828);e.exports=function(e){return n.isPlainObject(e.colorbar)}},2311:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"colorbar",attributes:r(3583),supplyDefaults:r(2499),draw:r(8981).draw,hasColorbar:r(6228)}},693:function(e,t,r){"use strict";var n=r(3583),a=r(587).counter,i=r(8607),o=r(3282).scales;function l(e){return"`"+e+"`"}i(o),e.exports=function(e,t){e=e||"";var r,i=(t=t||{}).cLetter||"c",s=("onlyIfNumerical"in t?t.onlyIfNumerical:Boolean(e),"noScale"in t?t.noScale:"marker.line"===e),c="showScaleDflt"in t?t.showScaleDflt:"z"===i,u="string"==typeof t.colorscaleDflt?o[t.colorscaleDflt]:null,f=t.editTypeOverride||"",d=e?e+".":"";"colorAttr"in t?(r=t.colorAttr,t.colorAttr):l(d+(r={z:"z",c:"color"}[i]));var h=i+"auto",p=i+"min",v=i+"max",y=i+"mid",g=(l(d+h),l(d+p),l(d+v),{});g[p]=g[v]=void 0;var m={};m[h]=!1;var x={};return"color"===r&&(x.color={valType:"color",arrayOk:!0,editType:f||"style"},t.anim&&(x.color.anim=!0)),x[h]={valType:"boolean",dflt:!0,editType:"calc",impliedEdits:g},x[p]={valType:"number",dflt:null,editType:f||"plot",impliedEdits:m},x[v]={valType:"number",dflt:null,editType:f||"plot",impliedEdits:m},x[y]={valType:"number",dflt:null,editType:"calc",impliedEdits:g},x.colorscale={valType:"colorscale",editType:"calc",dflt:u,impliedEdits:{autocolorscale:!1}},x.autocolorscale={valType:"boolean",dflt:!1!==t.autoColorDflt,editType:"calc",impliedEdits:{colorscale:void 0}},x.reversescale={valType:"boolean",dflt:!1,editType:"plot"},s||(x.showscale={valType:"boolean",dflt:c,editType:"calc"},x.colorbar=n),t.noColorAxis||(x.coloraxis={valType:"subplotid",regex:a("coloraxis"),dflt:null,editType:"calc"}),x}},8803:function(e,t,r){"use strict";var n=r(2770),a=r(1828),i=r(2869).extractOpts;e.exports=function(e,t,r){var o,l=e._fullLayout,s=r.vals,c=r.containerStr,u=c?a.nestedProperty(t,c).get():t,f=i(u),d=!1!==f.auto,h=f.min,p=f.max,v=f.mid,y=function(){return a.aggNums(Math.min,null,s)},g=function(){return a.aggNums(Math.max,null,s)};void 0===h?h=y():d&&(h=u._colorAx&&n(h)?Math.min(h,y()):y()),void 0===p?p=g():d&&(p=u._colorAx&&n(p)?Math.max(p,g()):g()),d&&void 0!==v&&(p-v>v-h?h=v-(p-v):p-v<v-h&&(p=v+(v-h))),h===p&&(h-=.5,p+=.5),f._sync("min",h),f._sync("max",p),f.autocolorscale&&(o=h*p<0?l.colorscale.diverging:h>=0?l.colorscale.sequential:l.colorscale.sequentialminus,f._sync("colorscale",o))}},3046:function(e,t,r){"use strict";var n=r(1828),a=r(2869).hasColorscale,i=r(2869).extractOpts;e.exports=function(e,t){function r(e,t){var r=e["_"+t];void 0!==r&&(e[t]=r)}function o(e,a){var o=a.container?n.nestedProperty(e,a.container).get():e;if(o)if(o.coloraxis)o._colorAx=t[o.coloraxis];else{var l=i(o),s=l.auto;(s||void 0===l.min)&&r(o,a.min),(s||void 0===l.max)&&r(o,a.max),l.autocolorscale&&r(o,"colorscale")}}for(var l=0;l<e.length;l++){var s=e[l],c=s._module.colorbar;if(c)if(Array.isArray(c))for(var u=0;u<c.length;u++)o(s,c[u]);else o(s,c);a(s,"marker.line")&&o(s,{container:"marker.line",min:"cmin",max:"cmax"})}for(var f in t._colorAxes)o(t[f],{min:"cmin",max:"cmax"})}},1586:function(e,t,r){"use strict";var n=r(2770),a=r(1828),i=r(6228),o=r(2499),l=r(3282).isValid,s=r(3972).traceIs;function c(e,t){var r=t.slice(0,t.length-1);return t?a.nestedProperty(e,r).get()||{}:e}e.exports=function e(t,r,u,f,d){var h=d.prefix,p=d.cLetter,v="_module"in r,y=c(t,h),g=c(r,h),m=c(r._template||{},h)||{},x=function(){return delete t.coloraxis,delete r.coloraxis,e(t,r,u,f,d)};if(v){var b=u._colorAxes||{},_=f(h+"coloraxis");if(_){var w=s(r,"contour")&&a.nestedProperty(r,"contours.coloring").get()||"heatmap",T=b[_];return void(T?(T[2].push(x),T[0]!==w&&(T[0]=!1,a.warn(["Ignoring coloraxis:",_,"setting","as it is linked to incompatible colorscales."].join(" ")))):b[_]=[w,r,[x]])}}var M=y[p+"min"],k=y[p+"max"],A=n(M)&&n(k)&&M<k;f(h+p+"auto",!A)?f(h+p+"mid"):(f(h+p+"min"),f(h+p+"max"));var L,S,O=y.colorscale,D=m.colorscale;void 0!==O&&(L=!l(O)),void 0!==D&&(L=!l(D)),f(h+"autocolorscale",L),f(h+"colorscale"),f(h+"reversescale"),"marker.line."!==h&&(h&&v&&(S=i(y)),f(h+"showscale",S)&&(h&&m&&(g._template=m),o(y,g,u)))}},2869:function(e,t,r){"use strict";var n=r(9898),a=r(4267),i=r(2770),o=r(1828),l=r(7901),s=r(3282).isValid,c=["showscale","autocolorscale","colorscale","reversescale","colorbar"],u=["min","max","mid","auto"];function f(e){var t,r,n,a=e._colorAx,i=a||e,o={};for(r=0;r<c.length;r++)o[n=c[r]]=i[n];if(a)for(t="c",r=0;r<u.length;r++)o[n=u[r]]=i["c"+n];else{var l;for(r=0;r<u.length;r++)((l="c"+(n=u[r]))in i||(l="z"+n)in i)&&(o[n]=i[l]);t=l.charAt(0)}return o._sync=function(e,r){var n=-1!==u.indexOf(e)?t+e:e;i[n]=i["_"+n]=r},o}function d(e){for(var t=f(e),r=t.min,n=t.max,a=t.reversescale?h(t.colorscale):t.colorscale,i=a.length,o=new Array(i),l=new Array(i),s=0;s<i;s++){var c=a[s];o[s]=r+c[0]*(n-r),l[s]=c[1]}return{domain:o,range:l}}function h(e){for(var t=e.length,r=new Array(t),n=t-1,a=0;n>=0;n--,a++){var i=e[n];r[a]=[1-i[0],i[1]]}return r}function p(e,t){t=t||{};for(var r=e.domain,o=e.range,s=o.length,c=new Array(s),u=0;u<s;u++){var f=a(o[u]).toRgb();c[u]=[f.r,f.g,f.b,f.a]}var d,h=n.scale.linear().domain(r).range(c).clamp(!0),p=t.noNumericCheck,y=t.returnArray;return(d=p&&y?h:p?function(e){return v(h(e))}:y?function(e){return i(e)?h(e):a(e).isValid()?e:l.defaultLine}:function(e){return i(e)?v(h(e)):a(e).isValid()?e:l.defaultLine}).domain=h.domain,d.range=function(){return o},d}function v(e){var t={r:e[0],g:e[1],b:e[2],a:e[3]};return a(t).toRgbString()}e.exports={hasColorscale:function(e,t,r){var n=t?o.nestedProperty(e,t).get()||{}:e,a=n[r||"color"],l=!1;if(o.isArrayOrTypedArray(a))for(var c=0;c<a.length;c++)if(i(a[c])){l=!0;break}return o.isPlainObject(n)&&(l||!0===n.showscale||i(n.cmin)&&i(n.cmax)||s(n.colorscale)||o.isPlainObject(n.colorbar))},extractOpts:f,extractScale:d,flipScale:h,makeColorScaleFunc:p,makeColorScaleFuncFromTrace:function(e,t){return p(d(e),t)}}},1081:function(e,t,r){"use strict";var n=r(3282),a=r(2869);e.exports={moduleType:"component",name:"colorscale",attributes:r(693),layoutAttributes:r(2673),supplyLayoutDefaults:r(959),handleDefaults:r(1586),crossTraceDefaults:r(3046),calc:r(8803),scales:n.scales,defaultScale:n.defaultScale,getScale:n.get,isValidScale:n.isValid,hasColorscale:a.hasColorscale,extractOpts:a.extractOpts,extractScale:a.extractScale,flipScale:a.flipScale,makeColorScaleFunc:a.makeColorScaleFunc,makeColorScaleFuncFromTrace:a.makeColorScaleFuncFromTrace}},2673:function(e,t,r){"use strict";var n=r(1426).extendFlat,a=r(693),i=r(3282).scales;e.exports={editType:"calc",colorscale:{editType:"calc",sequential:{valType:"colorscale",dflt:i.Reds,editType:"calc"},sequentialminus:{valType:"colorscale",dflt:i.Blues,editType:"calc"},diverging:{valType:"colorscale",dflt:i.RdBu,editType:"calc"}},coloraxis:n({_isSubplotObj:!0,editType:"calc"},a("",{colorAttr:"corresponding trace color array(s)",noColorAxis:!0,showScaleDflt:!0}))}},959:function(e,t,r){"use strict";var n=r(1828),a=r(4467),i=r(2673),o=r(1586);e.exports=function(e,t){function r(r,a){return n.coerce(e,t,i,r,a)}r("colorscale.sequential"),r("colorscale.sequentialminus"),r("colorscale.diverging");var l,s,c=t._colorAxes;function u(e,t){return n.coerce(l,s,i.coloraxis,e,t)}for(var f in c){var d=c[f];if(d[0])l=e[f]||{},(s=a.newContainer(t,f,"coloraxis"))._name=f,o(l,s,t,u,{prefix:"",cLetter:"c"});else{for(var h=0;h<d[2].length;h++)d[2][h]();delete t._colorAxes[f]}}}},3282:function(e,t,r){"use strict";var n=r(4267),a={Greys:[[0,"rgb(0,0,0)"],[1,"rgb(255,255,255)"]],YlGnBu:[[0,"rgb(8,29,88)"],[.125,"rgb(37,52,148)"],[.25,"rgb(34,94,168)"],[.375,"rgb(29,145,192)"],[.5,"rgb(65,182,196)"],[.625,"rgb(127,205,187)"],[.75,"rgb(199,233,180)"],[.875,"rgb(237,248,217)"],[1,"rgb(255,255,217)"]],Greens:[[0,"rgb(0,68,27)"],[.125,"rgb(0,109,44)"],[.25,"rgb(35,139,69)"],[.375,"rgb(65,171,93)"],[.5,"rgb(116,196,118)"],[.625,"rgb(161,217,155)"],[.75,"rgb(199,233,192)"],[.875,"rgb(229,245,224)"],[1,"rgb(247,252,245)"]],YlOrRd:[[0,"rgb(128,0,38)"],[.125,"rgb(189,0,38)"],[.25,"rgb(227,26,28)"],[.375,"rgb(252,78,42)"],[.5,"rgb(253,141,60)"],[.625,"rgb(254,178,76)"],[.75,"rgb(254,217,118)"],[.875,"rgb(255,237,160)"],[1,"rgb(255,255,204)"]],Bluered:[[0,"rgb(0,0,255)"],[1,"rgb(255,0,0)"]],RdBu:[[0,"rgb(5,10,172)"],[.35,"rgb(106,137,247)"],[.5,"rgb(190,190,190)"],[.6,"rgb(220,170,132)"],[.7,"rgb(230,145,90)"],[1,"rgb(178,10,28)"]],Reds:[[0,"rgb(220,220,220)"],[.2,"rgb(245,195,157)"],[.4,"rgb(245,160,105)"],[1,"rgb(178,10,28)"]],Blues:[[0,"rgb(5,10,172)"],[.35,"rgb(40,60,190)"],[.5,"rgb(70,100,245)"],[.6,"rgb(90,120,245)"],[.7,"rgb(106,137,247)"],[1,"rgb(220,220,220)"]],Picnic:[[0,"rgb(0,0,255)"],[.1,"rgb(51,153,255)"],[.2,"rgb(102,204,255)"],[.3,"rgb(153,204,255)"],[.4,"rgb(204,204,255)"],[.5,"rgb(255,255,255)"],[.6,"rgb(255,204,255)"],[.7,"rgb(255,153,255)"],[.8,"rgb(255,102,204)"],[.9,"rgb(255,102,102)"],[1,"rgb(255,0,0)"]],Rainbow:[[0,"rgb(150,0,90)"],[.125,"rgb(0,0,200)"],[.25,"rgb(0,25,255)"],[.375,"rgb(0,152,255)"],[.5,"rgb(44,255,150)"],[.625,"rgb(151,255,0)"],[.75,"rgb(255,234,0)"],[.875,"rgb(255,111,0)"],[1,"rgb(255,0,0)"]],Portland:[[0,"rgb(12,51,131)"],[.25,"rgb(10,136,186)"],[.5,"rgb(242,211,56)"],[.75,"rgb(242,143,56)"],[1,"rgb(217,30,30)"]],Jet:[[0,"rgb(0,0,131)"],[.125,"rgb(0,60,170)"],[.375,"rgb(5,255,255)"],[.625,"rgb(255,255,0)"],[.875,"rgb(250,0,0)"],[1,"rgb(128,0,0)"]],Hot:[[0,"rgb(0,0,0)"],[.3,"rgb(230,0,0)"],[.6,"rgb(255,210,0)"],[1,"rgb(255,255,255)"]],Blackbody:[[0,"rgb(0,0,0)"],[.2,"rgb(230,0,0)"],[.4,"rgb(230,210,0)"],[.7,"rgb(255,255,255)"],[1,"rgb(160,200,255)"]],Earth:[[0,"rgb(0,0,130)"],[.1,"rgb(0,180,180)"],[.2,"rgb(40,210,40)"],[.4,"rgb(230,230,50)"],[.6,"rgb(120,70,20)"],[1,"rgb(255,255,255)"]],Electric:[[0,"rgb(0,0,0)"],[.15,"rgb(30,0,100)"],[.4,"rgb(120,0,100)"],[.6,"rgb(160,90,0)"],[.8,"rgb(230,200,0)"],[1,"rgb(255,250,220)"]],Viridis:[[0,"#440154"],[.06274509803921569,"#48186a"],[.12549019607843137,"#472d7b"],[.18823529411764706,"#424086"],[.25098039215686274,"#3b528b"],[.3137254901960784,"#33638d"],[.3764705882352941,"#2c728e"],[.4392156862745098,"#26828e"],[.5019607843137255,"#21918c"],[.5647058823529412,"#1fa088"],[.6274509803921569,"#28ae80"],[.6901960784313725,"#3fbc73"],[.7529411764705882,"#5ec962"],[.8156862745098039,"#84d44b"],[.8784313725490196,"#addc30"],[.9411764705882353,"#d8e219"],[1,"#fde725"]],Cividis:[[0,"rgb(0,32,76)"],[.058824,"rgb(0,42,102)"],[.117647,"rgb(0,52,110)"],[.176471,"rgb(39,63,108)"],[.235294,"rgb(60,74,107)"],[.294118,"rgb(76,85,107)"],[.352941,"rgb(91,95,109)"],[.411765,"rgb(104,106,112)"],[.470588,"rgb(117,117,117)"],[.529412,"rgb(131,129,120)"],[.588235,"rgb(146,140,120)"],[.647059,"rgb(161,152,118)"],[.705882,"rgb(176,165,114)"],[.764706,"rgb(192,177,109)"],[.823529,"rgb(209,191,102)"],[.882353,"rgb(225,204,92)"],[.941176,"rgb(243,219,79)"],[1,"rgb(255,233,69)"]]},i=a.RdBu;function o(e){var t=0;if(!Array.isArray(e)||e.length<2)return!1;if(!e[0]||!e[e.length-1])return!1;if(0!=+e[0][0]||1!=+e[e.length-1][0])return!1;for(var r=0;r<e.length;r++){var a=e[r];if(2!==a.length||+a[0]<t||!n(a[1]).isValid())return!1;t=+a[0]}return!0}e.exports={scales:a,defaultScale:i,get:function(e,t){if(t||(t=i),!e)return t;function r(){try{e=a[e]||JSON.parse(e)}catch(r){e=t}}return"string"==typeof e&&(r(),"string"==typeof e&&r()),o(e)?e:t},isValid:function(e){return void 0!==a[e]||o(e)}}},2807:function(e){"use strict";e.exports=function(e,t,r,n,a){var i=(e-r)/(n-r),o=i+t/(n-r),l=(i+o)/2;return"left"===a||"bottom"===a?i:"center"===a||"middle"===a?l:"right"===a||"top"===a?o:i<2/3-l?i:o>4/3-l?o:l}},461:function(e,t,r){"use strict";var n=r(1828),a=[["sw-resize","s-resize","se-resize"],["w-resize","move","e-resize"],["nw-resize","n-resize","ne-resize"]];e.exports=function(e,t,r,i){return e="left"===r?0:"center"===r?1:"right"===r?2:n.constrain(Math.floor(3*e),0,2),t="bottom"===i?0:"middle"===i?1:"top"===i?2:n.constrain(Math.floor(3*t),0,2),a[t][e]}},4505:function(e,t){"use strict";t.selectMode=function(e){return"lasso"===e||"select"===e},t.drawMode=function(e){return"drawclosedpath"===e||"drawopenpath"===e||"drawline"===e||"drawrect"===e||"drawcircle"===e},t.openMode=function(e){return"drawline"===e||"drawopenpath"===e},t.rectMode=function(e){return"select"===e||"drawline"===e||"drawrect"===e||"drawcircle"===e},t.freeMode=function(e){return"lasso"===e||"drawclosedpath"===e||"drawopenpath"===e},t.selectingOrDrawing=function(e){return t.freeMode(e)||t.rectMode(e)}},8569:function(e,t,r){"use strict";var n=r(8956),a=r(7035),i=r(8520),o=r(1828).removeElement,l=r(5555),s=e.exports={};s.align=r(2807),s.getCursor=r(461);var c=r(6041);function u(){var e=document.createElement("div");e.className="dragcover";var t=e.style;return t.position="fixed",t.left=0,t.right=0,t.top=0,t.bottom=0,t.zIndex=999999999,t.background="none",document.body.appendChild(e),e}function f(e){return n(e.changedTouches?e.changedTouches[0]:e,document.body)}s.unhover=c.wrapped,s.unhoverRaw=c.raw,s.init=function(e){var t,r,n,c,d,h,p,v,y=e.gd,g=1,m=y._context.doubleClickDelay,x=e.element;y._mouseDownTime||(y._mouseDownTime=0),x.style.pointerEvents="all",x.onmousedown=_,i?(x._ontouchstart&&x.removeEventListener("touchstart",x._ontouchstart),x._ontouchstart=_,x.addEventListener("touchstart",_,{passive:!1})):x.ontouchstart=_;var b=e.clampFn||function(e,t,r){return Math.abs(e)<r&&(e=0),Math.abs(t)<r&&(t=0),[e,t]};function _(i){y._dragged=!1,y._dragging=!0;var o=f(i);t=o[0],r=o[1],p=i.target,h=i,v=2===i.buttons||i.ctrlKey,void 0===i.clientX&&void 0===i.clientY&&(i.clientX=t,i.clientY=r),(n=(new Date).getTime())-y._mouseDownTime<m?g+=1:(g=1,y._mouseDownTime=n),e.prepFn&&e.prepFn(i,t,r),a&&!v?(d=u()).style.cursor=window.getComputedStyle(x).cursor:a||(d=document,c=window.getComputedStyle(document.documentElement).cursor,document.documentElement.style.cursor=window.getComputedStyle(x).cursor),document.addEventListener("mouseup",T),document.addEventListener("touchend",T),!1!==e.dragmode&&(i.preventDefault(),document.addEventListener("mousemove",w),document.addEventListener("touchmove",w,{passive:!1}))}function w(n){n.preventDefault();var a=f(n),i=e.minDrag||l.MINDRAG,o=b(a[0]-t,a[1]-r,i),c=o[0],u=o[1];(c||u)&&(y._dragged=!0,s.unhover(y,n)),y._dragged&&e.moveFn&&!v&&(y._dragdata={element:x,dx:c,dy:u},e.moveFn(c,u))}function T(t){if(delete y._dragdata,!1!==e.dragmode&&(t.preventDefault(),document.removeEventListener("mousemove",w),document.removeEventListener("touchmove",w)),document.removeEventListener("mouseup",T),document.removeEventListener("touchend",T),a?o(d):c&&(d.documentElement.style.cursor=c,c=null),y._dragging){if(y._dragging=!1,(new Date).getTime()-y._mouseDownTime>m&&(g=Math.max(g-1,1)),y._dragged)e.doneFn&&e.doneFn();else if(e.clickFn&&e.clickFn(g,h),!v){var r;try{r=new MouseEvent("click",t)}catch(i){var n=f(t);(r=document.createEvent("MouseEvents")).initMouseEvent("click",t.bubbles,t.cancelable,t.view,t.detail,t.screenX,t.screenY,n[0],n[1],t.ctrlKey,t.altKey,t.shiftKey,t.metaKey,t.button,t.relatedTarget)}p.dispatchEvent(r)}y._dragging=!1,y._dragged=!1}else y._dragged=!1}},s.coverSlip=u},6041:function(e,t,r){"use strict";var n=r(1086),a=r(9990),i=r(4401).getGraphDiv,o=r(6675),l=e.exports={};l.wrapped=function(e,t,r){(e=i(e))._fullLayout&&a.clear(e._fullLayout._uid+o.HOVERID),l.raw(e,t,r)},l.raw=function(e,t){var r=e._fullLayout,a=e._hoverdata;t||(t={}),t.target&&!e._dragged&&!1===n.triggerHandler(e,"plotly_beforehover",t)||(r._hoverlayer.selectAll("g").remove(),r._hoverlayer.selectAll("line").remove(),r._hoverlayer.selectAll("circle").remove(),e._hoverdata=void 0,t.target&&a&&e.emit("plotly_unhover",{event:t,points:a}))}},9952:function(e,t){"use strict";t.P={valType:"string",values:["solid","dot","dash","longdash","dashdot","longdashdot"],dflt:"solid",editType:"style"},t.u={shape:{valType:"enumerated",values:["","/","\\","x","-","|","+","."],dflt:"",arrayOk:!0,editType:"style"},fillmode:{valType:"enumerated",values:["replace","overlay"],dflt:"replace",editType:"style"},bgcolor:{valType:"color",arrayOk:!0,editType:"style"},fgcolor:{valType:"color",arrayOk:!0,editType:"style"},fgopacity:{valType:"number",editType:"style",min:0,max:1},size:{valType:"number",min:0,dflt:8,arrayOk:!0,editType:"style"},solidity:{valType:"number",min:0,max:1,dflt:.3,arrayOk:!0,editType:"style"},editType:"style"}},1424:function(e,t,r){"use strict";var n=r(9898),a=r(1828),i=a.numberFormat,o=r(2770),l=r(4267),s=r(3972),c=r(7901),u=r(1081),f=a.strTranslate,d=r(3893),h=r(7922),p=r(8783).LINE_SPACING,v=r(7822).DESELECTDIM,y=r(4098),g=r(9984),m=r(3469).appendArrayPointValue,x=e.exports={};function b(e,t,r){var n=t.fillpattern,a=n&&x.getPatternAttr(n.shape,0,"");if(a){var i=x.getPatternAttr(n.bgcolor,0,null),o=x.getPatternAttr(n.fgcolor,0,null),l=n.fgopacity,s=x.getPatternAttr(n.size,0,8),u=x.getPatternAttr(n.solidity,0,.3),f=t.uid;x.pattern(e,"point",r,f,a,s,u,void 0,n.fillmode,i,o,l)}else t.fillcolor&&e.call(c.fill,t.fillcolor)}x.font=function(e,t,r,n){a.isPlainObject(t)&&(n=t.color,r=t.size,t=t.family),t&&e.style("font-family",t),r+1&&e.style("font-size",r+"px"),n&&e.call(c.fill,n)},x.setPosition=function(e,t,r){e.attr("x",t).attr("y",r)},x.setSize=function(e,t,r){e.attr("width",t).attr("height",r)},x.setRect=function(e,t,r,n,a){e.call(x.setPosition,t,r).call(x.setSize,n,a)},x.translatePoint=function(e,t,r,n){var a=r.c2p(e.x),i=n.c2p(e.y);return!!(o(a)&&o(i)&&t.node())&&("text"===t.node().nodeName?t.attr("x",a).attr("y",i):t.attr("transform",f(a,i)),!0)},x.translatePoints=function(e,t,r){e.each((function(e){var a=n.select(this);x.translatePoint(e,a,t,r)}))},x.hideOutsideRangePoint=function(e,t,r,n,a,i){t.attr("display",r.isPtWithinRange(e,a)&&n.isPtWithinRange(e,i)?null:"none")},x.hideOutsideRangePoints=function(e,t){if(t._hasClipOnAxisFalse){var r=t.xaxis,a=t.yaxis;e.each((function(t){var i=t[0].trace,o=i.xcalendar,l=i.ycalendar,c=s.traceIs(i,"bar-like")?".bartext":".point,.textpoint";e.selectAll(c).each((function(e){x.hideOutsideRangePoint(e,n.select(this),r,a,o,l)}))}))}},x.crispRound=function(e,t,r){return t&&o(t)?e._context.staticPlot?t:t<1?1:Math.round(t):r||0},x.singleLineStyle=function(e,t,r,n,a){t.style("fill","none");var i=(((e||[])[0]||{}).trace||{}).line||{},o=r||i.width||0,l=a||i.dash||"";c.stroke(t,n||i.color),x.dashLine(t,l,o)},x.lineGroupStyle=function(e,t,r,a){e.style("fill","none").each((function(e){var i=(((e||[])[0]||{}).trace||{}).line||{},o=t||i.width||0,l=a||i.dash||"";n.select(this).call(c.stroke,r||i.color).call(x.dashLine,l,o)}))},x.dashLine=function(e,t,r){r=+r||0,t=x.dashStyle(t,r),e.style({"stroke-dasharray":t,"stroke-width":r+"px"})},x.dashStyle=function(e,t){t=+t||1;var r=Math.max(t,3);return"solid"===e?e="":"dot"===e?e=r+"px,"+r+"px":"dash"===e?e=3*r+"px,"+3*r+"px":"longdash"===e?e=5*r+"px,"+5*r+"px":"dashdot"===e?e=3*r+"px,"+r+"px,"+r+"px,"+r+"px":"longdashdot"===e&&(e=5*r+"px,"+2*r+"px,"+r+"px,"+2*r+"px"),e},x.singleFillStyle=function(e,t){var r=n.select(e.node());b(e,((r.data()[0]||[])[0]||{}).trace||{},t)},x.fillGroupStyle=function(e,t){e.style("stroke-width",0).each((function(e){var r=n.select(this);e[0].trace&&b(r,e[0].trace,t)}))};var _=r(998);x.symbolNames=[],x.symbolFuncs=[],x.symbolBackOffs=[],x.symbolNeedLines={},x.symbolNoDot={},x.symbolNoFill={},x.symbolList=[],Object.keys(_).forEach((function(e){var t=_[e],r=t.n;x.symbolList.push(r,String(r),e,r+100,String(r+100),e+"-open"),x.symbolNames[r]=e,x.symbolFuncs[r]=t.f,x.symbolBackOffs[r]=t.backoff||0,t.needLine&&(x.symbolNeedLines[r]=!0),t.noDot?x.symbolNoDot[r]=!0:x.symbolList.push(r+200,String(r+200),e+"-dot",r+300,String(r+300),e+"-open-dot"),t.noFill&&(x.symbolNoFill[r]=!0)}));var w=x.symbolNames.length;function T(e,t,r,n){var a=e%100;return x.symbolFuncs[a](t,r,n)+(e>=200?"M0,0.5L0.5,0L0,-0.5L-0.5,0Z":"")}x.symbolNumber=function(e){if(o(e))e=+e;else if("string"==typeof e){var t=0;e.indexOf("-open")>0&&(t=100,e=e.replace("-open","")),e.indexOf("-dot")>0&&(t+=200,e=e.replace("-dot","")),(e=x.symbolNames.indexOf(e))>=0&&(e+=t)}return e%100>=w||e>=400?0:Math.floor(Math.max(e,0))};var M={x1:1,x2:0,y1:0,y2:0},k={x1:0,x2:0,y1:1,y2:0},A=i("~f"),L={radial:{node:"radialGradient"},radialreversed:{node:"radialGradient",reversed:!0},horizontal:{node:"linearGradient",attrs:M},horizontalreversed:{node:"linearGradient",attrs:M,reversed:!0},vertical:{node:"linearGradient",attrs:k},verticalreversed:{node:"linearGradient",attrs:k,reversed:!0}};x.gradient=function(e,t,r,i,o,s){for(var u=o.length,f=L[i],d=new Array(u),h=0;h<u;h++)f.reversed?d[u-1-h]=[A(100*(1-o[h][0])),o[h][1]]:d[h]=[A(100*o[h][0]),o[h][1]];var p=t._fullLayout,v="g"+p._uid+"-"+r,y=p._defs.select(".gradients").selectAll("#"+v).data([i+d.join(";")],a.identity);y.exit().remove(),y.enter().append(f.node).each((function(){var e=n.select(this);f.attrs&&e.attr(f.attrs),e.attr("id",v);var t=e.selectAll("stop").data(d);t.exit().remove(),t.enter().append("stop"),t.each((function(e){var t=l(e[1]);n.select(this).attr({offset:e[0]+"%","stop-color":c.tinyRGB(t),"stop-opacity":t.getAlpha()})}))})),e.style(s,Y(v,t)).style(s+"-opacity",null),e.classed("gradient_filled",!0)},x.pattern=function(e,t,r,i,o,s,u,f,d,h,p,v){var y="legend"===t;f&&("overlay"===d?(h=f,p=c.contrast(h)):(h=void 0,p=f));var g,m,x,b,_,w,T,M,k,A,L,S=r._fullLayout,O="p"+S._uid+"-"+i,D={},C=l(p),P=c.tinyRGB(C),I=v*C.getAlpha();switch(o){case"/":g=s*Math.sqrt(2),m=s*Math.sqrt(2),w="path",D={d:x="M-"+g/4+","+m/4+"l"+g/2+",-"+m/2+"M0,"+m+"L"+g+",0M"+g/4*3+","+m/4*5+"l"+g/2+",-"+m/2,opacity:I,stroke:P,"stroke-width":(b=u*s)+"px"};break;case"\\":g=s*Math.sqrt(2),m=s*Math.sqrt(2),w="path",D={d:x="M"+g/4*3+",-"+m/4+"l"+g/2+","+m/2+"M0,0L"+g+","+m+"M-"+g/4+","+m/4*3+"l"+g/2+","+m/2,opacity:I,stroke:P,"stroke-width":(b=u*s)+"px"};break;case"x":g=s*Math.sqrt(2),m=s*Math.sqrt(2),x="M-"+g/4+","+m/4+"l"+g/2+",-"+m/2+"M0,"+m+"L"+g+",0M"+g/4*3+","+m/4*5+"l"+g/2+",-"+m/2+"M"+g/4*3+",-"+m/4+"l"+g/2+","+m/2+"M0,0L"+g+","+m+"M-"+g/4+","+m/4*3+"l"+g/2+","+m/2,b=s-s*Math.sqrt(1-u),w="path",D={d:x,opacity:I,stroke:P,"stroke-width":b+"px"};break;case"|":w="path",w="path",D={d:x="M"+(g=s)/2+",0L"+g/2+","+(m=s),opacity:I,stroke:P,"stroke-width":(b=u*s)+"px"};break;case"-":w="path",w="path",D={d:x="M0,"+(m=s)/2+"L"+(g=s)+","+m/2,opacity:I,stroke:P,"stroke-width":(b=u*s)+"px"};break;case"+":w="path",x="M"+(g=s)/2+",0L"+g/2+","+(m=s)+"M0,"+m/2+"L"+g+","+m/2,b=s-s*Math.sqrt(1-u),w="path",D={d:x,opacity:I,stroke:P,"stroke-width":b+"px"};break;case".":g=s,m=s,u<Math.PI/4?_=Math.sqrt(u*s*s/Math.PI):(T=u,M=Math.PI/4,k=1,A=s/2,L=s/Math.sqrt(2),_=A+(L-A)*(T-M)/(k-M)),w="circle",D={cx:g/2,cy:m/2,r:_,opacity:I,fill:P}}var R=[o||"noSh",h||"noBg",p||"noFg",s,u].join(";"),z=S._defs.select(".patterns").selectAll("#"+O).data([R],a.identity);z.exit().remove(),z.enter().append("pattern").each((function(){var e=n.select(this);if(e.attr({id:O,width:g+"px",height:m+"px",patternUnits:"userSpaceOnUse",patternTransform:y?"scale(0.8)":""}),h){var t=l(h),r=c.tinyRGB(t),a=t.getAlpha(),i=e.selectAll("rect").data([0]);i.exit().remove(),i.enter().append("rect").attr({width:g+"px",height:m+"px",fill:r,"fill-opacity":a})}var o=e.selectAll(w).data([0]);o.exit().remove(),o.enter().append(w).attr(D)})),e.style("fill",Y(O,r)).style("fill-opacity",null),e.classed("pattern_filled",!0)},x.initGradients=function(e){var t=e._fullLayout;a.ensureSingle(t._defs,"g","gradients").selectAll("linearGradient,radialGradient").remove(),n.select(e).selectAll(".gradient_filled").classed("gradient_filled",!1)},x.initPatterns=function(e){var t=e._fullLayout;a.ensureSingle(t._defs,"g","patterns").selectAll("pattern").remove(),n.select(e).selectAll(".pattern_filled").classed("pattern_filled",!1)},x.getPatternAttr=function(e,t,r){return e&&a.isArrayOrTypedArray(e)?t<e.length?e[t]:r:e},x.pointStyle=function(e,t,r,a){if(e.size()){var i=x.makePointStyleFns(t);e.each((function(e){x.singlePointStyle(e,n.select(this),t,i,r,a)}))}},x.singlePointStyle=function(e,t,r,n,i,o){var l=r.marker,s=l.line;if(o&&o.i>=0&&void 0===e.i&&(e.i=o.i),t.style("opacity",n.selectedOpacityFn?n.selectedOpacityFn(e):void 0===e.mo?l.opacity:e.mo),n.ms2mrc){var u;u="various"===e.ms||"various"===l.size?3:n.ms2mrc(e.ms),e.mrc=u,n.selectedSizeFn&&(u=e.mrc=n.selectedSizeFn(e));var f=x.symbolNumber(e.mx||l.symbol)||0;e.om=f%200>=100;var d=re(e,r),h=q(e,r);t.attr("d",T(f,u,d,h))}var p,v,y,g=!1;if(e.so)y=s.outlierwidth,v=s.outliercolor,p=l.outliercolor;else{var m=(s||{}).width;y=(e.mlw+1||m+1||(e.trace?(e.trace.marker.line||{}).width:0)+1)-1||0,v="mlc"in e?e.mlcc=n.lineScale(e.mlc):a.isArrayOrTypedArray(s.color)?c.defaultLine:s.color,a.isArrayOrTypedArray(l.color)&&(p=c.defaultLine,g=!0),p="mc"in e?e.mcc=n.markerScale(e.mc):l.color||l.colors||"rgba(0,0,0,0)",n.selectedColorFn&&(p=n.selectedColorFn(e))}if(e.om)t.call(c.stroke,p).style({"stroke-width":(y||1)+"px",fill:"none"});else{t.style("stroke-width",(e.isBlank?0:y)+"px");var b=l.gradient,_=e.mgt;_?g=!0:_=b&&b.type,a.isArrayOrTypedArray(_)&&(_=_[0],L[_]||(_=0));var w=l.pattern,M=w&&x.getPatternAttr(w.shape,e.i,"");if(_&&"none"!==_){var k=e.mgc;k?g=!0:k=b.color;var A=r.uid;g&&(A+="-"+e.i),x.gradient(t,i,A,_,[[0,k],[1,p]],"fill")}else if(M){var S=!1,O=w.fgcolor;!O&&o&&o.color&&(O=o.color,S=!0);var D=x.getPatternAttr(O,e.i,o&&o.color||null),C=x.getPatternAttr(w.bgcolor,e.i,null),P=w.fgopacity,I=x.getPatternAttr(w.size,e.i,8),R=x.getPatternAttr(w.solidity,e.i,.3);S=S||e.mcc||a.isArrayOrTypedArray(w.shape)||a.isArrayOrTypedArray(w.bgcolor)||a.isArrayOrTypedArray(w.fgcolor)||a.isArrayOrTypedArray(w.size)||a.isArrayOrTypedArray(w.solidity);var z=r.uid;S&&(z+="-"+e.i),x.pattern(t,"point",i,z,M,I,R,e.mcc,w.fillmode,C,D,P)}else a.isArrayOrTypedArray(p)?c.fill(t,p[e.i]):c.fill(t,p);y&&c.stroke(t,v)}},x.makePointStyleFns=function(e){var t={},r=e.marker;return t.markerScale=x.tryColorscale(r,""),t.lineScale=x.tryColorscale(r,"line"),s.traceIs(e,"symbols")&&(t.ms2mrc=y.isBubble(e)?g(e):function(){return(r.size||6)/2}),e.selectedpoints&&a.extendFlat(t,x.makeSelectedPointStyleFns(e)),t},x.makeSelectedPointStyleFns=function(e){var t={},r=e.selected||{},n=e.unselected||{},i=e.marker||{},o=r.marker||{},l=n.marker||{},c=i.opacity,u=o.opacity,f=l.opacity,d=void 0!==u,h=void 0!==f;(a.isArrayOrTypedArray(c)||d||h)&&(t.selectedOpacityFn=function(e){var t=void 0===e.mo?i.opacity:e.mo;return e.selected?d?u:t:h?f:v*t});var p=i.color,y=o.color,g=l.color;(y||g)&&(t.selectedColorFn=function(e){var t=e.mcc||p;return e.selected?y||t:g||t});var m=i.size,x=o.size,b=l.size,_=void 0!==x,w=void 0!==b;return s.traceIs(e,"symbols")&&(_||w)&&(t.selectedSizeFn=function(e){var t=e.mrc||m/2;return e.selected?_?x/2:t:w?b/2:t}),t},x.makeSelectedTextStyleFns=function(e){var t={},r=e.selected||{},n=e.unselected||{},a=e.textfont||{},i=r.textfont||{},o=n.textfont||{},l=a.color,s=i.color,u=o.color;return t.selectedTextColorFn=function(e){var t=e.tc||l;return e.selected?s||t:u||(s?t:c.addOpacity(t,v))},t},x.selectedPointStyle=function(e,t){if(e.size()&&t.selectedpoints){var r=x.makeSelectedPointStyleFns(t),a=t.marker||{},i=[];r.selectedOpacityFn&&i.push((function(e,t){e.style("opacity",r.selectedOpacityFn(t))})),r.selectedColorFn&&i.push((function(e,t){c.fill(e,r.selectedColorFn(t))})),r.selectedSizeFn&&i.push((function(e,n){var i=n.mx||a.symbol||0,o=r.selectedSizeFn(n);e.attr("d",T(x.symbolNumber(i),o,re(n,t),q(n,t))),n.mrc2=o})),i.length&&e.each((function(e){for(var t=n.select(this),r=0;r<i.length;r++)i[r](t,e)}))}},x.tryColorscale=function(e,t){var r=t?a.nestedProperty(e,t).get():e;if(r){var n=r.color;if((r.colorscale||r._colorAx)&&a.isArrayOrTypedArray(n))return u.makeColorScaleFuncFromTrace(r)}return a.identity};var S,O,D={start:1,end:-1,middle:0,bottom:1,top:-1};function C(e,t,r,a,i){var o=n.select(e.node().parentNode),l=-1!==t.indexOf("top")?"top":-1!==t.indexOf("bottom")?"bottom":"middle",s=-1!==t.indexOf("left")?"end":-1!==t.indexOf("right")?"start":"middle",c=a?a/.8+1:0,u=(d.lineCount(e)-1)*p+1,h=D[s]*c,v=.75*r+D[l]*c+(D[l]-1)*u*r/2;e.attr("text-anchor",s),i||o.attr("transform",f(h,v))}function P(e,t){var r=e.ts||t.textfont.size;return o(r)&&r>0?r:0}function I(e,t,r){return r&&(e=H(e)),t?z(e[1]):R(e[0])}function R(e){var t=n.round(e,2);return S=t,t}function z(e){var t=n.round(e,2);return O=t,t}function N(e,t,r,n){var a=e[0]-t[0],i=e[1]-t[1],o=r[0]-t[0],l=r[1]-t[1],s=Math.pow(a*a+i*i,.25),c=Math.pow(o*o+l*l,.25),u=(c*c*a-s*s*o)*n,f=(c*c*i-s*s*l)*n,d=3*c*(s+c),h=3*s*(s+c);return[[R(t[0]+(d&&u/d)),z(t[1]+(d&&f/d))],[R(t[0]-(h&&u/h)),z(t[1]-(h&&f/h))]]}x.textPointStyle=function(e,t,r){if(e.size()){var i;if(t.selectedpoints){var o=x.makeSelectedTextStyleFns(t);i=o.selectedTextColorFn}var l=t.texttemplate,s=r._fullLayout;e.each((function(e){var o=n.select(this),c=l?a.extractOption(e,t,"txt","texttemplate"):a.extractOption(e,t,"tx","text");if(c||0===c){if(l){var u=t._module.formatLabels,f=u?u(e,t,s):{},h={};m(h,t,e.i);var p=t._meta||{};c=a.texttemplateString(c,f,s._d3locale,h,e,p)}var v=e.tp||t.textposition,y=P(e,t),g=i?i(e):e.tc||t.textfont.color;o.call(x.font,e.tf||t.textfont.family,y,g).text(c).call(d.convertToTspans,r).call(C,v,y,e.mrc)}else o.remove()}))}},x.selectedTextStyle=function(e,t){if(e.size()&&t.selectedpoints){var r=x.makeSelectedTextStyleFns(t);e.each((function(e){var a=n.select(this),i=r.selectedTextColorFn(e),o=e.tp||t.textposition,l=P(e,t);c.fill(a,i);var u=s.traceIs(t,"bar-like");C(a,o,l,e.mrc2||e.mrc,u)}))}},x.smoothopen=function(e,t){if(e.length<3)return"M"+e.join("L");var r,n="M"+e[0],a=[];for(r=1;r<e.length-1;r++)a.push(N(e[r-1],e[r],e[r+1],t));for(n+="Q"+a[0][0]+" "+e[1],r=2;r<e.length-1;r++)n+="C"+a[r-2][1]+" "+a[r-1][0]+" "+e[r];return n+="Q"+a[e.length-3][1]+" "+e[e.length-1]},x.smoothclosed=function(e,t){if(e.length<3)return"M"+e.join("L")+"Z";var r,n="M"+e[0],a=e.length-1,i=[N(e[a],e[0],e[1],t)];for(r=1;r<a;r++)i.push(N(e[r-1],e[r],e[r+1],t));for(i.push(N(e[a-1],e[a],e[0],t)),r=1;r<=a;r++)n+="C"+i[r-1][1]+" "+i[r][0]+" "+e[r];return n+="C"+i[a][1]+" "+i[0][0]+" "+e[0]+"Z"};var E={hv:function(e,t,r){return"H"+R(t[0])+"V"+I(t,1,r)},vh:function(e,t,r){return"V"+z(t[1])+"H"+I(t,0,r)},hvh:function(e,t,r){return"H"+R((e[0]+t[0])/2)+"V"+z(t[1])+"H"+I(t,0,r)},vhv:function(e,t,r){return"V"+z((e[1]+t[1])/2)+"H"+R(t[0])+"V"+I(t,1,r)}},F=function(e,t,r){return"L"+I(t,0,r)+","+I(t,1,r)};function H(e,t){var r=e.backoff,n=e.trace,i=e.d,o=e.i;if(r&&n&&n.marker&&n.marker.angle%360==0&&n.line&&"spline"!==n.line.shape){var l=a.isArrayOrTypedArray(r),s=e,c=t?t[0]:S||0,u=t?t[1]:O||0,f=s[0],d=s[1],h=f-c,p=d-u,v=Math.atan2(p,h),y=l?r[o]:r;if("auto"===y){var g=s.i;"scatter"===n.type&&g--;var m=s.marker,b=m.symbol;a.isArrayOrTypedArray(b)&&(b=b[g]);var _=m.size;a.isArrayOrTypedArray(_)&&(_=_[g]),y=m?x.symbolBackOffs[x.symbolNumber(b)]*_:0,y+=x.getMarkerStandoff(i[g],n)||0}var w=f-y*Math.cos(v),T=d-y*Math.sin(v);(w<=f&&w>=c||w>=f&&w<=c)&&(T<=d&&T>=u||T>=d&&T<=u)&&(e=[w,T])}return e}x.steps=function(e){var t=E[e]||F;return function(e){for(var r="M"+R(e[0][0])+","+z(e[0][1]),n=e.length,a=1;a<n;a++)r+=t(e[a-1],e[a],a===n-1);return r}},x.applyBackoff=H,x.makeTester=function(){var e=a.ensureSingleById(n.select("body"),"svg","js-plotly-tester",(function(e){e.attr(h.svgAttrs).style({position:"absolute",left:"-10000px",top:"-10000px",width:"9000px",height:"9000px","z-index":"1"})})),t=a.ensureSingle(e,"path","js-reference-point",(function(e){e.attr("d","M0,0H1V1H0Z").style({"stroke-width":0,fill:"black"})}));x.tester=e,x.testref=t},x.savedBBoxes={};var j=0;function B(e){var t=e.getAttribute("data-unformatted");if(null!==t)return t+e.getAttribute("data-math")+e.getAttribute("text-anchor")+e.getAttribute("style")}function Y(e,t){if(!e)return null;var r=t._context,n=r._exportedPlot?"":r._baseUrl||"";return n?"url('"+n+"#"+e+"')":"url(#"+e+")"}x.bBox=function(e,t,r){var i,o,l;if(r||(r=B(e)),r){if(i=x.savedBBoxes[r])return a.extendFlat({},i)}else if(1===e.childNodes.length){var s=e.childNodes[0];if(r=B(s)){var c=+s.getAttribute("x")||0,u=+s.getAttribute("y")||0,f=s.getAttribute("transform");if(!f){var h=x.bBox(s,!1,r);return c&&(h.left+=c,h.right+=c),u&&(h.top+=u,h.bottom+=u),h}if(r+="~"+c+"~"+u+"~"+f,i=x.savedBBoxes[r])return a.extendFlat({},i)}}t?o=e:(l=x.tester.node(),o=e.cloneNode(!0),l.appendChild(o)),n.select(o).attr("transform",null).call(d.positionText,0,0);var p=o.getBoundingClientRect(),v=x.testref.node().getBoundingClientRect();t||l.removeChild(o);var y={height:p.height,width:p.width,left:p.left-v.left,top:p.top-v.top,right:p.right-v.left,bottom:p.bottom-v.top};return j>=1e4&&(x.savedBBoxes={},j=0),r&&(x.savedBBoxes[r]=y),j++,a.extendFlat({},y)},x.setClipUrl=function(e,t,r){e.attr("clip-path",Y(t,r))},x.getTranslate=function(e){var t=(e[e.attr?"attr":"getAttribute"]("transform")||"").replace(/.*\btranslate\((-?\d*\.?\d*)[^-\d]*(-?\d*\.?\d*)[^\d].*/,(function(e,t,r){return[t,r].join(" ")})).split(" ");return{x:+t[0]||0,y:+t[1]||0}},x.setTranslate=function(e,t,r){var n=e.attr?"attr":"getAttribute",a=e.attr?"attr":"setAttribute",i=e[n]("transform")||"";return t=t||0,r=r||0,i=i.replace(/(\btranslate\(.*?\);?)/,"").trim(),i=(i+=f(t,r)).trim(),e[a]("transform",i),i},x.getScale=function(e){var t=(e[e.attr?"attr":"getAttribute"]("transform")||"").replace(/.*\bscale\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/,(function(e,t,r){return[t,r].join(" ")})).split(" ");return{x:+t[0]||1,y:+t[1]||1}},x.setScale=function(e,t,r){var n=e.attr?"attr":"getAttribute",a=e.attr?"attr":"setAttribute",i=e[n]("transform")||"";return t=t||1,r=r||1,i=i.replace(/(\bscale\(.*?\);?)/,"").trim(),i=(i+="scale("+t+","+r+")").trim(),e[a]("transform",i),i};var U=/\s*sc.*/;x.setPointGroupScale=function(e,t,r){if(t=t||1,r=r||1,e){var n=1===t&&1===r?"":"scale("+t+","+r+")";e.each((function(){var e=(this.getAttribute("transform")||"").replace(U,"");e=(e+=n).trim(),this.setAttribute("transform",e)}))}};var V=/translate\([^)]*\)\s*$/;function q(e,t){var r;return e&&(r=e.mf),void 0===r&&(r=t.marker&&t.marker.standoff||0),t._geo||t._xA?r:-r}x.setTextPointsScale=function(e,t,r){e&&e.each((function(){var e,a=n.select(this),i=a.select("text");if(i.node()){var o=parseFloat(i.attr("x")||0),l=parseFloat(i.attr("y")||0),s=(a.attr("transform")||"").match(V);e=1===t&&1===r?[]:[f(o,l),"scale("+t+","+r+")",f(-o,-l)],s&&e.push(s),a.attr("transform",e.join(""))}}))},x.getMarkerStandoff=q;var Z,G,W,X,J,K,Q=Math.atan2,$=Math.cos,ee=Math.sin;function te(e,t){var r=t[0],n=t[1];return[r*$(e)-n*ee(e),r*ee(e)+n*$(e)]}function re(e,t){var r,n,a=e.ma;void 0===a&&(a=t.marker.angle||0);var i=t.marker.angleref;if("previous"===i||"north"===i){if(t._geo){var l=t._geo.project(e.lonlat);r=l[0],n=l[1]}else{var s=t._xA,c=t._yA;if(!s||!c)return 90;r=s.c2p(e.x),n=c.c2p(e.y)}if(t._geo){var u,f=e.lonlat[0],d=e.lonlat[1],h=t._geo.project([f,d+1e-5]),p=t._geo.project([f+1e-5,d]),v=Q(p[1]-n,p[0]-r),y=Q(h[1]-n,h[0]-r);if("north"===i)u=a/180*Math.PI;else if("previous"===i){var g=f/180*Math.PI,m=d/180*Math.PI,x=Z/180*Math.PI,b=G/180*Math.PI,_=x-g,w=$(b)*ee(_),T=ee(b)*$(m)-$(b)*ee(m)*$(_);u=-Q(w,T)-Math.PI,Z=f,G=d}var M=te(v,[$(u),0]),k=te(y,[ee(u),0]);a=Q(M[1]+k[1],M[0]+k[0])/Math.PI*180,"previous"!==i||K===t.uid&&e.i===J+1||(a=null)}if("previous"===i&&!t._geo)if(K===t.uid&&e.i===J+1&&o(r)&&o(n)){var A=r-W,L=n-X,S=t.line&&t.line.shape||"",O=S.slice(S.length-1);"h"===O&&(L=0),"v"===O&&(A=0),a+=Q(L,A)/Math.PI*180+90}else a=null}return W=r,X=n,J=e.i,K=t.uid,a}x.getMarkerAngle=re},998:function(e,t,r){"use strict";var n,a,i,o,l=r(5616),s=r(9898).round,c="M0,0Z",u=Math.sqrt(2),f=Math.sqrt(3),d=Math.PI,h=Math.cos,p=Math.sin;function v(e){return null===e}function y(e,t,r){if(!(e&&e%360!=0||t))return r;if(i===e&&o===t&&n===r)return a;function s(e,r){var n=h(e),a=p(e),i=r[0],o=r[1]+(t||0);return[i*n-o*a,i*a+o*n]}i=e,o=t,n=r;for(var c=e/180*d,u=0,f=0,v=l(r),y="",g=0;g<v.length;g++){var m=v[g],x=m[0],b=u,_=f;if("M"===x||"L"===x)u=+m[1],f=+m[2];else if("m"===x||"l"===x)u+=+m[1],f+=+m[2];else if("H"===x)u=+m[1];else if("h"===x)u+=+m[1];else if("V"===x)f=+m[1];else if("v"===x)f+=+m[1];else if("A"===x){u=+m[1],f=+m[2];var w=s(c,[+m[6],+m[7]]);m[6]=w[0],m[7]=w[1],m[3]=+m[3]+e}"H"!==x&&"V"!==x||(x="L"),"h"!==x&&"v"!==x||(x="l"),"m"!==x&&"l"!==x||(u-=b,f-=_);var T=s(c,[u,f]);"H"!==x&&"V"!==x||(x="L"),"M"!==x&&"L"!==x&&"m"!==x&&"l"!==x||(m[1]=T[0],m[2]=T[1]),m[0]=x,y+=m[0]+m.slice(1).join(",")}return a=y,y}e.exports={circle:{n:0,f:function(e,t,r){if(v(t))return c;var n=s(e,2),a="M"+n+",0A"+n+","+n+" 0 1,1 0,-"+n+"A"+n+","+n+" 0 0,1 "+n+",0Z";return r?y(t,r,a):a}},square:{n:1,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"H-"+n+"V-"+n+"H"+n+"Z")}},diamond:{n:2,f:function(e,t,r){if(v(t))return c;var n=s(1.3*e,2);return y(t,r,"M"+n+",0L0,"+n+"L-"+n+",0L0,-"+n+"Z")}},cross:{n:3,f:function(e,t,r){if(v(t))return c;var n=s(.4*e,2),a=s(1.2*e,2);return y(t,r,"M"+a+","+n+"H"+n+"V"+a+"H-"+n+"V"+n+"H-"+a+"V-"+n+"H-"+n+"V-"+a+"H"+n+"V-"+n+"H"+a+"Z")}},x:{n:4,f:function(e,t,r){if(v(t))return c;var n=s(.8*e/u,2),a="l"+n+","+n,i="l"+n+",-"+n,o="l-"+n+",-"+n,l="l-"+n+","+n;return y(t,r,"M0,"+n+a+i+o+i+o+l+o+l+a+l+a+"Z")}},"triangle-up":{n:5,f:function(e,t,r){if(v(t))return c;var n=s(2*e/f,2);return y(t,r,"M-"+n+","+s(e/2,2)+"H"+n+"L0,-"+s(e,2)+"Z")}},"triangle-down":{n:6,f:function(e,t,r){if(v(t))return c;var n=s(2*e/f,2);return y(t,r,"M-"+n+",-"+s(e/2,2)+"H"+n+"L0,"+s(e,2)+"Z")}},"triangle-left":{n:7,f:function(e,t,r){if(v(t))return c;var n=s(2*e/f,2);return y(t,r,"M"+s(e/2,2)+",-"+n+"V"+n+"L-"+s(e,2)+",0Z")}},"triangle-right":{n:8,f:function(e,t,r){if(v(t))return c;var n=s(2*e/f,2);return y(t,r,"M-"+s(e/2,2)+",-"+n+"V"+n+"L"+s(e,2)+",0Z")}},"triangle-ne":{n:9,f:function(e,t,r){if(v(t))return c;var n=s(.6*e,2),a=s(1.2*e,2);return y(t,r,"M-"+a+",-"+n+"H"+n+"V"+a+"Z")}},"triangle-se":{n:10,f:function(e,t,r){if(v(t))return c;var n=s(.6*e,2),a=s(1.2*e,2);return y(t,r,"M"+n+",-"+a+"V"+n+"H-"+a+"Z")}},"triangle-sw":{n:11,f:function(e,t,r){if(v(t))return c;var n=s(.6*e,2),a=s(1.2*e,2);return y(t,r,"M"+a+","+n+"H-"+n+"V-"+a+"Z")}},"triangle-nw":{n:12,f:function(e,t,r){if(v(t))return c;var n=s(.6*e,2),a=s(1.2*e,2);return y(t,r,"M-"+n+","+a+"V-"+n+"H"+a+"Z")}},pentagon:{n:13,f:function(e,t,r){if(v(t))return c;var n=s(.951*e,2),a=s(.588*e,2),i=s(-e,2),o=s(-.309*e,2);return y(t,r,"M"+n+","+o+"L"+a+","+s(.809*e,2)+"H-"+a+"L-"+n+","+o+"L0,"+i+"Z")}},hexagon:{n:14,f:function(e,t,r){if(v(t))return c;var n=s(e,2),a=s(e/2,2),i=s(e*f/2,2);return y(t,r,"M"+i+",-"+a+"V"+a+"L0,"+n+"L-"+i+","+a+"V-"+a+"L0,-"+n+"Z")}},hexagon2:{n:15,f:function(e,t,r){if(v(t))return c;var n=s(e,2),a=s(e/2,2),i=s(e*f/2,2);return y(t,r,"M-"+a+","+i+"H"+a+"L"+n+",0L"+a+",-"+i+"H-"+a+"L-"+n+",0Z")}},octagon:{n:16,f:function(e,t,r){if(v(t))return c;var n=s(.924*e,2),a=s(.383*e,2);return y(t,r,"M-"+a+",-"+n+"H"+a+"L"+n+",-"+a+"V"+a+"L"+a+","+n+"H-"+a+"L-"+n+","+a+"V-"+a+"Z")}},star:{n:17,f:function(e,t,r){if(v(t))return c;var n=1.4*e,a=s(.225*n,2),i=s(.951*n,2),o=s(.363*n,2),l=s(.588*n,2),u=s(-n,2),f=s(-.309*n,2),d=s(.118*n,2),h=s(.809*n,2);return y(t,r,"M"+a+","+f+"H"+i+"L"+o+","+d+"L"+l+","+h+"L0,"+s(.382*n,2)+"L-"+l+","+h+"L-"+o+","+d+"L-"+i+","+f+"H-"+a+"L0,"+u+"Z")}},hexagram:{n:18,f:function(e,t,r){if(v(t))return c;var n=s(.66*e,2),a=s(.38*e,2),i=s(.76*e,2);return y(t,r,"M-"+i+",0l-"+a+",-"+n+"h"+i+"l"+a+",-"+n+"l"+a+","+n+"h"+i+"l-"+a+","+n+"l"+a+","+n+"h-"+i+"l-"+a+","+n+"l-"+a+",-"+n+"h-"+i+"Z")}},"star-triangle-up":{n:19,f:function(e,t,r){if(v(t))return c;var n=s(e*f*.8,2),a=s(.8*e,2),i=s(1.6*e,2),o=s(4*e,2),l="A "+o+","+o+" 0 0 1 ";return y(t,r,"M-"+n+","+a+l+n+","+a+l+"0,-"+i+l+"-"+n+","+a+"Z")}},"star-triangle-down":{n:20,f:function(e,t,r){if(v(t))return c;var n=s(e*f*.8,2),a=s(.8*e,2),i=s(1.6*e,2),o=s(4*e,2),l="A "+o+","+o+" 0 0 1 ";return y(t,r,"M"+n+",-"+a+l+"-"+n+",-"+a+l+"0,"+i+l+n+",-"+a+"Z")}},"star-square":{n:21,f:function(e,t,r){if(v(t))return c;var n=s(1.1*e,2),a=s(2*e,2),i="A "+a+","+a+" 0 0 1 ";return y(t,r,"M-"+n+",-"+n+i+"-"+n+","+n+i+n+","+n+i+n+",-"+n+i+"-"+n+",-"+n+"Z")}},"star-diamond":{n:22,f:function(e,t,r){if(v(t))return c;var n=s(1.4*e,2),a=s(1.9*e,2),i="A "+a+","+a+" 0 0 1 ";return y(t,r,"M-"+n+",0"+i+"0,"+n+i+n+",0"+i+"0,-"+n+i+"-"+n+",0Z")}},"diamond-tall":{n:23,f:function(e,t,r){if(v(t))return c;var n=s(.7*e,2),a=s(1.4*e,2);return y(t,r,"M0,"+a+"L"+n+",0L0,-"+a+"L-"+n+",0Z")}},"diamond-wide":{n:24,f:function(e,t,r){if(v(t))return c;var n=s(1.4*e,2),a=s(.7*e,2);return y(t,r,"M0,"+a+"L"+n+",0L0,-"+a+"L-"+n+",0Z")}},hourglass:{n:25,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"H-"+n+"L"+n+",-"+n+"H-"+n+"Z")},noDot:!0},bowtie:{n:26,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"V-"+n+"L-"+n+","+n+"V-"+n+"Z")},noDot:!0},"circle-cross":{n:27,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M0,"+n+"V-"+n+"M"+n+",0H-"+n+"M"+n+",0A"+n+","+n+" 0 1,1 0,-"+n+"A"+n+","+n+" 0 0,1 "+n+",0Z")},needLine:!0,noDot:!0},"circle-x":{n:28,f:function(e,t,r){if(v(t))return c;var n=s(e,2),a=s(e/u,2);return y(t,r,"M"+a+","+a+"L-"+a+",-"+a+"M"+a+",-"+a+"L-"+a+","+a+"M"+n+",0A"+n+","+n+" 0 1,1 0,-"+n+"A"+n+","+n+" 0 0,1 "+n+",0Z")},needLine:!0,noDot:!0},"square-cross":{n:29,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M0,"+n+"V-"+n+"M"+n+",0H-"+n+"M"+n+","+n+"H-"+n+"V-"+n+"H"+n+"Z")},needLine:!0,noDot:!0},"square-x":{n:30,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"L-"+n+",-"+n+"M"+n+",-"+n+"L-"+n+","+n+"M"+n+","+n+"H-"+n+"V-"+n+"H"+n+"Z")},needLine:!0,noDot:!0},"diamond-cross":{n:31,f:function(e,t,r){if(v(t))return c;var n=s(1.3*e,2);return y(t,r,"M"+n+",0L0,"+n+"L-"+n+",0L0,-"+n+"ZM0,-"+n+"V"+n+"M-"+n+",0H"+n)},needLine:!0,noDot:!0},"diamond-x":{n:32,f:function(e,t,r){if(v(t))return c;var n=s(1.3*e,2),a=s(.65*e,2);return y(t,r,"M"+n+",0L0,"+n+"L-"+n+",0L0,-"+n+"ZM-"+a+",-"+a+"L"+a+","+a+"M-"+a+","+a+"L"+a+",-"+a)},needLine:!0,noDot:!0},"cross-thin":{n:33,f:function(e,t,r){if(v(t))return c;var n=s(1.4*e,2);return y(t,r,"M0,"+n+"V-"+n+"M"+n+",0H-"+n)},needLine:!0,noDot:!0,noFill:!0},"x-thin":{n:34,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"L-"+n+",-"+n+"M"+n+",-"+n+"L-"+n+","+n)},needLine:!0,noDot:!0,noFill:!0},asterisk:{n:35,f:function(e,t,r){if(v(t))return c;var n=s(1.2*e,2),a=s(.85*e,2);return y(t,r,"M0,"+n+"V-"+n+"M"+n+",0H-"+n+"M"+a+","+a+"L-"+a+",-"+a+"M"+a+",-"+a+"L-"+a+","+a)},needLine:!0,noDot:!0,noFill:!0},hash:{n:36,f:function(e,t,r){if(v(t))return c;var n=s(e/2,2),a=s(e,2);return y(t,r,"M"+n+","+a+"V-"+a+"M"+(n-a)+",-"+a+"V"+a+"M"+a+","+n+"H-"+a+"M-"+a+","+(n-a)+"H"+a)},needLine:!0,noFill:!0},"y-up":{n:37,f:function(e,t,r){if(v(t))return c;var n=s(1.2*e,2),a=s(1.6*e,2),i=s(.8*e,2);return y(t,r,"M-"+n+","+i+"L0,0M"+n+","+i+"L0,0M0,-"+a+"L0,0")},needLine:!0,noDot:!0,noFill:!0},"y-down":{n:38,f:function(e,t,r){if(v(t))return c;var n=s(1.2*e,2),a=s(1.6*e,2),i=s(.8*e,2);return y(t,r,"M-"+n+",-"+i+"L0,0M"+n+",-"+i+"L0,0M0,"+a+"L0,0")},needLine:!0,noDot:!0,noFill:!0},"y-left":{n:39,f:function(e,t,r){if(v(t))return c;var n=s(1.2*e,2),a=s(1.6*e,2),i=s(.8*e,2);return y(t,r,"M"+i+","+n+"L0,0M"+i+",-"+n+"L0,0M-"+a+",0L0,0")},needLine:!0,noDot:!0,noFill:!0},"y-right":{n:40,f:function(e,t,r){if(v(t))return c;var n=s(1.2*e,2),a=s(1.6*e,2),i=s(.8*e,2);return y(t,r,"M-"+i+","+n+"L0,0M-"+i+",-"+n+"L0,0M"+a+",0L0,0")},needLine:!0,noDot:!0,noFill:!0},"line-ew":{n:41,f:function(e,t,r){if(v(t))return c;var n=s(1.4*e,2);return y(t,r,"M"+n+",0H-"+n)},needLine:!0,noDot:!0,noFill:!0},"line-ns":{n:42,f:function(e,t,r){if(v(t))return c;var n=s(1.4*e,2);return y(t,r,"M0,"+n+"V-"+n)},needLine:!0,noDot:!0,noFill:!0},"line-ne":{n:43,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+",-"+n+"L-"+n+","+n)},needLine:!0,noDot:!0,noFill:!0},"line-nw":{n:44,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M"+n+","+n+"L-"+n+",-"+n)},needLine:!0,noDot:!0,noFill:!0},"arrow-up":{n:45,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M0,0L-"+n+","+s(2*e,2)+"H"+n+"Z")},backoff:1,noDot:!0},"arrow-down":{n:46,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M0,0L-"+n+",-"+s(2*e,2)+"H"+n+"Z")},noDot:!0},"arrow-left":{n:47,f:function(e,t,r){if(v(t))return c;var n=s(2*e,2),a=s(e,2);return y(t,r,"M0,0L"+n+",-"+a+"V"+a+"Z")},noDot:!0},"arrow-right":{n:48,f:function(e,t,r){if(v(t))return c;var n=s(2*e,2),a=s(e,2);return y(t,r,"M0,0L-"+n+",-"+a+"V"+a+"Z")},noDot:!0},"arrow-bar-up":{n:49,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M-"+n+",0H"+n+"M0,0L-"+n+","+s(2*e,2)+"H"+n+"Z")},backoff:1,needLine:!0,noDot:!0},"arrow-bar-down":{n:50,f:function(e,t,r){if(v(t))return c;var n=s(e,2);return y(t,r,"M-"+n+",0H"+n+"M0,0L-"+n+",-"+s(2*e,2)+"H"+n+"Z")},needLine:!0,noDot:!0},"arrow-bar-left":{n:51,f:function(e,t,r){if(v(t))return c;var n=s(2*e,2),a=s(e,2);return y(t,r,"M0,-"+a+"V"+a+"M0,0L"+n+",-"+a+"V"+a+"Z")},needLine:!0,noDot:!0},"arrow-bar-right":{n:52,f:function(e,t,r){if(v(t))return c;var n=s(2*e,2),a=s(e,2);return y(t,r,"M0,-"+a+"V"+a+"M0,0L-"+n+",-"+a+"V"+a+"Z")},needLine:!0,noDot:!0},arrow:{n:53,f:function(e,t,r){if(v(t))return c;var n=d/2.5,a=2*e*h(n),i=2*e*p(n);return y(t,r,"M0,0L"+-a+","+i+"L"+a+","+i+"Z")},backoff:.9,noDot:!0},"arrow-wide":{n:54,f:function(e,t,r){if(v(t))return c;var n=d/4,a=2*e*h(n),i=2*e*p(n);return y(t,r,"M0,0L"+-a+","+i+"A "+2*e+","+2*e+" 0 0 1 "+a+","+i+"Z")},backoff:.4,noDot:!0}}},5673:function(e){"use strict";e.exports={visible:{valType:"boolean",editType:"calc"},type:{valType:"enumerated",values:["percent","constant","sqrt","data"],editType:"calc"},symmetric:{valType:"boolean",editType:"calc"},array:{valType:"data_array",editType:"calc"},arrayminus:{valType:"data_array",editType:"calc"},value:{valType:"number",min:0,dflt:10,editType:"calc"},valueminus:{valType:"number",min:0,dflt:10,editType:"calc"},traceref:{valType:"integer",min:0,dflt:0,editType:"style"},tracerefminus:{valType:"integer",min:0,dflt:0,editType:"style"},copy_ystyle:{valType:"boolean",editType:"plot"},copy_zstyle:{valType:"boolean",editType:"style"},color:{valType:"color",editType:"style"},thickness:{valType:"number",min:0,dflt:2,editType:"style"},width:{valType:"number",min:0,editType:"plot"},editType:"calc",_deprecated:{opacity:{valType:"number",editType:"style"}}}},4532:function(e,t,r){"use strict";var n=r(2770),a=r(3972),i=r(9298),o=r(1828),l=r(5827);function s(e,t,r,a){var s=t["error_"+a]||{},c=[];if(s.visible&&-1!==["linear","log"].indexOf(r.type)){for(var u=l(s),f=0;f<e.length;f++){var d=e[f],h=d.i;if(void 0===h)h=f;else if(null===h)continue;var p=d[a];if(n(r.c2l(p))){var v=u(p,h);if(n(v[0])&&n(v[1])){var y=d[a+"s"]=p-v[0],g=d[a+"h"]=p+v[1];c.push(y,g)}}}var m=r._id,x=t._extremes[m],b=i.findExtremes(r,c,o.extendFlat({tozero:x.opts.tozero},{padded:!0}));x.min=x.min.concat(b.min),x.max=x.max.concat(b.max)}}e.exports=function(e){for(var t=e.calcdata,r=0;r<t.length;r++){var n=t[r],o=n[0].trace;if(!0===o.visible&&a.traceIs(o,"errorBarsOK")){var l=i.getFromId(e,o.xaxis),c=i.getFromId(e,o.yaxis);s(n,o,l,"x"),s(n,o,c,"y")}}}},5827:function(e){"use strict";function t(e,t){return"percent"===e?function(e){return Math.abs(e*t/100)}:"constant"===e?function(){return Math.abs(t)}:"sqrt"===e?function(e){return Math.sqrt(Math.abs(e))}:void 0}e.exports=function(e){var r=e.type,n=e.symmetric;if("data"===r){var a=e.array||[];if(n)return function(e,t){var r=+a[t];return[r,r]};var i=e.arrayminus||[];return function(e,t){var r=+a[t],n=+i[t];return isNaN(r)&&isNaN(n)?[NaN,NaN]:[n||0,r||0]}}var o=t(r,e.value),l=t(r,e.valueminus);return n||void 0===e.valueminus?function(e){var t=o(e);return[t,t]}:function(e){return[l(e),o(e)]}}},7587:function(e,t,r){"use strict";var n=r(2770),a=r(3972),i=r(1828),o=r(4467),l=r(5673);e.exports=function(e,t,r,s){var c="error_"+s.axis,u=o.newContainer(t,c),f=e[c]||{};function d(e,t){return i.coerce(f,u,l,e,t)}if(!1!==d("visible",void 0!==f.array||void 0!==f.value||"sqrt"===f.type)){var h=d("type","array"in f?"data":"percent"),p=!0;"sqrt"!==h&&(p=d("symmetric",!(("data"===h?"arrayminus":"valueminus")in f))),"data"===h?(d("array"),d("traceref"),p||(d("arrayminus"),d("tracerefminus"))):"percent"!==h&&"constant"!==h||(d("value"),p||d("valueminus"));var v="copy_"+s.inherit+"style";s.inherit&&(t["error_"+s.inherit]||{}).visible&&d(v,!(f.color||n(f.thickness)||n(f.width))),s.inherit&&u[v]||(d("color",r),d("thickness"),d("width",a.traceIs(t,"gl3d")?0:4))}}},7369:function(e,t,r){"use strict";var n=r(1828),a=r(962).overrideAll,i=r(5673),o={error_x:n.extendFlat({},i),error_y:n.extendFlat({},i)};delete o.error_x.copy_zstyle,delete o.error_y.copy_zstyle,delete o.error_y.copy_ystyle;var l={error_x:n.extendFlat({},i),error_y:n.extendFlat({},i),error_z:n.extendFlat({},i)};delete l.error_x.copy_ystyle,delete l.error_y.copy_ystyle,delete l.error_z.copy_ystyle,delete l.error_z.copy_zstyle,e.exports={moduleType:"component",name:"errorbars",schema:{traces:{scatter:o,bar:o,histogram:o,scatter3d:a(l,"calc","nested"),scattergl:a(o,"calc","nested")}},supplyDefaults:r(7587),calc:r(4532),makeComputeError:r(5827),plot:r(9398),style:r(2662),hoverInfo:function(e,t,r){(t.error_y||{}).visible&&(r.yerr=e.yh-e.y,t.error_y.symmetric||(r.yerrneg=e.y-e.ys)),(t.error_x||{}).visible&&(r.xerr=e.xh-e.x,t.error_x.symmetric||(r.xerrneg=e.x-e.xs))}}},9398:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(1424),o=r(4098);e.exports=function(e,t,r,l){var s=r.xaxis,c=r.yaxis,u=l&&l.duration>0,f=e._context.staticPlot;t.each((function(t){var d,h=t[0].trace,p=h.error_x||{},v=h.error_y||{};h.ids&&(d=function(e){return e.id});var y=o.hasMarkers(h)&&h.marker.maxdisplayed>0;v.visible||p.visible||(t=[]);var g=n.select(this).selectAll("g.errorbar").data(t,d);if(g.exit().remove(),t.length){p.visible||g.selectAll("path.xerror").remove(),v.visible||g.selectAll("path.yerror").remove(),g.style("opacity",1);var m=g.enter().append("g").classed("errorbar",!0);u&&m.style("opacity",0).transition().duration(l.duration).style("opacity",1),i.setClipUrl(g,r.layerClipId,e),g.each((function(e){var t=n.select(this),r=function(e,t,r){var n={x:t.c2p(e.x),y:r.c2p(e.y)};return void 0!==e.yh&&(n.yh=r.c2p(e.yh),n.ys=r.c2p(e.ys),a(n.ys)||(n.noYS=!0,n.ys=r.c2p(e.ys,!0))),void 0!==e.xh&&(n.xh=t.c2p(e.xh),n.xs=t.c2p(e.xs),a(n.xs)||(n.noXS=!0,n.xs=t.c2p(e.xs,!0))),n}(e,s,c);if(!y||e.vis){var i,o=t.select("path.yerror");if(v.visible&&a(r.x)&&a(r.yh)&&a(r.ys)){var d=v.width;i="M"+(r.x-d)+","+r.yh+"h"+2*d+"m-"+d+",0V"+r.ys,r.noYS||(i+="m-"+d+",0h"+2*d),o.size()?u&&(o=o.transition().duration(l.duration).ease(l.easing)):o=t.append("path").style("vector-effect",f?"none":"non-scaling-stroke").classed("yerror",!0),o.attr("d",i)}else o.remove();var h=t.select("path.xerror");if(p.visible&&a(r.y)&&a(r.xh)&&a(r.xs)){var g=(p.copy_ystyle?v:p).width;i="M"+r.xh+","+(r.y-g)+"v"+2*g+"m0,-"+g+"H"+r.xs,r.noXS||(i+="m0,-"+g+"v"+2*g),h.size()?u&&(h=h.transition().duration(l.duration).ease(l.easing)):h=t.append("path").style("vector-effect",f?"none":"non-scaling-stroke").classed("xerror",!0),h.attr("d",i)}else h.remove()}}))}}))}},2662:function(e,t,r){"use strict";var n=r(9898),a=r(7901);e.exports=function(e){e.each((function(e){var t=e[0].trace,r=t.error_y||{},i=t.error_x||{},o=n.select(this);o.selectAll("path.yerror").style("stroke-width",r.thickness+"px").call(a.stroke,r.color),i.copy_ystyle&&(i=r),o.selectAll("path.xerror").style("stroke-width",i.thickness+"px").call(a.stroke,i.color)}))}},7914:function(e,t,r){"use strict";var n=r(1940),a=r(528).hoverlabel,i=r(1426).extendFlat;e.exports={hoverlabel:{bgcolor:i({},a.bgcolor,{arrayOk:!0}),bordercolor:i({},a.bordercolor,{arrayOk:!0}),font:n({arrayOk:!0,editType:"none"}),align:i({},a.align,{arrayOk:!0}),namelength:i({},a.namelength,{arrayOk:!0}),editType:"none"}}},732:function(e,t,r){"use strict";var n=r(1828),a=r(3972);function i(e,t,r,a){a=a||n.identity,Array.isArray(e)&&(t[0][r]=a(e))}e.exports=function(e){var t=e.calcdata,r=e._fullLayout;function o(e){return function(t){return n.coerceHoverinfo({hoverinfo:t},{_module:e._module},r)}}for(var l=0;l<t.length;l++){var s=t[l],c=s[0].trace;if(!a.traceIs(c,"pie-like")){var u=a.traceIs(c,"2dMap")?i:n.fillArray;u(c.hoverinfo,s,"hi",o(c)),c.hovertemplate&&u(c.hovertemplate,s,"ht"),c.hoverlabel&&(u(c.hoverlabel.bgcolor,s,"hbg"),u(c.hoverlabel.bordercolor,s,"hbc"),u(c.hoverlabel.font.size,s,"hts"),u(c.hoverlabel.font.color,s,"htc"),u(c.hoverlabel.font.family,s,"htf"),u(c.hoverlabel.namelength,s,"hnl"),u(c.hoverlabel.align,s,"hta"))}}}},5914:function(e,t,r){"use strict";var n=r(3972),a=r(8335).hover;e.exports=function(e,t,r){var i=n.getComponentMethod("annotations","onClick")(e,e._hoverdata);function o(){e.emit("plotly_click",{points:e._hoverdata,event:t})}void 0!==r&&a(e,t,r,!0),e._hoverdata&&t&&t.target&&(i&&i.then?i.then(o):o(),t.stopImmediatePropagation&&t.stopImmediatePropagation())}},6675:function(e){"use strict";e.exports={YANGLE:60,HOVERARROWSIZE:6,HOVERTEXTPAD:3,HOVERFONTSIZE:13,HOVERFONT:"Arial, sans-serif",HOVERMINTIME:50,HOVERID:"-hover"}},4268:function(e,t,r){"use strict";var n=r(1828),a=r(7914),i=r(8048);e.exports=function(e,t,r,o){var l=n.extendFlat({},o.hoverlabel);t.hovertemplate&&(l.namelength=-1),i(e,t,(function(r,i){return n.coerce(e,t,a,r,i)}),l)}},3469:function(e,t,r){"use strict";var n=r(1828);t.getSubplot=function(e){return e.subplot||e.xaxis+e.yaxis||e.geo},t.isTraceInSubplots=function(e,r){if("splom"===e.type){for(var n=e.xaxes||[],a=e.yaxes||[],i=0;i<n.length;i++)for(var o=0;o<a.length;o++)if(-1!==r.indexOf(n[i]+a[o]))return!0;return!1}return-1!==r.indexOf(t.getSubplot(e))},t.flat=function(e,t){for(var r=new Array(e.length),n=0;n<e.length;n++)r[n]=t;return r},t.p2c=function(e,t){for(var r=new Array(e.length),n=0;n<e.length;n++)r[n]=e[n].p2c(t);return r},t.getDistanceFunction=function(e,r,n,a){return"closest"===e?a||t.quadrature(r,n):"x"===e.charAt(0)?r:n},t.getClosest=function(e,t,r){if(!1!==r.index)r.index>=0&&r.index<e.length?r.distance=0:r.index=!1;else for(var n=0;n<e.length;n++){var a=t(e[n]);a<=r.distance&&(r.index=n,r.distance=a)}return r},t.inbox=function(e,t,r){return e*t<0||0===e?r:1/0},t.quadrature=function(e,t){return function(r){var n=e(r),a=t(r);return Math.sqrt(n*n+a*a)}},t.makeEventData=function(e,r,n){var a="index"in e?e.index:e.pointNumber,i={data:r._input,fullData:r,curveNumber:r.index,pointNumber:a};if(r._indexToPoints){var o=r._indexToPoints[a];1===o.length?i.pointIndex=o[0]:i.pointIndices=o}else i.pointIndex=a;return r._module.eventData?i=r._module.eventData(i,e,r,n,a):("xVal"in e?i.x=e.xVal:"x"in e&&(i.x=e.x),"yVal"in e?i.y=e.yVal:"y"in e&&(i.y=e.y),e.xa&&(i.xaxis=e.xa),e.ya&&(i.yaxis=e.ya),void 0!==e.zLabelVal&&(i.z=e.zLabelVal)),t.appendArrayPointValue(i,r,a),i},t.appendArrayPointValue=function(e,t,r){var a=t._arrayAttrs;if(a)for(var l=0;l<a.length;l++){var s=a[l],c=i(s);if(void 0===e[c]){var u=o(n.nestedProperty(t,s).get(),r);void 0!==u&&(e[c]=u)}}},t.appendArrayMultiPointValues=function(e,t,r){var a=t._arrayAttrs;if(a)for(var l=0;l<a.length;l++){var s=a[l],c=i(s);if(void 0===e[c]){for(var u=n.nestedProperty(t,s).get(),f=new Array(r.length),d=0;d<r.length;d++)f[d]=o(u,r[d]);e[c]=f}}};var a={ids:"id",locations:"location",labels:"label",values:"value","marker.colors":"color",parents:"parent"};function i(e){return a[e]||e}function o(e,t){return Array.isArray(t)?Array.isArray(e)&&Array.isArray(e[t[0]])?e[t[0]][t[1]]:void 0:e[t]}var l={x:!0,y:!0},s={"x unified":!0,"y unified":!0};t.isUnifiedHover=function(e){return"string"==typeof e&&!!s[e]},t.isXYhover=function(e){return"string"==typeof e&&!!l[e]}},8335:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(4267),o=r(1828),l=o.strTranslate,s=o.strRotate,c=r(1086),u=r(3893),f=r(9918),d=r(1424),h=r(7901),p=r(8569),v=r(9298),y=r(3972),g=r(3469),m=r(6675),x=r(9017),b=r(3969),_=m.YANGLE,w=Math.PI*_/180,T=1/Math.sin(w),M=Math.cos(w),k=Math.sin(w),A=m.HOVERARROWSIZE,L=m.HOVERTEXTPAD,S={box:!0,ohlc:!0,violin:!0,candlestick:!0},O={scatter:!0,scattergl:!0,splom:!0};function D(e){return[e.trace.index,e.index,e.x0,e.y0,e.name,e.attr,e.xa?e.xa._id:"",e.ya?e.ya._id:""].join(",")}t.hover=function(e,t,r,i){e=o.getGraphDiv(e);var l=t.target;o.throttle(e._fullLayout._uid+m.HOVERID,m.HOVERMINTIME,(function(){!function(e,t,r,i,l){r||(r="xy");var s=Array.isArray(r)?r:[r],u=e._fullLayout,d=u._plots||[],v=d[r],m=u._has("cartesian");if(v){var x=v.overlays.map((function(e){return e.id}));s=s.concat(x)}for(var b=s.length,_=new Array(b),w=new Array(b),M=!1,k=0;k<b;k++){var L=s[k];if(d[L])M=!0,_[k]=d[L].xaxis,w[k]=d[L].yaxis;else{if(!u[L]||!u[L]._subplot)return void o.warn("Unrecognized subplot: "+L);var C=u[L]._subplot;_[k]=C.xaxis,w[k]=C.yaxis}}var I=t.hovermode||u.hovermode;if(I&&!M&&(I="closest"),-1===["x","y","closest","x unified","y unified"].indexOf(I)||!e.calcdata||e.querySelector(".zoombox")||e._dragging)return p.unhoverRaw(e,t);var H=u.hoverdistance;-1===H&&(H=1/0);var U=u.spikedistance;-1===U&&(U=1/0);var V,q,Z,G,W,X,J,K,Q,$,ee,te,re,ne=[],ae=[],ie={hLinePoint:null,vLinePoint:null},oe=!1;if(Array.isArray(t))for(I="array",Z=0;Z<t.length;Z++)(W=e.calcdata[t[Z].curveNumber||0])&&(X=W[0].trace,"skip"!==W[0].trace.hoverinfo&&(ae.push(W),"h"===X.orientation&&(oe=!0)));else{for(G=0;G<e.calcdata.length;G++)W=e.calcdata[G],"skip"!==(X=W[0].trace).hoverinfo&&g.isTraceInSubplots(X,s)&&(ae.push(W),"h"===X.orientation&&(oe=!0));var le,se;if(l){if(!1===c.triggerHandler(e,"plotly_beforehover",t))return;var ce=l.getBoundingClientRect();le=t.clientX-ce.left,se=t.clientY-ce.top,u._calcInverseTransform(e);var ue=o.apply3DTransform(u._invTransform)(le,se);if(le=ue[0],se=ue[1],le<0||le>_[0]._length||se<0||se>w[0]._length)return p.unhoverRaw(e,t)}else le="xpx"in t?t.xpx:_[0]._length/2,se="ypx"in t?t.ypx:w[0]._length/2;if(t.pointerX=le+_[0]._offset,t.pointerY=se+w[0]._offset,V="xval"in t?g.flat(s,t.xval):g.p2c(_,le),q="yval"in t?g.flat(s,t.yval):g.p2c(w,se),!a(V[0])||!a(q[0]))return o.warn("Fx.hover failed",t,e),p.unhoverRaw(e,t)}var fe=1/0;function de(e,r){for(G=0;G<ae.length;G++)if((W=ae[G])&&W[0]&&W[0].trace&&!0===(X=W[0].trace).visible&&0!==X._length&&-1===["carpet","contourcarpet"].indexOf(X._module.name)){if("splom"===X.type?J=s[K=0]:(J=g.getSubplot(X),K=s.indexOf(J)),Q=I,g.isUnifiedHover(Q)&&(Q=Q.charAt(0)),te={cd:W,trace:X,xa:_[K],ya:w[K],maxHoverDistance:H,maxSpikeDistance:U,index:!1,distance:Math.min(fe,H),spikeDistance:1/0,xSpike:void 0,ySpike:void 0,color:h.defaultLine,name:X.name,x0:void 0,x1:void 0,y0:void 0,y1:void 0,xLabelVal:void 0,yLabelVal:void 0,zLabelVal:void 0,text:void 0},u[J]&&(te.subplot=u[J]._subplot),u._splomScenes&&u._splomScenes[X.uid]&&(te.scene=u._splomScenes[X.uid]),re=ne.length,"array"===Q){var n=t[G];"pointNumber"in n?(te.index=n.pointNumber,Q="closest"):(Q="","xval"in n&&($=n.xval,Q="x"),"yval"in n&&(ee=n.yval,Q=Q?"closest":"y"))}else void 0!==e&&void 0!==r?($=e,ee=r):($=V[K],ee=q[K]);if(0!==H)if(X._module&&X._module.hoverPoints){var i=X._module.hoverPoints(te,$,ee,Q,{finiteRange:!0,hoverLayer:u._hoverlayer});if(i)for(var l,c=0;c<i.length;c++)l=i[c],a(l.x0)&&a(l.y0)&&ne.push(N(l,I))}else o.log("Unrecognized trace type in hover:",X);if("closest"===I&&ne.length>re&&(ne.splice(0,re),fe=ne[0].distance),m&&0!==U&&0===ne.length){te.distance=U,te.index=!1;var f=X._module.hoverPoints(te,$,ee,"closest",{hoverLayer:u._hoverlayer});if(f&&(f=f.filter((function(e){return e.spikeDistance<=U}))),f&&f.length){var d,p=f.filter((function(e){return e.xa.showspikes&&"hovered data"!==e.xa.spikesnap}));if(p.length){var v=p[0];a(v.x0)&&a(v.y0)&&(d=pe(v),(!ie.vLinePoint||ie.vLinePoint.spikeDistance>d.spikeDistance)&&(ie.vLinePoint=d))}var y=f.filter((function(e){return e.ya.showspikes&&"hovered data"!==e.ya.spikesnap}));if(y.length){var x=y[0];a(x.x0)&&a(x.y0)&&(d=pe(x),(!ie.hLinePoint||ie.hLinePoint.spikeDistance>d.spikeDistance)&&(ie.hLinePoint=d))}}}}}function he(e,t,r){for(var n,a=null,i=1/0,o=0;o<e.length;o++)n=e[o].spikeDistance,r&&0===o&&(n=-1/0),n<=i&&n<=t&&(a=e[o],i=n);return a}function pe(e){return e?{xa:e.xa,ya:e.ya,x:void 0!==e.xSpike?e.xSpike:(e.x0+e.x1)/2,y:void 0!==e.ySpike?e.ySpike:(e.y0+e.y1)/2,distance:e.distance,spikeDistance:e.spikeDistance,curveNumber:e.trace.index,color:e.color,pointNumber:e.index}:null}de();var ve={fullLayout:u,container:u._hoverlayer,event:t},ye=e._spikepoints,ge={vLinePoint:ie.vLinePoint,hLinePoint:ie.hLinePoint};e._spikepoints=ge;var me=function(){ne.sort((function(e,t){return e.distance-t.distance})),ne=function(e,t){for(var r=t.charAt(0),n=[],a=[],i=[],o=0;o<e.length;o++){var l=e[o];y.traceIs(l.trace,"bar-like")||y.traceIs(l.trace,"box-violin")?i.push(l):l.trace[r+"period"]?a.push(l):n.push(l)}return n.concat(a).concat(i)}(ne,I)};me();var xe=I.charAt(0),be=("x"===xe||"y"===xe)&&ne[0]&&O[ne[0].trace.type];if(m&&0!==U&&0!==ne.length){var _e=he(ne.filter((function(e){return e.ya.showspikes})),U,be);ie.hLinePoint=pe(_e);var we=he(ne.filter((function(e){return e.xa.showspikes})),U,be);ie.vLinePoint=pe(we)}if(0===ne.length){var Te=p.unhoverRaw(e,t);return!m||null===ie.hLinePoint&&null===ie.vLinePoint||F(ye)&&E(e,ie,ve),Te}if(m&&F(ye)&&E(e,ie,ve),g.isXYhover(Q)&&0!==ne[0].length&&"splom"!==ne[0].trace.type){var Me=ne[0],ke=(ne=S[Me.trace.type]?ne.filter((function(e){return e.trace.index===Me.trace.index})):[Me]).length;de(j("x",Me,u),j("y",Me,u));var Ae,Le=[],Se={},Oe=0,De=function(e){var t=S[e.trace.type]?D(e):e.trace.index;if(Se[t]){var r=Se[t]-1,n=Le[r];r>0&&Math.abs(e.distance)<Math.abs(n.distance)&&(Le[r]=e)}else Oe++,Se[t]=Oe,Le.push(e)};for(Ae=0;Ae<ke;Ae++)De(ne[Ae]);for(Ae=ne.length-1;Ae>ke-1;Ae--)De(ne[Ae]);ne=Le,me()}var Ce=e._hoverdata,Pe=[],Ie=B(e),Re=Y(e);for(Z=0;Z<ne.length;Z++){var ze=ne[Z],Ne=g.makeEventData(ze,ze.trace,ze.cd);if(!1!==ze.hovertemplate){var Ee=!1;ze.cd[ze.index]&&ze.cd[ze.index].ht&&(Ee=ze.cd[ze.index].ht),ze.hovertemplate=Ee||ze.trace.hovertemplate||!1}if(ze.xa&&ze.ya){var Fe=ze.x0+ze.xa._offset,He=ze.x1+ze.xa._offset,je=ze.y0+ze.ya._offset,Be=ze.y1+ze.ya._offset,Ye=Math.min(Fe,He),Ue=Math.max(Fe,He),Ve=Math.min(je,Be),qe=Math.max(je,Be);Ne.bbox={x0:Ye+Re,x1:Ue+Re,y0:Ve+Ie,y1:qe+Ie}}ze.eventData=[Ne],Pe.push(Ne)}e._hoverdata=Pe;var Ze="y"===I&&(ae.length>1||ne.length>1)||"closest"===I&&oe&&ne.length>1,Ge=h.combine(u.plot_bgcolor||h.background,u.paper_bgcolor),We=P(ne,{gd:e,hovermode:I,rotateLabels:Ze,bgColor:Ge,container:u._hoverlayer,outerContainer:u._paper.node(),commonLabelOpts:u.hoverlabel,hoverdistance:u.hoverdistance}),Xe=We.hoverLabels;if(g.isUnifiedHover(I)||(function(e,t,r,n){var a,i,o,l,s,c,u,f=t?"xa":"ya",d=t?"ya":"xa",h=0,p=1,v=e.size(),y=new Array(v),g=0,m=n.minX,x=n.maxX,b=n.minY,_=n.maxY,w=function(e){return e*r._invScaleX},M=function(e){return e*r._invScaleY};function k(e){var t=e[0],r=e[e.length-1];if(i=t.pmin-t.pos-t.dp+t.size,o=r.pos+r.dp+r.size-t.pmax,i>.01){for(s=e.length-1;s>=0;s--)e[s].dp+=i;a=!1}if(!(o<.01)){if(i<-.01){for(s=e.length-1;s>=0;s--)e[s].dp-=o;a=!1}if(a){var n=0;for(l=0;l<e.length;l++)(c=e[l]).pos+c.dp+c.size>t.pmax&&n++;for(l=e.length-1;l>=0&&!(n<=0);l--)(c=e[l]).pos>t.pmax-1&&(c.del=!0,n--);for(l=0;l<e.length&&!(n<=0);l++)if((c=e[l]).pos<t.pmin+1)for(c.del=!0,n--,o=2*c.size,s=e.length-1;s>=0;s--)e[s].dp-=o;for(l=e.length-1;l>=0&&!(n<=0);l--)(c=e[l]).pos+c.dp+c.size>t.pmax&&(c.del=!0,n--)}}}for(e.each((function(e){var n=e[f],a=e[d],i="x"===n._id.charAt(0),o=n.range;0===g&&o&&o[0]>o[1]!==i&&(p=-1);var l=0,s=i?r.width:r.height;if("x"===r.hovermode||"y"===r.hovermode){var c,u,h=R(e,t),v=e.anchor,k="end"===v?-1:1;if("middle"===v)u=(c=e.crossPos+(i?M(h.y-e.by/2):w(e.bx/2+e.tx2width/2)))+(i?M(e.by):w(e.bx));else if(i)u=(c=e.crossPos+M(A+h.y)-M(e.by/2-A))+M(e.by);else{var L=w(k*A+h.x),S=L+w(k*e.bx);c=e.crossPos+Math.min(L,S),u=e.crossPos+Math.max(L,S)}i?void 0!==b&&void 0!==_&&Math.min(u,_)-Math.max(c,b)>1&&("left"===a.side?(l=a._mainLinePosition,s=r.width):s=a._mainLinePosition):void 0!==m&&void 0!==x&&Math.min(u,x)-Math.max(c,m)>1&&("top"===a.side?(l=a._mainLinePosition,s=r.height):s=a._mainLinePosition)}y[g++]=[{datum:e,traceIndex:e.trace.index,dp:0,pos:e.pos,posref:e.posref,size:e.by*(i?T:1)/2,pmin:l,pmax:s}]})),y.sort((function(e,t){return e[0].posref-t[0].posref||p*(t[0].traceIndex-e[0].traceIndex)}));!a&&h<=v;){for(h++,a=!0,l=0;l<y.length-1;){var L=y[l],S=y[l+1],O=L[L.length-1],D=S[0];if((i=O.pos+O.dp+O.size-D.pos-D.dp+D.size)>.01&&O.pmin===D.pmin&&O.pmax===D.pmax){for(s=S.length-1;s>=0;s--)S[s].dp+=i;for(L.push.apply(L,S),y.splice(l+1,1),u=0,s=L.length-1;s>=0;s--)u+=L[s].dp;for(o=u/L.length,s=L.length-1;s>=0;s--)L[s].dp-=o;a=!1}else l++}y.forEach(k)}for(l=y.length-1;l>=0;l--){var C=y[l];for(s=C.length-1;s>=0;s--){var P=C[s],I=P.datum;I.offset=P.dp,I.del=P.del}}}(Xe,Ze,u,We.commonLabelBoundingBox),z(Xe,Ze,u._invScaleX,u._invScaleY)),l&&l.tagName){var Je=y.getComponentMethod("annotations","hasClickToShow")(e,Pe);f(n.select(l),Je?"pointer":"")}l&&!i&&function(e,t,r){if(!r||r.length!==e._hoverdata.length)return!0;for(var n=r.length-1;n>=0;n--){var a=r[n],i=e._hoverdata[n];if(a.curveNumber!==i.curveNumber||String(a.pointNumber)!==String(i.pointNumber)||String(a.pointNumbers)!==String(i.pointNumbers))return!0}return!1}(e,0,Ce)&&(Ce&&e.emit("plotly_unhover",{event:t,points:Ce}),e.emit("plotly_hover",{event:t,points:e._hoverdata,xaxes:_,yaxes:w,xvals:V,yvals:q}))}(e,t,r,i,l)}))},t.loneHover=function(e,t){var r=!0;Array.isArray(e)||(r=!1,e=[e]);var a=t.gd,i=B(a),o=Y(a),l=P(e.map((function(e){var r=e._x0||e.x0||e.x||0,n=e._x1||e.x1||e.x||0,l=e._y0||e.y0||e.y||0,s=e._y1||e.y1||e.y||0,c=e.eventData;if(c){var u=Math.min(r,n),f=Math.max(r,n),d=Math.min(l,s),p=Math.max(l,s),v=e.trace;if(y.traceIs(v,"gl3d")){var g=a._fullLayout[v.scene]._scene.container,m=g.offsetLeft,x=g.offsetTop;u+=m,f+=m,d+=x,p+=x}c.bbox={x0:u+o,x1:f+o,y0:d+i,y1:p+i},t.inOut_bbox&&t.inOut_bbox.push(c.bbox)}else c=!1;return{color:e.color||h.defaultLine,x0:e.x0||e.x||0,x1:e.x1||e.x||0,y0:e.y0||e.y||0,y1:e.y1||e.y||0,xLabel:e.xLabel,yLabel:e.yLabel,zLabel:e.zLabel,text:e.text,name:e.name,idealAlign:e.idealAlign,borderColor:e.borderColor,fontFamily:e.fontFamily,fontSize:e.fontSize,fontColor:e.fontColor,nameLength:e.nameLength,textAlign:e.textAlign,trace:e.trace||{index:0,hoverinfo:""},xa:{_offset:0},ya:{_offset:0},index:0,hovertemplate:e.hovertemplate||!1,hovertemplateLabels:e.hovertemplateLabels||!1,eventData:c}})),{gd:a,hovermode:"closest",rotateLabels:!1,bgColor:t.bgColor||h.background,container:n.select(t.container),outerContainer:t.outerContainer||t.container}).hoverLabels,s=0,c=0;return l.sort((function(e,t){return e.y0-t.y0})).each((function(e,r){var n=e.y0-e.by/2;e.offset=n-5<s?s-n+5:0,s=n+e.by+e.offset,r===t.anchorIndex&&(c=e.offset)})).each((function(e){e.offset-=c})),z(l,!1,a._fullLayout._invScaleX,a._fullLayout._invScaleY),r?l:l.node()};var C=/<extra>([\s\S]*)<\/extra>/;function P(e,t){var r=t.gd,a=r._fullLayout,i=t.hovermode,c=t.rotateLabels,f=t.bgColor,p=t.container,v=t.outerContainer,w=t.commonLabelOpts||{};if(0===e.length)return[[]];var T=t.fontFamily||m.HOVERFONT,M=t.fontSize||m.HOVERFONTSIZE,k=e[0],S=k.xa,O=k.ya,C=i.charAt(0),P=C+"Label",R=k[P];if(void 0===R&&"multicategory"===S.type)for(var z=0;z<e.length&&void 0===(R=e[z][P]);z++);var N=U(r,v),E=N.top,F=N.width,H=N.height,j=void 0!==R&&k.distance<=t.hoverdistance&&("x"===i||"y"===i);if(j){var B,Y,V=!0;for(B=0;B<e.length;B++)if(V&&void 0===e[B].zLabel&&(V=!1),Y=e[B].hoverinfo||e[B].trace.hoverinfo){var q=Array.isArray(Y)?Y:Y.split("+");if(-1===q.indexOf("all")&&-1===q.indexOf(i)){j=!1;break}}V&&(j=!1)}var Z=p.selectAll("g.axistext").data(j?[0]:[]);Z.enter().append("g").classed("axistext",!0),Z.exit().remove();var G={minX:0,maxX:0,minY:0,maxY:0};if(Z.each((function(){var e=n.select(this),t=o.ensureSingle(e,"path","",(function(e){e.style({"stroke-width":"1px"})})),s=o.ensureSingle(e,"text","",(function(e){e.attr("data-notex",1)})),c=w.bgcolor||h.defaultLine,f=w.bordercolor||h.contrast(c),p=h.contrast(c),v={family:w.font.family||T,size:w.font.size||M,color:w.font.color||p};t.style({fill:c,stroke:f}),s.text(R).call(d.font,v).call(u.positionText,0,0).call(u.convertToTspans,r),e.attr("transform","");var y,g,m=U(r,s.node());if("x"===i){var x="top"===S.side?"-":"";s.attr("text-anchor","middle").call(u.positionText,0,"top"===S.side?E-m.bottom-A-L:E-m.top+A+L),y=S._offset+(k.x0+k.x1)/2,g=O._offset+("top"===S.side?0:O._length);var b=m.width/2+L;y<b?(y=b,t.attr("d","M-"+(b-A)+",0L-"+(b-2*A)+","+x+A+"H"+b+"v"+x+(2*L+m.height)+"H-"+b+"V"+x+A+"Z")):y>a.width-b?(y=a.width-b,t.attr("d","M"+(b-A)+",0L"+b+","+x+A+"v"+x+(2*L+m.height)+"H-"+b+"V"+x+A+"H"+(b-2*A)+"Z")):t.attr("d","M0,0L"+A+","+x+A+"H"+b+"v"+x+(2*L+m.height)+"H-"+b+"V"+x+A+"H-"+A+"Z"),G.minX=y-b,G.maxX=y+b,"top"===S.side?(G.minY=g-(2*L+m.height),G.maxY=g-L):(G.minY=g+L,G.maxY=g+(2*L+m.height))}else{var _,D,C;"right"===O.side?(_="start",D=1,C="",y=S._offset+S._length):(_="end",D=-1,C="-",y=S._offset),g=O._offset+(k.y0+k.y1)/2,s.attr("text-anchor",_),t.attr("d","M0,0L"+C+A+","+A+"V"+(L+m.height/2)+"h"+C+(2*L+m.width)+"V-"+(L+m.height/2)+"H"+C+A+"V-"+A+"Z"),G.minY=g-(L+m.height/2),G.maxY=g+(L+m.height/2),"right"===O.side?(G.minX=y+A,G.maxX=y+A+(2*L+m.width)):(G.minX=y-A-(2*L+m.width),G.maxX=y-A);var P,I=m.height/2,z=E-m.top-I,N="clip"+a._uid+"commonlabel"+O._id;if(y<m.width+2*L+A){P="M-"+(A+L)+"-"+I+"h-"+(m.width-L)+"V"+I+"h"+(m.width-L)+"Z";var F=m.width-y+L;u.positionText(s,F,z),"end"===_&&s.selectAll("tspan").each((function(){var e=n.select(this),t=d.tester.append("text").text(e.text()).call(d.font,v),a=U(r,t.node());Math.round(a.width)<Math.round(m.width)&&e.attr("x",F-a.width),t.remove()}))}else u.positionText(s,D*(L+A),z),P=null;var H=a._topclips.selectAll("#"+N).data(P?[0]:[]);H.enter().append("clipPath").attr("id",N).append("path"),H.exit().remove(),H.select("path").attr("d",P),d.setClipUrl(s,P?N:null,r)}e.attr("transform",l(y,g))})),g.isUnifiedHover(i)){p.selectAll("g.hovertext").remove();var W=e.filter((function(e){return"none"!==e.hoverinfo}));if(0===W.length)return[];var X=a.hoverlabel,J=X.font,K={showlegend:!0,legend:{title:{text:R,font:J},font:J,bgcolor:X.bgcolor,bordercolor:X.bordercolor,borderwidth:1,tracegroupgap:7,traceorder:a.legend?a.legend.traceorder:void 0,orientation:"v"}},Q={font:J};x(K,Q,r._fullData);var $=Q.legend;$.entries=[];for(var ee=0;ee<W.length;ee++){var te=W[ee];if("none"!==te.hoverinfo){var re=I(te,!0,i,a,R),ne=re[0],ae=re[1];te.name=ae,te.text=""!==ae?ae+" : "+ne:ne;var ie=te.cd[te.index];ie&&(ie.mc&&(te.mc=ie.mc),ie.mcc&&(te.mc=ie.mcc),ie.mlc&&(te.mlc=ie.mlc),ie.mlcc&&(te.mlc=ie.mlcc),ie.mlw&&(te.mlw=ie.mlw),ie.mrc&&(te.mrc=ie.mrc),ie.dir&&(te.dir=ie.dir)),te._distinct=!0,$.entries.push([te])}}$.entries.sort((function(e,t){return e[0].trace.index-t[0].trace.index})),$.layer=p,$._inHover=!0,$._groupTitleFont=X.grouptitlefont,b(r,$);var oe,le,se,ce,ue=p.select("g.legend"),fe=U(r,ue.node()),de=fe.width+2*L,he=fe.height+2*L,pe=W[0],ve=(pe.x0+pe.x1)/2,ye=(pe.y0+pe.y1)/2,ge=!(y.traceIs(pe.trace,"bar-like")||y.traceIs(pe.trace,"box-violin"));"y"===C?ge?(le=ye-L,oe=ye+L):(le=Math.min.apply(null,W.map((function(e){return Math.min(e.y0,e.y1)}))),oe=Math.max.apply(null,W.map((function(e){return Math.max(e.y0,e.y1)})))):le=oe=o.mean(W.map((function(e){return(e.y0+e.y1)/2})))-he/2,"x"===C?ge?(se=ve+L,ce=ve-L):(se=Math.max.apply(null,W.map((function(e){return Math.max(e.x0,e.x1)}))),ce=Math.min.apply(null,W.map((function(e){return Math.min(e.x0,e.x1)})))):se=ce=o.mean(W.map((function(e){return(e.x0+e.x1)/2})))-de/2;var me,xe,be=S._offset,_e=O._offset;return ce+=be-de,le+=_e-he,me=(se+=be)+de<F&&se>=0?se:ce+de<F&&ce>=0?ce:be+de<F?be:se-ve<ve-ce+de?F-de:0,me+=L,xe=(oe+=_e)+he<H&&oe>=0?oe:le+he<H&&le>=0?le:_e+he<H?_e:oe-ye<ye-le+he?H-he:0,xe+=L,ue.attr("transform",l(me-1,xe-1)),ue}var we=p.selectAll("g.hovertext").data(e,(function(e){return D(e)}));return we.enter().append("g").classed("hovertext",!0).each((function(){var e=n.select(this);e.append("rect").call(h.fill,h.addOpacity(f,.8)),e.append("text").classed("name",!0),e.append("path").style("stroke-width","1px"),e.append("text").classed("nums",!0).call(d.font,T,M)})),we.exit().remove(),we.each((function(e){var t=n.select(this).attr("transform",""),o=e.color;Array.isArray(o)&&(o=o[e.eventData[0].pointNumber]);var p=e.bgcolor||o,v=h.combine(h.opacity(p)?p:h.defaultLine,f),y=h.combine(h.opacity(o)?o:h.defaultLine,f),g=e.borderColor||h.contrast(v),m=I(e,j,i,a,R,t),x=m[0],b=m[1],w=t.select("text.nums").call(d.font,e.fontFamily||T,e.fontSize||M,e.fontColor||g).text(x).attr("data-notex",1).call(u.positionText,0,0).call(u.convertToTspans,r),k=t.select("text.name"),S=0,O=0;if(b&&b!==x){k.call(d.font,e.fontFamily||T,e.fontSize||M,y).text(b).attr("data-notex",1).call(u.positionText,0,0).call(u.convertToTspans,r);var D=U(r,k.node());S=D.width+2*L,O=D.height+2*L}else k.remove(),t.select("rect").remove();t.select("path").style({fill:v,stroke:g});var C=e.xa._offset+(e.x0+e.x1)/2,P=e.ya._offset+(e.y0+e.y1)/2,z=Math.abs(e.x1-e.x0),N=Math.abs(e.y1-e.y0),B=U(r,w.node()),Y=B.width/a._invScaleX,V=B.height/a._invScaleY;e.ty0=(E-B.top)/a._invScaleY,e.bx=Y+2*L,e.by=Math.max(V+2*L,O),e.anchor="start",e.txwidth=Y,e.tx2width=S,e.offset=0;var q,Z,G=(Y+A+L+S)*a._invScaleX;if(c)e.pos=C,q=P+N/2+G<=H,Z=P-N/2-G>=0,"top"!==e.idealAlign&&q||!Z?q?(P+=N/2,e.anchor="start"):e.anchor="middle":(P-=N/2,e.anchor="end"),e.crossPos=P;else{if(e.pos=P,q=C+z/2+G<=F,Z=C-z/2-G>=0,"left"!==e.idealAlign&&q||!Z)if(q)C+=z/2,e.anchor="start";else{e.anchor="middle";var W=G/2,X=C+W-F,J=C-W;X>0&&(C-=X),J<0&&(C+=-J)}else C-=z/2,e.anchor="end";e.crossPos=C}w.attr("text-anchor",e.anchor),S&&k.attr("text-anchor",e.anchor),t.attr("transform",l(C,P)+(c?s(_):""))})),{hoverLabels:we,commonLabelBoundingBox:G}}function I(e,t,r,n,a,i){var l="",s="";void 0!==e.nameOverride&&(e.name=e.nameOverride),e.name&&(e.trace._meta&&(e.name=o.templateString(e.name,e.trace._meta)),l=H(e.name,e.nameLength));var c=r.charAt(0),u="x"===c?"y":"x";void 0!==e.zLabel?(void 0!==e.xLabel&&(s+="x: "+e.xLabel+"<br>"),void 0!==e.yLabel&&(s+="y: "+e.yLabel+"<br>"),"choropleth"!==e.trace.type&&"choroplethmapbox"!==e.trace.type&&(s+=(s?"z: ":"")+e.zLabel)):t&&e[c+"Label"]===a?s=e[u+"Label"]||"":void 0===e.xLabel?void 0!==e.yLabel&&"scattercarpet"!==e.trace.type&&(s=e.yLabel):s=void 0===e.yLabel?e.xLabel:"("+e.xLabel+", "+e.yLabel+")",!e.text&&0!==e.text||Array.isArray(e.text)||(s+=(s?"<br>":"")+e.text),void 0!==e.extraText&&(s+=(s?"<br>":"")+e.extraText),i&&""===s&&!e.hovertemplate&&(""===l&&i.remove(),s=l);var f=e.hovertemplate||!1;if(f){var d=e.hovertemplateLabels||e;e[c+"Label"]!==a&&(d[c+"other"]=d[c+"Val"],d[c+"otherLabel"]=d[c+"Label"]),s=(s=o.hovertemplateString(f,d,n._d3locale,e.eventData[0]||{},e.trace._meta)).replace(C,(function(t,r){return l=H(r,e.nameLength),""}))}return[s,l]}function R(e,t){var r=0,n=e.offset;return t&&(n*=-k,r=e.offset*M),{x:r,y:n}}function z(e,t,r,a){var i=function(e){return e*r},o=function(e){return e*a};e.each((function(e){var r=n.select(this);if(e.del)return r.remove();var a,l,s,c,f=r.select("text.nums"),h=e.anchor,p="end"===h?-1:1,v=(l={start:1,end:-1,middle:0}[(a=e).anchor],c=(s=l*(A+L))+l*(a.txwidth+L),"middle"===a.anchor&&(s-=a.tx2width/2,c+=a.txwidth/2+L),{alignShift:l,textShiftX:s,text2ShiftX:c}),y=R(e,t),g=y.x,m=y.y,x="middle"===h;r.select("path").attr("d",x?"M-"+i(e.bx/2+e.tx2width/2)+","+o(m-e.by/2)+"h"+i(e.bx)+"v"+o(e.by)+"h-"+i(e.bx)+"Z":"M0,0L"+i(p*A+g)+","+o(A+m)+"v"+o(e.by/2-A)+"h"+i(p*e.bx)+"v-"+o(e.by)+"H"+i(p*A+g)+"V"+o(m-A)+"Z");var b=g+v.textShiftX,_=m+e.ty0-e.by/2+L,w=e.textAlign||"auto";"auto"!==w&&("left"===w&&"start"!==h?(f.attr("text-anchor","start"),b=x?-e.bx/2-e.tx2width/2+L:-e.bx-L):"right"===w&&"end"!==h&&(f.attr("text-anchor","end"),b=x?e.bx/2-e.tx2width/2-L:e.bx+L)),f.call(u.positionText,i(b),o(_)),e.tx2width&&(r.select("text.name").call(u.positionText,i(v.text2ShiftX+v.alignShift*L+g),o(m+e.ty0-e.by/2+L)),r.select("rect").call(d.setRect,i(v.text2ShiftX+(v.alignShift-1)*e.tx2width/2+g),o(m-e.by/2-1),i(e.tx2width),o(e.by+2)))}))}function N(e,t){var r=e.index,n=e.trace||{},i=e.cd[0],l=e.cd[r]||{};function s(e){return e||a(e)&&0===e}var c=Array.isArray(r)?function(e,t){var a=o.castOption(i,r,e);return s(a)?a:o.extractOption({},n,"",t)}:function(e,t){return o.extractOption(l,n,e,t)};function u(t,r,n){var a=c(r,n);s(a)&&(e[t]=a)}if(u("hoverinfo","hi","hoverinfo"),u("bgcolor","hbg","hoverlabel.bgcolor"),u("borderColor","hbc","hoverlabel.bordercolor"),u("fontFamily","htf","hoverlabel.font.family"),u("fontSize","hts","hoverlabel.font.size"),u("fontColor","htc","hoverlabel.font.color"),u("nameLength","hnl","hoverlabel.namelength"),u("textAlign","hta","hoverlabel.align"),e.posref="y"===t||"closest"===t&&"h"===n.orientation?e.xa._offset+(e.x0+e.x1)/2:e.ya._offset+(e.y0+e.y1)/2,e.x0=o.constrain(e.x0,0,e.xa._length),e.x1=o.constrain(e.x1,0,e.xa._length),e.y0=o.constrain(e.y0,0,e.ya._length),e.y1=o.constrain(e.y1,0,e.ya._length),void 0!==e.xLabelVal&&(e.xLabel="xLabel"in e?e.xLabel:v.hoverLabelText(e.xa,e.xLabelVal,n.xhoverformat),e.xVal=e.xa.c2d(e.xLabelVal)),void 0!==e.yLabelVal&&(e.yLabel="yLabel"in e?e.yLabel:v.hoverLabelText(e.ya,e.yLabelVal,n.yhoverformat),e.yVal=e.ya.c2d(e.yLabelVal)),void 0!==e.zLabelVal&&void 0===e.zLabel&&(e.zLabel=String(e.zLabelVal)),!(isNaN(e.xerr)||"log"===e.xa.type&&e.xerr<=0)){var f=v.tickText(e.xa,e.xa.c2l(e.xerr),"hover").text;void 0!==e.xerrneg?e.xLabel+=" +"+f+" / -"+v.tickText(e.xa,e.xa.c2l(e.xerrneg),"hover").text:e.xLabel+=" \xb1 "+f,"x"===t&&(e.distance+=1)}if(!(isNaN(e.yerr)||"log"===e.ya.type&&e.yerr<=0)){var d=v.tickText(e.ya,e.ya.c2l(e.yerr),"hover").text;void 0!==e.yerrneg?e.yLabel+=" +"+d+" / -"+v.tickText(e.ya,e.ya.c2l(e.yerrneg),"hover").text:e.yLabel+=" \xb1 "+d,"y"===t&&(e.distance+=1)}var h=e.hoverinfo||e.trace.hoverinfo;return h&&"all"!==h&&(-1===(h=Array.isArray(h)?h:h.split("+")).indexOf("x")&&(e.xLabel=void 0),-1===h.indexOf("y")&&(e.yLabel=void 0),-1===h.indexOf("z")&&(e.zLabel=void 0),-1===h.indexOf("text")&&(e.text=void 0),-1===h.indexOf("name")&&(e.name=void 0)),e}function E(e,t,r){var n,a,o=r.container,l=r.fullLayout,s=l._size,c=r.event,u=!!t.hLinePoint,f=!!t.vLinePoint;if(o.selectAll(".spikeline").remove(),f||u){var p=h.combine(l.plot_bgcolor,l.paper_bgcolor);if(u){var y,g,m=t.hLinePoint;n=m&&m.xa,"cursor"===(a=m&&m.ya).spikesnap?(y=c.pointerX,g=c.pointerY):(y=n._offset+m.x,g=a._offset+m.y);var x,b,_=i.readability(m.color,p)<1.5?h.contrast(p):m.color,w=a.spikemode,T=a.spikethickness,M=a.spikecolor||_,k=v.getPxPosition(e,a);if(-1!==w.indexOf("toaxis")||-1!==w.indexOf("across")){if(-1!==w.indexOf("toaxis")&&(x=k,b=y),-1!==w.indexOf("across")){var A=a._counterDomainMin,L=a._counterDomainMax;"free"===a.anchor&&(A=Math.min(A,a.position),L=Math.max(L,a.position)),x=s.l+A*s.w,b=s.l+L*s.w}o.insert("line",":first-child").attr({x1:x,x2:b,y1:g,y2:g,"stroke-width":T,stroke:M,"stroke-dasharray":d.dashStyle(a.spikedash,T)}).classed("spikeline",!0).classed("crisp",!0),o.insert("line",":first-child").attr({x1:x,x2:b,y1:g,y2:g,"stroke-width":T+2,stroke:p}).classed("spikeline",!0).classed("crisp",!0)}-1!==w.indexOf("marker")&&o.insert("circle",":first-child").attr({cx:k+("right"!==a.side?T:-T),cy:g,r:T,fill:M}).classed("spikeline",!0)}if(f){var S,O,D=t.vLinePoint;n=D&&D.xa,a=D&&D.ya,"cursor"===n.spikesnap?(S=c.pointerX,O=c.pointerY):(S=n._offset+D.x,O=a._offset+D.y);var C,P,I=i.readability(D.color,p)<1.5?h.contrast(p):D.color,R=n.spikemode,z=n.spikethickness,N=n.spikecolor||I,E=v.getPxPosition(e,n);if(-1!==R.indexOf("toaxis")||-1!==R.indexOf("across")){if(-1!==R.indexOf("toaxis")&&(C=E,P=O),-1!==R.indexOf("across")){var F=n._counterDomainMin,H=n._counterDomainMax;"free"===n.anchor&&(F=Math.min(F,n.position),H=Math.max(H,n.position)),C=s.t+(1-H)*s.h,P=s.t+(1-F)*s.h}o.insert("line",":first-child").attr({x1:S,x2:S,y1:C,y2:P,"stroke-width":z,stroke:N,"stroke-dasharray":d.dashStyle(n.spikedash,z)}).classed("spikeline",!0).classed("crisp",!0),o.insert("line",":first-child").attr({x1:S,x2:S,y1:C,y2:P,"stroke-width":z+2,stroke:p}).classed("spikeline",!0).classed("crisp",!0)}-1!==R.indexOf("marker")&&o.insert("circle",":first-child").attr({cx:S,cy:E-("top"!==n.side?z:-z),r:z,fill:N}).classed("spikeline",!0)}}}function F(e,t){return!t||t.vLinePoint!==e._spikepoints.vLinePoint||t.hLinePoint!==e._spikepoints.hLinePoint}function H(e,t){return u.plainText(e||"",{len:t,allowedTags:["br","sub","sup","b","i","em"]})}function j(e,t,r){var n=t[e+"a"],a=t[e+"Val"],i=t.cd[0];if("category"===n.type||"multicategory"===n.type)a=n._categoriesMap[a];else if("date"===n.type){var o=t.trace[e+"periodalignment"];if(o){var l=t.cd[t.index],s=l[e+"Start"];void 0===s&&(s=l[e]);var c=l[e+"End"];void 0===c&&(c=l[e]);var u=c-s;"end"===o?a+=u:"middle"===o&&(a+=u/2)}a=n.d2c(a)}return i&&i.t&&i.t.posLetter===n._id&&("group"!==r.boxmode&&"group"!==r.violinmode||(a+=i.t.dPos)),a}function B(e){return e.offsetTop+e.clientTop}function Y(e){return e.offsetLeft+e.clientLeft}function U(e,t){var r=e._fullLayout,n=t.getBoundingClientRect(),a=n.left,i=n.top,l=a+n.width,s=i+n.height,c=o.apply3DTransform(r._invTransform)(a,i),u=o.apply3DTransform(r._invTransform)(l,s),f=c[0],d=c[1],h=u[0],p=u[1];return{x:f,y:d,width:h-f,height:p-d,top:Math.min(d,p),left:Math.min(f,h),right:Math.max(f,h),bottom:Math.max(d,p)}}},8048:function(e,t,r){"use strict";var n=r(1828),a=r(7901),i=r(3469).isUnifiedHover;e.exports=function(e,t,r,o){o=o||{};var l=t.legend;function s(e){o.font[e]||(o.font[e]=l?t.legend.font[e]:t.font[e])}t&&i(t.hovermode)&&(o.font||(o.font={}),s("size"),s("family"),s("color"),l?(o.bgcolor||(o.bgcolor=a.combine(t.legend.bgcolor,t.paper_bgcolor)),o.bordercolor||(o.bordercolor=t.legend.bordercolor)):o.bgcolor||(o.bgcolor=t.paper_bgcolor)),r("hoverlabel.bgcolor",o.bgcolor),r("hoverlabel.bordercolor",o.bordercolor),r("hoverlabel.namelength",o.namelength),n.coerceFont(r,"hoverlabel.font",o.font),r("hoverlabel.align",o.align)}},8212:function(e,t,r){"use strict";var n=r(1828),a=r(528);e.exports=function(e,t){function r(r,i){return void 0!==t[r]?t[r]:n.coerce(e,t,a,r,i)}return r("clickmode"),r("hovermode")}},211:function(e,t,r){"use strict";var n=r(9898),a=r(1828),i=r(8569),o=r(3469),l=r(528),s=r(8335);e.exports={moduleType:"component",name:"fx",constants:r(6675),schema:{layout:l},attributes:r(7914),layoutAttributes:l,supplyLayoutGlobalDefaults:r(2774),supplyDefaults:r(4268),supplyLayoutDefaults:r(4938),calc:r(732),getDistanceFunction:o.getDistanceFunction,getClosest:o.getClosest,inbox:o.inbox,quadrature:o.quadrature,appendArrayPointValue:o.appendArrayPointValue,castHoverOption:function(e,t,r){return a.castOption(e,t,"hoverlabel."+r)},castHoverinfo:function(e,t,r){return a.castOption(e,r,"hoverinfo",(function(r){return a.coerceHoverinfo({hoverinfo:r},{_module:e._module},t)}))},hover:s.hover,unhover:i.unhover,loneHover:s.loneHover,loneUnhover:function(e){var t=a.isD3Selection(e)?e:n.select(e);t.selectAll("g.hovertext").remove(),t.selectAll(".spikeline").remove()},click:r(5914)}},528:function(e,t,r){"use strict";var n=r(6675),a=r(1940),i=a({editType:"none"});i.family.dflt=n.HOVERFONT,i.size.dflt=n.HOVERFONTSIZE,e.exports={clickmode:{valType:"flaglist",flags:["event","select"],dflt:"event",editType:"plot",extras:["none"]},dragmode:{valType:"enumerated",values:["zoom","pan","select","lasso","drawclosedpath","drawopenpath","drawline","drawrect","drawcircle","orbit","turntable",!1],dflt:"zoom",editType:"modebar"},hovermode:{valType:"enumerated",values:["x","y","closest",!1,"x unified","y unified"],dflt:"closest",editType:"modebar"},hoverdistance:{valType:"integer",min:-1,dflt:20,editType:"none"},spikedistance:{valType:"integer",min:-1,dflt:-1,editType:"none"},hoverlabel:{bgcolor:{valType:"color",editType:"none"},bordercolor:{valType:"color",editType:"none"},font:i,grouptitlefont:a({editType:"none"}),align:{valType:"enumerated",values:["left","right","auto"],dflt:"auto",editType:"none"},namelength:{valType:"integer",min:-1,dflt:15,editType:"none"},editType:"none"},selectdirection:{valType:"enumerated",values:["h","v","d","any"],dflt:"any",editType:"none"}}},4938:function(e,t,r){"use strict";var n=r(1828),a=r(528),i=r(8212),o=r(8048);e.exports=function(e,t){function r(r,i){return n.coerce(e,t,a,r,i)}i(e,t)&&(r("hoverdistance"),r("spikedistance")),"select"===r("dragmode")&&r("selectdirection");var l=t._has("mapbox"),s=t._has("geo"),c=t._basePlotModules.length;"zoom"===t.dragmode&&((l||s)&&1===c||l&&s&&2===c)&&(t.dragmode="pan"),o(e,t,r),n.coerceFont(r,"hoverlabel.grouptitlefont",t.hoverlabel.font)}},2774:function(e,t,r){"use strict";var n=r(1828),a=r(8048),i=r(528);e.exports=function(e,t){a(e,t,(function(r,a){return n.coerce(e,t,i,r,a)}))}},3312:function(e,t,r){"use strict";var n=r(1828),a=r(587).counter,i=r(7670).Y,o=r(5555).idRegex,l=r(4467),s={rows:{valType:"integer",min:1,editType:"plot"},roworder:{valType:"enumerated",values:["top to bottom","bottom to top"],dflt:"top to bottom",editType:"plot"},columns:{valType:"integer",min:1,editType:"plot"},subplots:{valType:"info_array",freeLength:!0,dimensions:2,items:{valType:"enumerated",values:[a("xy").toString(),""],editType:"plot"},editType:"plot"},xaxes:{valType:"info_array",freeLength:!0,items:{valType:"enumerated",values:[o.x.toString(),""],editType:"plot"},editType:"plot"},yaxes:{valType:"info_array",freeLength:!0,items:{valType:"enumerated",values:[o.y.toString(),""],editType:"plot"},editType:"plot"},pattern:{valType:"enumerated",values:["independent","coupled"],dflt:"coupled",editType:"plot"},xgap:{valType:"number",min:0,max:1,editType:"plot"},ygap:{valType:"number",min:0,max:1,editType:"plot"},domain:i({name:"grid",editType:"plot",noGridCell:!0},{}),xside:{valType:"enumerated",values:["bottom","bottom plot","top plot","top"],dflt:"bottom plot",editType:"plot"},yside:{valType:"enumerated",values:["left","left plot","right plot","right"],dflt:"left plot",editType:"plot"},editType:"plot"};function c(e,t,r){var n=t[r+"axes"],a=Object.keys((e._splomAxes||{})[r]||{});return Array.isArray(n)?n:a.length?a:void 0}function u(e,t,r,n,a,i){var o=t(e+"gap",r),l=t("domain."+e);t(e+"side",n);for(var s=new Array(a),c=l[0],u=(l[1]-c)/(a-o),f=u*(1-o),d=0;d<a;d++){var h=c+u*d;s[i?a-1-d:d]=[h,h+f]}return s}function f(e,t,r,n,a){var i,o=new Array(r);function l(e,r){-1!==t.indexOf(r)&&void 0===n[r]?(o[e]=r,n[r]=e):o[e]=""}if(Array.isArray(e))for(i=0;i<r;i++)l(i,e[i]);else for(l(0,a),i=1;i<r;i++)l(i,a+(i+1));return o}e.exports={moduleType:"component",name:"grid",schema:{layout:{grid:s}},layoutAttributes:s,sizeDefaults:function(e,t){var r=e.grid||{},a=c(t,r,"x"),i=c(t,r,"y");if(e.grid||a||i){var o,f,d=Array.isArray(r.subplots)&&Array.isArray(r.subplots[0]),h=Array.isArray(a),p=Array.isArray(i),v=h&&a!==r.xaxes&&p&&i!==r.yaxes;d?(o=r.subplots.length,f=r.subplots[0].length):(p&&(o=i.length),h&&(f=a.length));var y=l.newContainer(t,"grid"),g=M("rows",o),m=M("columns",f);if(g*m>1){d||h||p||"independent"===M("pattern")&&(d=!0),y._hasSubplotGrid=d;var x,b,_="top to bottom"===M("roworder"),w=d?.2:.1,T=d?.3:.1;v&&t._splomGridDflt&&(x=t._splomGridDflt.xside,b=t._splomGridDflt.yside),y._domains={x:u("x",M,w,x,m),y:u("y",M,T,b,g,_)}}else delete t.grid}function M(e,t){return n.coerce(r,y,s,e,t)}},contentDefaults:function(e,t){var r=t.grid;if(r&&r._domains){var n,a,i,o,l,s,u,d=e.grid||{},h=t._subplots,p=r._hasSubplotGrid,v=r.rows,y=r.columns,g="independent"===r.pattern,m=r._axisMap={};if(p){var x=d.subplots||[];s=r.subplots=new Array(v);var b=1;for(n=0;n<v;n++){var _=s[n]=new Array(y),w=x[n]||[];for(a=0;a<y;a++)if(g?(l=1===b?"xy":"x"+b+"y"+b,b++):l=w[a],_[a]="",-1!==h.cartesian.indexOf(l)){if(u=l.indexOf("y"),i=l.slice(0,u),o=l.slice(u),void 0!==m[i]&&m[i]!==a||void 0!==m[o]&&m[o]!==n)continue;_[a]=l,m[i]=a,m[o]=n}}}else{var T=c(t,d,"x"),M=c(t,d,"y");r.xaxes=f(T,h.xaxis,y,m,"x"),r.yaxes=f(M,h.yaxis,v,m,"y")}var k=r._anchors={},A="top to bottom"===r.roworder;for(var L in m){var S,O,D,C=L.charAt(0),P=r[C+"side"];if(P.length<8)k[L]="free";else if("x"===C){if("t"===P.charAt(0)===A?(S=0,O=1,D=v):(S=v-1,O=-1,D=-1),p){var I=m[L];for(n=S;n!==D;n+=O)if((l=s[n][I])&&(u=l.indexOf("y"),l.slice(0,u)===L)){k[L]=l.slice(u);break}}else for(n=S;n!==D;n+=O)if(o=r.yaxes[n],-1!==h.cartesian.indexOf(L+o)){k[L]=o;break}}else if("l"===P.charAt(0)?(S=0,O=1,D=y):(S=y-1,O=-1,D=-1),p){var R=m[L];for(n=S;n!==D;n+=O)if((l=s[R][n])&&(u=l.indexOf("y"),l.slice(u)===L)){k[L]=l.slice(0,u);break}}else for(n=S;n!==D;n+=O)if(i=r.xaxes[n],-1!==h.cartesian.indexOf(i+L)){k[L]=i;break}}}}}},9819:function(e,t,r){"use strict";var n=r(5555),a=r(4467).templatedArray;r(4695),e.exports=a("image",{visible:{valType:"boolean",dflt:!0,editType:"arraydraw"},source:{valType:"string",editType:"arraydraw"},layer:{valType:"enumerated",values:["below","above"],dflt:"above",editType:"arraydraw"},sizex:{valType:"number",dflt:0,editType:"arraydraw"},sizey:{valType:"number",dflt:0,editType:"arraydraw"},sizing:{valType:"enumerated",values:["fill","contain","stretch"],dflt:"contain",editType:"arraydraw"},opacity:{valType:"number",min:0,max:1,dflt:1,editType:"arraydraw"},x:{valType:"any",dflt:0,editType:"arraydraw"},y:{valType:"any",dflt:0,editType:"arraydraw"},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left",editType:"arraydraw"},yanchor:{valType:"enumerated",values:["top","middle","bottom"],dflt:"top",editType:"arraydraw"},xref:{valType:"enumerated",values:["paper",n.idRegex.x.toString()],dflt:"paper",editType:"arraydraw"},yref:{valType:"enumerated",values:["paper",n.idRegex.y.toString()],dflt:"paper",editType:"arraydraw"},editType:"arraydraw"})},5378:function(e,t,r){"use strict";var n=r(2770),a=r(8163);e.exports=function(e,t,r,i){t=t||{};var o="log"===r&&"linear"===t.type,l="linear"===r&&"log"===t.type;if(o||l)for(var s,c,u=e._fullLayout.images,f=t._id.charAt(0),d=0;d<u.length;d++)if(c="images["+d+"].",(s=u[d])[f+"ref"]===t._id){var h=s[f],p=s["size"+f],v=null,y=null;if(o){v=a(h,t.range);var g=p/Math.pow(10,v)/2;y=2*Math.log(g+Math.sqrt(1+g*g))/Math.LN10}else y=(v=Math.pow(10,h))*(Math.pow(10,p/2)-Math.pow(10,-p/2));n(v)?n(y)||(y=null):(v=null,y=null),i(c+f,v),i(c+"size"+f,y)}}},1603:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(5501),o=r(9819);function l(e,t,r){function i(r,a){return n.coerce(e,t,o,r,a)}var l=i("source");if(!i("visible",!!l))return t;i("layer"),i("xanchor"),i("yanchor"),i("sizex"),i("sizey"),i("sizing"),i("opacity");for(var s={_fullLayout:r},c=["x","y"],u=0;u<2;u++){var f=c[u],d=a.coerceRef(e,t,s,f,"paper",void 0);"paper"!==d&&a.getFromId(s,d)._imgIndices.push(t._index),a.coercePosition(t,s,i,d,f,0)}return t}e.exports=function(e,t){i(e,t,{name:"images",handleItemDefaults:l})}},750:function(e,t,r){"use strict";var n=r(9898),a=r(1424),i=r(9298),o=r(1675),l=r(7922);e.exports=function(e){var t,r,s=e._fullLayout,c=[],u={},f=[];for(r=0;r<s.images.length;r++){var d=s.images[r];if(d.visible)if("below"===d.layer&&"paper"!==d.xref&&"paper"!==d.yref){t=o.ref2id(d.xref)+o.ref2id(d.yref);var h=s._plots[t];if(!h){f.push(d);continue}h.mainplot&&(t=h.mainplot.id),u[t]||(u[t]=[]),u[t].push(d)}else"above"===d.layer?c.push(d):f.push(d)}var p={left:{sizing:"xMin",offset:0},center:{sizing:"xMid",offset:-.5},right:{sizing:"xMax",offset:-1}},v={top:{sizing:"YMin",offset:0},middle:{sizing:"YMid",offset:-.5},bottom:{sizing:"YMax",offset:-1}};function y(t){var r=n.select(this);if(this._imgSrc!==t.source)if(r.attr("xmlns",l.svg),t.source&&"data:"===t.source.slice(0,5))r.attr("xlink:href",t.source),this._imgSrc=t.source;else{var a=new Promise(function(e){var n=new Image;function a(){r.remove(),e()}this.img=n,n.setAttribute("crossOrigin","anonymous"),n.onerror=a,n.onload=function(){var t=document.createElement("canvas");t.width=this.width,t.height=this.height,t.getContext("2d",{willReadFrequently:!0}).drawImage(this,0,0);var n=t.toDataURL("image/png");r.attr("xlink:href",n),e()},r.on("error",a),n.src=t.source,this._imgSrc=t.source}.bind(this));e._promises.push(a)}}function g(t){var r,o,l=n.select(this),c=i.getFromId(e,t.xref),u=i.getFromId(e,t.yref),f="domain"===i.getRefType(t.xref),d="domain"===i.getRefType(t.yref),h=s._size;r=void 0!==c?"string"==typeof t.xref&&f?c._length*t.sizex:Math.abs(c.l2p(t.sizex)-c.l2p(0)):t.sizex*h.w,o=void 0!==u?"string"==typeof t.yref&&d?u._length*t.sizey:Math.abs(u.l2p(t.sizey)-u.l2p(0)):t.sizey*h.h;var y,g,m=r*p[t.xanchor].offset,x=o*v[t.yanchor].offset,b=p[t.xanchor].sizing+v[t.yanchor].sizing;switch(y=void 0!==c?"string"==typeof t.xref&&f?c._length*t.x+c._offset:c.r2p(t.x)+c._offset:t.x*h.w+h.l,y+=m,g=void 0!==u?"string"==typeof t.yref&&d?u._length*(1-t.y)+u._offset:u.r2p(t.y)+u._offset:h.h-t.y*h.h+h.t,g+=x,t.sizing){case"fill":b+=" slice";break;case"stretch":b="none"}l.attr({x:y,y:g,width:r,height:o,preserveAspectRatio:b,opacity:t.opacity});var _=(c&&"domain"!==i.getRefType(t.xref)?c._id:"")+(u&&"domain"!==i.getRefType(t.yref)?u._id:"");a.setClipUrl(l,_?"clip"+s._uid+_:null,e)}var m=s._imageLowerLayer.selectAll("image").data(f),x=s._imageUpperLayer.selectAll("image").data(c);m.enter().append("image"),x.enter().append("image"),m.exit().remove(),x.exit().remove(),m.each((function(e){y.bind(this)(e),g.bind(this)(e)})),x.each((function(e){y.bind(this)(e),g.bind(this)(e)}));var b=Object.keys(s._plots);for(r=0;r<b.length;r++){t=b[r];var _=s._plots[t];if(_.imagelayer){var w=_.imagelayer.selectAll("image").data(u[t]||[]);w.enter().append("image"),w.exit().remove(),w.each((function(e){y.bind(this)(e),g.bind(this)(e)}))}}}},8804:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"images",layoutAttributes:r(9819),supplyLayoutDefaults:r(1603),includeBasePlot:r(6325)("images"),draw:r(750),convertCoords:r(5378)}},3030:function(e,t,r){"use strict";var n=r(1940),a=r(2399);e.exports={_isSubplotObj:!0,visible:{valType:"boolean",dflt:!0,editType:"legend"},bgcolor:{valType:"color",editType:"legend"},bordercolor:{valType:"color",dflt:a.defaultLine,editType:"legend"},borderwidth:{valType:"number",min:0,dflt:0,editType:"legend"},font:n({editType:"legend"}),grouptitlefont:n({editType:"legend"}),orientation:{valType:"enumerated",values:["v","h"],dflt:"v",editType:"legend"},traceorder:{valType:"flaglist",flags:["reversed","grouped"],extras:["normal"],editType:"legend"},tracegroupgap:{valType:"number",min:0,dflt:10,editType:"legend"},entrywidth:{valType:"number",min:0,editType:"legend"},entrywidthmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"pixels",editType:"legend"},itemsizing:{valType:"enumerated",values:["trace","constant"],dflt:"trace",editType:"legend"},itemwidth:{valType:"number",min:30,dflt:30,editType:"legend"},itemclick:{valType:"enumerated",values:["toggle","toggleothers",!1],dflt:"toggle",editType:"legend"},itemdoubleclick:{valType:"enumerated",values:["toggle","toggleothers",!1],dflt:"toggleothers",editType:"legend"},groupclick:{valType:"enumerated",values:["toggleitem","togglegroup"],dflt:"togglegroup",editType:"legend"},x:{valType:"number",editType:"legend"},xref:{valType:"enumerated",dflt:"paper",values:["container","paper"],editType:"layoutstyle"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left",editType:"legend"},y:{valType:"number",editType:"legend"},yref:{valType:"enumerated",dflt:"paper",values:["container","paper"],editType:"layoutstyle"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],editType:"legend"},uirevision:{valType:"any",editType:"none"},valign:{valType:"enumerated",values:["top","middle","bottom"],dflt:"middle",editType:"legend"},title:{text:{valType:"string",dflt:"",editType:"legend"},font:n({editType:"legend"}),side:{valType:"enumerated",values:["top","left","top left"],editType:"legend"},editType:"legend"},editType:"legend"}},4928:function(e){"use strict";e.exports={scrollBarWidth:6,scrollBarMinHeight:20,scrollBarColor:"#808BA4",scrollBarMargin:4,scrollBarEnterAttrs:{rx:20,ry:3,width:0,height:0},titlePad:2,itemGap:5}},9017:function(e,t,r){"use strict";var n=r(3972),a=r(1828),i=r(4467),o=r(9012),l=r(3030),s=r(820),c=r(130);function u(e,t,r,u){var f=t[e]||{},d=i.newContainer(r,e);function h(e,t){return a.coerce(f,d,l,e,t)}var p=a.coerceFont(h,"font",r.font);if(h("bgcolor",r.paper_bgcolor),h("bordercolor"),h("visible")){for(var v,y=function(e,t){var r=v._input,n=v;return a.coerce(r,n,o,e,t)},g=r.font||{},m=a.coerceFont(h,"grouptitlefont",a.extendFlat({},g,{size:Math.round(1.1*g.size)})),x=0,b=!1,_="normal",w=0;w<u.length;w++)(v=u[w]).visible&&((v.showlegend||v._dfltShowLegend&&!(v._module&&v._module.attributes&&v._module.attributes.showlegend&&!1===v._module.attributes.showlegend.dflt))&&(x++,v.showlegend&&(b=!0,(n.traceIs(v,"pie-like")||!0===v._input.showlegend)&&x++),a.coerceFont(y,"legendgrouptitle.font",m)),(n.traceIs(v,"bar")&&"stack"===r.barmode||-1!==["tonextx","tonexty"].indexOf(v.fill))&&(_=c.isGrouped({traceorder:_})?"grouped+reversed":"reversed"),void 0!==v.legendgroup&&""!==v.legendgroup&&(_=c.isReversed({traceorder:_})?"reversed+grouped":"grouped"));var T=a.coerce(t,r,s,"showlegend",b&&x>1);if(!1===T&&(r.legend=void 0),(!1!==T||f.uirevision)&&(h("uirevision",r.uirevision),!1!==T)){h("borderwidth");var M,k,A,L="h"===h("orientation"),S="paper"===h("yref"),O="paper"===h("xref"),D="left";if(L?(M=0,n.getComponentMethod("rangeslider","isVisible")(t.xaxis)?S?(k=1.1,A="bottom"):(k=1,A="top"):S?(k=-.1,A="top"):(k=0,A="bottom")):(k=1,A="auto",O?M=1.02:(M=1,D="right")),a.coerce(f,d,{x:{valType:"number",editType:"legend",min:O?-2:0,max:O?3:1,dflt:M}},"x"),a.coerce(f,d,{y:{valType:"number",editType:"legend",min:S?-2:0,max:S?3:1,dflt:k}},"y"),h("traceorder",_),c.isGrouped(r.legend)&&h("tracegroupgap"),h("entrywidth"),h("entrywidthmode"),h("itemsizing"),h("itemwidth"),h("itemclick"),h("itemdoubleclick"),h("groupclick"),h("xanchor",D),h("yanchor",A),h("valign"),a.noneOrAll(f,d,["x","y"]),h("title.text")){h("title.side",L?"left":"top");var C=a.extendFlat({},p,{size:a.bigFont(p.size)});a.coerceFont(h,"title.font",C)}}}}e.exports=function(e,t,r){var n,i=["legend"];for(n=0;n<r.length;n++)a.pushUnique(i,r[n].legend);for(t._legends=[],n=0;n<i.length;n++){var o=i[n];u(o,e,t,r),t[o]&&t[o].visible&&(t[o]._id=o),t._legends.push(o)}}},3969:function(e,t,r){"use strict";var n=r(9898),a=r(1828),i=r(4875),o=r(3972),l=r(1086),s=r(8569),c=r(1424),u=r(7901),f=r(3893),d=r(5167),h=r(4928),p=r(8783),v=p.LINE_SPACING,y=p.FROM_TL,g=p.FROM_BR,m=r(2424),x=r(3630),b=r(130),_=1,w=/^legend[0-9]*$/;function T(e,t){var r,l,f=t||{},d=e._fullLayout,p=P(f),v=f._inHover;if(v?(l=f.layer,r="hover"):(l=d._infolayer,r=p),l){var w;if(r+=d._uid,e._legendMouseDownTime||(e._legendMouseDownTime=0),v){if(!f.entries)return;w=m(f.entries,f)}else{if(!e.calcdata)return;w=d.showlegend&&m(e.calcdata,f,d._legends.length>1)}var T=d.hiddenlabels||[];if(!(v||d.showlegend&&w.length))return l.selectAll("."+p).remove(),d._topdefs.select("#"+r).remove(),i.autoMargin(e,p);var L=a.ensureSingle(l,"g",p,(function(e){v||e.attr("pointer-events","all")})),I=a.ensureSingleById(d._topdefs,"clipPath",r,(function(e){e.append("rect")})),R=a.ensureSingle(L,"rect","bg",(function(e){e.attr("shape-rendering","crispEdges")}));R.call(u.stroke,f.bordercolor).call(u.fill,f.bgcolor).style("stroke-width",f.borderwidth+"px");var z=a.ensureSingle(L,"g","scrollbox"),N=f.title;if(f._titleWidth=0,f._titleHeight=0,N.text){var E=a.ensureSingle(z,"text",p+"titletext");E.attr("text-anchor","start").call(c.font,N.font).text(N.text),O(E,z,e,f,_)}else z.selectAll("."+p+"titletext").remove();var F=a.ensureSingle(L,"rect","scrollbar",(function(e){e.attr(h.scrollBarEnterAttrs).call(u.fill,h.scrollBarColor)})),H=z.selectAll("g.groups").data(w);H.enter().append("g").attr("class","groups"),H.exit().remove();var j=H.selectAll("g.traces").data(a.identity);j.enter().append("g").attr("class","traces"),j.exit().remove(),j.style("opacity",(function(e){var t=e[0].trace;return o.traceIs(t,"pie-like")?-1!==T.indexOf(e[0].label)?.5:1:"legendonly"===t.visible?.5:1})).each((function(){n.select(this).call(A,e,f)})).call(x,e,f).each((function(){v||n.select(this).call(S,e,p)})),a.syncOrAsync([i.previousPromises,function(){return function(e,t,r,a){var i=e._fullLayout,o=P(a);a||(a=i[o]);var l=i._size,s=b.isVertical(a),u=b.isGrouped(a),f="fraction"===a.entrywidthmode,d=a.borderwidth,p=2*d,v=h.itemGap,y=a.itemwidth+2*v,g=2*(d+v),m=C(a),x=a.y<0||0===a.y&&"top"===m,_=a.y>1||1===a.y&&"bottom"===m,w=a.tracegroupgap,T={};a._maxHeight=Math.max(x||_?i.height/2:l.h,30);var k=0;a._width=0,a._height=0;var A=function(e){var t=0,r=0,n=e.title.side;return n&&(-1!==n.indexOf("left")&&(t=e._titleWidth),-1!==n.indexOf("top")&&(r=e._titleHeight)),[t,r]}(a);if(s)r.each((function(e){var t=e[0].height;c.setTranslate(this,d+A[0],d+A[1]+a._height+t/2+v),a._height+=t,a._width=Math.max(a._width,e[0].width)})),k=y+a._width,a._width+=v+y+p,a._height+=g,u&&(t.each((function(e,t){c.setTranslate(this,0,t*a.tracegroupgap)})),a._height+=(a._lgroupsLength-1)*a.tracegroupgap);else{var L=D(a),S=a.x<0||0===a.x&&"right"===L,O=a.x>1||1===a.x&&"left"===L,I=_||x,R=i.width/2;a._maxWidth=Math.max(S?I&&"left"===L?l.l+l.w:R:O?I&&"right"===L?l.r+l.w:R:l.w,2*y);var z=0,N=0;r.each((function(e){var t=M(e,a,y);z=Math.max(z,t),N+=t})),k=null;var E=0;if(u){var F=0,H=0,j=0;t.each((function(){var e=0,t=0;n.select(this).selectAll("g.traces").each((function(r){var n=M(r,a,y),i=r[0].height;c.setTranslate(this,A[0],A[1]+d+v+i/2+t),t+=i,e=Math.max(e,n),T[r[0].trace.legendgroup]=e}));var r=e+v;H>0&&r+d+H>a._maxWidth?(E=Math.max(E,H),H=0,j+=F+w,F=t):F=Math.max(F,t),c.setTranslate(this,H,j),H+=r})),a._width=Math.max(E,H)+d,a._height=j+F+g}else{var B=r.size(),Y=N+p+(B-1)*v<a._maxWidth,U=0,V=0,q=0,Z=0;r.each((function(e){var t=e[0].height,r=M(e,a,y),n=Y?r:z;f||(n+=v),n+d+V-v>=a._maxWidth&&(E=Math.max(E,Z),V=0,q+=U,a._height+=U,U=0),c.setTranslate(this,A[0]+d+V,A[1]+d+q+t/2+v),Z=V+r+v,V+=n,U=Math.max(U,t)})),Y?(a._width=V+p,a._height=U+g):(a._width=Math.max(E,Z)+p,a._height+=U+g)}}a._width=Math.ceil(Math.max(a._width+A[0],a._titleWidth+2*(d+h.titlePad))),a._height=Math.ceil(Math.max(a._height+A[1],a._titleHeight+2*(d+h.itemGap))),a._effHeight=Math.min(a._height,a._maxHeight);var G=e._context.edits,W=G.legendText||G.legendPosition;r.each((function(e){var t=n.select(this).select("."+o+"toggle"),r=e[0].height,i=e[0].trace.legendgroup,l=M(e,a,y);u&&""!==i&&(l=T[i]);var d=W?y:k||l;s||f||(d+=v/2),c.setRect(t,0,-r/2,d,r)}))}(e,H,j,f)},function(){var t,l,u,m,x=d._size,b=f.borderwidth,_="paper"===f.xref,w="paper"===f.yref;if(!v){var T,M;T=_?x.l+x.w*f.x-y[D(f)]*f._width:d.width*f.x-y[D(f)]*f._width,M=w?x.t+x.h*(1-f.y)-y[C(f)]*f._effHeight:d.height*(1-f.y)-y[C(f)]*f._effHeight;var A=function(e,t,r,n){var a=e._fullLayout,o=a[t],l=D(o),s=C(o),c="paper"===o.xref,u="paper"===o.yref;e._fullLayout._reservedMargin[t]={};var f=o.y<.5?"b":"t",d=o.x<.5?"l":"r",h={r:a.width-r,l:r+o._width,b:a.height-n,t:n+o._effHeight};if(c&&u)return i.autoMargin(e,t,{x:o.x,y:o.y,l:o._width*y[l],r:o._width*g[l],b:o._effHeight*g[s],t:o._effHeight*y[s]});c?e._fullLayout._reservedMargin[t][f]=h[f]:u||"v"===o.orientation?e._fullLayout._reservedMargin[t][d]=h[d]:e._fullLayout._reservedMargin[t][f]=h[f]}(e,p,T,M);if(A)return;if(d.margin.autoexpand){var S=T,O=M;T=_?a.constrain(T,0,d.width-f._width):S,M=w?a.constrain(M,0,d.height-f._effHeight):O,T!==S&&a.log("Constrain "+p+".x to make legend fit inside graph"),M!==O&&a.log("Constrain "+p+".y to make legend fit inside graph")}c.setTranslate(L,T,M)}if(F.on(".drag",null),L.on("wheel",null),v||f._height<=f._maxHeight||e._context.staticPlot){var P=f._effHeight;v&&(P=f._height),R.attr({width:f._width-b,height:P-b,x:b/2,y:b/2}),c.setTranslate(z,0,0),I.select("rect").attr({width:f._width-2*b,height:P-2*b,x:b,y:b}),c.setClipUrl(z,r,e),c.setRect(F,0,0,0,0),delete f._scrollY}else{var N,E,j,B=Math.max(h.scrollBarMinHeight,f._effHeight*f._effHeight/f._height),Y=f._effHeight-B-2*h.scrollBarMargin,U=f._height-f._effHeight,V=Y/U,q=Math.min(f._scrollY||0,U);R.attr({width:f._width-2*b+h.scrollBarWidth+h.scrollBarMargin,height:f._effHeight-b,x:b/2,y:b/2}),I.select("rect").attr({width:f._width-2*b+h.scrollBarWidth+h.scrollBarMargin,height:f._effHeight-2*b,x:b,y:b+q}),c.setClipUrl(z,r,e),W(q,B,V),L.on("wheel",(function(){W(q=a.constrain(f._scrollY+n.event.deltaY/Y*U,0,U),B,V),0!==q&&q!==U&&n.event.preventDefault()}));var Z=n.behavior.drag().on("dragstart",(function(){var e=n.event.sourceEvent;N="touchstart"===e.type?e.changedTouches[0].clientY:e.clientY,j=q})).on("drag",(function(){var e=n.event.sourceEvent;2===e.buttons||e.ctrlKey||(E="touchmove"===e.type?e.changedTouches[0].clientY:e.clientY,q=function(e,t,r){var n=(r-t)/V+e;return a.constrain(n,0,U)}(j,N,E),W(q,B,V))}));F.call(Z);var G=n.behavior.drag().on("dragstart",(function(){var e=n.event.sourceEvent;"touchstart"===e.type&&(N=e.changedTouches[0].clientY,j=q)})).on("drag",(function(){var e=n.event.sourceEvent;"touchmove"===e.type&&(E=e.changedTouches[0].clientY,q=function(e,t,r){var n=(t-r)/V+e;return a.constrain(n,0,U)}(j,N,E),W(q,B,V))}));z.call(G)}function W(t,r,n){f._scrollY=e._fullLayout[p]._scrollY=t,c.setTranslate(z,0,-t),c.setRect(F,f._width,h.scrollBarMargin+t*n,h.scrollBarWidth,r),I.select("rect").attr("y",b+t)}e._context.edits.legendPosition&&(L.classed("cursor-move",!0),s.init({element:L.node(),gd:e,prepFn:function(){var e=c.getTranslate(L);u=e.x,m=e.y},moveFn:function(e,r){var n=u+e,a=m+r;c.setTranslate(L,n,a),t=s.align(n,f._width,x.l,x.l+x.w,f.xanchor),l=s.align(a+f._height,-f._height,x.t+x.h,x.t,f.yanchor)},doneFn:function(){if(void 0!==t&&void 0!==l){var r={};r[p+".x"]=t,r[p+".y"]=l,o.call("_guiRelayout",e,r)}},clickFn:function(t,r){var n=H.selectAll("g.traces").filter((function(){var e=this.getBoundingClientRect();return r.clientX>=e.left&&r.clientX<=e.right&&r.clientY>=e.top&&r.clientY<=e.bottom}));n.size()>0&&k(e,L,n,t,r)}}))}],e)}}function M(e,t,r){var n=e[0],a=n.width,i=t.entrywidthmode,o=n.trace.legendwidth||t.entrywidth;return"fraction"===i?t._maxWidth*o:r+(o||a)}function k(e,t,r,n,a){var i=r.data()[0][0].trace,s={event:a,node:r.node(),curveNumber:i.index,expandedIndex:i._expandedIndex,data:e.data,layout:e.layout,frames:e._transitionData._frames,config:e._context,fullData:e._fullData,fullLayout:e._fullLayout};i._group&&(s.group=i._group),o.traceIs(i,"pie-like")&&(s.label=r.datum()[0].label),!1!==l.triggerHandler(e,"plotly_legendclick",s)&&(1===n?t._clickTimeout=setTimeout((function(){e._fullLayout&&d(r,e,n)}),e._context.doubleClickDelay):2===n&&(t._clickTimeout&&clearTimeout(t._clickTimeout),e._legendMouseDownTime=0,!1!==l.triggerHandler(e,"plotly_legenddoubleclick",s)&&d(r,e,n)))}function A(e,t,r){var n,i,l=P(r),s=e.data()[0][0],u=s.trace,d=o.traceIs(u,"pie-like"),p=!r._inHover&&t._context.edits.legendText&&!d,v=r._maxNameLength;s.groupTitle?(n=s.groupTitle.text,i=s.groupTitle.font):(i=r.font,r.entries?n=s.text:(n=d?s.label:u.name,u._meta&&(n=a.templateString(n,u._meta))));var y=a.ensureSingle(e,"text",l+"text");y.attr("text-anchor","start").call(c.font,i).text(p?L(n,v):n);var g=r.itemwidth+2*h.itemGap;f.positionText(y,g,0),p?y.call(f.makeEditable,{gd:t,text:n}).call(O,e,t,r).on("edit",(function(n){this.text(L(n,v)).call(O,e,t,r);var i=s.trace._fullInput||{},l={};if(o.hasTransform(i,"groupby")){var c=o.getTransformIndices(i,"groupby"),f=c[c.length-1],d=a.keyedContainer(i,"transforms["+f+"].styles","target","value.name");d.set(s.trace._group,n),l=d.constructUpdate()}else l.name=n;return o.call("_guiRestyle",t,l,u.index)})):O(y,e,t,r)}function L(e,t){var r=Math.max(4,t);if(e&&e.trim().length>=r/2)return e;for(var n=r-(e=e||"").length;n>0;n--)e+=" ";return e}function S(e,t,r){var i,o=t._context.doubleClickDelay,l=1,s=a.ensureSingle(e,"rect",r+"toggle",(function(e){t._context.staticPlot||e.style("cursor","pointer").attr("pointer-events","all"),e.call(u.fill,"rgba(0,0,0,0)")}));t._context.staticPlot||(s.on("mousedown",(function(){(i=(new Date).getTime())-t._legendMouseDownTime<o?l+=1:(l=1,t._legendMouseDownTime=i)})),s.on("mouseup",(function(){if(!t._dragged&&!t._editing){var a=t._fullLayout[r];(new Date).getTime()-t._legendMouseDownTime>o&&(l=Math.max(l-1,1)),k(t,a,e,l,n.event)}})))}function O(e,t,r,n,a){n._inHover&&e.attr("data-notex",!0),f.convertToTspans(e,r,(function(){!function(e,t,r,n){var a=e.data()[0][0];if(r._inHover||!a||a.trace.showlegend){var i=e.select("g[class*=math-group]"),o=i.node(),l=P(r);r||(r=t._fullLayout[l]);var s,u,d=r.borderwidth,p=(n===_?r.title.font:a.groupTitle?a.groupTitle.font:r.font).size*v;if(o){var y=c.bBox(o);s=y.height,u=y.width,n===_?c.setTranslate(i,d,d+.75*s):c.setTranslate(i,0,.25*s)}else{var g="."+l+(n===_?"title":"")+"text",m=e.select(g),x=f.lineCount(m),b=m.node();if(s=p*x,u=b?c.bBox(b).width:0,n===_)"left"===r.title.side&&(u+=2*h.itemGap),f.positionText(m,d+h.titlePad,d+p);else{var w=2*h.itemGap+r.itemwidth;a.groupTitle&&(w=h.itemGap,u-=r.itemwidth),f.positionText(m,w,-p*((x-1)/2-.3))}}n===_?(r._titleWidth=u,r._titleHeight=s):(a.lineHeight=p,a.height=Math.max(s,16)+3,a.width=u)}else e.remove()}(t,r,n,a)}))}function D(e){return a.isRightAnchor(e)?"right":a.isCenterAnchor(e)?"center":"left"}function C(e){return a.isBottomAnchor(e)?"bottom":a.isMiddleAnchor(e)?"middle":"top"}function P(e){return e._id||"legend"}e.exports=function(e,t){if(t)T(e,t);else{var r=e._fullLayout,a=r._legends;r._infolayer.selectAll('[class^="legend"]').each((function(){var e=n.select(this),t=e.attr("class").split(" ")[0];t.match(w)&&-1===a.indexOf(t)&&e.remove()}));for(var i=0;i<a.length;i++){var o=a[i];T(e,e._fullLayout[o])}}}},2424:function(e,t,r){"use strict";var n=r(3972),a=r(130);e.exports=function(e,t,r){var i,o,l=t._inHover,s=a.isGrouped(t),c=a.isReversed(t),u={},f=[],d=!1,h={},p=0,v=0;function y(e,n,i){if(!1!==t.visible&&(!r||e===t._id))if(""!==n&&a.isGrouped(t))-1===f.indexOf(n)?(f.push(n),d=!0,u[n]=[i]):u[n].push(i);else{var o="~~i"+p;f.push(o),u[o]=[i],p++}}for(i=0;i<e.length;i++){var g=e[i],m=g[0],x=m.trace,b=x.legend,_=x.legendgroup;if(l||x.visible&&x.showlegend)if(n.traceIs(x,"pie-like"))for(h[_]||(h[_]={}),o=0;o<g.length;o++){var w=g[o].label;h[_][w]||(y(b,_,{label:w,color:g[o].color,i:g[o].i,trace:x,pts:g[o].pts}),h[_][w]=!0,v=Math.max(v,(w||"").length))}else y(b,_,m),v=Math.max(v,(x.name||"").length)}if(!f.length)return[];var T=!d||!s,M=[];for(i=0;i<f.length;i++){var k=u[f[i]];T?M.push(k[0]):M.push(k)}for(T&&(M=[M]),i=0;i<M.length;i++){var A=1/0;for(o=0;o<M[i].length;o++){var L=M[i][o].trace.legendrank;A>L&&(A=L)}M[i][0]._groupMinRank=A,M[i][0]._preGroupSort=i}var S=function(e,t){return e.trace.legendrank-t.trace.legendrank||e._preSort-t._preSort};for(M.forEach((function(e,t){e[0]._preGroupSort=t})),M.sort((function(e,t){return e[0]._groupMinRank-t[0]._groupMinRank||e[0]._preGroupSort-t[0]._preGroupSort})),i=0;i<M.length;i++){M[i].forEach((function(e,t){e._preSort=t})),M[i].sort(S);var O=M[i][0].trace,D=null;for(o=0;o<M[i].length;o++){var C=M[i][o].trace.legendgrouptitle;if(C&&C.text){D=C,l&&(C.font=t._groupTitleFont);break}}if(c&&M[i].reverse(),D){var P=!1;for(o=0;o<M[i].length;o++)if(n.traceIs(M[i][o].trace,"pie-like")){P=!0;break}M[i].unshift({i:-1,groupTitle:D,noClick:P,trace:{showlegend:O.showlegend,legendgroup:O.legendgroup,visible:"toggleitem"===t.groupclick||O.visible}})}for(o=0;o<M[i].length;o++)M[i][o]=[M[i][o]]}return t._lgroupsLength=M.length,t._maxNameLength=v,M}},5167:function(e,t,r){"use strict";var n=r(1828),a=r(3972),i=!0;e.exports=function(e,t,r){var o=t._fullLayout;if(!t._dragged&&!t._editing){var l,s=o.legend.itemclick,c=o.legend.itemdoubleclick,u=o.legend.groupclick;if(1===r&&"toggle"===s&&"toggleothers"===c&&i&&t.data&&t._context.showTips?(n.notifier(n._(t,"Double-click on legend to isolate one trace"),"long"),i=!1):i=!1,1===r?l=s:2===r&&(l=c),l){var f="togglegroup"===u,d=o.hiddenlabels?o.hiddenlabels.slice():[],h=e.data()[0][0];if(!h.groupTitle||!h.noClick){var p,v,y,g,m,x=t._fullData,b=h.trace,_=b.legendgroup,w={},T=[],M=[],k=[];if(a.traceIs(b,"pie-like")){var A=h.label,L=d.indexOf(A);"toggle"===l?-1===L?d.push(A):d.splice(L,1):"toggleothers"===l&&(d=[],t.calcdata[0].forEach((function(e){A!==e.label&&d.push(e.label)})),t._fullLayout.hiddenlabels&&t._fullLayout.hiddenlabels.length===d.length&&-1===L&&(d=[])),a.call("_guiRelayout",t,"hiddenlabels",d)}else{var S,O=_&&_.length,D=[];if(O)for(p=0;p<x.length;p++)(S=x[p]).visible&&S.legendgroup===_&&D.push(p);if("toggle"===l){var C;switch(b.visible){case!0:C="legendonly";break;case!1:C=!1;break;case"legendonly":C=!0}if(O)if(f)for(p=0;p<x.length;p++)!1!==x[p].visible&&x[p].legendgroup===_&&j(x[p],C);else j(b,C);else j(b,C)}else if("toggleothers"===l){var P,I,R,z,N=!0;for(p=0;p<x.length;p++)if(P=x[p]===b,R=!0!==x[p].showlegend,!(P||R||(I=O&&x[p].legendgroup===_)||!0!==x[p].visible||a.traceIs(x[p],"notLegendIsolatable"))){N=!1;break}for(p=0;p<x.length;p++)if(!1!==x[p].visible&&!a.traceIs(x[p],"notLegendIsolatable"))switch(b.visible){case"legendonly":j(x[p],!0);break;case!0:z=!!N||"legendonly",P=x[p]===b,R=!0!==x[p].showlegend&&!x[p].legendgroup,I=P||O&&x[p].legendgroup===_,j(x[p],!(!I&&!R)||z)}}for(p=0;p<M.length;p++)if(y=M[p]){var E=y.constructUpdate(),F=Object.keys(E);for(v=0;v<F.length;v++)g=F[v],(w[g]=w[g]||[])[k[p]]=E[g]}for(m=Object.keys(w),p=0;p<m.length;p++)for(g=m[p],v=0;v<T.length;v++)w[g].hasOwnProperty(v)||(w[g][v]=void 0);a.call("_guiRestyle",t,w,T)}}}}function H(e,t,r){var n=T.indexOf(e),a=w[t];return a||(a=w[t]=[]),-1===T.indexOf(e)&&(T.push(e),n=T.length-1),a[n]=r,n}function j(e,t){if(!h.groupTitle||f){var r=e._fullInput;if(a.hasTransform(r,"groupby")){var i=M[r.index];if(!i){var o=a.getTransformIndices(r,"groupby"),l=o[o.length-1];i=n.keyedContainer(r,"transforms["+l+"].styles","target","value.visible"),M[r.index]=i}var s=i.get(e._group);void 0===s&&(s=!0),!1!==s&&i.set(e._group,t),k[r.index]=H(r.index,"visible",!1!==r.visible)}else{var c=!1!==r.visible&&t;H(r.index,"visible",c)}}}}},130:function(e,t){"use strict";t.isGrouped=function(e){return-1!==(e.traceorder||"").indexOf("grouped")},t.isVertical=function(e){return"h"!==e.orientation},t.isReversed=function(e){return-1!==(e.traceorder||"").indexOf("reversed")}},2199:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"legend",layoutAttributes:r(3030),supplyLayoutDefaults:r(9017),draw:r(3969),style:r(3630)}},3630:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(1828),o=i.strTranslate,l=r(1424),s=r(7901),c=r(2869).extractOpts,u=r(4098),f=r(3463),d=r(3581).castOption,h=r(4928);function p(e,t){return(t?"radial":"horizontal")+(e?"":"reversed")}function v(e){var t=e[0].trace,r=t.contours,n=u.hasLines(t),a=u.hasMarkers(t),i=t.visible&&t.fill&&"none"!==t.fill,o=!1,l=!1;if(r){var s=r.coloring;"lines"===s?o=!0:n="none"===s||"heatmap"===s||r.showlines,"constraint"===r.type?i="="!==r._operation:"fill"!==s&&"heatmap"!==s||(l=!0)}return{showMarker:a,showLine:n,showFill:i,showGradientLine:o,showGradientFill:l,anyLine:n||o,anyFill:i||l}}function y(e,t,r){return e&&i.isArrayOrTypedArray(e)?t:e>r?r:e}e.exports=function(e,t,r){var g=t._fullLayout;r||(r=g.legend);var m="constant"===r.itemsizing,x=r.itemwidth,b=(x+2*h.itemGap)/2,_=o(b,0),w=function(e,t,r,n){var a;if(e+1)a=e;else{if(!(t&&t.width>0))return 0;a=t.width}return m?n:Math.min(a,r)};function T(e,i,o){var u=e[0].trace,f=u.marker||{},d=f.line||{},h=o?u.visible&&u.type===o:a.traceIs(u,"bar"),p=n.select(i).select("g.legendpoints").selectAll("path.legend"+o).data(h?[e]:[]);p.enter().append("path").classed("legend"+o,!0).attr("d","M6,6H-6V-6H6Z").attr("transform",_),p.exit().remove(),p.each((function(e){var a=n.select(this),i=e[0],o=w(i.mlw,f.line,5,2);a.style("stroke-width",o+"px");var h=i.mcc;if(!r._inHover&&"mc"in i){var p=c(f),v=p.mid;void 0===v&&(v=(p.max+p.min)/2),h=l.tryColorscale(f,"")(v)}var g=h||i.mc||f.color,m=f.pattern,x=m&&l.getPatternAttr(m.shape,0,"");if(x){var b=l.getPatternAttr(m.bgcolor,0,null),_=l.getPatternAttr(m.fgcolor,0,null),T=m.fgopacity,M=y(m.size,8,10),k=y(m.solidity,.5,1),A="legend-"+u.uid;a.call(l.pattern,"legend",t,A,x,M,k,h,m.fillmode,b,_,T)}else a.call(s.fill,g);o&&s.stroke(a,i.mlc||d.color)}))}function M(e,r,o){var l=e[0],s=l.trace,c=o?s.visible&&s.type===o:a.traceIs(s,o),u=n.select(r).select("g.legendpoints").selectAll("path.legend"+o).data(c?[e]:[]);if(u.enter().append("path").classed("legend"+o,!0).attr("d","M6,6H-6V-6H6Z").attr("transform",_),u.exit().remove(),u.size()){var h=s.marker||{},p=w(d(h.line.width,l.pts),h.line,5,2),v=i.minExtend(s,{marker:{line:{width:p}}},!0),y=i.minExtend(l,{trace:v},!0);f(u,y,v,t)}}e.each((function(e){var t=n.select(this),a=i.ensureSingle(t,"g","layers");a.style("opacity",e[0].trace.opacity);var l=r.valign,s=e[0].lineHeight,c=e[0].height;if("middle"!==l&&s&&c){var u={top:1,bottom:-1}[l]*(.5*(s-c+3));a.attr("transform",o(0,u))}else a.attr("transform",null);a.selectAll("g.legendfill").data([e]).enter().append("g").classed("legendfill",!0),a.selectAll("g.legendlines").data([e]).enter().append("g").classed("legendlines",!0);var f=a.selectAll("g.legendsymbols").data([e]);f.enter().append("g").classed("legendsymbols",!0),f.selectAll("g.legendpoints").data([e]).enter().append("g").classed("legendpoints",!0)})).each((function(e){var r,a=e[0].trace,o=[];if(a.visible)switch(a.type){case"histogram2d":case"heatmap":o=[["M-15,-2V4H15V-2Z"]],r=!0;break;case"choropleth":case"choroplethmapbox":o=[["M-6,-6V6H6V-6Z"]],r=!0;break;case"densitymapbox":o=[["M-6,0 a6,6 0 1,0 12,0 a 6,6 0 1,0 -12,0"]],r="radial";break;case"cone":o=[["M-6,2 A2,2 0 0,0 -6,6 V6L6,4Z"],["M-6,-6 A2,2 0 0,0 -6,-2 L6,-4Z"],["M-6,-2 A2,2 0 0,0 -6,2 L6,0Z"]],r=!1;break;case"streamtube":o=[["M-6,2 A2,2 0 0,0 -6,6 H6 A2,2 0 0,1 6,2 Z"],["M-6,-6 A2,2 0 0,0 -6,-2 H6 A2,2 0 0,1 6,-6 Z"],["M-6,-2 A2,2 0 0,0 -6,2 H6 A2,2 0 0,1 6,-2 Z"]],r=!1;break;case"surface":o=[["M-6,-6 A2,3 0 0,0 -6,0 H6 A2,3 0 0,1 6,-6 Z"],["M-6,1 A2,3 0 0,1 -6,6 H6 A2,3 0 0,0 6,0 Z"]],r=!0;break;case"mesh3d":o=[["M-6,6H0L-6,-6Z"],["M6,6H0L6,-6Z"],["M-6,-6H6L0,6Z"]],r=!1;break;case"volume":o=[["M-6,6H0L-6,-6Z"],["M6,6H0L6,-6Z"],["M-6,-6H6L0,6Z"]],r=!0;break;case"isosurface":o=[["M-6,6H0L-6,-6Z"],["M6,6H0L6,-6Z"],["M-6,-6 A12,24 0 0,0 6,-6 L0,6Z"]],r=!1}var u=n.select(this).select("g.legendpoints").selectAll("path.legend3dandfriends").data(o);u.enter().append("path").classed("legend3dandfriends",!0).attr("transform",_).style("stroke-miterlimit",1),u.exit().remove(),u.each((function(e,o){var u,f=n.select(this),d=c(a),h=d.colorscale,v=d.reversescale;if(h){if(!r){var y=h.length;u=0===o?h[v?y-1:0][1]:1===o?h[v?0:y-1][1]:h[Math.floor((y-1)/2)][1]}}else{var g=a.vertexcolor||a.facecolor||a.color;u=i.isArrayOrTypedArray(g)?g[o]||g[0]:g}f.attr("d",e[0]),u?f.call(s.fill,u):f.call((function(e){if(e.size()){var n="legendfill-"+a.uid;l.gradient(e,t,n,p(v,"radial"===r),h,"fill")}}))}))})).each((function(e){var t=e[0].trace,r="waterfall"===t.type;if(e[0]._distinct&&r){var a=e[0].trace[e[0].dir].marker;return e[0].mc=a.color,e[0].mlw=a.line.width,e[0].mlc=a.line.color,T(e,this,"waterfall")}var i=[];t.visible&&r&&(i=e[0].hasTotals?[["increasing","M-6,-6V6H0Z"],["totals","M6,6H0L-6,-6H-0Z"],["decreasing","M6,6V-6H0Z"]]:[["increasing","M-6,-6V6H6Z"],["decreasing","M6,6V-6H-6Z"]]);var o=n.select(this).select("g.legendpoints").selectAll("path.legendwaterfall").data(i);o.enter().append("path").classed("legendwaterfall",!0).attr("transform",_).style("stroke-miterlimit",1),o.exit().remove(),o.each((function(e){var r=n.select(this),a=t[e[0]].marker,i=w(void 0,a.line,5,2);r.attr("d",e[1]).style("stroke-width",i+"px").call(s.fill,a.color),i&&r.call(s.stroke,a.line.color)}))})).each((function(e){T(e,this,"funnel")})).each((function(e){T(e,this)})).each((function(e){var r=e[0].trace,o=n.select(this).select("g.legendpoints").selectAll("path.legendbox").data(r.visible&&a.traceIs(r,"box-violin")?[e]:[]);o.enter().append("path").classed("legendbox",!0).attr("d","M6,6H-6V-6H6Z").attr("transform",_),o.exit().remove(),o.each((function(){var e=n.select(this);if("all"!==r.boxpoints&&"all"!==r.points||0!==s.opacity(r.fillcolor)||0!==s.opacity((r.line||{}).color)){var a=w(void 0,r.line,5,2);e.style("stroke-width",a+"px").call(s.fill,r.fillcolor),a&&s.stroke(e,r.line.color)}else{var c=i.minExtend(r,{marker:{size:m?12:i.constrain(r.marker.size,2,16),sizeref:1,sizemin:1,sizemode:"diameter"}});o.call(l.pointStyle,c,t)}}))})).each((function(e){M(e,this,"funnelarea")})).each((function(e){M(e,this,"pie")})).each((function(e){var r,a,o=v(e),s=o.showFill,f=o.showLine,d=o.showGradientLine,h=o.showGradientFill,y=o.anyFill,g=o.anyLine,m=e[0],b=m.trace,_=c(b),T=_.colorscale,M=_.reversescale,k=u.hasMarkers(b)||!y?"M5,0":g?"M5,-2":"M5,-3",A=n.select(this),L=A.select(".legendfill").selectAll("path").data(s||h?[e]:[]);if(L.enter().append("path").classed("js-fill",!0),L.exit().remove(),L.attr("d",k+"h"+x+"v6h-"+x+"z").call((function(e){if(e.size())if(s)l.fillGroupStyle(e,t);else{var r="legendfill-"+b.uid;l.gradient(e,t,r,p(M),T,"fill")}})),f||d){var S=w(void 0,b.line,10,5);a=i.minExtend(b,{line:{width:S}}),r=[i.minExtend(m,{trace:a})]}var O=A.select(".legendlines").selectAll("path").data(f||d?[r]:[]);O.enter().append("path").classed("js-line",!0),O.exit().remove(),O.attr("d",k+(d?"l"+x+",0.0001":"h"+x)).call(f?l.lineGroupStyle:function(e){if(e.size()){var r="legendline-"+b.uid;l.lineGroupStyle(e),l.gradient(e,t,r,p(M),T,"stroke")}})})).each((function(e){var r,a,o=v(e),s=o.anyFill,c=o.anyLine,f=o.showLine,d=o.showMarker,h=e[0],p=h.trace,y=!d&&!c&&!s&&u.hasText(p);function g(e,t,r,n){var a=i.nestedProperty(p,e).get(),o=i.isArrayOrTypedArray(a)&&t?t(a):a;if(m&&o&&void 0!==n&&(o=n),r){if(o<r[0])return r[0];if(o>r[1])return r[1]}return o}function x(e){return h._distinct&&h.index&&e[h.index]?e[h.index]:e[0]}if(d||y||f){var b={},w={};if(d){b.mc=g("marker.color",x),b.mx=g("marker.symbol",x),b.mo=g("marker.opacity",i.mean,[.2,1]),b.mlc=g("marker.line.color",x),b.mlw=g("marker.line.width",i.mean,[0,5],2),w.marker={sizeref:1,sizemin:1,sizemode:"diameter"};var T=g("marker.size",i.mean,[2,16],12);b.ms=T,w.marker.size=T}f&&(w.line={width:g("line.width",x,[0,10],5)}),y&&(b.tx="Aa",b.tp=g("textposition",x),b.ts=10,b.tc=g("textfont.color",x),b.tf=g("textfont.family",x)),r=[i.minExtend(h,b)],(a=i.minExtend(p,w)).selectedpoints=null,a.texttemplate=null}var M=n.select(this).select("g.legendpoints"),k=M.selectAll("path.scatterpts").data(d?r:[]);k.enter().insert("path",":first-child").classed("scatterpts",!0).attr("transform",_),k.exit().remove(),k.call(l.pointStyle,a,t),d&&(r[0].mrc=3);var A=M.selectAll("g.pointtext").data(y?r:[]);A.enter().append("g").classed("pointtext",!0).append("text").attr("transform",_),A.exit().remove(),A.selectAll("text").call(l.textPointStyle,a,t)})).each((function(e){var t=e[0].trace,r=n.select(this).select("g.legendpoints").selectAll("path.legendcandle").data(t.visible&&"candlestick"===t.type?[e,e]:[]);r.enter().append("path").classed("legendcandle",!0).attr("d",(function(e,t){return t?"M-15,0H-8M-8,6V-6H8Z":"M15,0H8M8,-6V6H-8Z"})).attr("transform",_).style("stroke-miterlimit",1),r.exit().remove(),r.each((function(e,r){var a=n.select(this),i=t[r?"increasing":"decreasing"],o=w(void 0,i.line,5,2);a.style("stroke-width",o+"px").call(s.fill,i.fillcolor),o&&s.stroke(a,i.line.color)}))})).each((function(e){var t=e[0].trace,r=n.select(this).select("g.legendpoints").selectAll("path.legendohlc").data(t.visible&&"ohlc"===t.type?[e,e]:[]);r.enter().append("path").classed("legendohlc",!0).attr("d",(function(e,t){return t?"M-15,0H0M-8,-6V0":"M15,0H0M8,6V0"})).attr("transform",_).style("stroke-miterlimit",1),r.exit().remove(),r.each((function(e,r){var a=n.select(this),i=t[r?"increasing":"decreasing"],o=w(void 0,i.line,5,2);a.style("fill","none").call(l.dashLine,i.line.dash,o),o&&s.stroke(a,i.line.color)}))}))}},2068:function(e,t,r){"use strict";r(3348),e.exports={editType:"modebar",orientation:{valType:"enumerated",values:["v","h"],dflt:"h",editType:"modebar"},bgcolor:{valType:"color",editType:"modebar"},color:{valType:"color",editType:"modebar"},activecolor:{valType:"color",editType:"modebar"},uirevision:{valType:"any",editType:"none"},add:{valType:"string",arrayOk:!0,dflt:"",editType:"modebar"},remove:{valType:"string",arrayOk:!0,dflt:"",editType:"modebar"}}},6023:function(e,t,r){"use strict";var n=r(3972),a=r(4875),i=r(1675),o=r(4255),l=r(4031).eraseActiveShape,s=r(1828),c=s._,u=e.exports={};function f(e,t){var r,a,o=t.currentTarget,l=o.getAttribute("data-attr"),s=o.getAttribute("data-val")||!0,c=e._fullLayout,u={},f=i.list(e,null,!0),d=c._cartesianSpikesEnabled;if("zoom"===l){var h,p="in"===s?.5:2,v=(1+p)/2,y=(1-p)/2;for(a=0;a<f.length;a++)if(!(r=f[a]).fixedrange)if(h=r._name,"auto"===s)u[h+".autorange"]=!0;else if("reset"===s){if(void 0===r._rangeInitial)u[h+".autorange"]=!0;else{var g=r._rangeInitial.slice();u[h+".range[0]"]=g[0],u[h+".range[1]"]=g[1]}void 0!==r._showSpikeInitial&&(u[h+".showspikes"]=r._showSpikeInitial,"on"!==d||r._showSpikeInitial||(d="off"))}else{var m=[r.r2l(r.range[0]),r.r2l(r.range[1])],x=[v*m[0]+y*m[1],v*m[1]+y*m[0]];u[h+".range[0]"]=r.l2r(x[0]),u[h+".range[1]"]=r.l2r(x[1])}}else"hovermode"!==l||"x"!==s&&"y"!==s||(s=c._isHoriz?"y":"x",o.setAttribute("data-val",s)),u[l]=s;c._cartesianSpikesEnabled=d,n.call("_guiRelayout",e,u)}function d(e,t){for(var r=t.currentTarget,a=r.getAttribute("data-attr"),i=r.getAttribute("data-val")||!0,o=e._fullLayout._subplots.gl3d||[],l={},s=a.split("."),c=0;c<o.length;c++)l[o[c]+"."+s[1]]=i;var u="pan"===i?i:"zoom";l.dragmode=u,n.call("_guiRelayout",e,l)}function h(e,t){for(var r=t.currentTarget.getAttribute("data-attr"),a="resetLastSave"===r,i="resetDefault"===r,o=e._fullLayout,l=o._subplots.gl3d||[],s={},c=0;c<l.length;c++){var u,f=l[c],d=f+".camera",h=f+".aspectratio",p=f+".aspectmode",v=o[f]._scene;a?(s[d+".up"]=v.viewInitial.up,s[d+".eye"]=v.viewInitial.eye,s[d+".center"]=v.viewInitial.center,u=!0):i&&(s[d+".up"]=null,s[d+".eye"]=null,s[d+".center"]=null,u=!0),u&&(s[h+".x"]=v.viewInitial.aspectratio.x,s[h+".y"]=v.viewInitial.aspectratio.y,s[h+".z"]=v.viewInitial.aspectratio.z,s[p]=v.viewInitial.aspectmode)}n.call("_guiRelayout",e,s)}function p(e,t){var r=t.currentTarget,n=r._previousVal,a=e._fullLayout,i=a._subplots.gl3d||[],o=["xaxis","yaxis","zaxis"],l={},s={};if(n)s=n,r._previousVal=null;else{for(var c=0;c<i.length;c++){var u=i[c],f=a[u],d=u+".hovermode";l[d]=f.hovermode,s[d]=!1;for(var h=0;h<3;h++){var p=o[h],v=u+"."+p+".showspikes";s[v]=!1,l[v]=f[p].showspikes}}r._previousVal=l}return s}function v(e,t){for(var r=t.currentTarget,a=r.getAttribute("data-attr"),i=r.getAttribute("data-val")||!0,o=e._fullLayout,l=o._subplots.geo||[],s=0;s<l.length;s++){var c=l[s],u=o[c];if("zoom"===a){var f=u.projection.scale,d="in"===i?2*f:.5*f;n.call("_guiRelayout",e,c+".projection.scale",d)}}"reset"===a&&x(e,"geo")}function y(e){var t=e._fullLayout;return!t.hovermode&&(t._has("cartesian")?t._isHoriz?"y":"x":"closest")}function g(e){var t=y(e);n.call("_guiRelayout",e,"hovermode",t)}function m(e,t){for(var r=t.currentTarget.getAttribute("data-val"),a=e._fullLayout,i=a._subplots.mapbox||[],o={},l=0;l<i.length;l++){var s=i[l],c=a[s].zoom,u="in"===r?1.05*c:c/1.05;o[s+".zoom"]=u}n.call("_guiRelayout",e,o)}function x(e,t){for(var r=e._fullLayout,a=r._subplots[t]||[],i={},o=0;o<a.length;o++)for(var l=a[o],s=r[l]._subplot.viewInitial,c=Object.keys(s),u=0;u<c.length;u++){var f=c[u];i[l+"."+f]=s[f]}n.call("_guiRelayout",e,i)}u.toImage={name:"toImage",title:function(e){var t=(e._context.toImageButtonOptions||{}).format||"png";return c(e,"png"===t?"Download plot as a png":"Download plot")},icon:o.camera,click:function(e){var t=e._context.toImageButtonOptions,r={format:t.format||"png"};s.notifier(c(e,"Taking snapshot - this may take a few seconds"),"long"),"svg"!==r.format&&s.isIE()&&(s.notifier(c(e,"IE only supports svg. Changing format to svg."),"long"),r.format="svg"),["filename","width","height","scale"].forEach((function(e){e in t&&(r[e]=t[e])})),n.call("downloadImage",e,r).then((function(t){s.notifier(c(e,"Snapshot succeeded")+" - "+t,"long")})).catch((function(){s.notifier(c(e,"Sorry, there was a problem downloading your snapshot!"),"long")}))}},u.sendDataToCloud={name:"sendDataToCloud",title:function(e){return c(e,"Edit in Chart Studio")},icon:o.disk,click:function(e){a.sendDataToCloud(e)}},u.editInChartStudio={name:"editInChartStudio",title:function(e){return c(e,"Edit in Chart Studio")},icon:o.pencil,click:function(e){a.sendDataToCloud(e)}},u.zoom2d={name:"zoom2d",_cat:"zoom",title:function(e){return c(e,"Zoom")},attr:"dragmode",val:"zoom",icon:o.zoombox,click:f},u.pan2d={name:"pan2d",_cat:"pan",title:function(e){return c(e,"Pan")},attr:"dragmode",val:"pan",icon:o.pan,click:f},u.select2d={name:"select2d",_cat:"select",title:function(e){return c(e,"Box Select")},attr:"dragmode",val:"select",icon:o.selectbox,click:f},u.lasso2d={name:"lasso2d",_cat:"lasso",title:function(e){return c(e,"Lasso Select")},attr:"dragmode",val:"lasso",icon:o.lasso,click:f},u.drawclosedpath={name:"drawclosedpath",title:function(e){return c(e,"Draw closed freeform")},attr:"dragmode",val:"drawclosedpath",icon:o.drawclosedpath,click:f},u.drawopenpath={name:"drawopenpath",title:function(e){return c(e,"Draw open freeform")},attr:"dragmode",val:"drawopenpath",icon:o.drawopenpath,click:f},u.drawline={name:"drawline",title:function(e){return c(e,"Draw line")},attr:"dragmode",val:"drawline",icon:o.drawline,click:f},u.drawrect={name:"drawrect",title:function(e){return c(e,"Draw rectangle")},attr:"dragmode",val:"drawrect",icon:o.drawrect,click:f},u.drawcircle={name:"drawcircle",title:function(e){return c(e,"Draw circle")},attr:"dragmode",val:"drawcircle",icon:o.drawcircle,click:f},u.eraseshape={name:"eraseshape",title:function(e){return c(e,"Erase active shape")},icon:o.eraseshape,click:l},u.zoomIn2d={name:"zoomIn2d",_cat:"zoomin",title:function(e){return c(e,"Zoom in")},attr:"zoom",val:"in",icon:o.zoom_plus,click:f},u.zoomOut2d={name:"zoomOut2d",_cat:"zoomout",title:function(e){return c(e,"Zoom out")},attr:"zoom",val:"out",icon:o.zoom_minus,click:f},u.autoScale2d={name:"autoScale2d",_cat:"autoscale",title:function(e){return c(e,"Autoscale")},attr:"zoom",val:"auto",icon:o.autoscale,click:f},u.resetScale2d={name:"resetScale2d",_cat:"resetscale",title:function(e){return c(e,"Reset axes")},attr:"zoom",val:"reset",icon:o.home,click:f},u.hoverClosestCartesian={name:"hoverClosestCartesian",_cat:"hoverclosest",title:function(e){return c(e,"Show closest data on hover")},attr:"hovermode",val:"closest",icon:o.tooltip_basic,gravity:"ne",click:f},u.hoverCompareCartesian={name:"hoverCompareCartesian",_cat:"hoverCompare",title:function(e){return c(e,"Compare data on hover")},attr:"hovermode",val:function(e){return e._fullLayout._isHoriz?"y":"x"},icon:o.tooltip_compare,gravity:"ne",click:f},u.zoom3d={name:"zoom3d",_cat:"zoom",title:function(e){return c(e,"Zoom")},attr:"scene.dragmode",val:"zoom",icon:o.zoombox,click:d},u.pan3d={name:"pan3d",_cat:"pan",title:function(e){return c(e,"Pan")},attr:"scene.dragmode",val:"pan",icon:o.pan,click:d},u.orbitRotation={name:"orbitRotation",title:function(e){return c(e,"Orbital rotation")},attr:"scene.dragmode",val:"orbit",icon:o["3d_rotate"],click:d},u.tableRotation={name:"tableRotation",title:function(e){return c(e,"Turntable rotation")},attr:"scene.dragmode",val:"turntable",icon:o["z-axis"],click:d},u.resetCameraDefault3d={name:"resetCameraDefault3d",_cat:"resetCameraDefault",title:function(e){return c(e,"Reset camera to default")},attr:"resetDefault",icon:o.home,click:h},u.resetCameraLastSave3d={name:"resetCameraLastSave3d",_cat:"resetCameraLastSave",title:function(e){return c(e,"Reset camera to last save")},attr:"resetLastSave",icon:o.movie,click:h},u.hoverClosest3d={name:"hoverClosest3d",_cat:"hoverclosest",title:function(e){return c(e,"Toggle show closest data on hover")},attr:"hovermode",val:null,toggle:!0,icon:o.tooltip_basic,gravity:"ne",click:function(e,t){var r=p(e,t);n.call("_guiRelayout",e,r)}},u.zoomInGeo={name:"zoomInGeo",_cat:"zoomin",title:function(e){return c(e,"Zoom in")},attr:"zoom",val:"in",icon:o.zoom_plus,click:v},u.zoomOutGeo={name:"zoomOutGeo",_cat:"zoomout",title:function(e){return c(e,"Zoom out")},attr:"zoom",val:"out",icon:o.zoom_minus,click:v},u.resetGeo={name:"resetGeo",_cat:"reset",title:function(e){return c(e,"Reset")},attr:"reset",val:null,icon:o.autoscale,click:v},u.hoverClosestGeo={name:"hoverClosestGeo",_cat:"hoverclosest",title:function(e){return c(e,"Toggle show closest data on hover")},attr:"hovermode",val:null,toggle:!0,icon:o.tooltip_basic,gravity:"ne",click:g},u.hoverClosestGl2d={name:"hoverClosestGl2d",_cat:"hoverclosest",title:function(e){return c(e,"Toggle show closest data on hover")},attr:"hovermode",val:null,toggle:!0,icon:o.tooltip_basic,gravity:"ne",click:g},u.hoverClosestPie={name:"hoverClosestPie",_cat:"hoverclosest",title:function(e){return c(e,"Toggle show closest data on hover")},attr:"hovermode",val:"closest",icon:o.tooltip_basic,gravity:"ne",click:g},u.resetViewSankey={name:"resetSankeyGroup",title:function(e){return c(e,"Reset view")},icon:o.home,click:function(e){for(var t={"node.groups":[],"node.x":[],"node.y":[]},r=0;r<e._fullData.length;r++){var a=e._fullData[r]._viewInitial;t["node.groups"].push(a.node.groups.slice()),t["node.x"].push(a.node.x.slice()),t["node.y"].push(a.node.y.slice())}n.call("restyle",e,t)}},u.toggleHover={name:"toggleHover",title:function(e){return c(e,"Toggle show closest data on hover")},attr:"hovermode",val:null,toggle:!0,icon:o.tooltip_basic,gravity:"ne",click:function(e,t){var r=p(e,t);r.hovermode=y(e),n.call("_guiRelayout",e,r)}},u.resetViews={name:"resetViews",title:function(e){return c(e,"Reset views")},icon:o.home,click:function(e,t){var r=t.currentTarget;r.setAttribute("data-attr","zoom"),r.setAttribute("data-val","reset"),f(e,t),r.setAttribute("data-attr","resetLastSave"),h(e,t),x(e,"geo"),x(e,"mapbox")}},u.toggleSpikelines={name:"toggleSpikelines",title:function(e){return c(e,"Toggle Spike Lines")},icon:o.spikeline,attr:"_cartesianSpikesEnabled",val:"on",click:function(e){var t=e._fullLayout,r=t._cartesianSpikesEnabled;t._cartesianSpikesEnabled="on"===r?"off":"on",n.call("_guiRelayout",e,function(e){for(var t="on"===e._fullLayout._cartesianSpikesEnabled,r=i.list(e,null,!0),n={},a=0;a<r.length;a++){var o=r[a];n[o._name+".showspikes"]=!!t||o._showSpikeInitial}return n}(e))}},u.resetViewMapbox={name:"resetViewMapbox",_cat:"resetView",title:function(e){return c(e,"Reset view")},attr:"reset",icon:o.home,click:function(e){x(e,"mapbox")}},u.zoomInMapbox={name:"zoomInMapbox",_cat:"zoomin",title:function(e){return c(e,"Zoom in")},attr:"zoom",val:"in",icon:o.zoom_plus,click:m},u.zoomOutMapbox={name:"zoomOutMapbox",_cat:"zoomout",title:function(e){return c(e,"Zoom out")},attr:"zoom",val:"out",icon:o.zoom_minus,click:m}},3348:function(e,t,r){"use strict";var n=r(6023),a=Object.keys(n),i=["drawline","drawopenpath","drawclosedpath","drawcircle","drawrect","eraseshape"],o=["v1hovermode","hoverclosest","hovercompare","togglehover","togglespikelines"].concat(i),l=[];a.forEach((function(e){!function(e){if(-1===o.indexOf(e._cat||e.name)){var t=e.name,r=(e._cat||e.name).toLowerCase();-1===l.indexOf(t)&&l.push(t),-1===l.indexOf(r)&&l.push(r)}}(n[e])})),l.sort(),e.exports={DRAW_MODES:i,backButtons:o,foreButtons:l}},5750:function(e,t,r){"use strict";var n=r(1828),a=r(7901),i=r(4467),o=r(2068);e.exports=function(e,t){var r=e.modebar||{},l=i.newContainer(t,"modebar");function s(e,t){return n.coerce(r,l,o,e,t)}s("orientation"),s("bgcolor",a.addOpacity(t.paper_bgcolor,.5));var c=a.contrast(a.rgb(t.modebar.bgcolor));s("color",a.addOpacity(c,.3)),s("activecolor",a.addOpacity(c,.7)),s("uirevision",t.uirevision),s("add"),s("remove")}},4168:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"modebar",layoutAttributes:r(2068),supplyLayoutDefaults:r(5750),manage:r(4192)}},4192:function(e,t,r){"use strict";var n=r(1675),a=r(4098),i=r(3972),o=r(3469).isUnifiedHover,l=r(7676),s=r(6023),c=r(3348).DRAW_MODES,u=r(1828).extendDeep;e.exports=function(e){var t=e._fullLayout,r=e._context,f=t._modeBar;if(r.displayModeBar||r.watermark){if(!Array.isArray(r.modeBarButtonsToRemove))throw new Error(["*modeBarButtonsToRemove* configuration options","must be an array."].join(" "));if(!Array.isArray(r.modeBarButtonsToAdd))throw new Error(["*modeBarButtonsToAdd* configuration options","must be an array."].join(" "));var d,h=r.modeBarButtons;d=Array.isArray(h)&&h.length?function(e){for(var t=u([],e),r=0;r<t.length;r++)for(var n=t[r],a=0;a<n.length;a++){var i=n[a];if("string"==typeof i){if(void 0===s[i])throw new Error(["*modeBarButtons* configuration options","invalid button name"].join(" "));t[r][a]=s[i]}}return t}(h):!r.displayModeBar&&r.watermark?[]:function(e){var t=e._fullLayout,r=e._fullData,l=e._context;function u(e,t){if("string"==typeof t){if(t.toLowerCase()===e.toLowerCase())return!0}else{var r=t.name,n=t._cat||t.name;if(r===e||n===e.toLowerCase())return!0}return!1}var f=t.modebar.add;"string"==typeof f&&(f=[f]);var d=t.modebar.remove;"string"==typeof d&&(d=[d]);var h=l.modeBarButtonsToAdd.concat(f.filter((function(e){for(var t=0;t<l.modeBarButtonsToRemove.length;t++)if(u(e,l.modeBarButtonsToRemove[t]))return!1;return!0}))),p=l.modeBarButtonsToRemove.concat(d.filter((function(e){for(var t=0;t<l.modeBarButtonsToAdd.length;t++)if(u(e,l.modeBarButtonsToAdd[t]))return!1;return!0}))),v=t._has("cartesian"),y=t._has("gl3d"),g=t._has("geo"),m=t._has("pie"),x=t._has("funnelarea"),b=t._has("gl2d"),_=t._has("ternary"),w=t._has("mapbox"),T=t._has("polar"),M=t._has("smith"),k=t._has("sankey"),A=function(e){for(var t=n.list({_fullLayout:e},null,!0),r=0;r<t.length;r++)if(!t[r].fixedrange)return!1;return!0}(t),L=o(t.hovermode),S=[];function O(e){if(e.length){for(var t=[],r=0;r<e.length;r++){for(var n=e[r],a=s[n],i=a.name.toLowerCase(),o=(a._cat||a.name).toLowerCase(),l=!1,c=0;c<p.length;c++){var u=p[c].toLowerCase();if(u===i||u===o){l=!0;break}}l||t.push(s[n])}S.push(t)}}var D=["toImage"];l.showEditInChartStudio?D.push("editInChartStudio"):l.showSendToCloud&&D.push("sendDataToCloud"),O(D);var C=[],P=[],I=[],R=[];(v||b||m||x||_)+g+y+w+T+M>1?(P=["toggleHover"],I=["resetViews"]):g?(C=["zoomInGeo","zoomOutGeo"],P=["hoverClosestGeo"],I=["resetGeo"]):y?(P=["hoverClosest3d"],I=["resetCameraDefault3d","resetCameraLastSave3d"]):w?(C=["zoomInMapbox","zoomOutMapbox"],P=["toggleHover"],I=["resetViewMapbox"]):b?P=["hoverClosestGl2d"]:m?P=["hoverClosestPie"]:k?(P=["hoverClosestCartesian","hoverCompareCartesian"],I=["resetViewSankey"]):P=["toggleHover"],v&&(P=["toggleSpikelines","hoverClosestCartesian","hoverCompareCartesian"]),(function(e){for(var t=0;t<e.length;t++)if(!i.traceIs(e[t],"noHover"))return!1;return!0}(r)||L)&&(P=[]),!v&&!b||A||(C=["zoomIn2d","zoomOut2d","autoScale2d"],"resetViews"!==I[0]&&(I=["resetScale2d"])),y?R=["zoom3d","pan3d","orbitRotation","tableRotation"]:(v||b)&&!A||_?R=["zoom2d","pan2d"]:w||g?R=["pan2d"]:T&&(R=["zoom2d"]),function(e){for(var t=!1,r=0;r<e.length&&!t;r++){var n=e[r];n._module&&n._module.selectPoints&&(i.traceIs(n,"scatter-like")?(a.hasMarkers(n)||a.hasText(n))&&(t=!0):i.traceIs(n,"box-violin")&&"all"!==n.boxpoints&&"all"!==n.points||(t=!0))}return t}(r)&&R.push("select2d","lasso2d");var z=[],N=function(e){-1===z.indexOf(e)&&-1!==P.indexOf(e)&&z.push(e)};if(Array.isArray(h)){for(var E=[],F=0;F<h.length;F++){var H=h[F];"string"==typeof H?(H=H.toLowerCase(),-1!==c.indexOf(H)?(t._has("mapbox")||t._has("cartesian"))&&R.push(H):"togglespikelines"===H?N("toggleSpikelines"):"togglehover"===H?N("toggleHover"):"hovercompare"===H?N("hoverCompareCartesian"):"hoverclosest"===H?(N("hoverClosestCartesian"),N("hoverClosestGeo"),N("hoverClosest3d"),N("hoverClosestGl2d"),N("hoverClosestPie")):"v1hovermode"===H&&(N("toggleHover"),N("hoverClosestCartesian"),N("hoverCompareCartesian"),N("hoverClosestGeo"),N("hoverClosest3d"),N("hoverClosestGl2d"),N("hoverClosestPie"))):E.push(H)}h=E}return O(R),O(C.concat(I)),O(z),function(e,t){if(t.length)if(Array.isArray(t[0]))for(var r=0;r<t.length;r++)e.push(t[r]);else e.push(t);return e}(S,h)}(e),f?f.update(e,d):t._modeBar=l(e,d)}else f&&(f.destroy(),delete t._modeBar)}},7676:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(1828),o=r(4255),l=r(1506).version,s=new DOMParser;function c(e){this.container=e.container,this.element=document.createElement("div"),this.update(e.graphInfo,e.buttons),this.container.appendChild(this.element)}var u=c.prototype;u.update=function(e,t){this.graphInfo=e;var r=this.graphInfo._context,n=this.graphInfo._fullLayout,a="modebar-"+n._uid;this.element.setAttribute("id",a),this._uid=a,this.element.className="modebar","hover"===r.displayModeBar&&(this.element.className+=" modebar--hover ease-bg"),"v"===n.modebar.orientation&&(this.element.className+=" vertical",t=t.reverse());var o=n.modebar,l="hover"===r.displayModeBar?".js-plotly-plot .plotly:hover ":"";i.deleteRelatedStyleRule(a),i.addRelatedStyleRule(a,l+"#"+a+" .modebar-group","background-color: "+o.bgcolor),i.addRelatedStyleRule(a,"#"+a+" .modebar-btn .icon path","fill: "+o.color),i.addRelatedStyleRule(a,"#"+a+" .modebar-btn:hover .icon path","fill: "+o.activecolor),i.addRelatedStyleRule(a,"#"+a+" .modebar-btn.active .icon path","fill: "+o.activecolor);var s=!this.hasButtons(t),c=this.hasLogo!==r.displaylogo,u=this.locale!==r.locale;if(this.locale=r.locale,(s||c||u)&&(this.removeAllButtons(),this.updateButtons(t),r.watermark||r.displaylogo)){var f=this.getLogo();r.watermark&&(f.className=f.className+" watermark"),"v"===n.modebar.orientation?this.element.insertBefore(f,this.element.childNodes[0]):this.element.appendChild(f),this.hasLogo=!0}this.updateActiveButton()},u.updateButtons=function(e){var t=this;this.buttons=e,this.buttonElements=[],this.buttonsNames=[],this.buttons.forEach((function(e){var r=t.createGroup();e.forEach((function(e){var n=e.name;if(!n)throw new Error("must provide button 'name' in button config");if(-1!==t.buttonsNames.indexOf(n))throw new Error("button name '"+n+"' is taken");t.buttonsNames.push(n);var a=t.createButton(e);t.buttonElements.push(a),r.appendChild(a)})),t.element.appendChild(r)}))},u.createGroup=function(){var e=document.createElement("div");return e.className="modebar-group",e},u.createButton=function(e){var t=this,r=document.createElement("a");r.setAttribute("rel","tooltip"),r.className="modebar-btn";var a=e.title;void 0===a?a=e.name:"function"==typeof a&&(a=a(this.graphInfo)),(a||0===a)&&r.setAttribute("data-title",a),void 0!==e.attr&&r.setAttribute("data-attr",e.attr);var i=e.val;if(void 0!==i&&("function"==typeof i&&(i=i(this.graphInfo)),r.setAttribute("data-val",i)),"function"!=typeof e.click)throw new Error("must provide button 'click' function in button config");r.addEventListener("click",(function(r){e.click(t.graphInfo,r),t.updateActiveButton(r.currentTarget)})),r.setAttribute("data-toggle",e.toggle||!1),e.toggle&&n.select(r).classed("active",!0);var l=e.icon;return"function"==typeof l?r.appendChild(l()):r.appendChild(this.createIcon(l||o.question)),r.setAttribute("data-gravity",e.gravity||"n"),r},u.createIcon=function(e){var t,r=a(e.height)?Number(e.height):e.ascent-e.descent,n="http://www.w3.org/2000/svg";if(e.path){(t=document.createElementNS(n,"svg")).setAttribute("viewBox",[0,0,e.width,r].join(" ")),t.setAttribute("class","icon");var i=document.createElementNS(n,"path");i.setAttribute("d",e.path),e.transform?i.setAttribute("transform",e.transform):void 0!==e.ascent&&i.setAttribute("transform","matrix(1 0 0 -1 0 "+e.ascent+")"),t.appendChild(i)}return e.svg&&(t=s.parseFromString(e.svg,"application/xml").childNodes[0]),t.setAttribute("height","1em"),t.setAttribute("width","1em"),t},u.updateActiveButton=function(e){var t=this.graphInfo._fullLayout,r=void 0!==e?e.getAttribute("data-attr"):null;this.buttonElements.forEach((function(e){var a=e.getAttribute("data-val")||!0,o=e.getAttribute("data-attr"),l="true"===e.getAttribute("data-toggle"),s=n.select(e);if(l)o===r&&s.classed("active",!s.classed("active"));else{var c=null===o?o:i.nestedProperty(t,o).get();s.classed("active",c===a)}}))},u.hasButtons=function(e){var t=this.buttons;if(!t)return!1;if(e.length!==t.length)return!1;for(var r=0;r<e.length;++r){if(e[r].length!==t[r].length)return!1;for(var n=0;n<e[r].length;n++)if(e[r][n].name!==t[r][n].name)return!1}return!0},u.getLogo=function(){var e=this.createGroup(),t=document.createElement("a");return t.href="https://plotly.com/",t.target="_blank",t.setAttribute("data-title",i._(this.graphInfo,"Produced with Plotly.js")+" (v"+l+")"),t.className="modebar-btn plotlyjsicon modebar-btn--logo",t.appendChild(this.createIcon(o.newplotlylogo)),e.appendChild(t),e},u.removeAllButtons=function(){for(;this.element.firstChild;)this.element.removeChild(this.element.firstChild);this.hasLogo=!1},u.destroy=function(){i.removeElement(this.container.querySelector(".modebar")),i.deleteRelatedStyleRule(this._uid)},e.exports=function(e,t){var r=e._fullLayout,a=new c({graphInfo:e,container:r._modebardiv.node(),buttons:t});return r._privateplot&&n.select(a.element).append("span").classed("badge-private float--left",!0).text("PRIVATE"),a}},7113:function(e,t,r){"use strict";var n=r(1940),a=r(2399),i=(0,r(4467).templatedArray)("button",{visible:{valType:"boolean",dflt:!0,editType:"plot"},step:{valType:"enumerated",values:["month","year","day","hour","minute","second","all"],dflt:"month",editType:"plot"},stepmode:{valType:"enumerated",values:["backward","todate"],dflt:"backward",editType:"plot"},count:{valType:"number",min:0,dflt:1,editType:"plot"},label:{valType:"string",editType:"plot"},editType:"plot"});e.exports={visible:{valType:"boolean",editType:"plot"},buttons:i,x:{valType:"number",min:-2,max:3,editType:"plot"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left",editType:"plot"},y:{valType:"number",min:-2,max:3,editType:"plot"},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"bottom",editType:"plot"},font:n({editType:"plot"}),bgcolor:{valType:"color",dflt:a.lightLine,editType:"plot"},activecolor:{valType:"color",editType:"plot"},bordercolor:{valType:"color",dflt:a.defaultLine,editType:"plot"},borderwidth:{valType:"number",min:0,dflt:0,editType:"plot"},editType:"plot"}},9573:function(e){"use strict";e.exports={yPad:.02,minButtonWidth:30,rx:3,ry:3,lightAmount:25,darkAmount:10}},8674:function(e,t,r){"use strict";var n=r(1828),a=r(7901),i=r(4467),o=r(5501),l=r(7113),s=r(9573);function c(e,t,r,a){var i=a.calendar;function o(r,a){return n.coerce(e,t,l.buttons,r,a)}if(o("visible")){var s=o("step");"all"!==s&&(!i||"gregorian"===i||"month"!==s&&"year"!==s?o("stepmode"):t.stepmode="backward",o("count")),o("label")}}e.exports=function(e,t,r,u,f){var d=e.rangeselector||{},h=i.newContainer(t,"rangeselector");function p(e,t){return n.coerce(d,h,l,e,t)}if(p("visible",o(d,h,{name:"buttons",handleItemDefaults:c,calendar:f}).length>0)){var v=function(e,t,r){for(var n=r.filter((function(r){return t[r].anchor===e._id})),a=0,i=0;i<n.length;i++){var o=t[n[i]].domain;o&&(a=Math.max(o[1],a))}return[e.domain[0],a+s.yPad]}(t,r,u);p("x",v[0]),p("y",v[1]),n.noneOrAll(e,t,["x","y"]),p("xanchor"),p("yanchor"),n.coerceFont(p,"font",r.font);var y=p("bgcolor");p("activecolor",a.contrast(y,s.lightAmount,s.darkAmount)),p("bordercolor"),p("borderwidth")}}},1598:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(4875),o=r(7901),l=r(1424),s=r(1828),c=s.strTranslate,u=r(3893),f=r(1675),d=r(8783),h=d.LINE_SPACING,p=d.FROM_TL,v=d.FROM_BR,y=r(9573),g=r(7917);function m(e){return e._id}function x(e,t,r){var n=s.ensureSingle(e,"rect","selector-rect",(function(e){e.attr("shape-rendering","crispEdges")}));n.attr({rx:y.rx,ry:y.ry}),n.call(o.stroke,t.bordercolor).call(o.fill,function(e,t){return t._isActive||t._isHovered?e.activecolor:e.bgcolor}(t,r)).style("stroke-width",t.borderwidth+"px")}function b(e,t,r,n){var a,i;s.ensureSingle(e,"text","selector-text",(function(e){e.attr("text-anchor","middle")})).call(l.font,t.font).text((a=r,i=n._fullLayout._meta,a.label?i?s.templateString(a.label,i):a.label:"all"===a.step?"all":a.count+a.step.charAt(0))).call((function(e){u.convertToTspans(e,n)}))}e.exports=function(e){var t=e._fullLayout._infolayer.selectAll(".rangeselector").data(function(e){for(var t=f.list(e,"x",!0),r=[],n=0;n<t.length;n++){var a=t[n];a.rangeselector&&a.rangeselector.visible&&r.push(a)}return r}(e),m);t.enter().append("g").classed("rangeselector",!0),t.exit().remove(),t.style({cursor:"pointer","pointer-events":"all"}),t.each((function(t){var r=n.select(this),o=t,f=o.rangeselector,d=r.selectAll("g.button").data(s.filterVisible(f.buttons));d.enter().append("g").classed("button",!0),d.exit().remove(),d.each((function(t){var r=n.select(this),i=g(o,t);t._isActive=function(e,t,r){if("all"===t.step)return!0===e.autorange;var n=Object.keys(r);return e.range[0]===r[n[0]]&&e.range[1]===r[n[1]]}(o,t,i),r.call(x,f,t),r.call(b,f,t,e),r.on("click",(function(){e._dragged||a.call("_guiRelayout",e,i)})),r.on("mouseover",(function(){t._isHovered=!0,r.call(x,f,t)})),r.on("mouseout",(function(){t._isHovered=!1,r.call(x,f,t)}))})),function(e,t,r,a,o){var f=0,d=0,g=r.borderwidth;t.each((function(){var e=n.select(this).select(".selector-text"),t=r.font.size*h,a=Math.max(t*u.lineCount(e),16)+3;d=Math.max(d,a)})),t.each((function(){var e=n.select(this),t=e.select(".selector-rect"),a=e.select(".selector-text"),i=a.node()&&l.bBox(a.node()).width,o=r.font.size*h,s=u.lineCount(a),p=Math.max(i+10,y.minButtonWidth);e.attr("transform",c(g+f,g)),t.attr({x:0,y:0,width:p,height:d}),u.positionText(a,p/2,d/2-(s-1)*o/2+3),f+=p+5}));var m=e._fullLayout._size,x=m.l+m.w*r.x,b=m.t+m.h*(1-r.y),_="left";s.isRightAnchor(r)&&(x-=f,_="right"),s.isCenterAnchor(r)&&(x-=f/2,_="center");var w="top";s.isBottomAnchor(r)&&(b-=d,w="bottom"),s.isMiddleAnchor(r)&&(b-=d/2,w="middle"),f=Math.ceil(f),d=Math.ceil(d),x=Math.round(x),b=Math.round(b),i.autoMargin(e,a+"-range-selector",{x:r.x,y:r.y,l:f*p[_],r:f*v[_],b:d*v[w],t:d*p[w]}),o.attr("transform",c(x,b))}(e,d,f,o._name,r)}))}},7917:function(e,t,r){"use strict";var n=r(1041),a=r(1828).titleCase;e.exports=function(e,t){var r=e._name,i={};if("all"===t.step)i[r+".autorange"]=!0;else{var o=function(e,t){var r,i=e.range,o=new Date(e.r2l(i[1])),l=t.step,s=n["utc"+a(l)],c=t.count;switch(t.stepmode){case"backward":r=e.l2r(+s.offset(o,-c));break;case"todate":var u=s.offset(o,-c);r=e.l2r(+s.ceil(u))}var f=i[1];return[r,f]}(e,t);i[r+".range[0]"]=o[0],i[r+".range[1]"]=o[1]}return i}},7218:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"rangeselector",schema:{subplots:{xaxis:{rangeselector:r(7113)}}},layoutAttributes:r(7113),handleDefaults:r(8674),draw:r(1598)}},5148:function(e,t,r){"use strict";var n=r(2399);e.exports={bgcolor:{valType:"color",dflt:n.background,editType:"plot"},bordercolor:{valType:"color",dflt:n.defaultLine,editType:"plot"},borderwidth:{valType:"integer",dflt:0,min:0,editType:"plot"},autorange:{valType:"boolean",dflt:!0,editType:"calc",impliedEdits:{"range[0]":void 0,"range[1]":void 0}},range:{valType:"info_array",items:[{valType:"any",editType:"calc",impliedEdits:{"^autorange":!1}},{valType:"any",editType:"calc",impliedEdits:{"^autorange":!1}}],editType:"calc",impliedEdits:{autorange:!1}},thickness:{valType:"number",dflt:.15,min:0,max:1,editType:"plot"},visible:{valType:"boolean",dflt:!0,editType:"calc"},editType:"calc"}},8443:function(e,t,r){"use strict";var n=r(1675).list,a=r(1739).getAutoRange,i=r(3251);e.exports=function(e){for(var t=n(e,"x",!0),r=0;r<t.length;r++){var o=t[r],l=o[i.name];l&&l.visible&&l.autorange&&(l._input.autorange=!0,l._input.range=l.range=a(e,o))}}},3251:function(e){"use strict";e.exports={name:"rangeslider",containerClassName:"rangeslider-container",bgClassName:"rangeslider-bg",rangePlotClassName:"rangeslider-rangeplot",maskMinClassName:"rangeslider-mask-min",maskMaxClassName:"rangeslider-mask-max",slideBoxClassName:"rangeslider-slidebox",grabberMinClassName:"rangeslider-grabber-min",grabAreaMinClassName:"rangeslider-grabarea-min",handleMinClassName:"rangeslider-handle-min",grabberMaxClassName:"rangeslider-grabber-max",grabAreaMaxClassName:"rangeslider-grabarea-max",handleMaxClassName:"rangeslider-handle-max",maskMinOppAxisClassName:"rangeslider-mask-min-opp-axis",maskMaxOppAxisClassName:"rangeslider-mask-max-opp-axis",maskColor:"rgba(0,0,0,0.4)",maskOppAxisColor:"rgba(0,0,0,0.2)",slideBoxFill:"transparent",slideBoxCursor:"ew-resize",grabAreaFill:"transparent",grabAreaCursor:"col-resize",grabAreaWidth:10,handleWidth:4,handleRadius:1,handleStrokeWidth:1,extraPad:15}},6377:function(e,t,r){"use strict";var n=r(1828),a=r(4467),i=r(1675),o=r(5148),l=r(7850);e.exports=function(e,t,r){var s=e[r],c=t[r];if(s.rangeslider||t._requestRangeslider[c._id]){n.isPlainObject(s.rangeslider)||(s.rangeslider={});var u,f,d=s.rangeslider,h=a.newContainer(c,"rangeslider");if(_("visible")){_("bgcolor",t.plot_bgcolor),_("bordercolor"),_("borderwidth"),_("thickness"),_("autorange",!c.isValidRange(d.range)),_("range");var p=t._subplots;if(p)for(var v=p.cartesian.filter((function(e){return e.substr(0,e.indexOf("y"))===i.name2id(r)})).map((function(e){return e.substr(e.indexOf("y"),e.length)})),y=n.simpleMap(v,i.id2name),g=0;g<y.length;g++){var m=y[g];u=d[m]||{},f=a.newContainer(h,m,"yaxis");var x,b=t[m];u.range&&b.isValidRange(u.range)&&(x="fixed"),"match"!==w("rangemode",x)&&w("range",b.range.slice())}h._input=d}}function _(e,t){return n.coerce(d,h,o,e,t)}function w(e,t){return n.coerce(u,f,l,e,t)}}},2413:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(4875),o=r(1828),l=o.strTranslate,s=r(1424),c=r(7901),u=r(2998),f=r(3612),d=r(1675),h=r(8569),p=r(6964),v=r(3251);function y(e,t,r,n){var a=o.ensureSingle(e,"rect",v.bgClassName,(function(e){e.attr({x:0,y:0,"shape-rendering":"crispEdges"})})),i=n.borderwidth%2==0?n.borderwidth:n.borderwidth-1,u=-n._offsetShift,f=s.crispRound(t,n.borderwidth);a.attr({width:n._width+i,height:n._height+i,transform:l(u,u),"stroke-width":f}).call(c.stroke,n.bordercolor).call(c.fill,n.bgcolor)}function g(e,t,r,n){var a=t._fullLayout;o.ensureSingleById(a._topdefs,"clipPath",n._clipId,(function(e){e.append("rect").attr({x:0,y:0})})).select("rect").attr({width:n._width,height:n._height})}function m(e,t,r,a){var l,c=t.calcdata,u=e.selectAll("g."+v.rangePlotClassName).data(r._subplotsWith,o.identity);u.enter().append("g").attr("class",(function(e){return v.rangePlotClassName+" "+e})).call(s.setClipUrl,a._clipId,t),u.order(),u.exit().remove(),u.each((function(e,o){var s=n.select(this),u=0===o,h=d.getFromId(t,e,"y"),p=h._name,v=a[p],y={data:[],layout:{xaxis:{type:r.type,domain:[0,1],range:a.range.slice(),calendar:r.calendar},width:a._width,height:a._height,margin:{t:0,b:0,l:0,r:0}},_context:t._context};r.rangebreaks&&(y.layout.xaxis.rangebreaks=r.rangebreaks),y.layout[p]={type:h.type,domain:[0,1],range:"match"!==v.rangemode?v.range.slice():h.range.slice(),calendar:h.calendar},h.rangebreaks&&(y.layout[p].rangebreaks=h.rangebreaks),i.supplyDefaults(y);var g=y._fullLayout.xaxis,m=y._fullLayout[p];g.clearCalc(),g.setScale(),m.clearCalc(),m.setScale();var x={id:e,plotgroup:s,xaxis:g,yaxis:m,isRangePlot:!0};u?l=x:(x.mainplot="xy",x.mainplotinfo=l),f.rangePlot(t,x,function(e,t){for(var r=[],n=0;n<e.length;n++){var a=e[n],i=a[0].trace;i.xaxis+i.yaxis===t&&r.push(a)}return r}(c,e))}))}function x(e,t,r,n,a){o.ensureSingle(e,"rect",v.maskMinClassName,(function(e){e.attr({x:0,y:0,"shape-rendering":"crispEdges"})})).attr("height",n._height).call(c.fill,v.maskColor),o.ensureSingle(e,"rect",v.maskMaxClassName,(function(e){e.attr({y:0,"shape-rendering":"crispEdges"})})).attr("height",n._height).call(c.fill,v.maskColor),"match"!==a.rangemode&&(o.ensureSingle(e,"rect",v.maskMinOppAxisClassName,(function(e){e.attr({y:0,"shape-rendering":"crispEdges"})})).attr("width",n._width).call(c.fill,v.maskOppAxisColor),o.ensureSingle(e,"rect",v.maskMaxOppAxisClassName,(function(e){e.attr({y:0,"shape-rendering":"crispEdges"})})).attr("width",n._width).style("border-top",v.maskOppBorder).call(c.fill,v.maskOppAxisColor))}function b(e,t,r,n){t._context.staticPlot||o.ensureSingle(e,"rect",v.slideBoxClassName,(function(e){e.attr({y:0,cursor:v.slideBoxCursor,"shape-rendering":"crispEdges"})})).attr({height:n._height,fill:v.slideBoxFill})}function _(e,t,r,n){var a=o.ensureSingle(e,"g",v.grabberMinClassName),i=o.ensureSingle(e,"g",v.grabberMaxClassName),l={x:0,width:v.handleWidth,rx:v.handleRadius,fill:c.background,stroke:c.defaultLine,"stroke-width":v.handleStrokeWidth,"shape-rendering":"crispEdges"},s={y:Math.round(n._height/4),height:Math.round(n._height/2)};o.ensureSingle(a,"rect",v.handleMinClassName,(function(e){e.attr(l)})).attr(s),o.ensureSingle(i,"rect",v.handleMaxClassName,(function(e){e.attr(l)})).attr(s);var u={width:v.grabAreaWidth,x:0,y:0,fill:v.grabAreaFill,cursor:t._context.staticPlot?void 0:v.grabAreaCursor};o.ensureSingle(a,"rect",v.grabAreaMinClassName,(function(e){e.attr(u)})).attr("height",n._height),o.ensureSingle(i,"rect",v.grabAreaMaxClassName,(function(e){e.attr(u)})).attr("height",n._height)}e.exports=function(e){for(var t=e._fullLayout,r=t._rangeSliderData,i=0;i<r.length;i++){var s=r[i][v.name];s._clipId=s._id+"-"+t._uid}var c=t._infolayer.selectAll("g."+v.containerClassName).data(r,(function(e){return e._name}));c.exit().each((function(e){var r=e[v.name];t._topdefs.select("#"+r._clipId).remove()})).remove(),0!==r.length&&(c.enter().append("g").classed(v.containerClassName,!0).attr("pointer-events","all"),c.each((function(r){var i=n.select(this),s=r[v.name],c=t[d.id2name(r.anchor)],f=s[d.id2name(r.anchor)];if(s.range){var w,T=o.simpleMap(s.range,r.r2l),M=o.simpleMap(r.range,r.r2l);w=M[0]<M[1]?[Math.min(T[0],M[0]),Math.max(T[1],M[1])]:[Math.max(T[0],M[0]),Math.min(T[1],M[1])],s.range=s._input.range=o.simpleMap(w,r.l2r)}r.cleanRange("rangeslider.range");var k=t._size,A=r.domain;s._width=k.w*(A[1]-A[0]);var L=Math.round(k.l+k.w*A[0]),S=Math.round(k.t+k.h*(1-r._counterDomainMin)+("bottom"===r.side?r._depth:0)+s._offsetShift+v.extraPad);i.attr("transform",l(L,S)),s._rl=o.simpleMap(s.range,r.r2l);var O=s._rl[0],D=s._rl[1],C=D-O;if(s.p2d=function(e){return e/s._width*C+O},s.d2p=function(e){return(e-O)/C*s._width},r.rangebreaks){var P=r.locateBreaks(O,D);if(P.length){var I,R,z=0;for(I=0;I<P.length;I++)z+=(R=P[I]).max-R.min;var N=s._width/(D-O-z),E=[-N*O];for(I=0;I<P.length;I++)R=P[I],E.push(E[E.length-1]-N*(R.max-R.min));for(s.d2p=function(e){for(var t=E[0],r=0;r<P.length;r++){var n=P[r];if(e>=n.max)t=E[r+1];else if(e<n.min)break}return t+N*e},I=0;I<P.length;I++)(R=P[I]).pmin=s.d2p(R.min),R.pmax=s.d2p(R.max);s.p2d=function(e){for(var t=E[0],r=0;r<P.length;r++){var n=P[r];if(e>=n.pmax)t=E[r+1];else if(e<n.pmin)break}return(e-t)/N}}}if("match"!==f.rangemode){var F=c.r2l(f.range[0]),H=c.r2l(f.range[1])-F;s.d2pOppAxis=function(e){return(e-F)/H*s._height}}i.call(y,e,r,s).call(g,e,r,s).call(m,e,r,s).call(x,e,r,s,f).call(b,e,r,s).call(_,e,r,s),function(e,t,r,i){if(!t._context.staticPlot){var l=e.select("rect."+v.slideBoxClassName).node(),s=e.select("rect."+v.grabAreaMinClassName).node(),c=e.select("rect."+v.grabAreaMaxClassName).node();e.on("mousedown",u),e.on("touchstart",u)}function u(){var u=n.event,f=u.target,d=u.clientX||u.touches[0].clientX,v=d-e.node().getBoundingClientRect().left,y=i.d2p(r._rl[0]),g=i.d2p(r._rl[1]),m=h.coverSlip();function x(e){var u,h,x,b=+(e.clientX||e.touches[0].clientX)-d;switch(f){case l:if(x="ew-resize",y+b>r._length||g+b<0)return;u=y+b,h=g+b;break;case s:if(x="col-resize",y+b>r._length)return;u=y+b,h=g;break;case c:if(x="col-resize",g+b<0)return;u=y,h=g+b;break;default:x="ew-resize",u=v,h=v+b}if(h<u){var _=h;h=u,u=_}i._pixelMin=u,i._pixelMax=h,p(n.select(m),x),function(e,t,r,n){function i(e){return r.l2r(o.constrain(e,n._rl[0],n._rl[1]))}var l=i(n.p2d(n._pixelMin)),s=i(n.p2d(n._pixelMax));window.requestAnimationFrame((function(){a.call("_guiRelayout",t,r._name+".range",[l,s])}))}(0,t,r,i)}function b(){m.removeEventListener("mousemove",x),m.removeEventListener("mouseup",b),this.removeEventListener("touchmove",x),this.removeEventListener("touchend",b),o.removeElement(m)}this.addEventListener("touchmove",x),this.addEventListener("touchend",b),m.addEventListener("mousemove",x),m.addEventListener("mouseup",b)}}(i,e,r,s),function(e,t,r,n,a,i){var s=v.handleWidth/2;function c(e){return o.constrain(e,0,n._width)}function u(e){return o.constrain(e,0,n._height)}function f(e){return o.constrain(e,-s,n._width+s)}var d=c(n.d2p(r._rl[0])),h=c(n.d2p(r._rl[1]));if(e.select("rect."+v.slideBoxClassName).attr("x",d).attr("width",h-d),e.select("rect."+v.maskMinClassName).attr("width",d),e.select("rect."+v.maskMaxClassName).attr("x",h).attr("width",n._width-h),"match"!==i.rangemode){var p=n._height-u(n.d2pOppAxis(a._rl[1])),y=n._height-u(n.d2pOppAxis(a._rl[0]));e.select("rect."+v.maskMinOppAxisClassName).attr("x",d).attr("height",p).attr("width",h-d),e.select("rect."+v.maskMaxOppAxisClassName).attr("x",d).attr("y",y).attr("height",n._height-y).attr("width",h-d),e.select("rect."+v.slideBoxClassName).attr("y",p).attr("height",y-p)}var g=.5,m=Math.round(f(d-s))-g,x=Math.round(f(h-s))+g;e.select("g."+v.grabberMinClassName).attr("transform",l(m,g)),e.select("g."+v.grabberMaxClassName).attr("transform",l(x,g))}(i,0,r,s,c,f),"bottom"===r.side&&u.draw(e,r._id+"title",{propContainer:r,propName:r._name+".title",placeholder:t._dfltTitle.x,attributes:{x:r._offset+r._length/2,y:S+s._height+s._offsetShift+10+1.5*r.title.font.size,"text-anchor":"middle"}})})))}},549:function(e,t,r){"use strict";var n=r(1675),a=r(3893),i=r(3251),o=r(8783).LINE_SPACING,l=i.name;function s(e){var t=e&&e[l];return t&&t.visible}t.isVisible=s,t.makeData=function(e){var t=n.list({_fullLayout:e},"x",!0),r=e.margin,a=[];if(!e._has("gl2d"))for(var i=0;i<t.length;i++){var o=t[i];if(s(o)){a.push(o);var c=o[l];c._id=l+o._id,c._height=(e.height-r.b-r.t)*c.thickness,c._offsetShift=Math.floor(c.borderwidth/2)}}e._rangeSliderData=a},t.autoMarginOpts=function(e,t){var r=e._fullLayout,n=t[l],s=t._id.charAt(0),c=0,u=0;return"bottom"===t.side&&(c=t._depth,t.title.text!==r._dfltTitle[s]&&(u=1.5*t.title.font.size+10+n._offsetShift,u+=(t.title.text.match(a.BR_TAG_ALL)||[]).length*t.title.font.size*o)),{x:0,y:t._counterDomainMin,l:0,r:0,t:0,b:n._height+c+Math.max(r.margin.b,u),pad:i.extraPad+2*n._offsetShift}}},3137:function(e,t,r){"use strict";var n=r(1828),a=r(5148),i=r(7850),o=r(549);e.exports={moduleType:"component",name:"rangeslider",schema:{subplots:{xaxis:{rangeslider:n.extendFlat({},a,{yaxis:i})}}},layoutAttributes:r(5148),handleDefaults:r(6377),calcAutorange:r(8443),draw:r(2413),isVisible:o.isVisible,makeData:o.makeData,autoMarginOpts:o.autoMarginOpts}},7850:function(e){"use strict";e.exports={_isSubplotObj:!0,rangemode:{valType:"enumerated",values:["auto","fixed","match"],dflt:"match",editType:"calc"},range:{valType:"info_array",items:[{valType:"any",editType:"plot"},{valType:"any",editType:"plot"}],editType:"plot"},editType:"calc"}},8389:function(e,t,r){"use strict";var n=r(215),a=r(2196).line,i=r(9952).P,o=r(1426).extendFlat,l=r(962).overrideAll,s=r(4467).templatedArray;r(4695),e.exports=l(s("selection",{type:{valType:"enumerated",values:["rect","path"]},xref:o({},n.xref,{}),yref:o({},n.yref,{}),x0:{valType:"any"},x1:{valType:"any"},y0:{valType:"any"},y1:{valType:"any"},path:{valType:"string",editType:"arraydraw"},opacity:{valType:"number",min:0,max:1,dflt:.7,editType:"arraydraw"},line:{color:a.color,width:o({},a.width,{min:1,dflt:1}),dash:o({},i,{dflt:"dot"})}}),"arraydraw","from-root")},4122:function(e){"use strict";e.exports={BENDPX:1.5,MINSELECT:12,SELECTDELAY:100,SELECTID:"-select"}},9402:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(5501),o=r(8389),l=r(477);function s(e,t,r){function i(r,a){return n.coerce(e,t,o,r,a)}var s=i("path"),c="path"!==i("type",s?"path":"rect");c&&delete t.path,i("opacity"),i("line.color"),i("line.width"),i("line.dash");for(var u=["x","y"],f=0;f<2;f++){var d,h,p,v=u[f],y={_fullLayout:r},g=a.coerceRef(e,t,y,v);if((d=a.getFromId(y,g))._selectionIndices.push(t._index),p=l.rangeToShapePosition(d),h=l.shapePositionToRange(d),c){var m=v+"0",x=v+"1",b=e[m],_=e[x];e[m]=h(e[m],!0),e[x]=h(e[x],!0),a.coercePosition(t,y,i,g,m),a.coercePosition(t,y,i,g,x);var w=t[m],T=t[x];void 0!==w&&void 0!==T&&(t[m]=p(w),t[x]=p(T),e[m]=b,e[x]=_)}}c&&n.noneOrAll(e,t,["x0","x1","y0","y1"])}e.exports=function(e,t){i(e,t,{name:"selections",handleItemDefaults:s});for(var r=t.selections,n=0;n<r.length;n++){var a=r[n];a&&void 0===a.path&&(void 0!==a.x0&&void 0!==a.x1&&void 0!==a.y0&&void 0!==a.y1||(t.selections[n]=null))}}},2485:function(e,t,r){"use strict";var n=r(165).readPaths,a=r(2359),i=r(1873).clearOutlineControllers,o=r(7901),l=r(1424),s=r(4467).arrayEditor,c=r(477),u=c.getPathString;function f(e){var t=e._fullLayout;for(var r in i(e),t._selectionLayer.selectAll("path").remove(),t._plots){var n=t._plots[r].selectionLayer;n&&n.selectAll("path").remove()}for(var a=0;a<t.selections.length;a++)h(e,a)}function d(e){return e._context.editSelection}function h(e,t){e._fullLayout._paperdiv.selectAll('.selectionlayer [data-index="'+t+'"]').remove();var r=c.makeSelectionsOptionsAndPlotinfo(e,t),i=r.options,h=r.plotinfo;i._input&&function(r){var c=u(e,i),y={"data-index":t,"fill-rule":"evenodd",d:c},g=i.opacity,m="rgba(0,0,0,0)",x=i.line.color||o.contrast(e._fullLayout.plot_bgcolor),b=i.line.width,_=i.line.dash;b||(b=5,_="solid");var w=d(e)&&e._fullLayout._activeSelectionIndex===t;w&&(m=e._fullLayout.activeselection.fillcolor,g=e._fullLayout.activeselection.opacity);for(var T=[],M=1;M>=0;M--){var k=r.append("path").attr(y).style("opacity",M?.1:g).call(o.stroke,x).call(o.fill,m).call(l.dashLine,M?"solid":_,M?4+b:b);if(p(k,e,i),w){var A=s(e.layout,"selections",i);k.style({cursor:"move"});var L={element:k.node(),plotinfo:h,gd:e,editHelpers:A,isActiveSelection:!0},S=n(c,e);a(S,k,L)}else k.style("pointer-events",M?"all":"none");T[M]=k}var O=T[0];T[1].node().addEventListener("click",(function(){return function(e,t){if(d(e)){var r=t.node(),n=+r.getAttribute("data-index");if(n>=0){if(n===e._fullLayout._activeSelectionIndex)return void v(e);e._fullLayout._activeSelectionIndex=n,e._fullLayout._deactivateSelection=v,f(e)}}}(e,O)}))}(e._fullLayout._selectionLayer)}function p(e,t,r){var n=r.xref+r.yref;l.setClipUrl(e,"clip"+t._fullLayout._uid+n,t)}function v(e){d(e)&&e._fullLayout._activeSelectionIndex>=0&&(i(e),delete e._fullLayout._activeSelectionIndex,f(e))}e.exports={draw:f,drawOne:h,activateLastSelection:function(e){if(d(e)){var t=e._fullLayout.selections.length-1;e._fullLayout._activeSelectionIndex=t,e._fullLayout._deactivateSelection=v,f(e)}}}},3777:function(e,t,r){"use strict";var n=r(9952).P,a=r(1426).extendFlat;e.exports={newselection:{mode:{valType:"enumerated",values:["immediate","gradual"],dflt:"immediate",editType:"none"},line:{color:{valType:"color",editType:"none"},width:{valType:"number",min:1,dflt:1,editType:"none"},dash:a({},n,{dflt:"dot",editType:"none"}),editType:"none"},editType:"none"},activeselection:{fillcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"none"},opacity:{valType:"number",min:0,max:1,dflt:.5,editType:"none"},editType:"none"}}},849:function(e){"use strict";e.exports=function(e,t,r){r("newselection.mode"),r("newselection.line.width")&&(r("newselection.line.color"),r("newselection.line.dash")),r("activeselection.fillcolor"),r("activeselection.opacity")}},5855:function(e,t,r){"use strict";var n=r(4505).selectMode,a=r(1873).clearOutline,i=r(165),o=i.readPaths,l=i.writePaths,s=i.fixDatesForPaths;e.exports=function(e,t){if(e.length){var r=e[0][0];if(r){var i=r.getAttribute("d"),c=t.gd,u=c._fullLayout.newselection,f=t.plotinfo,d=f.xaxis,h=f.yaxis,p=t.isActiveSelection,v=t.dragmode,y=(c.layout||{}).selections||[];if(!n(v)&&void 0!==p){var g=c._fullLayout._activeSelectionIndex;if(g<y.length)switch(c._fullLayout.selections[g].type){case"rect":v="select";break;case"path":v="lasso"}}var m,x=o(i,c,f,p),b={xref:d._id,yref:h._id,opacity:u.opacity,line:{color:u.line.color,width:u.line.width,dash:u.line.dash}};1===x.length&&(m=x[0]),m&&5===m.length&&"select"===v?(b.type="rect",b.x0=m[0][1],b.y0=m[0][2],b.x1=m[2][1],b.y1=m[2][2]):(b.type="path",d&&h&&s(x,d,h),b.path=l(x),m=null),a(c);for(var _=t.editHelpers,w=(_||{}).modifyItem,T=[],M=0;M<y.length;M++){var k=c._fullLayout.selections[M];if(k){if(T[M]=k._input,void 0!==p&&M===c._fullLayout._activeSelectionIndex){var A=b;switch(k.type){case"rect":w("x0",A.x0),w("x1",A.x1),w("y0",A.y0),w("y1",A.y1);break;case"path":w("path",A.path)}}}else T[M]=k}return void 0===p?(T.push(b),T):_?_.getUpdateObj():{}}}}},5549:function(e,t,r){"use strict";var n=r(1828).strTranslate;function a(e,t){switch(e.type){case"log":return e.p2d(t);case"date":return e.p2r(t,0,e.calendar);default:return e.p2r(t)}}e.exports={p2r:a,r2p:function(e,t){switch(e.type){case"log":return e.d2p(t);case"date":return e.r2p(t,0,e.calendar);default:return e.r2p(t)}},axValue:function(e){var t="y"===e._id.charAt(0)?1:0;return function(r){return a(e,r[t])}},getTransform:function(e){return n(e.xaxis._offset,e.yaxis._offset)}}},7322:function(e,t,r){"use strict";var n=r(2485),a=r(3937);e.exports={moduleType:"component",name:"selections",layoutAttributes:r(8389),supplyLayoutDefaults:r(9402),supplyDrawNewSelectionDefaults:r(849),includeBasePlot:r(6325)("selections"),draw:n.draw,drawOne:n.drawOne,reselect:a.reselect,prepSelect:a.prepSelect,clearOutline:a.clearOutline,clearSelectionsCache:a.clearSelectionsCache,selectOnClick:a.selectOnClick}},3937:function(e,t,r){"use strict";var n=r(2142),a=r(8258),i=r(3972),o=r(1424).dashStyle,l=r(7901),s=r(211),c=r(3469).makeEventData,u=r(4505),f=u.freeMode,d=u.rectMode,h=u.drawMode,p=u.openMode,v=u.selectMode,y=r(477),g=r(1459),m=r(2359),x=r(1873).clearOutline,b=r(165),_=b.handleEllipse,w=b.readPaths,T=r(551).newShapes,M=r(5855),k=r(2485).activateLastSelection,A=r(1828),L=A.sorterAsc,S=r(1082),O=r(9990),D=r(1675).getFromId,C=r(3306),P=r(1549).redrawReglTraces,I=r(4122),R=I.MINSELECT,z=S.filter,N=S.tester,E=r(5549),F=E.p2r,H=E.axValue,j=E.getTransform;function B(e){return void 0!==e.subplot}function Y(e,t,r,n,a,i,o){var l,s,c,u,f,d,h,v,y,g=t._hoverdata,x=t._fullLayout.clickmode.indexOf("event")>-1,b=[];if(function(e){return e&&Array.isArray(e)&&!0!==e[0].hoverOnBox}(g)){Z(e,t,i);var _=function(e,t){var r,n,a=e[0],i=-1,o=[];for(n=0;n<t.length;n++)if(r=t[n],a.fullData._expandedIndex===r.cd[0].trace._expandedIndex){if(!0===a.hoverOnBox)break;void 0!==a.pointNumber?i=a.pointNumber:void 0!==a.binNumber&&(i=a.binNumber,o=a.pointNumbers);break}return{pointNumber:i,pointNumbers:o,searchInfo:r}}(g,l=X(t,r,n,a));if(_.pointNumbers.length>0?function(e,t){var r,n,a,i=[];for(a=0;a<e.length;a++)(r=e[a]).cd[0].trace.selectedpoints&&r.cd[0].trace.selectedpoints.length>0&&i.push(r);if(1===i.length&&i[0]===t.searchInfo&&(n=t.searchInfo.cd[0].trace).selectedpoints.length===t.pointNumbers.length){for(a=0;a<t.pointNumbers.length;a++)if(n.selectedpoints.indexOf(t.pointNumbers[a])<0)return!1;return!0}return!1}(l,_):function(e){var t,r,n=0;for(r=0;r<e.length;r++)if((t=e[r].cd[0].trace).selectedpoints){if(t.selectedpoints.length>1)return!1;if((n+=t.selectedpoints.length)>1)return!1}return 1===n}(l)&&(d=K(_))){for(o&&o.remove(),y=0;y<l.length;y++)(s=l[y])._module.selectPoints(s,!1);Q(t,l),G(i),x&&de(t)}else{for(h=e.shiftKey&&(void 0!==d?d:K(_)),c=function(e,t,r){return{pointNumber:e,searchInfo:t,subtract:!!r}}(_.pointNumber,_.searchInfo,h),u=q(i.selectionDefs.concat([c])),y=0;y<l.length;y++)if(f=ee(l[y]._module.selectPoints(l[y],u),l[y]),b.length)for(var w=0;w<f.length;w++)b.push(f[w]);else b=f;if(Q(t,l,v={points:b}),c&&i&&i.selectionDefs.push(c),o){var T=i.mergedPolygons,M=p(i.dragmode);m(te(T,M),o,i)}x&&fe(t,v)}}}function U(e){return"pointNumber"in e&&"searchInfo"in e}function V(e){return{xmin:0,xmax:0,ymin:0,ymax:0,pts:[],contains:function(t,r,n,a){var i=e.searchInfo.cd[0].trace._expandedIndex;return a.cd[0].trace._expandedIndex===i&&n===e.pointNumber},isRect:!1,degenerate:!1,subtract:!!e.subtract}}function q(e){if(e.length){for(var t=[],r=U(e[0])?0:e[0][0][0],n=r,a=U(e[0])?0:e[0][0][1],i=a,o=0;o<e.length;o++)if(U(e[o]))t.push(V(e[o]));else{var l=N(e[o]);l.subtract=!!e[o].subtract,t.push(l),r=Math.min(r,l.xmin),n=Math.max(n,l.xmax),a=Math.min(a,l.ymin),i=Math.max(i,l.ymax)}return{xmin:r,xmax:n,ymin:a,ymax:i,pts:[],contains:function(e,r,n,a){for(var i=!1,o=0;o<t.length;o++)t[o].contains(e,r,n,a)&&(i=!t[o].subtract);return i},isRect:!1,degenerate:!1}}}function Z(e,t,r){var n=t._fullLayout,a=r.plotinfo,i=r.dragmode,o=n._lastSelectedSubplot&&n._lastSelectedSubplot===a.id,l=(e.shiftKey||e.altKey)&&!(h(i)&&p(i));o&&l&&a.selection&&a.selection.selectionDefs&&!r.selectionDefs?(r.selectionDefs=a.selection.selectionDefs,r.mergedPolygons=a.selection.mergedPolygons):l&&a.selection||G(r),o||(x(t),n._lastSelectedSubplot=a.id)}function G(e,t){var r=e.dragmode,n=e.plotinfo,a=e.gd;(function(e){return e._fullLayout._activeShapeIndex>=0})(a)&&a._fullLayout._deactivateShape(a),function(e){return e._fullLayout._activeSelectionIndex>=0}(a)&&a._fullLayout._deactivateSelection(a);var o=a._fullLayout._zoomlayer,l=h(r),s=v(r);if(l||s){var c,u,f=o.selectAll(".select-outline-"+n.id);f&&a._fullLayout._outlining&&(l&&(c=T(f,e)),c&&i.call("_guiRelayout",a,{shapes:c}),s&&!B(e)&&(u=M(f,e)),u&&(a._fullLayout._noEmitSelectedAtStart=!0,i.call("_guiRelayout",a,{selections:u}).then((function(){t&&k(a)}))),a._fullLayout._outlining=!1)}n.selection={},n.selection.selectionDefs=e.selectionDefs=[],n.selection.mergedPolygons=e.mergedPolygons=[]}function W(e){return e._id}function X(e,t,r,n){if(!e.calcdata)return[];var a,i,o,l=[],s=t.map(W),c=r.map(W);for(o=0;o<e.calcdata.length;o++)if(!0===(i=(a=e.calcdata[o])[0].trace).visible&&i._module&&i._module.selectPoints)if(!B({subplot:n})||i.subplot!==n&&i.geo!==n)if("splom"===i.type){if(i._xaxes[s[0]]&&i._yaxes[c[0]]){var u=J(i._module,a,t[0],r[0]);u.scene=e._fullLayout._splomScenes[i.uid],l.push(u)}}else if("sankey"===i.type){var f=J(i._module,a,t[0],r[0]);l.push(f)}else{if(-1===s.indexOf(i.xaxis))continue;if(-1===c.indexOf(i.yaxis))continue;l.push(J(i._module,a,D(e,i.xaxis),D(e,i.yaxis)))}else l.push(J(i._module,a,t[0],r[0]));return l}function J(e,t,r,n){return{_module:e,cd:t,xaxis:r,yaxis:n}}function K(e){var t=e.searchInfo.cd[0].trace,r=e.pointNumber,n=e.pointNumbers,a=n.length>0?n[0]:r;return!!t.selectedpoints&&t.selectedpoints.indexOf(a)>-1}function Q(e,t,r){var n,a;for(n=0;n<t.length;n++){var o=t[n].cd[0].trace._fullInput,l=e._fullLayout._tracePreGUI[o.uid]||{};void 0===l.selectedpoints&&(l.selectedpoints=o._input.selectedpoints||null)}if(r){var s=r.points||[];for(n=0;n<t.length;n++)(a=t[n].cd[0].trace)._input.selectedpoints=a._fullInput.selectedpoints=[],a._fullInput!==a&&(a.selectedpoints=[]);for(var c=0;c<s.length;c++){var u=s[c],f=u.data,d=u.fullData,h=u.pointIndex,p=u.pointIndices;p?([].push.apply(f.selectedpoints,p),a._fullInput!==a&&[].push.apply(d.selectedpoints,p)):(f.selectedpoints.push(h),a._fullInput!==a&&d.selectedpoints.push(h))}}else for(n=0;n<t.length;n++)delete(a=t[n].cd[0].trace).selectedpoints,delete a._input.selectedpoints,a._fullInput!==a&&delete a._fullInput.selectedpoints;!function(e,t){for(var r=!1,n=0;n<t.length;n++){var a=t[n],o=a.cd;i.traceIs(o[0].trace,"regl")&&(r=!0);var l=a._module,s=l.styleOnSelect||l.style;s&&(s(e,o,o[0].node3),o[0].nodeRangePlot3&&s(e,o,o[0].nodeRangePlot3))}r&&(C(e),P(e))}(e,t)}function $(e,t,r){for(var a=(r?n.difference:n.union)({regions:e},{regions:[t]}).regions.reverse(),i=0;i<a.length;i++){var o=a[i];o.subtract=le(o,a.slice(0,i))}return a}function ee(e,t){if(Array.isArray(e))for(var r=t.cd,n=t.cd[0].trace,a=0;a<e.length;a++)e[a]=c(e[a],n,r);return e}function te(e,t){for(var r=[],n=0;n<e.length;n++){r[n]=[];for(var a=0;a<e[n].length;a++){r[n][a]=[],r[n][a][0]=a?"L":"M";for(var i=0;i<e[n][a].length;i++)r[n][a].push(e[n][a][i])}t||r[n].push(["Z",r[n][0][1],r[n][0][2]])}return r}function re(e,t){for(var r,n,a=[],i=[],o=0;o<t.length;o++){var l=t[o];n=l._module.selectPoints(l,e),i.push(n),r=ee(n,l),a=a.concat(r)}return a}function ne(e,t,r,n,a){var i,o,l,s=!!n;a&&(i=a.plotinfo,o=a.xaxes[0]._id,l=a.yaxes[0]._id);var c=[],u=[],f=oe(e),d=e._fullLayout;if(i){var p=d._zoomlayer,y=d.dragmode,g=h(y),m=v(y);if(g||m){var x=D(e,o,"x"),b=D(e,l,"y");if(x&&b){var _=p.selectAll(".select-outline-"+i.id);if(_&&e._fullLayout._outlining&&_.length){for(var T=_[0][0].getAttribute("d"),M=w(T,e,i),k=[],A=0;A<M.length;A++){for(var L=M[A],S=[],O=0;O<L.length;O++)S.push([se(x,L[O][1]),se(b,L[O][2])]);S.xref=o,S.yref=l,S.subtract=le(S,k),k.push(S)}f=f.concat(k)}}}}var C=o&&l?[o+l]:d._subplots.cartesian;!function(e){var t=e.calcdata;if(t)for(var r=0;r<t.length;r++){var n=t[r][0].trace,a=e._fullLayout._splomScenes;if(a){var i=a[n.uid];i&&(i.selectBatch=[])}}}(e);for(var P={},I=0;I<C.length;I++){var R=C[I],z=R.indexOf("y"),N=R.slice(0,z),E=R.slice(z),F=o&&l?r:void 0;if(F=ie(f,N,E,F)){var H=n;if(!s){var j=D(e,N,"x"),B=D(e,E,"y");H=X(e,[j],[B],R);for(var Y=0;Y<H.length;Y++){var U=H[Y],V=U.cd[0],q=V.trace;if("scattergl"===U._module.name&&!V.t.xpx){var Z=q.x,G=q.y,W=q._length;V.t.xpx=[],V.t.ypx=[];for(var J=0;J<W;J++)V.t.xpx[J]=j.c2p(Z[J]),V.t.ypx[J]=B.c2p(G[J])}"splom"===U._module.name&&(P[q.uid]||(P[q.uid]=!0))}}var K=re(F,H);c=c.concat(K),u=u.concat(H)}}var $={points:c};Q(e,u,$);var ee=d.clickmode.indexOf("event")>-1&&t;if(!i&&t){var te=oe(e,!0);if(te.length){var ne=te[0].xref,he=te[0].yref;if(ne&&he){var pe=ce(te);ue([D(e,ne,"x"),D(e,he,"y")])($,pe)}}e._fullLayout._noEmitSelectedAtStart?e._fullLayout._noEmitSelectedAtStart=!1:ee&&fe(e,$),d._reselect=!1}if(!i&&d._deselect){var ve=d._deselect;(function(e,t,r){for(var n=0;n<r.length;n++){var a=r[n];if(a.xaxis&&a.xaxis._id===e&&a.yaxis&&a.yaxis._id===t)return!0}return!1})(o=ve.xref,l=ve.yref,u)||ae(e,o,l,n),ee&&($.points.length?fe(e,$):de(e)),d._deselect=!1}return{eventData:$,selectionTesters:r}}function ae(e,t,r,n){n=X(e,[D(e,t,"x")],[D(e,r,"y")],t+r);for(var a=0;a<n.length;a++){var i=n[a];i._module.selectPoints(i,!1)}Q(e,n)}function ie(e,t,r,n){for(var a,i=0;i<e.length;i++){var o=e[i];t===o.xref&&r===o.yref&&(a?n=q(a=$(a,o,!!o.subtract)):(a=[o],n=N(o)))}return n}function oe(e,t){for(var r=[],n=e._fullLayout,a=n.selections,i=a.length,o=0;o<i;o++)if(!t||o===n._activeSelectionIndex){var l=a[o];if(l){var s,c,u,f,d,h=l.xref,p=l.yref,v=D(e,h,"x"),m=D(e,p,"y");if("rect"===l.type){d=[];var x=se(v,l.x0),b=se(v,l.x1),_=se(m,l.y0),w=se(m,l.y1);d=[[x,_],[x,w],[b,w],[b,_]],s=Math.min(x,b),c=Math.max(x,b),u=Math.min(_,w),f=Math.max(_,w),d.xmin=s,d.xmax=c,d.ymin=u,d.ymax=f,d.xref=h,d.yref=p,d.subtract=!1,d.isRect=!0,r.push(d)}else if("path"===l.type)for(var T=l.path.split("Z"),M=[],k=0;k<T.length;k++){var A=T[k];if(A){A+="Z";var L=y.extractPathCoords(A,g.paramIsX,"raw"),S=y.extractPathCoords(A,g.paramIsY,"raw");s=1/0,c=-1/0,u=1/0,f=-1/0,d=[];for(var O=0;O<L.length;O++){var C=se(v,L[O]),P=se(m,S[O]);d.push([C,P]),s=Math.min(C,s),c=Math.max(C,c),u=Math.min(P,u),f=Math.max(P,f)}d.xmin=s,d.xmax=c,d.ymin=u,d.ymax=f,d.xref=h,d.yref=p,d.subtract=le(d,M),M.push(d),r.push(d)}}}}return r}function le(e,t){for(var r=!1,n=0;n<t.length;n++)for(var i=t[n],o=0;o<e.length;o++)if(a(e[o],i)){r=!r;break}return r}function se(e,t){return"date"===e.type&&(t=t.replace("_"," ")),"log"===e.type?e.c2p(t):e.r2p(t,null,e.calendar)}function ce(e){for(var t=e.length,r=[],n=0;n<t;n++){var a=e[n];r=(r=r.concat(a)).concat([a[0]])}return(i=r).isRect=5===i.length&&i[0][0]===i[4][0]&&i[0][1]===i[4][1]&&i[0][0]===i[1][0]&&i[2][0]===i[3][0]&&i[0][1]===i[3][1]&&i[1][1]===i[2][1]||i[0][1]===i[1][1]&&i[2][1]===i[3][1]&&i[0][0]===i[3][0]&&i[1][0]===i[2][0],i.isRect&&(i.xmin=Math.min(i[0][0],i[2][0]),i.xmax=Math.max(i[0][0],i[2][0]),i.ymin=Math.min(i[0][1],i[2][1]),i.ymax=Math.max(i[0][1],i[2][1])),i;var i}function ue(e){return function(t,r){for(var n,a,i=0;i<e.length;i++){var o=e[i],l=o._id,s=l.charAt(0);if(r.isRect){n||(n={});var c=r[s+"min"],u=r[s+"max"];void 0!==c&&void 0!==u&&(n[l]=[F(o,c),F(o,u)].sort(L))}else a||(a={}),a[l]=r.map(H(o))}n&&(t.range=n),a&&(t.lassoPoints=a)}}function fe(e,t){t&&(t.selections=(e.layout||{}).selections||[]),e.emit("plotly_selected",t)}function de(e){e.emit("plotly_deselect",null)}e.exports={reselect:ne,prepSelect:function(e,t,r,n,a){var c=!B(n),u=f(a),y=d(a),g=p(a),x=h(a),b=v(a),w="drawcircle"===a,T="drawline"===a||w,M=n.gd,k=M._fullLayout,L=b&&"immediate"===k.newselection.mode&&c,S=k._zoomlayer,D=n.element.getBoundingClientRect(),C=n.plotinfo,P=j(C),E=t-D.left,F=r-D.top;k._calcInverseTransform(M);var H=A.apply3DTransform(k._invTransform)(E,F);E=H[0],F=H[1];var U,V,W,J,K,ee,ie,oe=k._invScaleX,le=k._invScaleY,se=E,he=F,pe="M"+E+","+F,ve=n.xaxes[0],ye=n.yaxes[0],ge=ve._length,me=ye._length,xe=e.altKey&&!(h(a)&&g);Z(e,M,n),u&&(U=z([[E,F]],I.BENDPX));var be=S.selectAll("path.select-outline-"+C.id).data([1]),_e=x?k.newshape:k.newselection;x&&(n.hasText=_e.label.text||_e.label.texttemplate);var we=x&&!g?_e.fillcolor:"rgba(0,0,0,0)",Te=_e.line.color||(c?l.contrast(M._fullLayout.plot_bgcolor):"#7f7f7f");be.enter().append("path").attr("class","select-outline select-outline-"+C.id).style({opacity:x?_e.opacity/2:1,"stroke-dasharray":o(_e.line.dash,_e.line.width),"stroke-width":_e.line.width+"px","shape-rendering":"crispEdges"}).call(l.stroke,Te).call(l.fill,we).attr("fill-rule","evenodd").classed("cursor-move",!!x).attr("transform",P).attr("d",pe+"Z");var Me=S.append("path").attr("class","zoombox-corners").style({fill:l.background,stroke:l.defaultLine,"stroke-width":1}).attr("transform",P).attr("d","M0,0Z");if(x&&n.hasText){var ke=S.select(".label-temp");ke.empty()&&(ke=S.append("g").classed("label-temp",!0).classed("select-outline",!0).style({opacity:.8}))}var Ae=k._uid+I.SELECTID,Le=[],Se=X(M,n.xaxes,n.yaxes,n.subplot);L&&!e.shiftKey&&(n._clearSubplotSelections=function(){if(c){var e=ve._id,t=ye._id;ae(M,e,t,Se);for(var r=(M.layout||{}).selections||[],n=[],a=!1,o=0;o<r.length;o++){var l=k.selections[o];l.xref!==e||l.yref!==t?n.push(r[o]):a=!0}a&&(M._fullLayout._noEmitSelectedAtStart=!0,i.call("_guiRelayout",M,{selections:n}))}});var Oe=function(e){var t=e.plotinfo;return t.fillRangeItems||ue(e.xaxes.concat(e.yaxes))}(n);n.moveFn=function(e,t){n._clearSubplotSelections&&(n._clearSubplotSelections(),n._clearSubplotSelections=void 0),se=Math.max(0,Math.min(ge,oe*e+E)),he=Math.max(0,Math.min(me,le*t+F));var r=Math.abs(se-E),a=Math.abs(he-F);if(y){var i,o,l;if(b){var s=k.selectdirection;switch(i="any"===s?a<Math.min(.6*r,R)?"h":r<Math.min(.6*a,R)?"v":"d":s){case"h":o=w?me/2:0,l=me;break;case"v":o=w?ge/2:0,l=ge}}if(x)switch(k.newshape.drawdirection){case"vertical":i="h",o=w?me/2:0,l=me;break;case"horizontal":i="v",o=w?ge/2:0,l=ge;break;case"ortho":r<a?(i="h",o=F,l=he):(i="v",o=E,l=se);break;default:i="d"}"h"===i?((J=T?_(w,[se,o],[se,l]):[[E,o],[E,l],[se,l],[se,o]]).xmin=T?se:Math.min(E,se),J.xmax=T?se:Math.max(E,se),J.ymin=Math.min(o,l),J.ymax=Math.max(o,l),Me.attr("d","M"+J.xmin+","+(F-R)+"h-4v"+2*R+"h4ZM"+(J.xmax-1)+","+(F-R)+"h4v"+2*R+"h-4Z")):"v"===i?((J=T?_(w,[o,he],[l,he]):[[o,F],[o,he],[l,he],[l,F]]).xmin=Math.min(o,l),J.xmax=Math.max(o,l),J.ymin=T?he:Math.min(F,he),J.ymax=T?he:Math.max(F,he),Me.attr("d","M"+(E-R)+","+J.ymin+"v-4h"+2*R+"v4ZM"+(E-R)+","+(J.ymax-1)+"v4h"+2*R+"v-4Z")):"d"===i&&((J=T?_(w,[E,F],[se,he]):[[E,F],[E,he],[se,he],[se,F]]).xmin=Math.min(E,se),J.xmax=Math.max(E,se),J.ymin=Math.min(F,he),J.ymax=Math.max(F,he),Me.attr("d","M0,0Z"))}else u&&(U.addPt([se,he]),J=U.filtered);if(n.selectionDefs&&n.selectionDefs.length?(W=$(n.mergedPolygons,J,xe),J.subtract=xe,V=q(n.selectionDefs.concat([J]))):(W=[J],V=N(J)),m(te(W,g),be,n),b){var c,f=ne(M,!1),d=f.eventData?f.eventData.points.slice():[];f=ne(M,!1,V,Se,n),V=f.selectionTesters,ie=f.eventData,c=U?U.filtered:ce(W),O.throttle(Ae,I.SELECTDELAY,(function(){for(var e=(Le=re(V,Se)).slice(),t=0;t<d.length;t++){for(var r=d[t],n=!1,a=0;a<e.length;a++)if(e[a].curveNumber===r.curveNumber&&e[a].pointNumber===r.pointNumber){n=!0;break}n||e.push(r)}e.length&&(ie||(ie={}),ie.points=e),Oe(ie,c),function(e,t){e.emit("plotly_selecting",t)}(M,ie)}))}},n.clickFn=function(e,t){if(Me.remove(),M._fullLayout._activeShapeIndex>=0)M._fullLayout._deactivateShape(M);else if(!x){var r=k.clickmode;O.done(Ae).then((function(){if(O.clear(Ae),2===e){for(be.remove(),K=0;K<Se.length;K++)(ee=Se[K])._module.selectPoints(ee,!1);if(Q(M,Se),G(n),de(M),Se.length){var a=Se[0].xaxis,o=Se[0].yaxis;if(a&&o){for(var l=[],c=M._fullLayout.selections,u=0;u<c.length;u++){var f=c[u];f&&(f.xref===a._id&&f.yref===o._id||l.push(f))}l.length<c.length&&(M._fullLayout._noEmitSelectedAtStart=!0,i.call("_guiRelayout",M,{selections:l}))}}}else r.indexOf("select")>-1&&Y(t,M,n.xaxes,n.yaxes,n.subplot,n,be),"event"===r&&fe(M,void 0);s.click(M,t)})).catch(A.error)}},n.doneFn=function(){Me.remove(),O.done(Ae).then((function(){O.clear(Ae),!L&&J&&n.selectionDefs&&(J.subtract=xe,n.selectionDefs.push(J),n.mergedPolygons.length=0,[].push.apply(n.mergedPolygons,W)),(L||x)&&G(n,L),n.doneFnCompleted&&n.doneFnCompleted(Le),b&&fe(M,ie)})).catch(A.error)}},clearOutline:x,clearSelectionsCache:G,selectOnClick:Y}},9827:function(e,t,r){"use strict";var n=r(215),a=r(1940),i=r(2196).line,o=r(9952).P,l=r(1426).extendFlat,s=r(4467).templatedArray,c=(r(4695),r(5386).R),u=r(7281);e.exports=s("shape",{visible:{valType:"boolean",dflt:!0,editType:"calc+arraydraw"},type:{valType:"enumerated",values:["circle","rect","path","line"],editType:"calc+arraydraw"},layer:{valType:"enumerated",values:["below","above"],dflt:"above",editType:"arraydraw"},xref:l({},n.xref,{}),xsizemode:{valType:"enumerated",values:["scaled","pixel"],dflt:"scaled",editType:"calc+arraydraw"},xanchor:{valType:"any",editType:"calc+arraydraw"},x0:{valType:"any",editType:"calc+arraydraw"},x1:{valType:"any",editType:"calc+arraydraw"},yref:l({},n.yref,{}),ysizemode:{valType:"enumerated",values:["scaled","pixel"],dflt:"scaled",editType:"calc+arraydraw"},yanchor:{valType:"any",editType:"calc+arraydraw"},y0:{valType:"any",editType:"calc+arraydraw"},y1:{valType:"any",editType:"calc+arraydraw"},path:{valType:"string",editType:"calc+arraydraw"},opacity:{valType:"number",min:0,max:1,dflt:1,editType:"arraydraw"},line:{color:l({},i.color,{editType:"arraydraw"}),width:l({},i.width,{editType:"calc+arraydraw"}),dash:l({},o,{editType:"arraydraw"}),editType:"calc+arraydraw"},fillcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"arraydraw"},fillrule:{valType:"enumerated",values:["evenodd","nonzero"],dflt:"evenodd",editType:"arraydraw"},editable:{valType:"boolean",dflt:!1,editType:"calc+arraydraw"},label:{text:{valType:"string",dflt:"",editType:"arraydraw"},texttemplate:c({},{keys:Object.keys(u)}),font:a({editType:"calc+arraydraw",colorEditType:"arraydraw"}),textposition:{valType:"enumerated",values:["top left","top center","top right","middle left","middle center","middle right","bottom left","bottom center","bottom right","start","middle","end"],editType:"arraydraw"},textangle:{valType:"angle",dflt:"auto",editType:"calc+arraydraw"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto",editType:"calc+arraydraw"},yanchor:{valType:"enumerated",values:["top","middle","bottom"],editType:"calc+arraydraw"},padding:{valType:"number",dflt:3,min:0,editType:"arraydraw"},editType:"arraydraw"},editType:"arraydraw"})},5627:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(1459),o=r(477);function l(e){return c(e.line.width,e.xsizemode,e.x0,e.x1,e.path,!1)}function s(e){return c(e.line.width,e.ysizemode,e.y0,e.y1,e.path,!0)}function c(e,t,r,a,l,s){var c=e/2,u=s;if("pixel"===t){var f=l?o.extractPathCoords(l,s?i.paramIsY:i.paramIsX):[r,a],d=n.aggNums(Math.max,null,f),h=n.aggNums(Math.min,null,f),p=h<0?Math.abs(h)+c:c,v=d>0?d+c:c;return{ppad:c,ppadplus:u?p:v,ppadminus:u?v:p}}return{ppad:c}}function u(e,t,r,n,a){var l="category"===e.type||"multicategory"===e.type?e.r2c:e.d2c;if(void 0!==t)return[l(t),l(r)];if(n){var s,c,u,f,d=1/0,h=-1/0,p=n.match(i.segmentRE);for("date"===e.type&&(l=o.decodeDate(l)),s=0;s<p.length;s++)void 0!==(c=a[p[s].charAt(0)].drawn)&&(!(u=p[s].substr(1).match(i.paramRE))||u.length<c||((f=l(u[c]))<d&&(d=f),f>h&&(h=f)));return h>=d?[d,h]:void 0}}e.exports=function(e){var t=e._fullLayout,r=n.filterVisible(t.shapes);if(r.length&&e._fullData.length)for(var o=0;o<r.length;o++){var c,f,d=r[o];d._extremes={};var h=a.getRefType(d.xref),p=a.getRefType(d.yref);if("paper"!==d.xref&&"domain"!==h){var v="pixel"===d.xsizemode?d.xanchor:d.x0,y="pixel"===d.xsizemode?d.xanchor:d.x1;(f=u(c=a.getFromId(e,d.xref),v,y,d.path,i.paramIsX))&&(d._extremes[c._id]=a.findExtremes(c,f,l(d)))}if("paper"!==d.yref&&"domain"!==p){var g="pixel"===d.ysizemode?d.yanchor:d.y0,m="pixel"===d.ysizemode?d.yanchor:d.y1;(f=u(c=a.getFromId(e,d.yref),g,m,d.path,i.paramIsY))&&(d._extremes[c._id]=a.findExtremes(c,f,s(d)))}}}},1459:function(e){"use strict";e.exports={segmentRE:/[MLHVQCTSZ][^MLHVQCTSZ]*/g,paramRE:/[^\s,]+/g,paramIsX:{M:{0:!0,drawn:0},L:{0:!0,drawn:0},H:{0:!0,drawn:0},V:{},Q:{0:!0,2:!0,drawn:2},C:{0:!0,2:!0,4:!0,drawn:4},T:{0:!0,drawn:0},S:{0:!0,2:!0,drawn:2},Z:{}},paramIsY:{M:{1:!0,drawn:1},L:{1:!0,drawn:1},H:{},V:{0:!0,drawn:0},Q:{1:!0,3:!0,drawn:3},C:{1:!0,3:!0,5:!0,drawn:5},T:{1:!0,drawn:1},S:{1:!0,3:!0,drawn:5},Z:{}},numParams:{M:2,L:2,H:1,V:1,Q:4,C:6,T:2,S:4,Z:0}}},4726:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(5501),o=r(9827),l=r(477);function s(e,t,r){function i(r,a){return n.coerce(e,t,o,r,a)}if(i("visible")){var s=i("path"),c=i("type",s?"path":"rect"),u="path"!==c;u&&delete t.path,i("editable"),i("layer"),i("opacity"),i("fillcolor"),i("fillrule"),i("line.width")&&(i("line.color"),i("line.dash"));for(var f=i("xsizemode"),d=i("ysizemode"),h=["x","y"],p=0;p<2;p++){var v,y,g,m=h[p],x=m+"anchor",b="x"===m?f:d,_={_fullLayout:r},w=a.coerceRef(e,t,_,m,void 0,"paper");if("range"===a.getRefType(w)?((v=a.getFromId(_,w))._shapeIndices.push(t._index),g=l.rangeToShapePosition(v),y=l.shapePositionToRange(v)):y=g=n.identity,u){var T=m+"0",M=m+"1",k=e[T],A=e[M];e[T]=y(e[T],!0),e[M]=y(e[M],!0),"pixel"===b?(i(T,0),i(M,10)):(a.coercePosition(t,_,i,w,T,.25),a.coercePosition(t,_,i,w,M,.75)),t[T]=g(t[T]),t[M]=g(t[M]),e[T]=k,e[M]=A}if("pixel"===b){var L=e[x];e[x]=y(e[x],!0),a.coercePosition(t,_,i,w,x,.25),t[x]=g(t[x]),e[x]=L}}u&&n.noneOrAll(e,t,["x0","x1","y0","y1"]);var S,O,D="line"===c;if(u&&(S=i("label.texttemplate")),S||(O=i("label.text")),O||S){i("label.textangle");var C=i("label.textposition",D?"middle":"middle center");i("label.xanchor"),i("label.yanchor",function(e,t){return e?"bottom":-1!==t.indexOf("top")?"top":-1!==t.indexOf("bottom")?"bottom":"middle"}(D,C)),i("label.padding"),n.coerceFont(i,"label.font",r.font)}}}e.exports=function(e,t){i(e,t,{name:"shapes",handleItemDefaults:s})}},8100:function(e,t,r){"use strict";var n=r(1828),a=r(9298),i=r(3893),o=r(1424),l=r(165).readPaths,s=r(477),c=s.getPathString,u=r(7281),f=r(8783).FROM_TL;e.exports=function(e,t,r,d){if(d.selectAll(".shape-label").remove(),r.label.text||r.label.texttemplate){var h;if(r.label.texttemplate){var p={};if("path"!==r.type){var v=a.getFromId(e,r.xref),y=a.getFromId(e,r.yref);for(var g in u){var m=u[g](r,v,y);void 0!==m&&(p[g]=m)}}h=n.texttemplateStringForShapes(r.label.texttemplate,{},e._fullLayout._d3locale,p)}else h=r.label.text;var x,b,_,w,T={"data-index":t},M=r.label.font,k=d.append("g").attr(T).classed("shape-label",!0).append("text").attr({"data-notex":1}).classed("shape-label-text",!0).text(h);if(r.path){var A=c(e,r),L=l(A,e);x=1/0,_=1/0,b=-1/0,w=-1/0;for(var S=0;S<L.length;S++)for(var O=0;O<L[S].length;O++)for(var D=L[S][O],C=1;C<D.length;C+=2){var P=D[C],I=D[C+1];x=Math.min(x,P),b=Math.max(b,P),_=Math.min(_,I),w=Math.max(w,I)}}else{var R=a.getFromId(e,r.xref),z=a.getRefType(r.xref),N=a.getFromId(e,r.yref),E=a.getRefType(r.yref),F=s.getDataToPixel(e,R,!1,z),H=s.getDataToPixel(e,N,!0,E);x=F(r.x0),b=F(r.x1),_=H(r.y0),w=H(r.y1)}var j=r.label.textangle;"auto"===j&&(j="line"===r.type?function(e,t,r,n){var a,i;return i=Math.abs(r-e),a=r>=e?t-n:n-t,-180/Math.PI*Math.atan2(a,i)}(x,_,b,w):0),k.call((function(t){return t.call(o.font,M).attr({}),i.convertToTspans(t,e),t}));var B=function(e,t,r,n,a,i,o){var l,s,c,u,d=a.label.textposition,h=a.label.textangle,p=a.label.padding,v=a.type,y=Math.PI/180*i,g=Math.sin(y),m=Math.cos(y),x=a.label.xanchor,b=a.label.yanchor;if("line"===v){"start"===d?(l=e,s=t):"end"===d?(l=r,s=n):(l=(e+r)/2,s=(t+n)/2),"auto"===x&&(x="start"===d?"auto"===h?r>e?"left":r<e?"right":"center":r>e?"right":r<e?"left":"center":"end"===d?"auto"===h?r>e?"right":r<e?"left":"center":r>e?"left":r<e?"right":"center":"center");var _={left:1,center:0,right:-1},w={bottom:-1,middle:0,top:1};if("auto"===h){var T=w[b];c=-p*g*T,u=p*m*T}else c=p*_[x],u=p*w[b];l+=c,s+=u}else c=p+3,-1!==d.indexOf("right")?(l=Math.max(e,r)-c,"auto"===x&&(x="right")):-1!==d.indexOf("left")?(l=Math.min(e,r)+c,"auto"===x&&(x="left")):(l=(e+r)/2,"auto"===x&&(x="center")),s=-1!==d.indexOf("top")?Math.min(t,n):-1!==d.indexOf("bottom")?Math.max(t,n):(t+n)/2,u=p,"bottom"===b?s-=u:"top"===b&&(s+=u);var M=f[b],k=a.label.font.size,A=o.height;return{textx:l+(A*M-k)*g,texty:s+-(A*M-k)*m,xanchor:x}}(x,_,b,w,r,j,o.bBox(k.node())),Y=B.textx,U=B.texty,V=B.xanchor;k.attr({"text-anchor":{left:"start",center:"middle",right:"end"}[V],y:U,x:Y,transform:"rotate("+j+","+Y+","+U+")"}).call(i.positionText,Y,U)}}},2359:function(e,t,r){"use strict";var n=r(1828).strTranslate,a=r(8569),i=r(4505),o=i.drawMode,l=i.selectMode,s=r(3972),c=r(7901),u=r(9995),f=u.i000,d=u.i090,h=u.i180,p=u.i270,v=r(1873).clearOutlineControllers,y=r(165),g=y.pointsOnRectangle,m=y.pointsOnEllipse,x=y.writePaths,b=r(551).newShapes,_=r(551).createShapeObj,w=r(5855),T=r(8100);function M(e,t){var r,n,a,i=e[t][1],o=e[t][2],l=e.length;return n=e[r=(t+1)%l][1],a=e[r][2],n===i&&a===o&&(n=e[r=(t+2)%l][1],a=e[r][2]),[r,n,a]}e.exports=function e(t,r,i,u){u||(u=0);var y=i.gd;function k(){e(t,r,i,u++),(m(t[0])||i.hasText)&&A({redrawing:!0})}function A(e){var t={};void 0!==i.isActiveShape&&(i.isActiveShape=!1,t=b(r,i)),void 0!==i.isActiveSelection&&(i.isActiveSelection=!1,t=w(r,i),y._fullLayout._reselect=!0),Object.keys(t).length&&s.call((e||{}).redrawing?"relayout":"_guiRelayout",y,t)}var L,S,O,D,C,P=y._fullLayout._zoomlayer,I=i.dragmode,R=o(I),z=l(I);if((R||z)&&(y._fullLayout._outlining=!0),v(y),r.attr("d",x(t)),u||!i.isActiveShape&&!i.isActiveSelection||(C=function(e,t){for(var r=0;r<t.length;r++){var n=t[r];e[r]=[];for(var a=0;a<n.length;a++){e[r][a]=[];for(var i=0;i<n[a].length;i++)e[r][a][i]=n[a][i]}}return e}([],t),function(e){L=[];for(var r=0;r<t.length;r++){var o=t[r],l=g(o),s=!l&&m(o);L[r]=[];for(var u=o.length,v=0;v<u;v++)if("Z"!==o[v][0]&&(!s||v===f||v===d||v===h||v===p)){var x,b=l&&i.isActiveSelection;b&&(x=M(o,v));var _=o[v][1],w=o[v][2],T=e.append(b?"rect":"circle").attr("data-i",r).attr("data-j",v).style({fill:c.background,stroke:c.defaultLine,"stroke-width":1,"shape-rendering":"crispEdges"});if(b){var k=x[1]-_,A=x[2]-w,S=A?5:Math.max(Math.min(25,Math.abs(k)-5),5),O=k?5:Math.max(Math.min(25,Math.abs(A)-5),5);T.classed(A?"cursor-ew-resize":"cursor-ns-resize",!0).attr("width",S).attr("height",O).attr("x",_-S/2).attr("y",w-O/2).attr("transform",n(k/2,A/2))}else T.classed("cursor-grab",!0).attr("r",5).attr("cx",_).attr("cy",w);L[r][v]={element:T.node(),gd:y,prepFn:F,doneFn:j,clickFn:B},a.init(L[r][v])}}}(P.append("g").attr("class","outline-controllers")),function(){if(S=[],t.length){var e=0;S[e]={element:r[0][0],gd:y,prepFn:U,doneFn:V,clickFn:q},a.init(S[e])}}()),R&&i.hasText){var N=P.select(".label-temp"),E=_(r,i,i.dragmode);T(y,"label-temp",E,N)}function F(e){O=+e.srcElement.getAttribute("data-i"),D=+e.srcElement.getAttribute("data-j"),L[O][D].moveFn=H}function H(e,r){if(t.length){var n=C[O][D][1],a=C[O][D][2],o=t[O],l=o.length;if(g(o)){var s=e,c=r;i.isActiveSelection&&(M(o,D)[1]===o[D][1]?c=0:s=0);for(var u=0;u<l;u++)if(u!==D){var f=o[u];f[1]===o[D][1]&&(f[1]=n+s),f[2]===o[D][2]&&(f[2]=a+c)}if(o[D][1]=n+s,o[D][2]=a+c,!g(o))for(var d=0;d<l;d++)for(var h=0;h<o[d].length;h++)o[d][h]=C[O][d][h]}else o[D][1]=n+e,o[D][2]=a+r;k()}}function j(){A()}function B(e,r){if(2===e){O=+r.srcElement.getAttribute("data-i"),D=+r.srcElement.getAttribute("data-j");var n=t[O];g(n)||m(n)||function(){if(t.length&&t[O]&&t[O].length){for(var e=[],r=0;r<t[O].length;r++)r!==D&&e.push(t[O][r]);e.length>1&&(2!==e.length||"Z"!==e[1][0])&&(0===D&&(e[0][0]="M"),t[O]=e,k(),A())}}()}}function Y(e,r){!function(e,r){if(t.length)for(var n=0;n<t.length;n++)for(var a=0;a<t[n].length;a++)for(var i=0;i+2<t[n][a].length;i+=2)t[n][a][i+1]=C[n][a][i+1]+e,t[n][a][i+2]=C[n][a][i+2]+r}(e,r),k()}function U(e){(O=+e.srcElement.getAttribute("data-i"))||(O=0),S[O].moveFn=Y}function V(){A()}function q(e){2===e&&function(e){if(l(e._fullLayout.dragmode)){v(e);var t=e._fullLayout._activeSelectionIndex,r=(e.layout||{}).selections||[];if(t<r.length){for(var n=[],a=0;a<r.length;a++)a!==t&&n.push(r[a]);delete e._fullLayout._activeSelectionIndex;var i=e._fullLayout.selections[t];e._fullLayout._deselect={xref:i.xref,yref:i.yref},s.call("_guiRelayout",e,{selections:n})}}}(y)}}},4031:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(1828),o=r(9298),l=r(165).readPaths,s=r(2359),c=r(8100),u=r(1873).clearOutlineControllers,f=r(7901),d=r(1424),h=r(4467).arrayEditor,p=r(8569),v=r(6964),y=r(1459),g=r(477),m=g.getPathString;function x(e){var t=e._fullLayout;for(var r in t._shapeUpperLayer.selectAll("path").remove(),t._shapeLowerLayer.selectAll("path").remove(),t._shapeUpperLayer.selectAll("text").remove(),t._shapeLowerLayer.selectAll("text").remove(),t._plots){var n=t._plots[r].shapelayer;n&&(n.selectAll("path").remove(),n.selectAll("text").remove())}for(var a=0;a<t.shapes.length;a++)t.shapes[a].visible&&w(e,a)}function b(e){return!!e._fullLayout._outlining}function _(e){return!e._context.edits.shapePosition}function w(e,t){e._fullLayout._paperdiv.selectAll('.shapelayer [data-index="'+t+'"]').remove();var r=g.makeShapesOptionsAndPlotinfo(e,t),u=r.options,w=r.plotinfo;function A(r){var A=m(e,u),L={"data-index":t,"fill-rule":u.fillrule,d:A},S=u.opacity,O=u.fillcolor,D=u.line.width?u.line.color:"rgba(0,0,0,0)",C=u.line.width,P=u.line.dash;C||!0!==u.editable||(C=5,P="solid");var I="Z"!==A[A.length-1],R=_(e)&&u.editable&&e._fullLayout._activeShapeIndex===t;R&&(O=I?"rgba(0,0,0,0)":e._fullLayout.activeshape.fillcolor,S=e._fullLayout.activeshape.opacity);var z,N=r.append("g").classed("shape-group",!0).attr({"data-index":t}),E=N.append("path").attr(L).style("opacity",S).call(f.stroke,D).call(f.fill,O).call(d.dashLine,P,C);if(T(N,e,u),c(e,t,u,N),(R||e._context.edits.shapePosition)&&(z=h(e.layout,"shapes",u)),R){E.style({cursor:"move"});var F={element:E.node(),plotinfo:w,gd:e,editHelpers:z,hasText:u.label.text||u.label.texttemplate,isActiveShape:!0},H=l(A,e);s(H,E,F)}else e._context.edits.shapePosition?function(e,t,r,l,s,u){var f,h,x,_,w,k,A,L,S,O,D,C,P,I,R,z,N=10,E=10,F="pixel"===r.xsizemode,H="pixel"===r.ysizemode,j="line"===r.type,B="path"===r.type,Y=u.modifyItem,U=n.select(t.node().parentNode),V=o.getFromId(e,r.xref),q=o.getRefType(r.xref),Z=o.getFromId(e,r.yref),G=o.getRefType(r.yref),W=g.getDataToPixel(e,V,!1,q),X=g.getDataToPixel(e,Z,!0,G),J=g.getPixelToData(e,V,!1,q),K=g.getPixelToData(e,Z,!0,G),Q=ee(),$={element:Q.node(),gd:e,prepFn:ne,doneFn:ae,clickFn:ie};function ee(){return j?te():t}function te(){var e=10,n=Math.max(r.line.width,e),a=s.append("g").attr("data-index",l).attr("drag-helper",!0);a.append("path").attr("d",t.attr("d")).style({cursor:"move","stroke-width":n,"stroke-opacity":"0"});var i={"fill-opacity":"0"},o=Math.max(n/2,e);return a.append("circle").attr({"data-line-point":"start-point",cx:F?W(r.xanchor)+r.x0:W(r.x0),cy:H?X(r.yanchor)-r.y0:X(r.y0),r:o}).style(i).classed("cursor-grab",!0),a.append("circle").attr({"data-line-point":"end-point",cx:F?W(r.xanchor)+r.x1:W(r.x1),cy:H?X(r.yanchor)-r.y1:X(r.y1),r:o}).style(i).classed("cursor-grab",!0),a}function re(r){if(b(e))z=null;else if(j)z="path"===r.target.tagName?"move":"start-point"===r.target.attributes["data-line-point"].value?"resize-over-start-point":"resize-over-end-point";else{var n=$.element.getBoundingClientRect(),a=n.right-n.left,i=n.bottom-n.top,o=r.clientX-n.left,l=r.clientY-n.top,s=!B&&a>N&&i>E&&!r.shiftKey?p.getCursor(o/a,1-l/i):"move";v(t,s),z=s.split("-")[0]}}function ne(n){b(e)||(F&&(w=W(r.xanchor)),H&&(k=X(r.yanchor)),"path"===r.type?R=r.path:(f=F?r.x0:W(r.x0),h=H?r.y0:X(r.y0),x=F?r.x1:W(r.x1),_=H?r.y1:X(r.y1)),f<x?(S=f,P="x0",O=x,I="x1"):(S=x,P="x1",O=f,I="x0"),!H&&h<_||H&&h>_?(A=h,D="y0",L=_,C="y1"):(A=_,D="y1",L=h,C="y0"),re(n),se(s,r),ue(t,r,e),$.moveFn="move"===z?oe:le,$.altKey=n.altKey)}function ae(){b(e)||(v(t),ce(s),T(t,e,r),a.call("_guiRelayout",e,u.getUpdateObj()))}function ie(){b(e)||ce(s)}function oe(n,a){if("path"===r.type){var i=function(e){return e},o=i,u=i;F?Y("xanchor",r.xanchor=J(w+n)):(o=function(e){return J(W(e)+n)},V&&"date"===V.type&&(o=g.encodeDate(o))),H?Y("yanchor",r.yanchor=K(k+a)):(u=function(e){return K(X(e)+a)},Z&&"date"===Z.type&&(u=g.encodeDate(u))),Y("path",r.path=M(R,o,u))}else F?Y("xanchor",r.xanchor=J(w+n)):(Y("x0",r.x0=J(f+n)),Y("x1",r.x1=J(x+n))),H?Y("yanchor",r.yanchor=K(k+a)):(Y("y0",r.y0=K(h+a)),Y("y1",r.y1=K(_+a)));t.attr("d",m(e,r)),se(s,r),c(e,l,r,U)}function le(n,a){if(B){var i=function(e){return e},o=i,u=i;F?Y("xanchor",r.xanchor=J(w+n)):(o=function(e){return J(W(e)+n)},V&&"date"===V.type&&(o=g.encodeDate(o))),H?Y("yanchor",r.yanchor=K(k+a)):(u=function(e){return K(X(e)+a)},Z&&"date"===Z.type&&(u=g.encodeDate(u))),Y("path",r.path=M(R,o,u))}else if(j){if("resize-over-start-point"===z){var d=f+n,p=H?h-a:h+a;Y("x0",r.x0=F?d:J(d)),Y("y0",r.y0=H?p:K(p))}else if("resize-over-end-point"===z){var v=x+n,y=H?_-a:_+a;Y("x1",r.x1=F?v:J(v)),Y("y1",r.y1=H?y:K(y))}}else{var b=function(e){return-1!==z.indexOf(e)},T=b("n"),q=b("s"),G=b("w"),Q=b("e"),$=T?A+a:A,ee=q?L+a:L,te=G?S+n:S,re=Q?O+n:O;H&&(T&&($=A-a),q&&(ee=L-a)),(!H&&ee-$>E||H&&$-ee>E)&&(Y(D,r[D]=H?$:K($)),Y(C,r[C]=H?ee:K(ee))),re-te>N&&(Y(P,r[P]=F?te:J(te)),Y(I,r[I]=F?re:J(re)))}t.attr("d",m(e,r)),se(s,r),c(e,l,r,U)}function se(e,t){function r(){var r="path"!==t.type,n=e.selectAll(".visual-cue").data([0]),a=1;n.enter().append("path").attr({fill:"#fff","fill-rule":"evenodd",stroke:"#000","stroke-width":a}).classed("visual-cue",!0);var o=W(F?t.xanchor:i.midRange(r?[t.x0,t.x1]:g.extractPathCoords(t.path,y.paramIsX))),l=X(H?t.yanchor:i.midRange(r?[t.y0,t.y1]:g.extractPathCoords(t.path,y.paramIsY)));if(o=g.roundPositionForSharpStrokeRendering(o,a),l=g.roundPositionForSharpStrokeRendering(l,a),F&&H){var s="M"+(o-1-a)+","+(l-1-a)+"h-8v2h8 v8h2v-8 h8v-2h-8 v-8h-2 Z";n.attr("d",s)}else if(F){var c="M"+(o-1-a)+","+(l-9-a)+"v18 h2 v-18 Z";n.attr("d",c)}else{var u="M"+(o-9-a)+","+(l-1-a)+"h18 v2 h-18 Z";n.attr("d",u)}}(F||H)&&r()}function ce(e){e.selectAll(".visual-cue").remove()}function ue(e,t,r){var n=t.xref,a=t.yref,i=o.getFromId(r,n),l=o.getFromId(r,a),s="";"paper"===n||i.autorange||(s+=n),"paper"===a||l.autorange||(s+=a),d.setClipUrl(e,s?"clip"+r._fullLayout._uid+s:null,r)}p.init($),Q.node().onmousemove=re}(e,E,u,t,r,z):!0===u.editable&&E.style("pointer-events",I||f.opacity(O)*S<=.5?"stroke":"all");E.node().addEventListener("click",(function(){return function(e,t){if(_(e)){var r=t.node(),n=+r.getAttribute("data-index");if(n>=0){if(n===e._fullLayout._activeShapeIndex)return void k(e);e._fullLayout._activeShapeIndex=n,e._fullLayout._deactivateShape=k,x(e)}}}(e,E)}))}u._input&&!1!==u.visible&&("below"!==u.layer?A(e._fullLayout._shapeUpperLayer):"paper"===u.xref||"paper"===u.yref?A(e._fullLayout._shapeLowerLayer):w._hadPlotinfo?A((w.mainplotinfo||w).shapelayer):A(e._fullLayout._shapeLowerLayer))}function T(e,t,r){var n=(r.xref+r.yref).replace(/paper/g,"").replace(/[xyz][1-9]* *domain/g,"");d.setClipUrl(e,n?"clip"+t._fullLayout._uid+n:null,t)}function M(e,t,r){return e.replace(y.segmentRE,(function(e){var n=0,a=e.charAt(0),i=y.paramIsX[a],o=y.paramIsY[a],l=y.numParams[a];return a+e.substr(1).replace(y.paramRE,(function(e){return n>=l||(i[n]?e=t(e):o[n]&&(e=r(e)),n++),e}))}))}function k(e){_(e)&&e._fullLayout._activeShapeIndex>=0&&(u(e),delete e._fullLayout._activeShapeIndex,x(e))}e.exports={draw:x,drawOne:w,eraseActiveShape:function(e){if(_(e)){u(e);var t=e._fullLayout._activeShapeIndex,r=(e.layout||{}).shapes||[];if(t<r.length){for(var n=[],i=0;i<r.length;i++)i!==t&&n.push(r[i]);delete e._fullLayout._activeShapeIndex,a.call("_guiRelayout",e,{shapes:n})}}},drawLabel:c}},9241:function(e,t,r){"use strict";var n=r(1940),a=r(9952).P,i=r(1426).extendFlat,o=r(5386).R,l=r(7281);e.exports={newshape:{line:{color:{valType:"color",editType:"none"},width:{valType:"number",min:0,dflt:4,editType:"none"},dash:i({},a,{dflt:"solid",editType:"none"}),editType:"none"},fillcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"none"},fillrule:{valType:"enumerated",values:["evenodd","nonzero"],dflt:"evenodd",editType:"none"},opacity:{valType:"number",min:0,max:1,dflt:1,editType:"none"},layer:{valType:"enumerated",values:["below","above"],dflt:"above",editType:"none"},drawdirection:{valType:"enumerated",values:["ortho","horizontal","vertical","diagonal"],dflt:"diagonal",editType:"none"},label:{text:{valType:"string",dflt:"",editType:"none"},texttemplate:o({newshape:!0,editType:"none"},{keys:Object.keys(l)}),font:n({editType:"none"}),textposition:{valType:"enumerated",values:["top left","top center","top right","middle left","middle center","middle right","bottom left","bottom center","bottom right","start","middle","end"],editType:"none"},textangle:{valType:"angle",dflt:"auto",editType:"none"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto",editType:"none"},yanchor:{valType:"enumerated",values:["top","middle","bottom"],editType:"none"},padding:{valType:"number",dflt:3,min:0,editType:"none"},editType:"none"},editType:"none"},activeshape:{fillcolor:{valType:"color",dflt:"rgb(255,0,255)",editType:"none"},opacity:{valType:"number",min:0,max:1,dflt:.5,editType:"none"},editType:"none"}}},9995:function(e){"use strict";e.exports={CIRCLE_SIDES:32,i000:0,i090:8,i180:16,i270:24,cos45:Math.cos(Math.PI/4),sin45:Math.sin(Math.PI/4),SQRT2:Math.sqrt(2)}},5547:function(e,t,r){"use strict";var n=r(7901),a=r(1828);e.exports=function(e,t,r){if(r("newshape.drawdirection"),r("newshape.layer"),r("newshape.fillcolor"),r("newshape.fillrule"),r("newshape.opacity"),r("newshape.line.width")){var i=(e||{}).plot_bgcolor||"#FFF";r("newshape.line.color",n.contrast(i)),r("newshape.line.dash")}var o="drawline"===e.dragmode,l=r("newshape.label.text"),s=r("newshape.label.texttemplate");if(l||s){r("newshape.label.textangle");var c=r("newshape.label.textposition",o?"middle":"middle center");r("newshape.label.xanchor"),r("newshape.label.yanchor",function(e,t){return e?"bottom":-1!==t.indexOf("top")?"top":-1!==t.indexOf("bottom")?"bottom":"middle"}(o,c)),r("newshape.label.padding"),a.coerceFont(r,"newshape.label.font",t.font)}r("activeshape.fillcolor"),r("activeshape.opacity")}},165:function(e,t,r){"use strict";var n=r(5616),a=r(9995),i=a.CIRCLE_SIDES,o=a.SQRT2,l=r(5549),s=l.p2r,c=l.r2p,u=[0,3,4,5,6,1,2],f=[0,3,4,1,2];function d(e,t){return Math.abs(e-t)<=1e-6}function h(e,t){var r=t[1]-e[1],n=t[2]-e[2];return Math.sqrt(r*r+n*n)}t.writePaths=function(e){var t=e.length;if(!t)return"M0,0Z";for(var r="",n=0;n<t;n++)for(var a=e[n].length,i=0;i<a;i++){var o=e[n][i][0];if("Z"===o)r+="Z";else for(var l=e[n][i].length,s=0;s<l;s++){var c=s;"Q"===o||"S"===o?c=f[s]:"C"===o&&(c=u[s]),r+=e[n][i][c],s>0&&s<l-1&&(r+=",")}}return r},t.readPaths=function(e,t,r,a){var o,l,u,f=n(e),d=[],h=-1,p=0,v=0,y=function(){l=p,u=v};y();for(var g=0;g<f.length;g++){var m,x,b,_,w=[],T=f[g][0],M=T;switch(T){case"M":h++,d[h]=[],p=+f[g][1],v=+f[g][2],w.push([M,p,v]),y();break;case"Q":case"S":m=+f[g][1],b=+f[g][2],p=+f[g][3],v=+f[g][4],w.push([M,p,v,m,b]);break;case"C":m=+f[g][1],b=+f[g][2],x=+f[g][3],_=+f[g][4],p=+f[g][5],v=+f[g][6],w.push([M,p,v,m,b,x,_]);break;case"T":case"L":p=+f[g][1],v=+f[g][2],w.push([M,p,v]);break;case"H":M="L",p=+f[g][1],w.push([M,p,v]);break;case"V":M="L",v=+f[g][1],w.push([M,p,v]);break;case"A":M="L";var k=+f[g][1],A=+f[g][2];+f[g][4]||(k=-k,A=-A);var L=p-k,S=v;for(o=1;o<=i/2;o++){var O=2*Math.PI*o/i;w.push([M,L+k*Math.cos(O),S+A*Math.sin(O)])}break;case"Z":p===l&&v===u||(p=l,v=u,w.push([M,p,v]))}for(var D=(r||{}).domain,C=t._fullLayout._size,P=r&&"pixel"===r.xsizemode,I=r&&"pixel"===r.ysizemode,R=!1===a,z=0;z<w.length;z++){for(o=0;o+2<7;o+=2){var N=w[z][o+1],E=w[z][o+2];void 0!==N&&void 0!==E&&(p=N,v=E,r&&(r.xaxis&&r.xaxis.p2r?(R&&(N-=r.xaxis._offset),N=P?c(r.xaxis,r.xanchor)+N:s(r.xaxis,N)):(R&&(N-=C.l),D?N=D.x[0]+N/C.w:N/=C.w),r.yaxis&&r.yaxis.p2r?(R&&(E-=r.yaxis._offset),E=I?c(r.yaxis,r.yanchor)-E:s(r.yaxis,E)):(R&&(E-=C.t),E=D?D.y[1]-E/C.h:1-E/C.h)),w[z][o+1]=N,w[z][o+2]=E)}d[h].push(w[z].slice())}}return d},t.pointsOnRectangle=function(e){if(5!==e.length)return!1;for(var t=1;t<3;t++){if(!d(e[0][t]-e[1][t],e[3][t]-e[2][t]))return!1;if(!d(e[0][t]-e[3][t],e[1][t]-e[2][t]))return!1}return!(!d(e[0][1],e[1][1])&&!d(e[0][1],e[3][1])||!(h(e[0],e[1])*h(e[0],e[3])))},t.pointsOnEllipse=function(e){var t=e.length;if(t!==i+1)return!1;t=i;for(var r=0;r<t;r++){var n=(2*t-r)%t,a=(t/2+n)%t,o=(t/2+r)%t;if(!d(h(e[r],e[o]),h(e[n],e[a])))return!1}return!0},t.handleEllipse=function(e,r,n){if(!e)return[r,n];var a=t.ellipseOver({x0:r[0],y0:r[1],x1:n[0],y1:n[1]}),l=(a.x1+a.x0)/2,s=(a.y1+a.y0)/2,c=(a.x1-a.x0)/2,u=(a.y1-a.y0)/2;c||(c=u/=o),u||(u=c/=o);for(var f=[],d=0;d<i;d++){var h=2*d*Math.PI/i;f.push([l+c*Math.cos(h),s+u*Math.sin(h)])}return f},t.ellipseOver=function(e){var t=e.x0,r=e.y0,n=e.x1,a=e.y1,i=n-t,l=a-r,s=((t-=i)+n)/2,c=((r-=l)+a)/2;return{x0:s-(i*=o),y0:c-(l*=o),x1:s+i,y1:c+l}},t.fixDatesForPaths=function(e,t,r){var n="date"===t.type,a="date"===r.type;if(!n&&!a)return e;for(var i=0;i<e.length;i++)for(var o=0;o<e[i].length;o++)for(var l=0;l+2<e[i][o].length;l+=2)n&&(e[i][o][l+1]=e[i][o][l+1].replace(" ","_")),a&&(e[i][o][l+2]=e[i][o][l+2].replace(" ","_"));return e}},551:function(e,t,r){"use strict";var n=r(4505),a=n.drawMode,i=n.openMode,o=r(9995),l=o.i000,s=o.i090,c=o.i180,u=o.i270,f=o.cos45,d=o.sin45,h=r(5549),p=h.p2r,v=h.r2p,y=r(1873).clearOutline,g=r(165),m=g.readPaths,x=g.writePaths,b=g.ellipseOver,_=g.fixDatesForPaths;function w(e,t,r){var n,a=e[0][0],o=t.gd,h=a.getAttribute("d"),y=o._fullLayout.newshape,g=t.plotinfo,w=t.isActiveShape,T=g.xaxis,M=g.yaxis,k=!!g.domain||!g.xaxis,A=!!g.domain||!g.yaxis,L=i(r),S=m(h,o,g,w),O={editable:!0,label:y.label,xref:k?"paper":T._id,yref:A?"paper":M._id,layer:y.layer,opacity:y.opacity,line:{color:y.line.color,width:y.line.width,dash:y.line.dash}};if(L||(O.fillcolor=y.fillcolor,O.fillrule=y.fillrule),1===S.length&&(n=S[0]),n&&5===n.length&&"drawrect"===r)O.type="rect",O.x0=n[0][1],O.y0=n[0][2],O.x1=n[2][1],O.y1=n[2][2];else if(n&&"drawline"===r)O.type="line",O.x0=n[0][1],O.y0=n[0][2],O.x1=n[1][1],O.y1=n[1][2];else if(n&&"drawcircle"===r){O.type="circle";var D=n[l][1],C=n[s][1],P=n[c][1],I=n[u][1],R=n[l][2],z=n[s][2],N=n[c][2],E=n[u][2],F=g.xaxis&&("date"===g.xaxis.type||"log"===g.xaxis.type),H=g.yaxis&&("date"===g.yaxis.type||"log"===g.yaxis.type);F&&(D=v(g.xaxis,D),C=v(g.xaxis,C),P=v(g.xaxis,P),I=v(g.xaxis,I)),H&&(R=v(g.yaxis,R),z=v(g.yaxis,z),N=v(g.yaxis,N),E=v(g.yaxis,E));var j=(C+I)/2,B=(R+N)/2,Y=b({x0:j,y0:B,x1:j+(I-C+P-D)/2*f,y1:B+(E-z+N-R)/2*d});F&&(Y.x0=p(g.xaxis,Y.x0),Y.x1=p(g.xaxis,Y.x1)),H&&(Y.y0=p(g.yaxis,Y.y0),Y.y1=p(g.yaxis,Y.y1)),O.x0=Y.x0,O.y0=Y.y0,O.x1=Y.x1,O.y1=Y.y1}else O.type="path",T&&M&&_(S,T,M),O.path=x(S),n=null;return O}e.exports={newShapes:function(e,t){if(e.length&&e[0][0]){var r=t.gd,n=t.isActiveShape,i=t.dragmode,o=(r.layout||{}).shapes||[];if(!a(i)&&void 0!==n){var l=r._fullLayout._activeShapeIndex;if(l<o.length)switch(r._fullLayout.shapes[l].type){case"rect":i="drawrect";break;case"circle":i="drawcircle";break;case"line":i="drawline";break;case"path":var s=o[l].path||"";i="Z"===s[s.length-1]?"drawclosedpath":"drawopenpath"}}var c=w(e,t,i);y(r);for(var u=t.editHelpers,f=(u||{}).modifyItem,d=[],h=0;h<o.length;h++){var p=r._fullLayout.shapes[h];if(d[h]=p._input,void 0!==n&&h===r._fullLayout._activeShapeIndex){var v=c;switch(p.type){case"line":case"rect":case"circle":f("x0",v.x0),f("x1",v.x1),f("y0",v.y0),f("y1",v.y1);break;case"path":f("path",v.path)}}}return void 0===n?(d.push(c),d):u?u.getUpdateObj():{}}},createShapeObj:w}},1873:function(e){"use strict";e.exports={clearOutlineControllers:function(e){var t=e._fullLayout._zoomlayer;t&&t.selectAll(".outline-controllers").remove()},clearOutline:function(e){var t=e._fullLayout._zoomlayer;t&&t.selectAll(".select-outline").remove(),e._fullLayout._outlining=!1}}},477:function(e,t,r){"use strict";var n=r(1459),a=r(1828),i=r(9298);t.rangeToShapePosition=function(e){return"log"===e.type?e.r2d:function(e){return e}},t.shapePositionToRange=function(e){return"log"===e.type?e.d2r:function(e){return e}},t.decodeDate=function(e){return function(t){return t.replace&&(t=t.replace("_"," ")),e(t)}},t.encodeDate=function(e){return function(t){return e(t).replace(" ","_")}},t.extractPathCoords=function(e,t,r){var i=[];return e.match(n.segmentRE).forEach((function(e){var o=t[e.charAt(0)].drawn;if(void 0!==o){var l=e.substr(1).match(n.paramRE);if(l&&!(l.length<o)){var s=l[o],c=r?s:a.cleanNumber(s);i.push(c)}}})),i},t.getDataToPixel=function(e,r,n,a){var i,o=e._fullLayout._size;if(r)if("domain"===a)i=function(e){return r._length*(n?1-e:e)+r._offset};else{var l=t.shapePositionToRange(r);i=function(e){return r._offset+r.r2p(l(e,!0))},"date"===r.type&&(i=t.decodeDate(i))}else i=n?function(e){return o.t+o.h*(1-e)}:function(e){return o.l+o.w*e};return i},t.getPixelToData=function(e,r,n,a){var i,o=e._fullLayout._size;if(r)if("domain"===a)i=function(e){var t=(e-r._offset)/r._length;return n?1-t:t};else{var l=t.rangeToShapePosition(r);i=function(e){return l(r.p2r(e-r._offset))}}else i=n?function(e){return 1-(e-o.t)/o.h}:function(e){return(e-o.l)/o.w};return i},t.roundPositionForSharpStrokeRendering=function(e,t){var r=1===Math.round(t%2),n=Math.round(e);return r?n+.5:n},t.makeShapesOptionsAndPlotinfo=function(e,t){var r=e._fullLayout.shapes[t]||{},n=e._fullLayout._plots[r.xref+r.yref];return n?n._hadPlotinfo=!0:(n={},r.xref&&"paper"!==r.xref&&(n.xaxis=e._fullLayout[r.xref+"axis"]),r.yref&&"paper"!==r.yref&&(n.yaxis=e._fullLayout[r.yref+"axis"])),n.xsizemode=r.xsizemode,n.ysizemode=r.ysizemode,n.xanchor=r.xanchor,n.yanchor=r.yanchor,{options:r,plotinfo:n}},t.makeSelectionsOptionsAndPlotinfo=function(e,t){var r=e._fullLayout.selections[t]||{},n=e._fullLayout._plots[r.xref+r.yref];return n?n._hadPlotinfo=!0:(n={},r.xref&&(n.xaxis=e._fullLayout[r.xref+"axis"]),r.yref&&(n.yaxis=e._fullLayout[r.yref+"axis"])),{options:r,plotinfo:n}},t.getPathString=function(e,r){var o,l,s,c,u,f,d,h,p=r.type,v=i.getRefType(r.xref),y=i.getRefType(r.yref),g=i.getFromId(e,r.xref),m=i.getFromId(e,r.yref),x=e._fullLayout._size;if(g?"domain"===v?l=function(e){return g._offset+g._length*e}:(o=t.shapePositionToRange(g),l=function(e){return g._offset+g.r2p(o(e,!0))}):l=function(e){return x.l+x.w*e},m?"domain"===y?c=function(e){return m._offset+m._length*(1-e)}:(s=t.shapePositionToRange(m),c=function(e){return m._offset+m.r2p(s(e,!0))}):c=function(e){return x.t+x.h*(1-e)},"path"===p)return g&&"date"===g.type&&(l=t.decodeDate(l)),m&&"date"===m.type&&(c=t.decodeDate(c)),function(e,t,r){var i=e.path,o=e.xsizemode,l=e.ysizemode,s=e.xanchor,c=e.yanchor;return i.replace(n.segmentRE,(function(e){var i=0,u=e.charAt(0),f=n.paramIsX[u],d=n.paramIsY[u],h=n.numParams[u],p=e.substr(1).replace(n.paramRE,(function(e){return f[i]?e="pixel"===o?t(s)+Number(e):t(e):d[i]&&(e="pixel"===l?r(c)-Number(e):r(e)),++i>h&&(e="X"),e}));return i>h&&(p=p.replace(/[\s,]*X.*/,""),a.log("Ignoring extra params in segment "+e)),u+p}))}(r,l,c);if("pixel"===r.xsizemode){var b=l(r.xanchor);u=b+r.x0,f=b+r.x1}else u=l(r.x0),f=l(r.x1);if("pixel"===r.ysizemode){var _=c(r.yanchor);d=_-r.y0,h=_-r.y1}else d=c(r.y0),h=c(r.y1);if("line"===p)return"M"+u+","+d+"L"+f+","+h;if("rect"===p)return"M"+u+","+d+"H"+f+"V"+h+"H"+u+"Z";var w=(u+f)/2,T=(d+h)/2,M=Math.abs(w-u),k=Math.abs(T-d),A="A"+M+","+k,L=w+M+","+T;return"M"+L+A+" 0 1,1 "+w+","+(T-k)+A+" 0 0,1 "+L+"Z"}},9853:function(e,t,r){"use strict";var n=r(4031);e.exports={moduleType:"component",name:"shapes",layoutAttributes:r(9827),supplyLayoutDefaults:r(4726),supplyDrawNewShapeDefaults:r(5547),includeBasePlot:r(6325)("shapes"),calcAutorange:r(5627),draw:n.draw,drawOne:n.drawOne}},7281:function(e){"use strict";function t(e,t){return t?t.d2l(e):e}function r(e,t){return t?t.l2d(e):e}function n(e,r){return t(e.x1,r)-t(e.x0,r)}function a(e,r,n){return t(e.y1,n)-t(e.y0,n)}e.exports={x0:function(e){return e.x0},x1:function(e){return e.x1},y0:function(e){return e.y0},y1:function(e){return e.y1},slope:function(e,t,r){return"line"!==e.type?void 0:a(e,0,r)/n(e,t)},dx:n,dy:a,width:function(e,t){return Math.abs(n(e,t))},height:function(e,t,r){return Math.abs(a(e,0,r))},length:function(e,t,r){return"line"!==e.type?void 0:Math.sqrt(Math.pow(n(e,t),2)+Math.pow(a(e,0,r),2))},xcenter:function(e,n){return r((t(e.x1,n)+t(e.x0,n))/2,n)},ycenter:function(e,n,a){return r((t(e.y1,a)+t(e.y0,a))/2,a)}}},5067:function(e,t,r){"use strict";var n=r(1940),a=r(5025),i=r(1426).extendDeepAll,o=r(962).overrideAll,l=r(5594),s=r(4467).templatedArray,c=r(8292),u=s("step",{visible:{valType:"boolean",dflt:!0},method:{valType:"enumerated",values:["restyle","relayout","animate","update","skip"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string"},value:{valType:"string"},execute:{valType:"boolean",dflt:!0}});e.exports=o(s("slider",{visible:{valType:"boolean",dflt:!0},active:{valType:"number",min:0,dflt:0},steps:u,lenmode:{valType:"enumerated",values:["fraction","pixels"],dflt:"fraction"},len:{valType:"number",min:0,dflt:1},x:{valType:"number",min:-2,max:3,dflt:0},pad:i(a({editType:"arraydraw"}),{},{t:{dflt:20}}),xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"left"},y:{valType:"number",min:-2,max:3,dflt:0},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},transition:{duration:{valType:"number",min:0,dflt:150},easing:{valType:"enumerated",values:l.transition.easing.values,dflt:"cubic-in-out"}},currentvalue:{visible:{valType:"boolean",dflt:!0},xanchor:{valType:"enumerated",values:["left","center","right"],dflt:"left"},offset:{valType:"number",dflt:10},prefix:{valType:"string"},suffix:{valType:"string"},font:n({})},font:n({}),activebgcolor:{valType:"color",dflt:c.gripBgActiveColor},bgcolor:{valType:"color",dflt:c.railBgColor},bordercolor:{valType:"color",dflt:c.railBorderColor},borderwidth:{valType:"number",min:0,dflt:c.railBorderWidth},ticklen:{valType:"number",min:0,dflt:c.tickLength},tickcolor:{valType:"color",dflt:c.tickColor},tickwidth:{valType:"number",min:0,dflt:1},minorticklen:{valType:"number",min:0,dflt:c.minorTickLength}}),"arraydraw","from-root")},8292:function(e){"use strict";e.exports={name:"sliders",containerClassName:"slider-container",groupClassName:"slider-group",inputAreaClass:"slider-input-area",railRectClass:"slider-rail-rect",railTouchRectClass:"slider-rail-touch-rect",gripRectClass:"slider-grip-rect",tickRectClass:"slider-tick-rect",inputProxyClass:"slider-input-proxy",labelsClass:"slider-labels",labelGroupClass:"slider-label-group",labelClass:"slider-label",currentValueClass:"slider-current-value",railHeight:5,menuIndexAttrName:"slider-active-index",autoMarginIdRoot:"slider-",minWidth:30,minHeight:30,textPadX:40,arrowOffsetX:4,railRadius:2,railWidth:5,railBorder:4,railBorderWidth:1,railBorderColor:"#bec8d9",railBgColor:"#f8fafc",railInset:8,stepInset:10,gripRadius:10,gripWidth:20,gripHeight:20,gripBorder:20,gripBorderWidth:1,gripBorderColor:"#bec8d9",gripBgColor:"#f6f8fa",gripBgActiveColor:"#dbdde0",labelPadding:8,labelOffset:0,tickWidth:1,tickColor:"#333",tickOffset:25,tickLength:7,minorTickOffset:25,minorTickColor:"#333",minorTickLength:4,currentValuePadding:8,currentValueInset:0}},2343:function(e,t,r){"use strict";var n=r(1828),a=r(5501),i=r(5067),o=r(8292).name,l=i.steps;function s(e,t,r){function o(r,a){return n.coerce(e,t,i,r,a)}for(var l=a(e,t,{name:"steps",handleItemDefaults:c}),s=0,u=0;u<l.length;u++)l[u].visible&&s++;if(s<2?t.visible=!1:o("visible")){t._stepCount=s;var f=t._visibleSteps=n.filterVisible(l);(l[o("active")]||{}).visible||(t.active=f[0]._index),o("x"),o("y"),n.noneOrAll(e,t,["x","y"]),o("xanchor"),o("yanchor"),o("len"),o("lenmode"),o("pad.t"),o("pad.r"),o("pad.b"),o("pad.l"),n.coerceFont(o,"font",r.font),o("currentvalue.visible")&&(o("currentvalue.xanchor"),o("currentvalue.prefix"),o("currentvalue.suffix"),o("currentvalue.offset"),n.coerceFont(o,"currentvalue.font",t.font)),o("transition.duration"),o("transition.easing"),o("bgcolor"),o("activebgcolor"),o("bordercolor"),o("borderwidth"),o("ticklen"),o("tickwidth"),o("tickcolor"),o("minorticklen")}}function c(e,t){function r(r,a){return n.coerce(e,t,l,r,a)}if("skip"===e.method||Array.isArray(e.args)?r("visible"):t.visible=!1){r("method"),r("args");var a=r("label","step-"+t._index);r("value",a),r("execute")}}e.exports=function(e,t){a(e,t,{name:o,handleItemDefaults:s})}},4504:function(e,t,r){"use strict";var n=r(9898),a=r(4875),i=r(7901),o=r(1424),l=r(1828),s=l.strTranslate,c=r(3893),u=r(4467).arrayEditor,f=r(8292),d=r(8783),h=d.LINE_SPACING,p=d.FROM_TL,v=d.FROM_BR;function y(e){return f.autoMarginIdRoot+e._index}function g(e){return e._index}function m(e,t){var r=o.tester.selectAll("g."+f.labelGroupClass).data(t._visibleSteps);r.enter().append("g").classed(f.labelGroupClass,!0);var i=0,s=0;r.each((function(e){var r=_(n.select(this),{step:e},t).node();if(r){var a=o.bBox(r);s=Math.max(s,a.height),i=Math.max(i,a.width)}})),r.remove();var u=t._dims={};u.inputAreaWidth=Math.max(f.railWidth,f.gripHeight);var d=e._fullLayout._size;u.lx=d.l+d.w*t.x,u.ly=d.t+d.h*(1-t.y),"fraction"===t.lenmode?u.outerLength=Math.round(d.w*t.len):u.outerLength=t.len,u.inputAreaStart=0,u.inputAreaLength=Math.round(u.outerLength-t.pad.l-t.pad.r);var h=(u.inputAreaLength-2*f.stepInset)/(t._stepCount-1),g=i+f.labelPadding;if(u.labelStride=Math.max(1,Math.ceil(g/h)),u.labelHeight=s,u.currentValueMaxWidth=0,u.currentValueHeight=0,u.currentValueTotalHeight=0,u.currentValueMaxLines=1,t.currentvalue.visible){var m=o.tester.append("g");r.each((function(e){var r=x(m,t,e.label),n=r.node()&&o.bBox(r.node())||{width:0,height:0},a=c.lineCount(r);u.currentValueMaxWidth=Math.max(u.currentValueMaxWidth,Math.ceil(n.width)),u.currentValueHeight=Math.max(u.currentValueHeight,Math.ceil(n.height)),u.currentValueMaxLines=Math.max(u.currentValueMaxLines,a)})),u.currentValueTotalHeight=u.currentValueHeight+t.currentvalue.offset,m.remove()}u.height=u.currentValueTotalHeight+f.tickOffset+t.ticklen+f.labelOffset+u.labelHeight+t.pad.t+t.pad.b;var b="left";l.isRightAnchor(t)&&(u.lx-=u.outerLength,b="right"),l.isCenterAnchor(t)&&(u.lx-=u.outerLength/2,b="center");var w="top";l.isBottomAnchor(t)&&(u.ly-=u.height,w="bottom"),l.isMiddleAnchor(t)&&(u.ly-=u.height/2,w="middle"),u.outerLength=Math.ceil(u.outerLength),u.height=Math.ceil(u.height),u.lx=Math.round(u.lx),u.ly=Math.round(u.ly);var T={y:t.y,b:u.height*v[w],t:u.height*p[w]};"fraction"===t.lenmode?(T.l=0,T.xl=t.x-t.len*p[b],T.r=0,T.xr=t.x+t.len*v[b]):(T.x=t.x,T.l=u.outerLength*p[b],T.r=u.outerLength*v[b]),a.autoMargin(e,y(t),T)}function x(e,t,r){if(t.currentvalue.visible){var n,a,i=t._dims;switch(t.currentvalue.xanchor){case"right":n=i.inputAreaLength-f.currentValueInset-i.currentValueMaxWidth,a="left";break;case"center":n=.5*i.inputAreaLength,a="middle";break;default:n=f.currentValueInset,a="left"}var s=l.ensureSingle(e,"text",f.labelClass,(function(e){e.attr({"text-anchor":a,"data-notex":1})})),u=t.currentvalue.prefix?t.currentvalue.prefix:"";if("string"==typeof r)u+=r;else{var d=t.steps[t.active].label,p=t._gd._fullLayout._meta;p&&(d=l.templateString(d,p)),u+=d}t.currentvalue.suffix&&(u+=t.currentvalue.suffix),s.call(o.font,t.currentvalue.font).text(u).call(c.convertToTspans,t._gd);var v=c.lineCount(s),y=(i.currentValueMaxLines+1-v)*t.currentvalue.font.size*h;return c.positionText(s,n,y),s}}function b(e,t,r){l.ensureSingle(e,"rect",f.gripRectClass,(function(n){n.call(k,t,e,r).style("pointer-events","all")})).attr({width:f.gripWidth,height:f.gripHeight,rx:f.gripRadius,ry:f.gripRadius}).call(i.stroke,r.bordercolor).call(i.fill,r.bgcolor).style("stroke-width",r.borderwidth+"px")}function _(e,t,r){var n=l.ensureSingle(e,"text",f.labelClass,(function(e){e.attr({"text-anchor":"middle","data-notex":1})})),a=t.step.label,i=r._gd._fullLayout._meta;return i&&(a=l.templateString(a,i)),n.call(o.font,r.font).text(a).call(c.convertToTspans,r._gd),n}function w(e,t){var r=l.ensureSingle(e,"g",f.labelsClass),a=t._dims,i=r.selectAll("g."+f.labelGroupClass).data(a.labelSteps);i.enter().append("g").classed(f.labelGroupClass,!0),i.exit().remove(),i.each((function(e){var r=n.select(this);r.call(_,e,t),o.setTranslate(r,S(t,e.fraction),f.tickOffset+t.ticklen+t.font.size*h+f.labelOffset+a.currentValueTotalHeight)}))}function T(e,t,r,n,a){var i=Math.round(n*(r._stepCount-1)),o=r._visibleSteps[i]._index;o!==r.active&&M(e,t,r,o,!0,a)}function M(e,t,r,n,i,o){var l=r.active;r.active=n,u(e.layout,f.name,r).applyUpdate("active",n);var s=r.steps[r.active];t.call(L,r,o),t.call(x,r),e.emit("plotly_sliderchange",{slider:r,step:r.steps[r.active],interaction:i,previousActive:l}),s&&s.method&&i&&(t._nextMethod?(t._nextMethod.step=s,t._nextMethod.doCallback=i,t._nextMethod.doTransition=o):(t._nextMethod={step:s,doCallback:i,doTransition:o},t._nextMethodRaf=window.requestAnimationFrame((function(){var r=t._nextMethod.step;r.method&&(r.execute&&a.executeAPICommand(e,r.method,r.args),t._nextMethod=null,t._nextMethodRaf=null)}))))}function k(e,t,r){if(!t._context.staticPlot){var a=r.node(),o=n.select(t);e.on("mousedown",s),e.on("touchstart",s)}function l(){return r.data()[0]}function s(){var e=l();t.emit("plotly_sliderstart",{slider:e});var s=r.select("."+f.gripRectClass);n.event.stopPropagation(),n.event.preventDefault(),s.call(i.fill,e.activebgcolor);var c=O(e,n.mouse(a)[0]);function u(){var e=l(),i=O(e,n.mouse(a)[0]);T(t,r,e,i,!1)}function d(){var e=l();e._dragging=!1,s.call(i.fill,e.bgcolor),o.on("mouseup",null),o.on("mousemove",null),o.on("touchend",null),o.on("touchmove",null),t.emit("plotly_sliderend",{slider:e,step:e.steps[e.active]})}T(t,r,e,c,!0),e._dragging=!0,o.on("mousemove",u),o.on("touchmove",u),o.on("mouseup",d),o.on("touchend",d)}}function A(e,t){var r=e.selectAll("rect."+f.tickRectClass).data(t._visibleSteps),a=t._dims;r.enter().append("rect").classed(f.tickRectClass,!0),r.exit().remove(),r.attr({width:t.tickwidth+"px","shape-rendering":"crispEdges"}),r.each((function(e,r){var l=r%a.labelStride==0,s=n.select(this);s.attr({height:l?t.ticklen:t.minorticklen}).call(i.fill,t.tickcolor),o.setTranslate(s,S(t,r/(t._stepCount-1))-.5*t.tickwidth,(l?f.tickOffset:f.minorTickOffset)+a.currentValueTotalHeight)}))}function L(e,t,r){for(var n=e.select("rect."+f.gripRectClass),a=0,i=0;i<t._stepCount;i++)if(t._visibleSteps[i]._index===t.active){a=i;break}var o=S(t,a/(t._stepCount-1));if(!t._invokingCommand){var l=n;r&&t.transition.duration>0&&(l=l.transition().duration(t.transition.duration).ease(t.transition.easing)),l.attr("transform",s(o-.5*f.gripWidth,t._dims.currentValueTotalHeight))}}function S(e,t){var r=e._dims;return r.inputAreaStart+f.stepInset+(r.inputAreaLength-2*f.stepInset)*Math.min(1,Math.max(0,t))}function O(e,t){var r=e._dims;return Math.min(1,Math.max(0,(t-f.stepInset-r.inputAreaStart)/(r.inputAreaLength-2*f.stepInset-2*r.inputAreaStart)))}function D(e,t,r){var n=r._dims,a=l.ensureSingle(e,"rect",f.railTouchRectClass,(function(n){n.call(k,t,e,r).style("pointer-events","all")}));a.attr({width:n.inputAreaLength,height:Math.max(n.inputAreaWidth,f.tickOffset+r.ticklen+n.labelHeight)}).call(i.fill,r.bgcolor).attr("opacity",0),o.setTranslate(a,0,n.currentValueTotalHeight)}function C(e,t){var r=t._dims,n=r.inputAreaLength-2*f.railInset,a=l.ensureSingle(e,"rect",f.railRectClass);a.attr({width:n,height:f.railWidth,rx:f.railRadius,ry:f.railRadius,"shape-rendering":"crispEdges"}).call(i.stroke,t.bordercolor).call(i.fill,t.bgcolor).style("stroke-width",t.borderwidth+"px"),o.setTranslate(a,f.railInset,.5*(r.inputAreaWidth-f.railWidth)+r.currentValueTotalHeight)}e.exports=function(e){var t=e._context.staticPlot,r=e._fullLayout,i=function(e,t){for(var r=e[f.name],n=[],a=0;a<r.length;a++){var i=r[a];i.visible&&(i._gd=t,n.push(i))}return n}(r,e),l=r._infolayer.selectAll("g."+f.containerClassName).data(i.length>0?[0]:[]);function s(t){t._commandObserver&&(t._commandObserver.remove(),delete t._commandObserver),a.autoMargin(e,y(t))}if(l.enter().append("g").classed(f.containerClassName,!0).style("cursor",t?null:"ew-resize"),l.exit().each((function(){n.select(this).selectAll("g."+f.groupClassName).each(s)})).remove(),0!==i.length){var c=l.selectAll("g."+f.groupClassName).data(i,g);c.enter().append("g").classed(f.groupClassName,!0),c.exit().each(s).remove();for(var u=0;u<i.length;u++){var d=i[u];m(e,d)}c.each((function(t){var r=n.select(this);!function(e){var t=e._dims;t.labelSteps=[];for(var r=e._stepCount,n=0;n<r;n+=t.labelStride)t.labelSteps.push({fraction:n/(r-1),step:e._visibleSteps[n]})}(t),a.manageCommandObserver(e,t,t._visibleSteps,(function(t){var n=r.data()[0];n.active!==t.index&&(n._dragging||M(e,r,n,t.index,!1,!0))})),function(e,t,r){(r.steps[r.active]||{}).visible||(r.active=r._visibleSteps[0]._index),t.call(x,r).call(C,r).call(w,r).call(A,r).call(D,e,r).call(b,e,r);var n=r._dims;o.setTranslate(t,n.lx+r.pad.l,n.ly+r.pad.t),t.call(L,r,!1),t.call(x,r)}(e,n.select(this),t)}))}}},3243:function(e,t,r){"use strict";var n=r(8292);e.exports={moduleType:"component",name:n.name,layoutAttributes:r(5067),supplyLayoutDefaults:r(2343),draw:r(4504)}},2998:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(4875),o=r(3972),l=r(1828),s=l.strTranslate,c=r(1424),u=r(7901),f=r(3893),d=r(7822),h=r(8783).OPPOSITE_SIDE,p=/ [XY][0-9]* /;e.exports={draw:function(e,t,r){var v,y=r.propContainer,g=r.propName,m=r.placeholder,x=r.traceIndex,b=r.avoid||{},_=r.attributes,w=r.transform,T=r.containerGroup,M=e._fullLayout,k=1,A=!1,L=y.title,S=(L&&L.text?L.text:"").trim(),O=L&&L.font?L.font:{},D=O.family,C=O.size,P=O.color;"title.text"===g?v="titleText":-1!==g.indexOf("axis")?v="axisTitleText":g.indexOf(!0)&&(v="colorbarTitleText");var I=e._context.edits[v];""===S?k=0:S.replace(p," % ")===m.replace(p," % ")&&(k=.2,A=!0,I||(S="")),r._meta?S=l.templateString(S,r._meta):M._meta&&(S=l.templateString(S,M._meta));var R,z=S||I;T||(T=l.ensureSingle(M._infolayer,"g","g-"+t),R=M._hColorbarMoveTitle);var N=T.selectAll("text").data(z?[0]:[]);if(N.enter().append("text"),N.text(S).attr("class",t),N.exit().remove(),!z)return T;function E(e){l.syncOrAsync([F,H],e)}function F(t){var r;return!w&&R&&(w={}),w?(r="",w.rotate&&(r+="rotate("+[w.rotate,_.x,_.y]+")"),(w.offset||R)&&(r+=s(0,(w.offset||0)-(R||0)))):r=null,t.attr("transform",r),t.style({"font-family":D,"font-size":n.round(C,2)+"px",fill:u.rgb(P),opacity:k*u.opacity(P),"font-weight":i.fontWeight}).attr(_).call(f.convertToTspans,e),i.previousPromises(e)}function H(t){var r=n.select(t.node().parentNode);if(b&&b.selection&&b.side&&S){r.attr("transform",null);var i=h[b.side],o="left"===b.side||"top"===b.side?-1:1,u=a(b.pad)?b.pad:2,f=c.bBox(r.node()),d={t:0,b:0,l:0,r:0},p=e._fullLayout._reservedMargin;for(var v in p)for(var g in p[v]){var m=p[v][g];d[g]=Math.max(d[g],m)}var x={left:d.l,top:d.t,right:M.width-d.r,bottom:M.height-d.b},_=b.maxShift||o*(x[b.side]-f[b.side]),w=0;if(_<0)w=_;else{var T=b.offsetLeft||0,k=b.offsetTop||0;f.left-=T,f.right-=T,f.top-=k,f.bottom-=k,b.selection.each((function(){var e=c.bBox(this);l.bBoxIntersect(f,e,u)&&(w=Math.max(w,o*(e[b.side]-f[i])+u))})),w=Math.min(_,w),y._titleScoot=Math.abs(w)}if(w>0||_<0){var A={left:[-w,0],right:[w,0],top:[0,-w],bottom:[0,w]}[b.side];r.attr("transform",s(A[0],A[1]))}}}return N.call(E),I&&(S?N.on(".opacity",null):(k=0,A=!0,N.text(m).on("mouseover.opacity",(function(){n.select(this).transition().duration(d.SHOW_PLACEHOLDER).style("opacity",1)})).on("mouseout.opacity",(function(){n.select(this).transition().duration(d.HIDE_PLACEHOLDER).style("opacity",0)}))),N.call(f.makeEditable,{gd:e}).on("edit",(function(t){void 0!==x?o.call("_guiRestyle",e,g,t,x):o.call("_guiRelayout",e,g,t)})).on("cancel",(function(){this.text(this.attr("data-unformatted")).call(E)})).on("input",(function(e){this.text(e||" ").call(f.positionText,_.x,_.y)}))),N.classed("js-placeholder",A),T}}},7163:function(e,t,r){"use strict";var n=r(1940),a=r(2399),i=r(1426).extendFlat,o=r(962).overrideAll,l=r(5025),s=r(4467).templatedArray,c=s("button",{visible:{valType:"boolean"},method:{valType:"enumerated",values:["restyle","relayout","animate","update","skip"],dflt:"restyle"},args:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},args2:{valType:"info_array",freeLength:!0,items:[{valType:"any"},{valType:"any"},{valType:"any"}]},label:{valType:"string",dflt:""},execute:{valType:"boolean",dflt:!0}});e.exports=o(s("updatemenu",{_arrayAttrRegexps:[/^updatemenus\[(0|[1-9][0-9]+)\]\.buttons/],visible:{valType:"boolean"},type:{valType:"enumerated",values:["dropdown","buttons"],dflt:"dropdown"},direction:{valType:"enumerated",values:["left","right","up","down"],dflt:"down"},active:{valType:"integer",min:-1,dflt:0},showactive:{valType:"boolean",dflt:!0},buttons:c,x:{valType:"number",min:-2,max:3,dflt:-.05},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"right"},y:{valType:"number",min:-2,max:3,dflt:1},yanchor:{valType:"enumerated",values:["auto","top","middle","bottom"],dflt:"top"},pad:i(l({editType:"arraydraw"}),{}),font:n({}),bgcolor:{valType:"color"},bordercolor:{valType:"color",dflt:a.borderLine},borderwidth:{valType:"number",min:0,dflt:1,editType:"arraydraw"}}),"arraydraw","from-root")},5909:function(e){"use strict";e.exports={name:"updatemenus",containerClassName:"updatemenu-container",headerGroupClassName:"updatemenu-header-group",headerClassName:"updatemenu-header",headerArrowClassName:"updatemenu-header-arrow",dropdownButtonGroupClassName:"updatemenu-dropdown-button-group",dropdownButtonClassName:"updatemenu-dropdown-button",buttonClassName:"updatemenu-button",itemRectClassName:"updatemenu-item-rect",itemTextClassName:"updatemenu-item-text",menuIndexAttrName:"updatemenu-active-index",autoMarginIdRoot:"updatemenu-",blankHeaderOpts:{label:" "},minWidth:30,minHeight:30,textPadX:24,arrowPadX:16,rx:2,ry:2,textOffsetX:12,textOffsetY:3,arrowOffsetX:4,gapButtonHeader:5,gapButton:2,activeColor:"#F4FAFF",hoverColor:"#F4FAFF",arrowSymbol:{left:"\u25c4",right:"\u25ba",up:"\u25b2",down:"\u25bc"}}},4897:function(e,t,r){"use strict";var n=r(1828),a=r(5501),i=r(7163),o=r(5909).name,l=i.buttons;function s(e,t,r){function o(r,a){return n.coerce(e,t,i,r,a)}o("visible",a(e,t,{name:"buttons",handleItemDefaults:c}).length>0)&&(o("active"),o("direction"),o("type"),o("showactive"),o("x"),o("y"),n.noneOrAll(e,t,["x","y"]),o("xanchor"),o("yanchor"),o("pad.t"),o("pad.r"),o("pad.b"),o("pad.l"),n.coerceFont(o,"font",r.font),o("bgcolor",r.paper_bgcolor),o("bordercolor"),o("borderwidth"))}function c(e,t){function r(r,a){return n.coerce(e,t,l,r,a)}r("visible","skip"===e.method||Array.isArray(e.args))&&(r("method"),r("args"),r("args2"),r("label"),r("execute"))}e.exports=function(e,t){a(e,t,{name:o,handleItemDefaults:s})}},3689:function(e,t,r){"use strict";var n=r(9898),a=r(4875),i=r(7901),o=r(1424),l=r(1828),s=r(3893),c=r(4467).arrayEditor,u=r(8783).LINE_SPACING,f=r(5909),d=r(5849);function h(e){return e._index}function p(e,t){return+e.attr(f.menuIndexAttrName)===t._index}function v(e,t,r,n,a,i,o,l){t.active=o,c(e.layout,f.name,t).applyUpdate("active",o),"buttons"===t.type?g(e,n,null,null,t):"dropdown"===t.type&&(a.attr(f.menuIndexAttrName,"-1"),y(e,n,a,i,t),l||g(e,n,a,i,t))}function y(e,t,r,n,a){var i=l.ensureSingle(t,"g",f.headerClassName,(function(e){e.style("pointer-events","all")})),s=a._dims,c=a.active,u=a.buttons[c]||f.blankHeaderOpts,d={y:a.pad.t,yPad:0,x:a.pad.l,xPad:0,index:0},h={width:s.headerWidth,height:s.headerHeight};i.call(m,a,u,e).call(A,a,d,h),l.ensureSingle(t,"text",f.headerArrowClassName,(function(e){e.attr("text-anchor","end").call(o.font,a.font).text(f.arrowSymbol[a.direction])})).attr({x:s.headerWidth-f.arrowOffsetX+a.pad.l,y:s.headerHeight/2+f.textOffsetY+a.pad.t}),i.on("click",(function(){r.call(L,String(p(r,a)?-1:a._index)),g(e,t,r,n,a)})),i.on("mouseover",(function(){i.call(w)})),i.on("mouseout",(function(){i.call(T,a)})),o.setTranslate(t,s.lx,s.ly)}function g(e,t,r,i,o){r||(r=t).attr("pointer-events","all");var s=function(e){return-1==+e.attr(f.menuIndexAttrName)}(r)&&"buttons"!==o.type?[]:o.buttons,c="dropdown"===o.type?f.dropdownButtonClassName:f.buttonClassName,u=r.selectAll("g."+c).data(l.filterVisible(s)),d=u.enter().append("g").classed(c,!0),h=u.exit();"dropdown"===o.type?(d.attr("opacity","0").transition().attr("opacity","1"),h.transition().attr("opacity","0").remove()):h.remove();var p=0,y=0,g=o._dims,x=-1!==["up","down"].indexOf(o.direction);"dropdown"===o.type&&(x?y=g.headerHeight+f.gapButtonHeader:p=g.headerWidth+f.gapButtonHeader),"dropdown"===o.type&&"up"===o.direction&&(y=-f.gapButtonHeader+f.gapButton-g.openHeight),"dropdown"===o.type&&"left"===o.direction&&(p=-f.gapButtonHeader+f.gapButton-g.openWidth);var b={x:g.lx+p+o.pad.l,y:g.ly+y+o.pad.t,yPad:f.gapButton,xPad:f.gapButton,index:0},M={l:b.x+o.borderwidth,t:b.y+o.borderwidth};u.each((function(l,s){var c=n.select(this);c.call(m,o,l,e).call(A,o,b),c.on("click",(function(){n.event.defaultPrevented||(l.execute&&(l.args2&&o.active===s?(v(e,o,0,t,r,i,-1),a.executeAPICommand(e,l.method,l.args2)):(v(e,o,0,t,r,i,s),a.executeAPICommand(e,l.method,l.args))),e.emit("plotly_buttonclicked",{menu:o,button:l,active:o.active}))})),c.on("mouseover",(function(){c.call(w)})),c.on("mouseout",(function(){c.call(T,o),u.call(_,o)}))})),u.call(_,o),x?(M.w=Math.max(g.openWidth,g.headerWidth),M.h=b.y-M.t):(M.w=b.x-M.l,M.h=Math.max(g.openHeight,g.headerHeight)),M.direction=o.direction,i&&(u.size()?function(e,t,r,n,a,i){var o,l,s,c=a.direction,u="up"===c||"down"===c,d=a._dims,h=a.active;if(u)for(l=0,s=0;s<h;s++)l+=d.heights[s]+f.gapButton;else for(o=0,s=0;s<h;s++)o+=d.widths[s]+f.gapButton;n.enable(i,o,l),n.hbar&&n.hbar.attr("opacity","0").transition().attr("opacity","1"),n.vbar&&n.vbar.attr("opacity","0").transition().attr("opacity","1")}(0,0,0,i,o,M):function(e){var t=!!e.hbar,r=!!e.vbar;t&&e.hbar.transition().attr("opacity","0").each("end",(function(){t=!1,r||e.disable()})),r&&e.vbar.transition().attr("opacity","0").each("end",(function(){r=!1,t||e.disable()}))}(i))}function m(e,t,r,n){e.call(x,t).call(b,t,r,n)}function x(e,t){l.ensureSingle(e,"rect",f.itemRectClassName,(function(e){e.attr({rx:f.rx,ry:f.ry,"shape-rendering":"crispEdges"})})).call(i.stroke,t.bordercolor).call(i.fill,t.bgcolor).style("stroke-width",t.borderwidth+"px")}function b(e,t,r,n){var a=l.ensureSingle(e,"text",f.itemTextClassName,(function(e){e.attr({"text-anchor":"start","data-notex":1})})),i=r.label,c=n._fullLayout._meta;c&&(i=l.templateString(i,c)),a.call(o.font,t.font).text(i).call(s.convertToTspans,n)}function _(e,t){var r=t.active;e.each((function(e,a){var o=n.select(this);a===r&&t.showactive&&o.select("rect."+f.itemRectClassName).call(i.fill,f.activeColor)}))}function w(e){e.select("rect."+f.itemRectClassName).call(i.fill,f.hoverColor)}function T(e,t){e.select("rect."+f.itemRectClassName).call(i.fill,t.bgcolor)}function M(e,t){var r=t._dims={width1:0,height1:0,heights:[],widths:[],totalWidth:0,totalHeight:0,openWidth:0,openHeight:0,lx:0,ly:0},i=o.tester.selectAll("g."+f.dropdownButtonClassName).data(l.filterVisible(t.buttons));i.enter().append("g").classed(f.dropdownButtonClassName,!0);var c=-1!==["up","down"].indexOf(t.direction);i.each((function(a,i){var l=n.select(this);l.call(m,t,a,e);var d=l.select("."+f.itemTextClassName),h=d.node()&&o.bBox(d.node()).width,p=Math.max(h+f.textPadX,f.minWidth),v=t.font.size*u,y=s.lineCount(d),g=Math.max(v*y,f.minHeight)+f.textOffsetY;g=Math.ceil(g),p=Math.ceil(p),r.widths[i]=p,r.heights[i]=g,r.height1=Math.max(r.height1,g),r.width1=Math.max(r.width1,p),c?(r.totalWidth=Math.max(r.totalWidth,p),r.openWidth=r.totalWidth,r.totalHeight+=g+f.gapButton,r.openHeight+=g+f.gapButton):(r.totalWidth+=p+f.gapButton,r.openWidth+=p+f.gapButton,r.totalHeight=Math.max(r.totalHeight,g),r.openHeight=r.totalHeight)})),c?r.totalHeight-=f.gapButton:r.totalWidth-=f.gapButton,r.headerWidth=r.width1+f.arrowPadX,r.headerHeight=r.height1,"dropdown"===t.type&&(c?(r.width1+=f.arrowPadX,r.totalHeight=r.height1):r.totalWidth=r.width1,r.totalWidth+=f.arrowPadX),i.remove();var d=r.totalWidth+t.pad.l+t.pad.r,h=r.totalHeight+t.pad.t+t.pad.b,p=e._fullLayout._size;r.lx=p.l+p.w*t.x,r.ly=p.t+p.h*(1-t.y);var v="left";l.isRightAnchor(t)&&(r.lx-=d,v="right"),l.isCenterAnchor(t)&&(r.lx-=d/2,v="center");var y="top";l.isBottomAnchor(t)&&(r.ly-=h,y="bottom"),l.isMiddleAnchor(t)&&(r.ly-=h/2,y="middle"),r.totalWidth=Math.ceil(r.totalWidth),r.totalHeight=Math.ceil(r.totalHeight),r.lx=Math.round(r.lx),r.ly=Math.round(r.ly),a.autoMargin(e,k(t),{x:t.x,y:t.y,l:d*({right:1,center:.5}[v]||0),r:d*({left:1,center:.5}[v]||0),b:h*({top:1,middle:.5}[y]||0),t:h*({bottom:1,middle:.5}[y]||0)})}function k(e){return f.autoMarginIdRoot+e._index}function A(e,t,r,n){n=n||{};var a=e.select("."+f.itemRectClassName),i=e.select("."+f.itemTextClassName),l=t.borderwidth,c=r.index,d=t._dims;o.setTranslate(e,l+r.x,l+r.y);var h=-1!==["up","down"].indexOf(t.direction),p=n.height||(h?d.heights[c]:d.height1);a.attr({x:0,y:0,width:n.width||(h?d.width1:d.widths[c]),height:p});var v=t.font.size*u,y=(s.lineCount(i)-1)*v/2;s.positionText(i,f.textOffsetX,p/2-y+f.textOffsetY),h?r.y+=d.heights[c]+r.yPad:r.x+=d.widths[c]+r.xPad,r.index++}function L(e,t){e.attr(f.menuIndexAttrName,t||"-1").selectAll("g."+f.dropdownButtonClassName).remove()}e.exports=function(e){var t=e._fullLayout,r=l.filterVisible(t[f.name]);function i(t){a.autoMargin(e,k(t))}var o=t._menulayer.selectAll("g."+f.containerClassName).data(r.length>0?[0]:[]);if(o.enter().append("g").classed(f.containerClassName,!0).style("cursor","pointer"),o.exit().each((function(){n.select(this).selectAll("g."+f.headerGroupClassName).each(i)})).remove(),0!==r.length){var s=o.selectAll("g."+f.headerGroupClassName).data(r,h);s.enter().append("g").classed(f.headerGroupClassName,!0);for(var c=l.ensureSingle(o,"g",f.dropdownButtonGroupClassName,(function(e){e.style("pointer-events","all")})),u=0;u<r.length;u++){var m=r[u];M(e,m)}var x="updatemenus"+t._uid,b=new d(e,c,x);s.enter().size()&&(c.node().parentNode.appendChild(c.node()),c.call(L)),s.exit().each((function(e){c.call(L),i(e)})).remove(),s.each((function(t){var r=n.select(this),i="dropdown"===t.type?c:null;a.manageCommandObserver(e,t,t.buttons,(function(n){v(e,t,t.buttons[n.index],r,i,b,n.index,!0)})),"dropdown"===t.type?(y(e,r,c,b,t),p(c,t)&&g(e,r,c,b,t)):g(e,r,null,null,t)}))}}},763:function(e,t,r){"use strict";var n=r(5909);e.exports={moduleType:"component",name:n.name,layoutAttributes:r(7163),supplyLayoutDefaults:r(4897),draw:r(3689)}},5849:function(e,t,r){"use strict";e.exports=l;var n=r(9898),a=r(7901),i=r(1424),o=r(1828);function l(e,t,r){this.gd=e,this.container=t,this.id=r,this.position=null,this.translateX=null,this.translateY=null,this.hbar=null,this.vbar=null,this.bg=this.container.selectAll("rect.scrollbox-bg").data([0]),this.bg.exit().on(".drag",null).on("wheel",null).remove(),this.bg.enter().append("rect").classed("scrollbox-bg",!0).style("pointer-events","all").attr({opacity:0,x:0,y:0,width:0,height:0})}l.barWidth=2,l.barLength=20,l.barRadius=2,l.barPad=1,l.barColor="#808BA4",l.prototype.enable=function(e,t,r){var o=this.gd._fullLayout,s=o.width,c=o.height;this.position=e;var u,f,d,h,p=this.position.l,v=this.position.w,y=this.position.t,g=this.position.h,m=this.position.direction,x="down"===m,b="left"===m,_="up"===m,w=v,T=g;x||b||"right"===m||_||(this.position.direction="down",x=!0),x||_?(f=(u=p)+w,x?(d=y,T=(h=Math.min(d+T,c))-d):T=(h=y+T)-(d=Math.max(h-T,0))):(h=(d=y)+T,b?w=(f=p+w)-(u=Math.max(f-w,0)):(u=p,w=(f=Math.min(u+w,s))-u)),this._box={l:u,t:d,w:w,h:T};var M=v>w,k=l.barLength+2*l.barPad,A=l.barWidth+2*l.barPad,L=p,S=y+g;S+A>c&&(S=c-A);var O=this.container.selectAll("rect.scrollbar-horizontal").data(M?[0]:[]);O.exit().on(".drag",null).remove(),O.enter().append("rect").classed("scrollbar-horizontal",!0).call(a.fill,l.barColor),M?(this.hbar=O.attr({rx:l.barRadius,ry:l.barRadius,x:L,y:S,width:k,height:A}),this._hbarXMin=L+k/2,this._hbarTranslateMax=w-k):(delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax);var D=g>T,C=l.barWidth+2*l.barPad,P=l.barLength+2*l.barPad,I=p+v,R=y;I+C>s&&(I=s-C);var z=this.container.selectAll("rect.scrollbar-vertical").data(D?[0]:[]);z.exit().on(".drag",null).remove(),z.enter().append("rect").classed("scrollbar-vertical",!0).call(a.fill,l.barColor),D?(this.vbar=z.attr({rx:l.barRadius,ry:l.barRadius,x:I,y:R,width:C,height:P}),this._vbarYMin=R+P/2,this._vbarTranslateMax=T-P):(delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax);var N=this.id,E=u-.5,F=D?f+C+.5:f+.5,H=d-.5,j=M?h+A+.5:h+.5,B=o._topdefs.selectAll("#"+N).data(M||D?[0]:[]);if(B.exit().remove(),B.enter().append("clipPath").attr("id",N).append("rect"),M||D?(this._clipRect=B.select("rect").attr({x:Math.floor(E),y:Math.floor(H),width:Math.ceil(F)-Math.floor(E),height:Math.ceil(j)-Math.floor(H)}),this.container.call(i.setClipUrl,N,this.gd),this.bg.attr({x:p,y:y,width:v,height:g})):(this.bg.attr({width:0,height:0}),this.container.on("wheel",null).on(".drag",null).call(i.setClipUrl,null),delete this._clipRect),M||D){var Y=n.behavior.drag().on("dragstart",(function(){n.event.sourceEvent.preventDefault()})).on("drag",this._onBoxDrag.bind(this));this.container.on("wheel",null).on("wheel",this._onBoxWheel.bind(this)).on(".drag",null).call(Y);var U=n.behavior.drag().on("dragstart",(function(){n.event.sourceEvent.preventDefault(),n.event.sourceEvent.stopPropagation()})).on("drag",this._onBarDrag.bind(this));M&&this.hbar.on(".drag",null).call(U),D&&this.vbar.on(".drag",null).call(U)}this.setTranslate(t,r)},l.prototype.disable=function(){(this.hbar||this.vbar)&&(this.bg.attr({width:0,height:0}),this.container.on("wheel",null).on(".drag",null).call(i.setClipUrl,null),delete this._clipRect),this.hbar&&(this.hbar.on(".drag",null),this.hbar.remove(),delete this.hbar,delete this._hbarXMin,delete this._hbarTranslateMax),this.vbar&&(this.vbar.on(".drag",null),this.vbar.remove(),delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax)},l.prototype._onBoxDrag=function(){var e=this.translateX,t=this.translateY;this.hbar&&(e-=n.event.dx),this.vbar&&(t-=n.event.dy),this.setTranslate(e,t)},l.prototype._onBoxWheel=function(){var e=this.translateX,t=this.translateY;this.hbar&&(e+=n.event.deltaY),this.vbar&&(t+=n.event.deltaY),this.setTranslate(e,t)},l.prototype._onBarDrag=function(){var e=this.translateX,t=this.translateY;if(this.hbar){var r=e+this._hbarXMin,a=r+this._hbarTranslateMax;e=(o.constrain(n.event.x,r,a)-r)/(a-r)*(this.position.w-this._box.w)}if(this.vbar){var i=t+this._vbarYMin,l=i+this._vbarTranslateMax;t=(o.constrain(n.event.y,i,l)-i)/(l-i)*(this.position.h-this._box.h)}this.setTranslate(e,t)},l.prototype.setTranslate=function(e,t){var r=this.position.w-this._box.w,n=this.position.h-this._box.h;if(e=o.constrain(e||0,0,r),t=o.constrain(t||0,0,n),this.translateX=e,this.translateY=t,this.container.call(i.setTranslate,this._box.l-this.position.l-e,this._box.t-this.position.t-t),this._clipRect&&this._clipRect.attr({x:Math.floor(this.position.l+e-.5),y:Math.floor(this.position.t+t-.5)}),this.hbar){var a=e/r;this.hbar.call(i.setTranslate,e+a*this._hbarTranslateMax,t)}if(this.vbar){var l=t/n;this.vbar.call(i.setTranslate,e,t+l*this._vbarTranslateMax)}}},8783:function(e){"use strict";e.exports={FROM_BL:{left:0,center:.5,right:1,bottom:0,middle:.5,top:1},FROM_TL:{left:0,center:.5,right:1,bottom:1,middle:.5,top:0},FROM_BR:{left:1,center:.5,right:0,bottom:0,middle:.5,top:1},LINE_SPACING:1.3,CAP_SHIFT:.7,MID_SHIFT:.35,OPPOSITE_SIDE:{left:"right",right:"left",top:"bottom",bottom:"top"}}},4695:function(e){"use strict";e.exports={axisRefDescription:function(e,t,r){return["If set to a",e,"axis id (e.g. *"+e+"* or","*"+e+"2*), the `"+e+"` position refers to a",e,"coordinate. If set to *paper*, the `"+e+"`","position refers to the distance from the",t,"of the plotting","area in normalized coordinates where *0* (*1*) corresponds to the",t,"("+r+"). If set to a",e,"axis ID followed by","*domain* (separated by a space), the position behaves like for","*paper*, but refers to the distance in fractions of the domain","length from the",t,"of the domain of that axis: e.g.,","*"+e+"2 domain* refers to the domain of the second",e," axis and a",e,"position of 0.5 refers to the","point between the",t,"and the",r,"of the domain of the","second",e,"axis."].join(" ")}}},1562:function(e){"use strict";e.exports={FORMAT_LINK:"https://github.com/d3/d3-format/tree/v1.4.5#d3-format",DATE_FORMAT_LINK:"https://github.com/d3/d3-time-format/tree/v2.2.3#locale_format"}},4808:function(e){"use strict";e.exports={COMPARISON_OPS:["=","!=","<",">=",">","<="],COMPARISON_OPS2:["=","<",">=",">","<="],INTERVAL_OPS:["[]","()","[)","(]","][",")(","](",")["],SET_OPS:["{}","}{"],CONSTRAINT_REDUCTION:{"=":"=","<":"<","<=":"<",">":">",">=":">","[]":"[]","()":"[]","[)":"[]","(]":"[]","][":"][",")(":"][","](":"][",")[":"]["}}},7822:function(e){"use strict";e.exports={SHOW_PLACEHOLDER:100,HIDE_PLACEHOLDER:1e3,DESELECTDIM:.2}},606:function(e){"use strict";e.exports={BADNUM:void 0,FP_SAFE:1e-4*Number.MAX_VALUE,ONEMAXYEAR:316224e5,ONEAVGYEAR:315576e5,ONEMINYEAR:31536e6,ONEMAXQUARTER:79488e5,ONEAVGQUARTER:78894e5,ONEMINQUARTER:76896e5,ONEMAXMONTH:26784e5,ONEAVGMONTH:26298e5,ONEMINMONTH:24192e5,ONEWEEK:6048e5,ONEDAY:864e5,ONEHOUR:36e5,ONEMIN:6e4,ONESEC:1e3,EPOCHJD:2440587.5,ALMOST_EQUAL:.999999,LOG_CLIP:10,MINUS_SIGN:"\u2212"}},7922:function(e,t){"use strict";t.xmlns="http://www.w3.org/2000/xmlns/",t.svg="http://www.w3.org/2000/svg",t.xlink="http://www.w3.org/1999/xlink",t.svgAttrs={xmlns:t.svg,"xmlns:xlink":t.xlink}},8729:function(e,t,r){"use strict";t.version=r(1506).version,r(7417),r(8847);for(var n=r(3972),a=t.register=n.register,i=r(641),o=Object.keys(i),l=0;l<o.length;l++){var s=o[l];"_"!==s.charAt(0)&&(t[s]=i[s]),a({moduleType:"apiMethod",name:s,fn:i[s]})}a(r(7368)),a([r(2199),r(211),r(2745),r(2468),r(7322),r(9853),r(8804),r(763),r(3243),r(3137),r(7218),r(3312),r(7369),r(1081),r(2311),r(4168)]),a([r(2177),r(7815)]),window.PlotlyLocales&&Array.isArray(window.PlotlyLocales)&&(a(window.PlotlyLocales),delete window.PlotlyLocales),t.Icons=r(4255);var c=r(211),u=r(4875);t.Plots={resize:u.resize,graphJson:u.graphJson,sendDataToCloud:u.sendDataToCloud},t.Fx={hover:c.hover,unhover:c.unhover,loneHover:c.loneHover,loneUnhover:c.loneUnhover},t.Snapshot=r(4511),t.PlotSchema=r(6281)},4255:function(e){"use strict";e.exports={undo:{width:857.1,height:1e3,path:"m857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z",transform:"matrix(1 0 0 -1 0 850)"},home:{width:928.6,height:1e3,path:"m786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z",transform:"matrix(1 0 0 -1 0 850)"},"camera-retro":{width:1e3,height:1e3,path:"m518 386q0 8-5 13t-13 5q-37 0-63-27t-26-63q0-8 5-13t13-5 12 5 5 13q0 23 16 38t38 16q8 0 13 5t5 13z m125-73q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m-572-320h858v71h-858v-71z m643 320q0 89-62 152t-152 62-151-62-63-152 63-151 151-63 152 63 62 151z m-571 358h214v72h-214v-72z m-72-107h858v143h-462l-36-71h-360v-72z m929 143v-714q0-30-21-51t-50-21h-858q-29 0-50 21t-21 51v714q0 30 21 51t50 21h858q29 0 50-21t21-51z",transform:"matrix(1 0 0 -1 0 850)"},zoombox:{width:1e3,height:1e3,path:"m1000-25l-250 251c40 63 63 138 63 218 0 224-182 406-407 406-224 0-406-182-406-406s183-406 407-406c80 0 155 22 218 62l250-250 125 125z m-812 250l0 438 437 0 0-438-437 0z m62 375l313 0 0-312-313 0 0 312z",transform:"matrix(1 0 0 -1 0 850)"},pan:{width:1e3,height:1e3,path:"m1000 350l-187 188 0-125-250 0 0 250 125 0-188 187-187-187 125 0 0-250-250 0 0 125-188-188 186-187 0 125 252 0 0-250-125 0 187-188 188 188-125 0 0 250 250 0 0-126 187 188z",transform:"matrix(1 0 0 -1 0 850)"},zoom_plus:{width:875,height:1e3,path:"m1 787l0-875 875 0 0 875-875 0z m687-500l-187 0 0-187-125 0 0 187-188 0 0 125 188 0 0 187 125 0 0-187 187 0 0-125z",transform:"matrix(1 0 0 -1 0 850)"},zoom_minus:{width:875,height:1e3,path:"m0 788l0-876 875 0 0 876-875 0z m688-500l-500 0 0 125 500 0 0-125z",transform:"matrix(1 0 0 -1 0 850)"},autoscale:{width:1e3,height:1e3,path:"m250 850l-187 0-63 0 0-62 0-188 63 0 0 188 187 0 0 62z m688 0l-188 0 0-62 188 0 0-188 62 0 0 188 0 62-62 0z m-875-938l0 188-63 0 0-188 0-62 63 0 187 0 0 62-187 0z m875 188l0-188-188 0 0-62 188 0 62 0 0 62 0 188-62 0z m-125 188l-1 0-93-94-156 156 156 156 92-93 2 0 0 250-250 0 0-2 93-92-156-156-156 156 94 92 0 2-250 0 0-250 0 0 93 93 157-156-157-156-93 94 0 0 0-250 250 0 0 0-94 93 156 157 156-157-93-93 0 0 250 0 0 250z",transform:"matrix(1 0 0 -1 0 850)"},tooltip_basic:{width:1500,height:1e3,path:"m375 725l0 0-375-375 375-374 0-1 1125 0 0 750-1125 0z",transform:"matrix(1 0 0 -1 0 850)"},tooltip_compare:{width:1125,height:1e3,path:"m187 786l0 2-187-188 188-187 0 0 937 0 0 373-938 0z m0-499l0 1-187-188 188-188 0 0 937 0 0 376-938-1z",transform:"matrix(1 0 0 -1 0 850)"},plotlylogo:{width:1542,height:1e3,path:"m0-10h182v-140h-182v140z m228 146h183v-286h-183v286z m225 714h182v-1000h-182v1000z m225-285h182v-715h-182v715z m225 142h183v-857h-183v857z m231-428h182v-429h-182v429z m225-291h183v-138h-183v138z",transform:"matrix(1 0 0 -1 0 850)"},"z-axis":{width:1e3,height:1e3,path:"m833 5l-17 108v41l-130-65 130-66c0 0 0 38 0 39 0-1 36-14 39-25 4-15-6-22-16-30-15-12-39-16-56-20-90-22-187-23-279-23-261 0-341 34-353 59 3 60 228 110 228 110-140-8-351-35-351-116 0-120 293-142 474-142 155 0 477 22 477 142 0 50-74 79-163 96z m-374 94c-58-5-99-21-99-40 0-24 65-43 144-43 79 0 143 19 143 43 0 19-42 34-98 40v216h87l-132 135-133-135h88v-216z m167 515h-136v1c16 16 31 34 46 52l84 109v54h-230v-71h124v-1c-16-17-28-32-44-51l-89-114v-51h245v72z",transform:"matrix(1 0 0 -1 0 850)"},"3d_rotate":{width:1e3,height:1e3,path:"m922 660c-5 4-9 7-14 11-359 263-580-31-580-31l-102 28 58-400c0 1 1 1 2 2 118 108 351 249 351 249s-62 27-100 42c88 83 222 183 347 122 16-8 30-17 44-27-2 1-4 2-6 4z m36-329c0 0 64 229-88 296-62 27-124 14-175-11 157-78 225-208 249-266 8-19 11-31 11-31 2 5 6 15 11 32-5-13-8-20-8-20z m-775-239c70-31 117-50 198-32-121 80-199 346-199 346l-96-15-58-12c0 0 55-226 155-287z m603 133l-317-139c0 0 4-4 19-14 7-5 24-15 24-15s-177-147-389 4c235-287 536-112 536-112l31-22 100 299-4-1z m-298-153c6-4 14-9 24-15 0 0-17 10-24 15z",transform:"matrix(1 0 0 -1 0 850)"},camera:{width:1e3,height:1e3,path:"m500 450c-83 0-150-67-150-150 0-83 67-150 150-150 83 0 150 67 150 150 0 83-67 150-150 150z m400 150h-120c-16 0-34 13-39 29l-31 93c-6 15-23 28-40 28h-340c-16 0-34-13-39-28l-31-94c-6-15-23-28-40-28h-120c-55 0-100-45-100-100v-450c0-55 45-100 100-100h800c55 0 100 45 100 100v450c0 55-45 100-100 100z m-400-550c-138 0-250 112-250 250 0 138 112 250 250 250 138 0 250-112 250-250 0-138-112-250-250-250z m365 380c-19 0-35 16-35 35 0 19 16 35 35 35 19 0 35-16 35-35 0-19-16-35-35-35z",transform:"matrix(1 0 0 -1 0 850)"},movie:{width:1e3,height:1e3,path:"m938 413l-188-125c0 37-17 71-44 94 64 38 107 107 107 187 0 121-98 219-219 219-121 0-219-98-219-219 0-61 25-117 66-156h-115c30 33 49 76 49 125 0 103-84 187-187 187s-188-84-188-187c0-57 26-107 65-141-38-22-65-62-65-109v-250c0-70 56-126 125-126h500c69 0 125 56 125 126l188-126c34 0 62 28 62 63v375c0 35-28 63-62 63z m-750 0c-69 0-125 56-125 125s56 125 125 125 125-56 125-125-56-125-125-125z m406-1c-87 0-157 70-157 157 0 86 70 156 157 156s156-70 156-156-70-157-156-157z",transform:"matrix(1 0 0 -1 0 850)"},question:{width:857.1,height:1e3,path:"m500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-14 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-16-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z",transform:"matrix(1 0 0 -1 0 850)"},disk:{width:857.1,height:1e3,path:"m214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-8 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z",transform:"matrix(1 0 0 -1 0 850)"},drawopenpath:{width:70,height:70,path:"M33.21,85.65a7.31,7.31,0,0,1-2.59-.48c-8.16-3.11-9.27-19.8-9.88-41.3-.1-3.58-.19-6.68-.35-9-.15-2.1-.67-3.48-1.43-3.79-2.13-.88-7.91,2.32-12,5.86L3,32.38c1.87-1.64,11.55-9.66,18.27-6.9,2.13.87,4.75,3.14,5.17,9,.17,2.43.26,5.59.36,9.25a224.17,224.17,0,0,0,1.5,23.4c1.54,10.76,4,12.22,4.48,12.4.84.32,2.79-.46,5.76-3.59L43,80.07C41.53,81.57,37.68,85.64,33.21,85.65ZM74.81,69a11.34,11.34,0,0,0,6.09-6.72L87.26,44.5,74.72,32,56.9,38.35c-2.37.86-5.57,3.42-6.61,6L38.65,72.14l8.42,8.43ZM55,46.27a7.91,7.91,0,0,1,3.64-3.17l14.8-5.3,8,8L76.11,60.6l-.06.19a6.37,6.37,0,0,1-3,3.43L48.25,74.59,44.62,71Zm16.57,7.82A6.9,6.9,0,1,0,64.64,61,6.91,6.91,0,0,0,71.54,54.09Zm-4.05,0a2.85,2.85,0,1,1-2.85-2.85A2.86,2.86,0,0,1,67.49,54.09Zm-4.13,5.22L60.5,56.45,44.26,72.7l2.86,2.86ZM97.83,35.67,84.14,22l-8.57,8.57L89.26,44.24Zm-13.69-8,8,8-2.85,2.85-8-8Z",transform:"matrix(1 0 0 1 -15 -15)"},drawclosedpath:{width:90,height:90,path:"M88.41,21.12a26.56,26.56,0,0,0-36.18,0l-2.07,2-2.07-2a26.57,26.57,0,0,0-36.18,0,23.74,23.74,0,0,0,0,34.8L48,90.12a3.22,3.22,0,0,0,4.42,0l36-34.21a23.73,23.73,0,0,0,0-34.79ZM84,51.24,50.16,83.35,16.35,51.25a17.28,17.28,0,0,1,0-25.47,20,20,0,0,1,27.3,0l4.29,4.07a3.23,3.23,0,0,0,4.44,0l4.29-4.07a20,20,0,0,1,27.3,0,17.27,17.27,0,0,1,0,25.46ZM66.76,47.68h-33v6.91h33ZM53.35,35H46.44V68h6.91Z",transform:"matrix(1 0 0 1 -5 -5)"},lasso:{width:1031,height:1e3,path:"m1018 538c-36 207-290 336-568 286-277-48-473-256-436-463 10-57 36-108 76-151-13-66 11-137 68-183 34-28 75-41 114-42l-55-70 0 0c-2-1-3-2-4-3-10-14-8-34 5-45 14-11 34-8 45 4 1 1 2 3 2 5l0 0 113 140c16 11 31 24 45 40 4 3 6 7 8 11 48-3 100 0 151 9 278 48 473 255 436 462z m-624-379c-80 14-149 48-197 96 42 42 109 47 156 9 33-26 47-66 41-105z m-187-74c-19 16-33 37-39 60 50-32 109-55 174-68-42-25-95-24-135 8z m360 75c-34-7-69-9-102-8 8 62-16 128-68 170-73 59-175 54-244-5-9 20-16 40-20 61-28 159 121 317 333 354s407-60 434-217c28-159-121-318-333-355z",transform:"matrix(1 0 0 -1 0 850)"},selectbox:{width:1e3,height:1e3,path:"m0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z",transform:"matrix(1 0 0 -1 0 850)"},drawline:{width:70,height:70,path:"M60.64,62.3a11.29,11.29,0,0,0,6.09-6.72l6.35-17.72L60.54,25.31l-17.82,6.4c-2.36.86-5.57,3.41-6.6,6L24.48,65.5l8.42,8.42ZM40.79,39.63a7.89,7.89,0,0,1,3.65-3.17l14.79-5.31,8,8L61.94,54l-.06.19a6.44,6.44,0,0,1-3,3.43L34.07,68l-3.62-3.63Zm16.57,7.81a6.9,6.9,0,1,0-6.89,6.9A6.9,6.9,0,0,0,57.36,47.44Zm-4,0a2.86,2.86,0,1,1-2.85-2.85A2.86,2.86,0,0,1,53.32,47.44Zm-4.13,5.22L46.33,49.8,30.08,66.05l2.86,2.86ZM83.65,29,70,15.34,61.4,23.9,75.09,37.59ZM70,21.06l8,8-2.84,2.85-8-8ZM87,80.49H10.67V87H87Z",transform:"matrix(1 0 0 1 -15 -15)"},drawrect:{width:80,height:80,path:"M78,22V79H21V22H78m9-9H12V88H87V13ZM68,46.22H31V54H68ZM53,32H45.22V69H53Z",transform:"matrix(1 0 0 1 -10 -10)"},drawcircle:{width:80,height:80,path:"M50,84.72C26.84,84.72,8,69.28,8,50.3S26.84,15.87,50,15.87,92,31.31,92,50.3,73.16,84.72,50,84.72Zm0-60.59c-18.6,0-33.74,11.74-33.74,26.17S31.4,76.46,50,76.46,83.74,64.72,83.74,50.3,68.6,24.13,50,24.13Zm17.15,22h-34v7.11h34Zm-13.8-13H46.24v34h7.11Z",transform:"matrix(1 0 0 1 -10 -10)"},eraseshape:{width:80,height:80,path:"M82.77,78H31.85L6,49.57,31.85,21.14H82.77a8.72,8.72,0,0,1,8.65,8.77V69.24A8.72,8.72,0,0,1,82.77,78ZM35.46,69.84H82.77a.57.57,0,0,0,.49-.6V29.91a.57.57,0,0,0-.49-.61H35.46L17,49.57Zm32.68-34.7-24,24,5,5,24-24Zm-19,.53-5,5,24,24,5-5Z",transform:"matrix(1 0 0 1 -10 -10)"},spikeline:{width:1e3,height:1e3,path:"M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z",transform:"matrix(1.5 0 0 -1.5 0 850)"},pencil:{width:1792,height:1792,path:"M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z",transform:"matrix(1 0 0 1 0 1)"},newplotlylogo:{name:"newplotlylogo",svg:["<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 132'>","<defs>"," <style>"," .cls-0{fill:#000;}"," .cls-1{fill:#FFF;}"," .cls-2{fill:#F26;}"," .cls-3{fill:#D69;}"," .cls-4{fill:#BAC;}"," .cls-5{fill:#9EF;}"," </style>","</defs>"," <title>plotly-logomark"," "," "," "," "," "," "," "," "," "," "," "," "," ",""].join("")}}},9863:function(e,t){"use strict";t.isLeftAnchor=function(e){return"left"===e.xanchor||"auto"===e.xanchor&&e.x<=1/3},t.isCenterAnchor=function(e){return"center"===e.xanchor||"auto"===e.xanchor&&e.x>1/3&&e.x<2/3},t.isRightAnchor=function(e){return"right"===e.xanchor||"auto"===e.xanchor&&e.x>=2/3},t.isTopAnchor=function(e){return"top"===e.yanchor||"auto"===e.yanchor&&e.y>=2/3},t.isMiddleAnchor=function(e){return"middle"===e.yanchor||"auto"===e.yanchor&&e.y>1/3&&e.y<2/3},t.isBottomAnchor=function(e){return"bottom"===e.yanchor||"auto"===e.yanchor&&e.y<=1/3}},6348:function(e,t,r){"use strict";var n=r(4872),a=n.mod,i=n.modHalf,o=Math.PI,l=2*o;function s(e){return Math.abs(e[1]-e[0])>l-1e-14}function c(e,t){return i(t-e,l)}function u(e,t){if(s(t))return!0;var r,n;t[0](n=a(n,l))&&(n+=l);var i=a(e,l),o=i+l;return i>=r&&i<=n||o>=r&&o<=n}function f(e,t,r,n,a,i,c){a=a||0,i=i||0;var u,f,d,h,p,v=s([r,n]);function y(e,t){return[e*Math.cos(t)+a,i-e*Math.sin(t)]}v?(u=0,f=o,d=l):r=a&&e<=i);var a,i},pathArc:function(e,t,r,n,a){return f(null,e,t,r,n,a,0)},pathSector:function(e,t,r,n,a){return f(null,e,t,r,n,a,1)},pathAnnulus:function(e,t,r,n,a,i){return f(e,t,r,n,a,i,1)}}},3627:function(e,t){"use strict";var r=Array.isArray,n=ArrayBuffer,a=DataView;function i(e){return n.isView(e)&&!(e instanceof a)}function o(e){return r(e)||i(e)}function l(e,t,r){if(o(e)){if(o(e[0])){for(var n=r,a=0;aa.max?t.set(r):t.set(+e)}},integer:{coerceFunction:function(e,t,r,a){e%1||!n(e)||void 0!==a.min&&ea.max?t.set(r):t.set(+e)}},string:{coerceFunction:function(e,t,r,n){if("string"!=typeof e){var a="number"==typeof e;!0!==n.strict&&a?t.set(String(e)):t.set(r)}else n.noBlank&&!e?t.set(r):t.set(e)}},color:{coerceFunction:function(e,t,r){a(e).isValid()?t.set(e):t.set(r)}},colorlist:{coerceFunction:function(e,t,r){Array.isArray(e)&&e.length&&e.every((function(e){return a(e).isValid()}))?t.set(e):t.set(r)}},colorscale:{coerceFunction:function(e,t,r){t.set(o.get(e,r))}},angle:{coerceFunction:function(e,t,r){"auto"===e?t.set("auto"):n(e)?t.set(f(+e,360)):t.set(r)}},subplotid:{coerceFunction:function(e,t,r,n){var a=n.regex||u(r);"string"==typeof e&&a.test(e)?t.set(e):t.set(r)},validateFunction:function(e,t){var r=t.dflt;return e===r||"string"==typeof e&&!!u(r).test(e)}},flaglist:{coerceFunction:function(e,t,r,n){if(-1===(n.extras||[]).indexOf(e))if("string"==typeof e){for(var a=e.split("+"),i=0;i=n&&e<=a?e:u}if("string"!=typeof e&&"number"!=typeof e)return u;e=String(e);var c=_(r),g=e.charAt(0);!c||"G"!==g&&"g"!==g||(e=e.substr(1),r="");var w=c&&"chinese"===r.substr(0,7),T=e.match(w?x:m);if(!T)return u;var M=T[1],k=T[3]||"1",A=Number(T[5]||1),L=Number(T[7]||0),S=Number(T[9]||0),O=Number(T[11]||0);if(c){if(2===M.length)return u;var D;M=Number(M);try{var C=y.getComponentMethod("calendars","getCal")(r);if(w){var P="i"===k.charAt(k.length-1);k=parseInt(k,10),D=C.newDate(M,C.toMonthIndex(M,k,P),A)}else D=C.newDate(M,Number(k),A)}catch(R){return u}return D?(D.toJD()-v)*f+L*d+S*h+O*p:u}M=2===M.length?(Number(M)+2e3-b)%100+b:Number(M),k-=1;var I=new Date(Date.UTC(2e3,k,A,L,S));return I.setUTCFullYear(M),I.getUTCMonth()!==k||I.getUTCDate()!==A?u:I.getTime()+O*p},n=t.MIN_MS=t.dateTime2ms("-9999"),a=t.MAX_MS=t.dateTime2ms("9999-12-31 23:59:59.9999"),t.isDateTime=function(e,r){return t.dateTime2ms(e,r)!==u};var T=90*f,M=3*d,k=5*h;function A(e,t,r,n,a){if((t||r||n||a)&&(e+=" "+w(t,2)+":"+w(r,2),(n||a)&&(e+=":"+w(n,2),a))){for(var i=4;a%10==0;)i-=1,a/=10;e+="."+w(a,i)}return e}t.ms2DateTime=function(e,t,r){if("number"!=typeof e||!(e>=n&&e<=a))return u;t||(t=0);var i,o,l,c,m,x,b=Math.floor(10*s(e+.05,1)),w=Math.round(e-b/10);if(_(r)){var L=Math.floor(w/f)+v,S=Math.floor(s(e,f));try{i=y.getComponentMethod("calendars","getCal")(r).fromJD(L).formatDate("yyyy-mm-dd")}catch(O){i=g("G%Y-%m-%d")(new Date(w))}if("-"===i.charAt(0))for(;i.length<11;)i="-0"+i.substr(1);else for(;i.length<10;)i="0"+i;o=t=n+f&&e<=a-f))return u;var t=Math.floor(10*s(e+.05,1)),r=new Date(Math.round(e-t/10));return A(i("%Y-%m-%d")(r),r.getHours(),r.getMinutes(),r.getSeconds(),10*r.getUTCMilliseconds()+t)},t.cleanDate=function(e,r,n){if(e===u)return r;if(t.isJSDate(e)||"number"==typeof e&&isFinite(e)){if(_(n))return l.error("JS Dates and milliseconds are incompatible with world calendars",e),r;if(!(e=t.ms2DateTimeLocal(+e))&&void 0!==r)return r}else if(!t.isDateTime(e,n))return l.error("unrecognized date",e),r;return e};var L=/%\d?f/g,S=/%h/g,O={1:"1",2:"1",3:"2",4:"2"};function D(e,t,r,n){e=e.replace(L,(function(e){var r=Math.min(+e.charAt(1)||6,6);return(t/1e3%1+2).toFixed(r).substr(2).replace(/0+$/,"")||"0"}));var a=new Date(Math.floor(t+.05));if(e=e.replace(S,(function(){return O[r("%q")(a)]})),_(n))try{e=y.getComponentMethod("calendars","worldCalFmt")(e,t,n)}catch(i){return"Invalid"}return r(e)(a)}var C=[59,59.9,59.99,59.999,59.9999];t.formatDate=function(e,t,r,n,a,i){if(a=_(a)&&a,!t)if("y"===r)t=i.year;else if("m"===r)t=i.month;else{if("d"!==r)return function(e,t){var r=s(e+.05,f),n=w(Math.floor(r/d),2)+":"+w(s(Math.floor(r/h),60),2);if("M"!==t){o(t)||(t=0);var a=(100+Math.min(s(e/p,60),C[t])).toFixed(t).substr(1);t>0&&(a=a.replace(/0+$/,"").replace(/[\.]$/,"")),n+=":"+a}return n}(e,r)+"\n"+D(i.dayMonthYear,e,n,a);t=i.dayMonth+"\n"+i.year}return D(t,e,n,a)};var P=3*f;t.incrementMonth=function(e,t,r){r=_(r)&&r;var n=s(e,f);if(e=Math.round(e-n),r)try{var a=Math.round(e/f)+v,i=y.getComponentMethod("calendars","getCal")(r),o=i.fromJD(a);return t%12?i.add(o,t,"m"):i.add(o,t/12,"y"),(o.toJD()-v)*f+n}catch(u){l.error("invalid ms "+e+" in calendar "+r)}var c=new Date(e+P);return c.setUTCMonth(c.getUTCMonth()+t)+n-P},t.findExactDates=function(e,t){for(var r,n,a=0,i=0,l=0,s=0,c=_(t)&&y.getComponentMethod("calendars","getCal")(t),u=0;u1||v<0||v>1?null:{x:e+s*v,y:t+f*v}}function s(e,t,r,n,a){var i=n*e+a*t;if(i<0)return n*n+a*a;if(i>r){var o=n-e,l=a-t;return o*o+l*l}var s=n*t-a*e;return s*s/r}t.segmentsIntersect=l,t.segmentDistance=function(e,t,r,n,a,i,o,c){if(l(e,t,r,n,a,i,o,c))return 0;var u=r-e,f=n-t,d=o-a,h=c-i,p=u*u+f*f,v=d*d+h*h,y=Math.min(s(u,f,p,a-e,i-t),s(u,f,p,o-e,c-t),s(d,h,v,e-a,t-i),s(d,h,v,r-a,n-i));return Math.sqrt(y)},t.getTextLocation=function(e,t,r,l){if(e===a&&l===i||(n={},a=e,i=l),n[r])return n[r];var s=e.getPointAtLength(o(r-l/2,t)),c=e.getPointAtLength(o(r+l/2,t)),u=Math.atan((c.y-s.y)/(c.x-s.x)),f=e.getPointAtLength(o(r,t)),d={x:(4*f.x+s.x+c.x)/6,y:(4*f.y+s.y+c.y)/6,theta:u};return n[r]=d,d},t.clearLocationCache=function(){a=null},t.getVisibleSegment=function(e,t,r){var n,a,i=t.left,o=t.right,l=t.top,s=t.bottom,c=0,u=e.getTotalLength(),f=u;function d(t){var r=e.getPointAtLength(t);0===t?n=r:t===u&&(a=r);var c=r.xo?r.x-o:0,f=r.ys?r.y-s:0;return Math.sqrt(c*c+f*f)}for(var h=d(c);h;){if((c+=h+r)>f)return;h=d(c)}for(h=d(f);h;){if(c>(f-=h+r))return;h=d(f)}return{min:c,max:f,len:f-c,total:u,isClosed:0===c&&f===u&&Math.abs(n.x-a.x)<.1&&Math.abs(n.y-a.y)<.1}},t.findPointOnPath=function(e,t,r,n){for(var a,i,o,l=(n=n||{}).pathLength||e.getTotalLength(),s=n.tolerance||.001,c=n.iterationLimit||30,u=e.getPointAtLength(0)[r]>e.getPointAtLength(l)[r]?-1:1,f=0,d=0,h=l;f0?h=a:d=a,f++}return i}},3389:function(e){"use strict";e.exports=function(e){return e}},9240:function(e){"use strict";e.exports=function(e,t){if(!t)return e;var r=1/Math.abs(t),n=r>1?(r*e+r*t)/r:e+t,a=String(n).length;if(a>16){var i=String(t).length;if(a>=String(e).length+i){var o=parseFloat(n).toPrecision(12);-1===o.indexOf("e+")&&(n=+o)}}return n}},1828:function(e,t,r){"use strict";var n=r(9898),a=r(4096).g0,i=r(721).WU,o=r(2770),l=r(606),s=l.FP_SAFE,c=-s,u=l.BADNUM,f=e.exports={};f.adjustFormat=function(e){return!e||/^\d[.]\df/.test(e)||/[.]\d%/.test(e)?e:"0.f"===e?"~f":/^\d%/.test(e)?"~%":/^\ds/.test(e)?"~s":!/^[~,.0$]/.test(e)&&/[&fps]/.test(e)?"~"+e:e};var d={};f.warnBadFormat=function(e){var t=String(e);d[t]||(d[t]=1,f.warn('encountered bad format: "'+t+'"'))},f.noFormat=function(e){return String(e)},f.numberFormat=function(e){var t;try{t=i(f.adjustFormat(e))}catch(r){return f.warnBadFormat(e),f.noFormat}return t},f.nestedProperty=r(5487),f.keyedContainer=r(6636),f.relativeAttr=r(6962),f.isPlainObject=r(1965),f.toLogRange=r(8163),f.relinkPrivateKeys=r(1332);var h=r(3627);f.isTypedArray=h.isTypedArray,f.isArrayOrTypedArray=h.isArrayOrTypedArray,f.isArray1D=h.isArray1D,f.ensureArray=h.ensureArray,f.concat=h.concat,f.maxRowLength=h.maxRowLength,f.minRowLength=h.minRowLength;var p=r(4872);f.mod=p.mod,f.modHalf=p.modHalf;var v=r(6554);f.valObjectMeta=v.valObjectMeta,f.coerce=v.coerce,f.coerce2=v.coerce2,f.coerceFont=v.coerceFont,f.coercePattern=v.coercePattern,f.coerceHoverinfo=v.coerceHoverinfo,f.coerceSelectionMarkerOpacity=v.coerceSelectionMarkerOpacity,f.validate=v.validate;var y=r(1631);f.dateTime2ms=y.dateTime2ms,f.isDateTime=y.isDateTime,f.ms2DateTime=y.ms2DateTime,f.ms2DateTimeLocal=y.ms2DateTimeLocal,f.cleanDate=y.cleanDate,f.isJSDate=y.isJSDate,f.formatDate=y.formatDate,f.incrementMonth=y.incrementMonth,f.dateTick0=y.dateTick0,f.dfltRange=y.dfltRange,f.findExactDates=y.findExactDates,f.MIN_MS=y.MIN_MS,f.MAX_MS=y.MAX_MS;var g=r(5888);f.findBin=g.findBin,f.sorterAsc=g.sorterAsc,f.sorterDes=g.sorterDes,f.distinctVals=g.distinctVals,f.roundUp=g.roundUp,f.sort=g.sort,f.findIndexOfMin=g.findIndexOfMin,f.sortObjectKeys=r(8607);var m=r(38);f.aggNums=m.aggNums,f.len=m.len,f.mean=m.mean,f.median=m.median,f.midRange=m.midRange,f.variance=m.variance,f.stdev=m.stdev,f.interp=m.interp;var x=r(5657);f.init2dArray=x.init2dArray,f.transposeRagged=x.transposeRagged,f.dot=x.dot,f.translationMatrix=x.translationMatrix,f.rotationMatrix=x.rotationMatrix,f.rotationXYMatrix=x.rotationXYMatrix,f.apply3DTransform=x.apply3DTransform,f.apply2DTransform=x.apply2DTransform,f.apply2DTransform2=x.apply2DTransform2,f.convertCssMatrix=x.convertCssMatrix,f.inverseTransformMatrix=x.inverseTransformMatrix;var b=r(6348);f.deg2rad=b.deg2rad,f.rad2deg=b.rad2deg,f.angleDelta=b.angleDelta,f.angleDist=b.angleDist,f.isFullCircle=b.isFullCircle,f.isAngleInsideSector=b.isAngleInsideSector,f.isPtInsideSector=b.isPtInsideSector,f.pathArc=b.pathArc,f.pathSector=b.pathSector,f.pathAnnulus=b.pathAnnulus;var _=r(9863);f.isLeftAnchor=_.isLeftAnchor,f.isCenterAnchor=_.isCenterAnchor,f.isRightAnchor=_.isRightAnchor,f.isTopAnchor=_.isTopAnchor,f.isMiddleAnchor=_.isMiddleAnchor,f.isBottomAnchor=_.isBottomAnchor;var w=r(7642);f.segmentsIntersect=w.segmentsIntersect,f.segmentDistance=w.segmentDistance,f.getTextLocation=w.getTextLocation,f.clearLocationCache=w.clearLocationCache,f.getVisibleSegment=w.getVisibleSegment,f.findPointOnPath=w.findPointOnPath;var T=r(1426);f.extendFlat=T.extendFlat,f.extendDeep=T.extendDeep,f.extendDeepAll=T.extendDeepAll,f.extendDeepNoArrays=T.extendDeepNoArrays;var M=r(7769);f.log=M.log,f.warn=M.warn,f.error=M.error;var k=r(587);f.counterRegex=k.counter;var A=r(9990);f.throttle=A.throttle,f.throttleDone=A.done,f.clearThrottle=A.clear;var L=r(4401);function S(e){var t={};for(var r in e)for(var n=e[r],a=0;as||e=t)&&o(e)&&e>=0&&e%1==0},f.noop=r(4213),f.identity=r(3389),f.repeat=function(e,t){for(var r=new Array(t),n=0;nr?Math.max(r,Math.min(t,e)):Math.max(t,Math.min(r,e))},f.bBoxIntersect=function(e,t,r){return r=r||0,e.left<=t.right+r&&t.left<=e.right+r&&e.top<=t.bottom+r&&t.top<=e.bottom+r},f.simpleMap=function(e,t,r,n,a){for(var i=e.length,o=new Array(i),l=0;l=Math.pow(2,r)?a>10?(f.warn("randstr failed uniqueness"),s):e(t,r,n,(a||0)+1):s},f.OptionControl=function(e,t){e||(e={}),t||(t="opt");var r={optionList:[],_newoption:function(n){n[t]=e,r[n.name]=n,r.optionList.push(n)}};return r["_"+t]=e,r},f.smooth=function(e,t){if((t=Math.round(t)||0)<2)return e;var r,n,a,i,o=e.length,l=2*o,s=2*t-1,c=new Array(s),u=new Array(o);for(r=0;r=l&&(a-=l*Math.floor(a/l)),a<0?a=-1-a:a>=o&&(a=l-1-a),i+=e[a]*c[n];u[r]=i}return u},f.syncOrAsync=function(e,t,r){var n;function a(){return f.syncOrAsync(e,t,r)}for(;e.length;)if((n=(0,e.splice(0,1)[0])(t))&&n.then)return n.then(a);return r&&r(t)},f.stripTrailingSlash=function(e){return"/"===e.substr(-1)?e.substr(0,e.length-1):e},f.noneOrAll=function(e,t,r){if(e){var n,a=!1,i=!0;for(n=0;n0?t:0}))},f.fillArray=function(e,t,r,n){if(n=n||f.identity,f.isArrayOrTypedArray(e))for(var a=0;a1?a+o[1]:"";if(i&&(o.length>1||l.length>4||r))for(;n.test(l);)l=l.replace(n,"$1"+i+"$2");return l+s},f.TEMPLATE_STRING_REGEX=/%{([^\s%{}:]*)([:|\|][^}]*)?}/g;var R=/^\w*$/;f.templateString=function(e,t){var r={};return e.replace(f.TEMPLATE_STRING_REGEX,(function(e,n){var a;return R.test(n)?a=t[n]:(r[n]=r[n]||f.nestedProperty(t,n).get,a=r[n]()),f.isValidTextValue(a)?a:""}))};var z={max:10,count:0,name:"hovertemplate"};f.hovertemplateString=function(){return j.apply(z,arguments)};var N={max:10,count:0,name:"texttemplate"};f.texttemplateString=function(){return j.apply(N,arguments)};var E=/^(\S+)([\*\/])(-?\d+(\.\d+)?)$/,F={max:10,count:0,name:"texttemplate",parseMultDiv:!0};f.texttemplateStringForShapes=function(){return j.apply(F,arguments)};var H=/^[:|\|]/;function j(e,t,r){var n=this,i=arguments;t||(t={});var o={};return e.replace(f.TEMPLATE_STRING_REGEX,(function(e,l,s){var c="_xother"===l||"_yother"===l,u="_xother_"===l||"_yother_"===l,d="xother_"===l||"yother_"===l,h="xother"===l||"yother"===l||c||d||u,p=l;(c||u)&&(p=p.substring(1)),(d||u)&&(p=p.substring(0,p.length-1));var v,y,g,m=null,x=null;if(n.parseMultDiv){var b=function(e){var t=e.match(E);return t?{key:t[1],op:t[2],number:Number(t[3])}:{key:e,op:null,number:null}}(p);p=b.key,m=b.op,x=b.number}if(h){if(void 0===(v=t[p]))return""}else for(g=3;g=48&&o<=57,c=l>=48&&l<=57;if(s&&(n=10*n+o-48),c&&(a=10*a+l-48),!s||!c){if(n!==a)return n-a;if(o!==l)return o-l}}return a-n};var B=2e9;f.seedPseudoRandom=function(){B=2e9},f.pseudoRandom=function(){var e=B;return B=(69069*B+1)%4294967296,Math.abs(B-e)<429496729?f.pseudoRandom():B/4294967296},f.fillText=function(e,t,r){var n=Array.isArray(r)?function(e){r.push(e)}:function(e){r.text=e},a=f.extractOption(e,t,"htx","hovertext");if(f.isValidTextValue(a))return n(a);var i=f.extractOption(e,t,"tx","text");return f.isValidTextValue(i)?n(i):void 0},f.isValidTextValue=function(e){return e||0===e},f.formatPercent=function(e,t){t=t||0;for(var r=(Math.round(100*e*Math.pow(10,t))*Math.pow(.1,t)).toFixed(t)+"%",n=0;n1&&(c=1):c=0,f.strTranslate(a-c*(r+o),i-c*(n+l))+f.strScale(c)+(s?"rotate("+s+(t?"":" "+r+" "+n)+")":"")},f.setTransormAndDisplay=function(e,t){e.attr("transform",f.getTextTransform(t)),e.style("display",t.scale?null:"none")},f.ensureUniformFontSize=function(e,t){var r=f.extendFlat({},t);return r.size=Math.max(t.size,e._fullLayout.uniformtext.minsize||0),r},f.join2=function(e,t,r){var n=e.length;return n>1?e.slice(0,-1).join(t)+r+e[n-1]:e.join(t)},f.bigFont=function(e){return Math.round(1.2*e)};var Y=f.getFirefoxVersion(),U=null!==Y&&Y<86;f.getPositionFromD3Event=function(){return U?[n.event.layerX,n.event.layerY]:[n.event.offsetX,n.event.offsetY]}},1965:function(e){"use strict";e.exports=function(e){return window&&window.process&&window.process.versions?"[object Object]"===Object.prototype.toString.call(e):"[object Object]"===Object.prototype.toString.call(e)&&Object.getPrototypeOf(e).hasOwnProperty("hasOwnProperty")}},6636:function(e,t,r){"use strict";var n=r(5487),a=/^\w*$/;e.exports=function(e,t,r,i){var o,l,s;r=r||"name",i=i||"value";var c={};t&&t.length?(s=n(e,t),l=s.get()):l=e,t=t||"";var u={};if(l)for(o=0;o2)return c[t]=2|c[t],d.set(e,null);if(f){for(o=t;o1){var t=["LOG:"];for(e=0;e1){var r=[];for(e=0;e"),"long")}},i.warn=function(){var e;if(n.logging>0){var t=["WARN:"];for(e=0;e0){var r=[];for(e=0;e"),"stick")}},i.error=function(){var e;if(n.logging>0){var t=["ERROR:"];for(e=0;e0){var r=[];for(e=0;e"),"stick")}}},7310:function(e,t,r){"use strict";var n=r(9898);e.exports=function(e,t,r){var a=e.selectAll("g."+r.replace(/\s/g,".")).data(t,(function(e){return e[0].trace.uid}));a.exit().remove(),a.enter().append("g").attr("class",r),a.order();var i=e.classed("rangeplot")?"nodeRangePlot3":"node3";return a.each((function(e){e[0][i]=n.select(this)})),a}},5657:function(e,t,r){"use strict";var n=r(9576);t.init2dArray=function(e,t){for(var r=new Array(e),n=0;nt/2?e-Math.round(e/t)*t:e}}},5487:function(e,t,r){"use strict";var n=r(2770),a=r(3627).isArrayOrTypedArray;function i(e,t){return function(){var r,n,o,l,s,c=e;for(l=0;l/g),s=0;si||c===a||cl||t&&s(e))}:function(e,t){var s=e[0],c=e[1];if(s===a||si||c===a||cl)return!1;var u,f,d,h,p,v=r.length,y=r[0][0],g=r[0][1],m=0;for(u=1;uMath.max(f,y)||c>Math.max(d,g)))if(cu||Math.abs(n(o,d))>a)return!0;return!1},i.filter=function(e,t){var r=[e[0]],n=0,a=0;function o(o){e.push(o);var l=r.length,s=n;r.splice(a+1);for(var c=s+1;c1&&o(e.pop()),{addPt:o,raw:e,filtered:r}}},5142:function(e,t,r){"use strict";var n=r(2770),a=r(5791);e.exports=function(e){var t;if("string"!=typeof(t=e&&e.hasOwnProperty("userAgent")?e.userAgent:function(){var e;return"undefined"!=typeof navigator&&(e=navigator.userAgent),e&&e.headers&&"string"==typeof e.headers["user-agent"]&&(e=e.headers["user-agent"]),e}()))return!0;var r=a({ua:{headers:{"user-agent":t}},tablet:!0,featureDetect:!1});if(!r)for(var i=t.split(" "),o=1;o-1;l--){var s=i[l];if("Version/"===s.substr(0,8)){var c=s.substr(8).split(".")[0];if(n(c)&&(c=+c),c>=13)return!0}}return r}},5138:function(e){"use strict";e.exports=function(e,t){if(t instanceof RegExp){for(var r=t.toString(),n=0;na.queueLength&&(e.undoQueue.queue.shift(),e.undoQueue.index--))},startSequence:function(e){e.undoQueue=e.undoQueue||{index:0,queue:[],sequence:!1},e.undoQueue.sequence=!0,e.undoQueue.beginSequence=!0},stopSequence:function(e){e.undoQueue=e.undoQueue||{index:0,queue:[],sequence:!1},e.undoQueue.sequence=!1,e.undoQueue.beginSequence=!1},undo:function(e){var t,r;if(!(void 0===e.undoQueue||isNaN(e.undoQueue.index)||e.undoQueue.index<=0)){for(e.undoQueue.index--,t=e.undoQueue.queue[e.undoQueue.index],e.undoQueue.inSequence=!0,r=0;r=e.undoQueue.queue.length)){for(t=e.undoQueue.queue[e.undoQueue.index],e.undoQueue.inSequence=!0,r=0;rt}function f(e,t){return e>=t}t.findBin=function(e,t,r){if(n(t.start))return r?Math.ceil((e-t.start)/t.size-l)-1:Math.floor((e-t.start)/t.size+l);var i,o,d=0,h=t.length,p=0,v=h>1?(t[h-1]-t[0])/(h-1):1;for(o=v>=0?r?s:c:r?f:u,e+=v*l*(r?-1:1)*(v>=0?1:-1);d90&&a.log("Long binary search..."),d-1},t.sorterAsc=function(e,t){return e-t},t.sorterDes=function(e,t){return t-e},t.distinctVals=function(e){var r,n=e.slice();for(n.sort(t.sorterAsc),r=n.length-1;r>-1&&n[r]===o;r--);for(var a,i=n[r]-n[0]||1,l=i/(r||1)/1e4,s=[],c=0;c<=r;c++){var u=n[c],f=u-a;void 0===a?(s.push(u),a=u):f>l&&(i=Math.min(i,f),s.push(u),a=u)}return{vals:s,minDiff:i}},t.roundUp=function(e,t,r){for(var n,a=0,i=t.length-1,o=0,l=r?0:1,s=r?1:0,c=r?Math.ceil:Math.floor;a0&&(n=1),r&&n)return e.sort(t)}return n?e:e.reverse()},t.findIndexOfMin=function(e,t){t=t||i;for(var r,n=1/0,a=0;ai.length)&&(o=i.length),n(r)||(r=!1),a(i[0])){for(s=new Array(o),l=0;le.length-1)return e[e.length-1];var r=t%1;return r*e[Math.ceil(t)]+(1-r)*e[Math.floor(t)]}},3893:function(e,t,r){"use strict";var n=r(9898),a=r(1828),i=a.strTranslate,o=r(7922),l=r(8783).LINE_SPACING,s=/([^$]*)([$]+[^$]*[$]+)([^$]*)/;t.convertToTspans=function(e,r,y){var L=e.text(),S=!e.attr("data-notex")&&r&&r._context.typesetMath&&"undefined"!=typeof MathJax&&L.match(s),C=n.select(e.node().parentNode);if(!C.empty()){var P=e.attr("class")?e.attr("class").split(" ")[0]:"text";return P+="-math",C.selectAll("svg."+P).remove(),C.selectAll("g."+P+"-group").remove(),e.style("display",null).attr({"data-unformatted":L,"data-math":"N"}),S?(r&&r._promises||[]).push(new Promise((function(t){e.style("display","none");var r=parseInt(e.node().style.fontSize,10),o={fontSize:r};!function(e,t,r){var i,o,l,s,d=parseInt((MathJax.version||"").split(".")[0]);if(2===d||3===d){var h=function(){return o=a.extendDeepAll({},MathJax.Hub.config),l=MathJax.Hub.processSectionDelay,void 0!==MathJax.Hub.processSectionDelay&&(MathJax.Hub.processSectionDelay=0),MathJax.Hub.Config({messageStyle:"none",tex2jax:{inlineMath:f},displayAlign:"left"})},p=function(){o=a.extendDeepAll({},MathJax.config),MathJax.config.tex||(MathJax.config.tex={}),MathJax.config.tex.inlineMath=f},v=function(){if("SVG"!==(i=MathJax.Hub.config.menuSettings.renderer))return MathJax.Hub.setRenderer("SVG")},y=function(){"svg"!==(i=MathJax.config.startup.output)&&(MathJax.config.startup.output="svg")},g=function(){var r="math-output-"+a.randstr({},64),i=(s=n.select("body").append("div").attr({id:r}).style({visibility:"hidden",position:"absolute","font-size":t.fontSize+"px"}).text(e.replace(c,"\\lt ").replace(u,"\\gt "))).node();return 2===d?MathJax.Hub.Typeset(i):MathJax.typeset([i])},m=function(){var t=s.select(2===d?".MathJax_SVG":".MathJax"),i=!t.empty()&&s.select("svg").node();if(i){var o,l=i.getBoundingClientRect();o=2===d?n.select("body").select("#MathJax_SVG_glyphs"):t.select("defs"),r(t,o,l)}else a.log("There was an error in the tex syntax.",e),r();s.remove()},x=function(){if("SVG"!==i)return MathJax.Hub.setRenderer(i)},b=function(){"svg"!==i&&(MathJax.config.startup.output=i)},_=function(){return void 0!==l&&(MathJax.Hub.processSectionDelay=l),MathJax.Hub.Config(o)},w=function(){MathJax.config=o};2===d?MathJax.Hub.Queue(h,v,g,m,x,_):3===d&&(p(),y(),MathJax.startup.defaultReady(),MathJax.startup.promise.then((function(){g(),m(),b(),w()})))}else a.warn("No MathJax version:",MathJax.version)}(S[2],o,(function(n,a,o){C.selectAll("svg."+P).remove(),C.selectAll("g."+P+"-group").remove();var l=n&&n.select("svg");if(!l||!l.node())return I(),void t();var s=C.append("g").classed(P+"-group",!0).attr({"pointer-events":"none","data-unformatted":L,"data-math":"Y"});s.node().appendChild(l.node()),a&&a.node()&&l.node().insertBefore(a.node().cloneNode(!0),l.node().firstChild);var c=o.width,u=o.height;l.attr({class:P,height:u,preserveAspectRatio:"xMinYMin meet"}).style({overflow:"visible","pointer-events":"none"});var f=e.node().style.fill||"black",d=l.select("g");d.attr({fill:f,stroke:f});var h=d.node().getBoundingClientRect(),p=h.width,v=h.height;(p>c||v>u)&&(l.style("overflow","hidden"),p=(h=l.node().getBoundingClientRect()).width,v=h.height);var g=+e.attr("x"),m=+e.attr("y"),x=-(r||e.node().getBoundingClientRect().height)/4;if("y"===P[0])s.attr({transform:"rotate("+[-90,g,m]+")"+i(-p/2,x-v/2)});else if("l"===P[0])m=x-v/2;else if("a"===P[0]&&0!==P.indexOf("atitle"))g=0,m=x;else{var b=e.attr("text-anchor");g-=p*("middle"===b?.5:"end"===b?1:0),m=m+x-v/2}l.attr({x:g,y:m}),y&&y.call(e,s),t(s)}))}))):I(),e}function I(){C.empty()||(P=e.attr("class")+"-math",C.select("svg."+P).remove()),e.text("").style("white-space","pre");var r=function(e,t){t=t.replace(g," ");var r,i=!1,s=[],c=-1;function u(){c++;var t=document.createElementNS(o.svg,"tspan");n.select(t).attr({class:"line",dy:c*l+"em"}),e.appendChild(t),r=t;var a=s;if(s=[{node:t}],a.length>1)for(var i=1;i doesnt match end tag <"+e+">. Pretending it did match.",t),r=s[s.length-1].node}else a.log("Ignoring unexpected end tag .",t)}var S=b.test(t);S?u():(r=e,s=[{node:e}]);for(var C=t.split(m),P=0;P|>|>)/g,f=[["$","$"],["\\(","\\)"]],d={sup:"font-size:70%",sub:"font-size:70%",b:"font-weight:bold",i:"font-style:italic",a:"cursor:pointer",span:"",em:"font-style:italic;font-weight:bold"},h={sub:"0.3em",sup:"-0.6em"},p={sub:"-0.21em",sup:"0.42em"},v="\u200b",y=["http:","https:","mailto:","",void 0,":"],g=t.NEWLINES=/(\r\n?|\n)/g,m=/(<[^<>]*>)/,x=/<(\/?)([^ >]*)(\s+(.*))?>/i,b=//i;t.BR_TAG_ALL=//gi;var _=/(^|[\s"'])style\s*=\s*("([^"]*);?"|'([^']*);?')/i,w=/(^|[\s"'])href\s*=\s*("([^"]*)"|'([^']*)')/i,T=/(^|[\s"'])target\s*=\s*("([^"\s]*)"|'([^'\s]*)')/i,M=/(^|[\s"'])popup\s*=\s*("([\w=,]*)"|'([\w=,]*)')/i;function k(e,t){if(!e)return null;var r=e.match(t),n=r&&(r[3]||r[4]);return n&&O(n)}var A=/(^|;)\s*color:/;t.plainText=function(e,t){for(var r=void 0!==(t=t||{}).len&&-1!==t.len?t.len:1/0,n=void 0!==t.allowedTags?t.allowedTags:["br"],a=e.split(m),i=[],o="",l=0,s=0;s3?i.push(c.substr(0,h-3)+"..."):i.push(c.substr(0,h));break}o=""}}return i.join("")};var L={mu:"\u03bc",amp:"&",lt:"<",gt:">",nbsp:"\xa0",times:"\xd7",plusmn:"\xb1",deg:"\xb0"},S=/&(#\d+|#x[\da-fA-F]+|[a-z]+);/g;function O(e){return e.replace(S,(function(e,t){return("#"===t.charAt(0)?function(e){if(!(e>1114111)){var t=String.fromCodePoint;if(t)return t(e);var r=String.fromCharCode;return e<=65535?r(e):r(55232+(e>>10),e%1024+56320)}}("x"===t.charAt(1)?parseInt(t.substr(2),16):parseInt(t.substr(1),10)):L[t])||e}))}function D(e){var t=encodeURI(decodeURI(e)),r=document.createElement("a"),n=document.createElement("a");r.href=e,n.href=t;var a=r.protocol,i=n.protocol;return-1!==y.indexOf(a)&&-1!==y.indexOf(i)?t:""}function C(e,t,r){var n,i,o,l=r.horizontalAlign,s=r.verticalAlign||"top",c=e.node().getBoundingClientRect(),u=t.node().getBoundingClientRect();return i="bottom"===s?function(){return c.bottom-n.height}:"middle"===s?function(){return c.top+(c.height-n.height)/2}:function(){return c.top},o="right"===l?function(){return c.right-n.width}:"center"===l?function(){return c.left+(c.width-n.width)/2}:function(){return c.left},function(){n=this.node().getBoundingClientRect();var e=o()-u.left,t=i()-u.top,l=r.gd||{};if(r.gd){l._fullLayout._calcInverseTransform(l);var s=a.apply3DTransform(l._fullLayout._invTransform)(e,t);e=s[0],t=s[1]}return this.style({top:t+"px",left:e+"px","z-index":1e3}),this}}t.convertEntities=O,t.sanitizeHTML=function(e){e=e.replace(g," ");for(var t=document.createElement("p"),r=t,a=[],i=e.split(m),o=0;oi.ts+t?s():i.timer=setTimeout((function(){s(),i.timer=null}),t)},t.done=function(e){var t=r[e];return t&&t.timer?new Promise((function(e){var r=t.onDone;t.onDone=function(){r&&r(),e(),t.onDone=null}})):Promise.resolve()},t.clear=function(e){if(e)n(r[e]),delete r[e];else for(var a in r)t.clear(a)}},8163:function(e,t,r){"use strict";var n=r(2770);e.exports=function(e,t){if(e>0)return Math.log(e)/Math.LN10;var r=Math.log(Math.min(t[0],t[1]))/Math.LN10;return n(r)||(r=Math.log(Math.max(t[0],t[1]))/Math.LN10-6),r}},7815:function(e){"use strict";e.exports={moduleType:"locale",name:"en-US",dictionary:{"Click to enter Colorscale title":"Click to enter Colorscale title"},format:{date:"%m/%d/%Y"}}},2177:function(e){"use strict";e.exports={moduleType:"locale",name:"en",dictionary:{"Click to enter Colorscale title":"Click to enter Colourscale title"},format:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],periods:["AM","PM"],dateTime:"%a %b %e %X %Y",date:"%d/%m/%Y",time:"%H:%M:%S",decimal:".",thousands:",",grouping:[3],currency:["$",""],year:"%Y",month:"%b %Y",dayMonth:"%b %-d",dayMonthYear:"%b %-d, %Y"}}},4458:function(e,t,r){"use strict";var n=r(3972);e.exports=function(e){for(var t,r,a=n.layoutArrayContainers,i=n.layoutArrayRegexes,o=e.split("[")[0],l=0;l0&&o.log("Clearing previous rejected promises from queue."),e._promises=[]},t.cleanLayout=function(e){var r,n;e||(e={}),e.xaxis1&&(e.xaxis||(e.xaxis=e.xaxis1),delete e.xaxis1),e.yaxis1&&(e.yaxis||(e.yaxis=e.yaxis1),delete e.yaxis1),e.scene1&&(e.scene||(e.scene=e.scene1),delete e.scene1);var i=(l.subplotsRegistry.cartesian||{}).attrRegex,s=(l.subplotsRegistry.polar||{}).attrRegex,f=(l.subplotsRegistry.ternary||{}).attrRegex,d=(l.subplotsRegistry.gl3d||{}).attrRegex,v=Object.keys(e);for(r=0;r3?(I.x=1.02,I.xanchor="left"):I.x<-2&&(I.x=-.02,I.xanchor="right"),I.y>3?(I.y=1.02,I.yanchor="bottom"):I.y<-2&&(I.y=-.02,I.yanchor="top")),p(e),"rotate"===e.dragmode&&(e.dragmode="orbit"),c.clean(e),e.template&&e.template.layout&&t.cleanLayout(e.template.layout),e},t.cleanData=function(e){for(var r=0;r0)return e.substr(0,t)}t.hasParent=function(e,t){for(var r=b(t);r;){if(r in e)return!0;r=b(r)}return!1};var _=["x","y","z"];t.clearAxisTypes=function(e,t,r){for(var n=0;n1&&i.warn("Full array edits are incompatible with other edits",f);var m=r[""][""];if(c(m))t.set(null);else{if(!Array.isArray(m))return i.warn("Unrecognized full array edit value",f,m),!0;t.set(m)}return!v&&(d(y,g),h(e),!0)}var x,b,_,w,T,M,k,A,L=Object.keys(r).map(Number).sort(o),S=t.get(),O=S||[],D=u(g,f).get(),C=[],P=-1,I=O.length;for(x=0;xO.length-(k?0:1))i.warn("index out of range",f,_);else if(void 0!==M)T.length>1&&i.warn("Insertion & removal are incompatible with edits to the same index.",f,_),c(M)?C.push(_):k?("add"===M&&(M={}),O.splice(_,0,M),D&&D.splice(_,0,{})):i.warn("Unrecognized full object edit value",f,_,M),-1===P&&(P=_);else for(b=0;b=0;x--)O.splice(C[x],1),D&&D.splice(C[x],1);if(O.length?S||t.set(O):t.set(null),v)return!1;if(d(y,g),p!==a){var R;if(-1===P)R=L;else{for(I=Math.max(O.length,I),R=[],x=0;x=P);x++)R.push(_);for(x=P;x=e.data.length||a<-e.data.length)throw new Error(r+" must be valid indices for gd.data.");if(t.indexOf(a,n+1)>-1||a>=0&&t.indexOf(-e.data.length+a)>-1||a<0&&t.indexOf(e.data.length+a)>-1)throw new Error("each index in "+r+" must be unique.")}}function P(e,t,r){if(!Array.isArray(e.data))throw new Error("gd.data must be an array.");if(void 0===t)throw new Error("currentIndices is a required argument.");if(Array.isArray(t)||(t=[t]),C(e,t,"currentIndices"),void 0===r||Array.isArray(r)||(r=[r]),void 0!==r&&C(e,r,"newIndices"),void 0!==r&&t.length!==r.length)throw new Error("current and new indices must be of equal length.")}function I(e,t,r,n,i){!function(e,t,r,n){var a=o.isPlainObject(n);if(!Array.isArray(e.data))throw new Error("gd.data must be an array");if(!o.isPlainObject(t))throw new Error("update must be a key:value object");if(void 0===r)throw new Error("indices must be an integer or array of integers");for(var i in C(e,r,"indices"),t){if(!Array.isArray(t[i])||t[i].length!==r.length)throw new Error("attribute "+i+" must be an array of length equal to indices array length");if(a&&(!(i in n)||!Array.isArray(n[i])||n[i].length!==t[i].length))throw new Error("when maxPoints is set as a key:value object it must contain a 1:1 corrispondence with the keys and number of traces in the update object")}}(e,t,r,n);for(var s=function(e,t,r,n){var i,s,c,u,f,d=o.isPlainObject(n),h=[];for(var p in Array.isArray(r)||(r=[r]),r=D(r,e.data.length-1),t)for(var v=0;v-1&&-1===r.indexOf("grouptitlefont")?s(r,r.replace("titlefont","title.font")):r.indexOf("titleposition")>-1?s(r,r.replace("titleposition","title.position")):r.indexOf("titleside")>-1?s(r,r.replace("titleside","title.side")):r.indexOf("titleoffset")>-1&&s(r,r.replace("titleoffset","title.offset")):s(r,r.replace("title","title.text"));function s(t,r){e[r]=e[t],delete e[t]}}function B(e,t,r){e=o.getGraphDiv(e),_.clearPromiseQueue(e);var n={};if("string"==typeof t)n[t]=r;else{if(!o.isPlainObject(t))return o.warn("Relayout fail.",t,r),Promise.reject();n=o.extendFlat({},t)}Object.keys(n).length&&(e.changed=!0);var a=G(e,n),i=a.flags;i.calc&&(e.calcdata=void 0);var l=[d.previousPromises];i.layoutReplot?l.push(w.layoutReplot):Object.keys(n).length&&(Y(e,i,a)||d.supplyDefaults(e),i.legend&&l.push(w.doLegend),i.layoutstyle&&l.push(w.layoutStyles),i.axrange&&U(l,a.rangesAltered),i.ticks&&l.push(w.doTicksRelayout),i.modebar&&l.push(w.doModeBar),i.camera&&l.push(w.doCamera),i.colorbars&&l.push(w.doColorBars),l.push(A)),l.push(d.rehover,d.redrag,d.reselect),c.add(e,B,[e,a.undoit],B,[e,a.redoit]);var s=o.syncOrAsync(l,e);return s&&s.then||(s=Promise.resolve(e)),s.then((function(){return e.emit("plotly_relayout",a.eventData),e}))}function Y(e,t,r){var n=e._fullLayout;if(!t.axrange)return!1;for(var a in t)if("axrange"!==a&&t[a])return!1;for(var i in r.rangesAltered){var o=h.id2name(i),l=e.layout[o],s=n[o];if(s.autorange=l.autorange,l.range&&(s.range=l.range.slice()),s.cleanRange(),s._matchGroup)for(var c in s._matchGroup)if(c!==i){var u=n[h.id2name(c)];u.autorange=s.autorange,u.range=s.range.slice(),u._input.range=s.range.slice()}}return!0}function U(e,t){var r=t?function(e){var r=[];for(var n in t){var a=h.getFromId(e,n);if(r.push(n),-1!==(a.ticklabelposition||"").indexOf("inside")&&a._anchorAxis&&r.push(a._anchorAxis._id),a._matchGroup)for(var i in a._matchGroup)t[i]||r.push(i)}return h.draw(e,r,{skipTitle:!0})}:function(e){return h.draw(e,"redraw")};e.push(m,w.doAutoRangeAndConstraints,r,w.drawData,w.finalDraw)}var V=/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/,q=/^[xyz]axis[0-9]*\.autorange$/,Z=/^[xyz]axis[0-9]*\.domain(\[[0|1]\])?$/;function G(e,t){var r,n,a,i=e.layout,s=e._fullLayout,c=s._guiEditing,d=E(s._preGUI,c),p=Object.keys(t),v=h.list(e),y=o.extendDeepAll({},t),g={};for(j(t),p=Object.keys(t),n=0;n0&&"string"!=typeof I.parts[z];)z--;var F=I.parts[z],H=I.parts[z-1]+"."+F,B=I.parts.slice(0,z).join("."),Y=l(e.layout,B).get(),U=l(s,B).get(),G=I.get();if(void 0!==R){A[P]=R,L[P]="reverse"===F?R:N(G);var X=f.getLayoutValObject(s,I.parts);if(X&&X.impliedEdits&&null!==R)for(var J in X.impliedEdits)S(o.relativeAttr(P,J),X.impliedEdits[J]);if(-1!==["width","height"].indexOf(P))if(R){S("autosize",null);var K="height"===P?"width":"height";S(K,s[K])}else s[P]=e._initialAutoSize[P];else if("autosize"===P)S("width",R?null:s.width),S("height",R?null:s.height);else if(H.match(V))C(H),l(s,B+"._inputRange").set(null);else if(H.match(q)){C(H),l(s,B+"._inputRange").set(null);var Q=l(s,B).get();Q._inputDomain&&(Q._input.domain=Q._inputDomain.slice())}else H.match(Z)&&l(s,B+"._inputDomain").set(null);if("type"===F){O=Y;var $="linear"===U.type&&"log"===R,ee="log"===U.type&&"linear"===R;if($||ee){if(O&&O.range)if(U.autorange)$&&(O.range=O.range[1]>O.range[0]?[1,2]:[2,1]);else{var te=O.range[0],re=O.range[1];$?(te<=0&&re<=0&&S(B+".autorange",!0),te<=0?te=re/1e6:re<=0&&(re=te/1e6),S(B+".range[0]",Math.log(te)/Math.LN10),S(B+".range[1]",Math.log(re)/Math.LN10)):(S(B+".range[0]",Math.pow(10,te)),S(B+".range[1]",Math.pow(10,re)))}else S(B+".autorange",!0);Array.isArray(s._subplots.polar)&&s._subplots.polar.length&&s[I.parts[0]]&&"radialaxis"===I.parts[1]&&delete s[I.parts[0]]._subplot.viewInitial["radialaxis.range"],u.getComponentMethod("annotations","convertCoords")(e,U,R,S),u.getComponentMethod("images","convertCoords")(e,U,R,S)}else S(B+".autorange",!0),S(B+".range",null);l(s,B+"._inputRange").set(null)}else if(F.match(M)){var ne=l(s,P).get(),ae=(R||{}).type;ae&&"-"!==ae||(ae="linear"),u.getComponentMethod("annotations","convertCoords")(e,ne,ae,S),u.getComponentMethod("images","convertCoords")(e,ne,ae,S)}var ie=b.containerArrayMatch(P);if(ie){r=ie.array,n=ie.index;var oe=ie.property,le=X||{editType:"calc"};""!==n&&""===oe&&(b.isAddVal(R)?L[P]=null:b.isRemoveVal(R)?L[P]=(l(i,r).get()||[])[n]:o.warn("unrecognized full object value",t)),T.update(k,le),g[r]||(g[r]={});var se=g[r][n];se||(se=g[r][n]={}),se[oe]=R,delete t[P]}else"reverse"===F?(Y.range?Y.range.reverse():(S(B+".autorange",!0),Y.range=[1,0]),U.autorange?k.calc=!0:k.plot=!0):("dragmode"===P&&(!1===R&&!1!==G||!1!==R&&!1===G)||s._has("scatter-like")&&s._has("regl")&&"dragmode"===P&&("lasso"===R||"select"===R)&&"lasso"!==G&&"select"!==G||s._has("gl2d")?k.plot=!0:X?T.update(k,X):k.calc=!0,I.set(R))}}for(r in g)b.applyContainerArrayChanges(e,d(i,r),g[r],k,d)||(k.plot=!0);for(var ce in D){var ue=(O=h.getFromId(e,ce))&&O._constraintGroup;if(ue)for(var fe in k.calc=!0,ue)D[fe]||(h.getFromId(e,fe)._constraintShrinkable=!0)}return(W(e)||t.height||t.width)&&(k.plot=!0),(k.plot||k.calc)&&(k.layoutReplot=!0),{flags:k,rangesAltered:D,undoit:L,redoit:A,eventData:y}}function W(e){var t=e._fullLayout,r=t.width,n=t.height;return e.layout.autosize&&d.plotAutoSize(e,e.layout,t),t.width!==r||t.height!==n}function X(e,r,n,a){e=o.getGraphDiv(e),_.clearPromiseQueue(e),o.isPlainObject(r)||(r={}),o.isPlainObject(n)||(n={}),Object.keys(r).length&&(e.changed=!0),Object.keys(n).length&&(e.changed=!0);var i=_.coerceTraceIndices(e,a),l=H(e,o.extendFlat({},r),i),s=l.flags,u=G(e,o.extendFlat({},n)),f=u.flags;(s.calc||f.calc)&&(e.calcdata=void 0),s.clearAxisTypes&&_.clearAxisTypes(e,i,n);var h=[];f.layoutReplot?h.push(w.layoutReplot):s.fullReplot?h.push(t._doPlot):(h.push(d.previousPromises),Y(e,f,u)||d.supplyDefaults(e),s.style&&h.push(w.doTraceStyle),(s.colorbars||f.colorbars)&&h.push(w.doColorBars),f.legend&&h.push(w.doLegend),f.layoutstyle&&h.push(w.layoutStyles),f.axrange&&U(h,u.rangesAltered),f.ticks&&h.push(w.doTicksRelayout),f.modebar&&h.push(w.doModeBar),f.camera&&h.push(w.doCamera),h.push(A)),h.push(d.rehover,d.redrag,d.reselect),c.add(e,X,[e,l.undoit,u.undoit,l.traces],X,[e,l.redoit,u.redoit,l.traces]);var p=o.syncOrAsync(h,e);return p&&p.then||(p=Promise.resolve(e)),p.then((function(){return e.emit("plotly_update",{data:l.eventData,layout:u.eventData}),e}))}function J(e){return function(t){t._fullLayout._guiEditing=!0;var r=e.apply(null,arguments);return t._fullLayout._guiEditing=!1,r}}var K=[{pattern:/^hiddenlabels/,attr:"legend.uirevision"},{pattern:/^((x|y)axis\d*)\.((auto)?range|title\.text)/},{pattern:/axis\d*\.showspikes$/,attr:"modebar.uirevision"},{pattern:/(hover|drag)mode$/,attr:"modebar.uirevision"},{pattern:/^(scene\d*)\.camera/},{pattern:/^(geo\d*)\.(projection|center|fitbounds)/},{pattern:/^(ternary\d*\.[abc]axis)\.(min|title\.text)$/},{pattern:/^(polar\d*\.radialaxis)\.((auto)?range|angle|title\.text)/},{pattern:/^(polar\d*\.angularaxis)\.rotation/},{pattern:/^(mapbox\d*)\.(center|zoom|bearing|pitch)/},{pattern:/^legend\.(x|y)$/,attr:"editrevision"},{pattern:/^(shapes|annotations)/,attr:"editrevision"},{pattern:/^title\.text$/,attr:"editrevision"}],Q=[{pattern:/^selectedpoints$/,attr:"selectionrevision"},{pattern:/(^|value\.)visible$/,attr:"legend.uirevision"},{pattern:/^dimensions\[\d+\]\.constraintrange/},{pattern:/^node\.(x|y|groups)/},{pattern:/^level$/},{pattern:/(^|value\.)name$/},{pattern:/colorbar\.title\.text$/},{pattern:/colorbar\.(x|y)$/,attr:"editrevision"}];function $(e,t){for(var r=0;r1;)if(n.pop(),void 0!==(r=l(t,n.join(".")+".uirevision").get()))return r;return t.uirevision}function te(e,t){for(var r=0;r=a.length?a[0]:a[e]:a}function s(e){return Array.isArray(i)?e>=i.length?i[0]:i[e]:i}function c(e,t){var r=0;return function(){if(e&&++r===t)return e()}}return void 0===n._frameWaitingCnt&&(n._frameWaitingCnt=0),new Promise((function(i,u){function f(){n._currentFrame&&n._currentFrame.onComplete&&n._currentFrame.onComplete();var t=n._currentFrame=n._frameQueue.shift();if(t){var r=t.name?t.name.toString():null;e._fullLayout._currentFrame=r,n._lastFrameAt=Date.now(),n._timeToNext=t.frameOpts.duration,d.transition(e,t.frame.data,t.frame.layout,_.coerceTraceIndices(e,t.frame.traces),t.frameOpts,t.transitionOpts).then((function(){t.onComplete&&t.onComplete()})),e.emit("plotly_animatingframe",{name:r,frame:t.frame,animation:{frame:t.frameOpts,transition:t.transitionOpts}})}else e.emit("plotly_animated"),window.cancelAnimationFrame(n._animationRaf),n._animationRaf=null}function h(){e.emit("plotly_animating"),n._lastFrameAt=-1/0,n._timeToNext=0,n._runningTransitions=0,n._currentFrame=null;var t=function(){n._animationRaf=window.requestAnimationFrame(t),Date.now()-n._lastFrameAt>n._timeToNext&&f()};t()}var p,v,y=0;function g(e){return Array.isArray(a)?y>=a.length?e.transitionOpts=a[y]:e.transitionOpts=a[0]:e.transitionOpts=a,y++,e}var m=[],x=null==t,b=Array.isArray(t);if(x||b||!o.isPlainObject(t)){if(x||-1!==["string","number"].indexOf(typeof t))for(p=0;p0&&MM)&&k.push(v);m=k}}m.length>0?function(t){if(0!==t.length){for(var a=0;a=0;n--)if(o.isPlainObject(t[n])){var v=t[n].name,y=(u[v]||p[v]||{}).name,g=t[n].name,m=u[y]||p[y];y&&g&&"number"==typeof g&&m&&k<5&&(k++,o.warn('addFrames: overwriting frame "'+(u[y]||p[y]).name+'" with a frame whose name of type "number" also equates to "'+y+'". This is valid but may potentially lead to unexpected behavior since all plotly.js frame names are stored internally as strings.'),5===k&&o.warn("addFrames: This API call has yielded too many of these warnings. For the rest of this call, further warnings about numeric frame names will be suppressed.")),p[v]={name:v},h.push({frame:d.supplyFrameDefaults(t[n]),index:r&&void 0!==r[n]&&null!==r[n]?r[n]:f+n})}h.sort((function(e,t){return e.index>t.index?-1:e.index=0;n--){if("number"==typeof(a=h[n].frame).name&&o.warn("Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings"),!a.name)for(;u[a.name="frame "+e._transitionData._counter++];);if(u[a.name]){for(i=0;i=0;r--)n=t[r],i.push({type:"delete",index:n}),l.unshift({type:"insert",index:n,value:a[n]});var s=d.modifyFrames,u=d.modifyFrames,f=[e,l],h=[e,i];return c&&c.add(e,s,f,u,h),d.modifyFrames(e,i)},t.addTraces=function e(r,n,a){r=o.getGraphDiv(r);var i,l,s=[],u=t.deleteTraces,f=e,d=[r,s],h=[r,n];for(function(e,t,r){var n,a;if(!Array.isArray(e.data))throw new Error("gd.data must be an array.");if(void 0===t)throw new Error("traces must be defined.");for(Array.isArray(t)||(t=[t]),n=0;n=0&&r=0&&r=i.length)return!1;if(2===e.dimensions){if(r++,t.length===r)return e;var o=t[r];if(!_(o))return!1;e=i[a][o]}else e=i[a]}else e=i}}return e}function _(e){return e===Math.round(e)&&e>=0}function w(){var e,t,r={};for(e in f(r,o),n.subplotsRegistry)if((t=n.subplotsRegistry[e]).layoutAttributes)if(Array.isArray(t.attr))for(var a=0;a=s.length)return!1;a=(r=(n.transformsRegistry[s[c].type]||{}).attributes)&&r[t[2]],l=3}else{var u=e._module;if(u||(u=(n.modules[e.type||i.type.dflt]||{})._module),!u)return!1;if(!(a=(r=u.attributes)&&r[o])){var f=u.basePlotModule;f&&f.attributes&&(a=f.attributes[o])}a||(a=i[o])}return b(a,t,l)},t.getLayoutValObject=function(e,t){var r=function(e,t){var r,a,i,l,s=e._basePlotModules;if(s){var c;for(r=0;r=a&&(r._input||{})._templateitemname;l&&(o=a);var s,c=t+"["+o+"]";function u(){s={},l&&(s[c]={},s[c][i]=l)}function f(e,t){l?n.nestedProperty(s[c],e).set(t):s[c+"."+e]=t}function d(){var e=s;return u(),e}return u(),{modifyBase:function(e,t){s[e]=t},modifyItem:f,getUpdateObj:d,applyUpdate:function(t,r){t&&f(t,r);var a=d();for(var i in a)n.nestedProperty(e,i).set(a[i])}}}},1549:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(4875),o=r(1828),l=r(3893),s=r(3306),c=r(7901),u=r(1424),f=r(2998),d=r(4168),h=r(9298),p=r(8783),v=r(9082),y=v.enforce,g=v.clean,m=r(1739).doAutoRange,x="start",b="middle",_="end";function w(e,t,r){for(var n=0;n=e[1]||a[1]<=e[0])&&i[0]t[0])return!0}return!1}function T(e){var r,a,l,s,f,v,y=e._fullLayout,g=y._size,m=g.p,x=h.list(e,"",!0);if(y._paperdiv.style({width:e._context.responsive&&y.autosize&&!e._context._hasZeroWidth&&!e.layout.width?"100%":y.width+"px",height:e._context.responsive&&y.autosize&&!e._context._hasZeroHeight&&!e.layout.height?"100%":y.height+"px"}).selectAll(".main-svg").call(u.setSize,y.width,y.height),e._context.setBackground(e,y.paper_bgcolor),t.drawMainTitle(e),d.manage(e),!y._has("cartesian"))return i.previousPromises(e);function b(e,t,r){var n=e._lw/2;return"x"===e._id.charAt(0)?t?"top"===r?t._offset-m-n:t._offset+t._length+m+n:g.t+g.h*(1-(e.position||0))+n%1:t?"right"===r?t._offset+t._length+m+n:t._offset-m-n:g.l+g.w*(e.position||0)+n%1}for(r=0;r.5?"t":"b",o=e._fullLayout.margin[i],l=0;return"paper"===t.yref?l=r+t.pad.t+t.pad.b:"container"===t.yref&&(l=function(e,t,r,n,a){var i=0;return"middle"===r&&(i+=a/2),"t"===e?("top"===r&&(i+=a),i+=n-t*n):("bottom"===r&&(i+=a),i+=t*n),i}(i,n,a,e._fullLayout.height,r)+t.pad.t+t.pad.b),l>o?l:0}(e,r,y);g>0&&(function(e,t,r,n){var a="title.automargin",l=e._fullLayout.title,s=l.y>.5?"t":"b",c={x:l.x,y:l.y,t:0,b:0},u={};"paper"===l.yref&&function(e,t,r,n,a){var i="paper"===t.yref?e._fullLayout._size.h:e._fullLayout.height,l=o.isTopAnchor(t)?n:n-a,s="b"===r?i-l:l;return!(o.isTopAnchor(t)&&"t"===r||o.isBottomAnchor(t)&&"b"===r)&&sT?u.push({code:"unused",traceType:m,templateCount:w,dataCount:T}):T>w&&u.push({code:"reused",traceType:m,templateCount:w,dataCount:T})}}else u.push({code:"data"});if(function e(t,r){for(var n in t)if("_"!==n.charAt(0)){var i=t[n],o=v(t,n,r);a(i)?(Array.isArray(t)&&!1===i._template&&i.templateitemname&&u.push({code:"missing",path:o,templateitemname:i.templateitemname}),e(i,o)):Array.isArray(i)&&y(i)&&e(i,o)}}({data:h,layout:d},""),u.length)return u.map(g)}},403:function(e,t,r){"use strict";var n=r(2770),a=r(2391),i=r(4875),o=r(1828),l=r(5095),s=r(5900),c=r(942),u=r(1506).version,f={format:{valType:"enumerated",values:["png","jpeg","webp","svg","full-json"],dflt:"png"},width:{valType:"number",min:1},height:{valType:"number",min:1},scale:{valType:"number",min:0,dflt:1},setBackground:{valType:"any",dflt:!1},imageDataOnly:{valType:"boolean",dflt:!1}};e.exports=function(e,t){var r,d,h,p;function v(e){return!(e in t)||o.validate(t[e],f[e])}if(t=t||{},o.isPlainObject(e)?(r=e.data||[],d=e.layout||{},h=e.config||{},p={}):(e=o.getGraphDiv(e),r=o.extendDeep([],e.data),d=o.extendDeep({},e.layout),h=e._context,p=e._fullLayout||{}),!v("width")&&null!==t.width||!v("height")&&null!==t.height)throw new Error("Height and width should be pixel values.");if(!v("format"))throw new Error("Export format is not "+o.join2(f.format.values,", "," or ")+".");var y={};function g(e,r){return o.coerce(t,y,f,e,r)}var m=g("format"),x=g("width"),b=g("height"),_=g("scale"),w=g("setBackground"),T=g("imageDataOnly"),M=document.createElement("div");M.style.position="absolute",M.style.left="-5000px",document.body.appendChild(M);var k=o.extendFlat({},d);x?k.width=x:null===t.width&&n(p.width)&&(k.width=p.width),b?k.height=b:null===t.height&&n(p.height)&&(k.height=p.height);var A=o.extendFlat({},h,{_exportedPlot:!0,staticPlot:!0,setBackground:w}),L=l.getRedrawFunc(M);function S(){return new Promise((function(e){setTimeout(e,l.getDelay(M._fullLayout))}))}function O(){return new Promise((function(e,t){var r=s(M,m,_),n=M._fullLayout.width,f=M._fullLayout.height;function d(){a.purge(M),document.body.removeChild(M)}if("full-json"===m){var h=i.graphJson(M,!1,"keepdata","object",!0,!0);return h.version=u,h=JSON.stringify(h),d(),e(T?h:l.encodeJSON(h))}if(d(),"svg"===m)return e(T?r:l.encodeSVG(r));var p=document.createElement("canvas");p.id=o.randstr(),c({format:m,width:n,height:f,scale:_,canvas:p,svg:r,promise:!0}).then(e).catch(t)}))}return new Promise((function(e,t){a.newPlot(M,r,k,A).then(L).then(S).then(O).then((function(t){e(function(e){return T?e.replace(l.IMAGE_URL_PREFIX,""):e}(t))})).catch((function(e){t(e)}))}))}},4936:function(e,t,r){"use strict";var n=r(1828),a=r(4875),i=r(6281),o=r(2075).dfltConfig,l=n.isPlainObject,s=Array.isArray,c=n.isArrayOrTypedArray;function u(e,t,r,a,i,o){o=o||[];for(var f=Object.keys(e),d=0;dx.length&&a.push(h("unused",i,g.concat(x.length)));var k,A,L,S,O,D=x.length,C=Array.isArray(M);if(C&&(D=Math.min(D,M.length)),2===b.dimensions)for(A=0;Ax[A].length&&a.push(h("unused",i,g.concat(A,x[A].length)));var P=x[A].length;for(k=0;k<(C?Math.min(P,M[A].length):P);k++)L=C?M[A][k]:M,S=m[A][k],O=x[A][k],n.validate(S,L)?O!==S&&O!==+S&&a.push(h("dynamic",i,g.concat(A,k),S,O)):a.push(h("value",i,g.concat(A,k),S))}else a.push(h("array",i,g.concat(A),m[A]));else for(A=0;A1&&d.push(h("object","layout"))),a.supplyDefaults(p);for(var v=p._fullData,y=r.length,g=0;g0&&Math.round(f)===f))return{vals:a};c=f}for(var d=t.calendar,h="start"===s,p="end"===s,v=e[r+"period0"],y=i(v,d)||0,g=[],m=[],x=[],b=a.length,_=0;_k;)M=o(M,-c,d);for(;M<=k;)M=o(M,c,d);T=o(M,-c,d)}else{for(M=y+(w=Math.round((k-y)/u))*u;M>k;)M-=u;for(;M<=k;)M+=u;T=M-u}g[_]=h?T:p?M:(T+M)/2,m[_]=T,x[_]=M}return{vals:g,starts:m,ends:x}}},9502:function(e){"use strict";e.exports={xaxis:{valType:"subplotid",dflt:"x",editType:"calc+clearAxisTypes"},yaxis:{valType:"subplotid",dflt:"y",editType:"calc+clearAxisTypes"}}},1739:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(1828),o=r(606).FP_SAFE,l=r(3972),s=r(1424),c=r(1675),u=c.getFromId,f=c.isLinked;function d(e,t){var r,n,a=[],o=e._fullLayout,l=p(o,t,0),s=p(o,t,1),c=y(e,t),u=c.min,f=c.max;if(0===u.length||0===f.length)return i.simpleMap(t.range,t.r2l);var d=u[0].val,v=f[0].val;for(r=1;r0&&((T=S-l(x)-s(b))>O?M/T>D&&(_=x,w=b,D=M/T):M/S>D&&(_={val:x.val,nopad:1},w={val:b.val,nopad:1},D=M/S));if(d===v){var C=d-1,P=d+1;if(A)if(0===d)a=[0,1];else{var I=(d>0?f:u).reduce((function(e,t){return Math.max(e,s(t))}),0),R=d/(1-Math.min(.5,I/S));a=d>0?[0,R]:[R,0]}else a=L?[Math.max(0,C),Math.max(1,P)]:[C,P]}else A?(_.val>=0&&(_={val:0,nopad:1}),w.val<=0&&(w={val:0,nopad:1})):L&&(_.val-D*l(_)<0&&(_={val:0,nopad:1}),w.val<=0&&(w={val:1,nopad:1})),D=(w.val-_.val-h(t,x.val,b.val))/(S-l(_)-s(w)),a=[_.val-D*l(_),w.val+D*s(w)];return g&&a.reverse(),i.simpleMap(a,t.l2r||Number)}function h(e,t,r){var n=0;if(e.rangebreaks)for(var a=e.locateBreaks(t,r),i=0;i0?r.ppadplus:r.ppadminus)||r.ppad||0),L=k((e._m>0?r.ppadminus:r.ppadplus)||r.ppad||0),S=k(r.vpadplus||r.vpad),O=k(r.vpadminus||r.vpad);if(!T){if(d=1/0,h=-1/0,w)for(n=0;n0&&(d=i),i>h&&i-o&&(d=i),i>h&&i=P;n--)C(n);return{min:p,max:v,opts:r}},concatExtremes:y};var v=3;function y(e,t,r){var n,a,i,o=t._id,l=e._fullData,s=e._fullLayout,c=[],f=[];function d(e,t){for(n=0;n=r&&(c.extrapad||!o)){l=!1;break}a(t,c.val)&&c.pad<=r&&(o||!c.extrapad)&&(e.splice(s,1),s--)}if(l){var u=i&&0===t;e.push({val:t,pad:u?0:r,extrapad:!u&&o})}}function b(e){return a(e)&&Math.abs(e)=t}},9298:function(e,t,r){"use strict";var n=r(9898),a=r(2770),i=r(4875),o=r(3972),l=r(1828),s=l.strTranslate,c=r(3893),u=r(2998),f=r(7901),d=r(1424),h=r(3838),p=r(6287),v=r(606),y=v.ONEMAXYEAR,g=v.ONEAVGYEAR,m=v.ONEMINYEAR,x=v.ONEMAXQUARTER,b=v.ONEAVGQUARTER,_=v.ONEMINQUARTER,w=v.ONEMAXMONTH,T=v.ONEAVGMONTH,M=v.ONEMINMONTH,k=v.ONEWEEK,A=v.ONEDAY,L=A/2,S=v.ONEHOUR,O=v.ONEMIN,D=v.ONESEC,C=v.MINUS_SIGN,P=v.BADNUM,I={K:"zeroline"},R={K:"gridline",L:"path"},z={K:"minor-gridline",L:"path"},N={K:"tick",L:"path"},E={K:"tick",L:"text"},F={width:["x","r","l","xl","xr"],height:["y","t","b","yt","yb"],right:["r","xr"],left:["l","xl"],top:["t","yt"],bottom:["b","yb"]},H=r(8783),j=H.MID_SHIFT,B=H.CAP_SHIFT,Y=H.LINE_SPACING,U=H.OPPOSITE_SIDE,V=e.exports={};V.setConvert=r(1994);var q=r(4322),Z=r(1675),G=Z.idSort,W=Z.isLinked;V.id2name=Z.id2name,V.name2id=Z.name2id,V.cleanId=Z.cleanId,V.list=Z.list,V.listIds=Z.listIds,V.getFromId=Z.getFromId,V.getFromTrace=Z.getFromTrace;var X=r(1739);V.getAutoRange=X.getAutoRange,V.findExtremes=X.findExtremes;var J=1e-4;function K(e){var t=(e[1]-e[0])*J;return[e[0]-t,e[1]+t]}V.coerceRef=function(e,t,r,n,a,i){var o=n.charAt(n.length-1),s=r._fullLayout._subplots[o+"axis"],c=n+"ref",u={};return a||(a=s[0]||("string"==typeof i?i:i[0])),i||(i=a),s=s.concat(s.map((function(e){return e+" domain"}))),u[c]={valType:"enumerated",values:s.concat(i?"string"==typeof i?[i]:i:[]),dflt:a},l.coerce(e,t,u,c)},V.getRefType=function(e){return void 0===e?e:"paper"===e?"paper":"pixel"===e?"pixel":/( domain)$/.test(e)?"domain":"range"},V.coercePosition=function(e,t,r,n,a,i){var o,s;if("range"!==V.getRefType(n))o=l.ensureNumber,s=r(a,i);else{var c=V.getFromId(t,n);s=r(a,i=c.fraction2r(i)),o=c.cleanPos}e[a]=o(s)},V.cleanPosition=function(e,t,r){return("paper"===r||"pixel"===r?l.ensureNumber:V.getFromId(t,r).cleanPos)(e)},V.redrawComponents=function(e,t){t=t||V.listIds(e);var r=e._fullLayout;function n(n,a,i,l){for(var s=o.getComponentMethod(n,a),c={},u=0;ur&&f2e-6||((r-e._forceTick0)/e._minDtick%1+1.000001)%1>2e-6)&&(e._minDtick=0)):e._minDtick=0},V.saveRangeInitial=function(e,t){for(var r=V.list(e,"",!0),n=!1,a=0;a.3*d||u(n)||u(i))){var h=r.dtick/2;e+=e+ho){var s=Number(r.substr(1));i.exactYears>o&&s%12==0?e=V.tickIncrement(e,"M6","reverse")+1.5*A:i.exactMonths>o?e=V.tickIncrement(e,"M1","reverse")+15.5*A:e-=L;var c=V.tickIncrement(e,r);if(c<=n)return c}return e}(m,e,g,c,i)),y=m;y<=u;)y=V.tickIncrement(y,g,!1,i);return{start:t.c2r(m,0,i),end:t.c2r(y,0,i),size:g,_dataSpan:u-c}},V.prepMinorTicks=function(e,t,r){if(!t.minor.dtick){delete e.dtick;var n,i=t.dtick&&a(t._tmin);if(i){var o=V.tickIncrement(t._tmin,t.dtick,!0);n=[t._tmin,.99*o+.01*t._tmin]}else{var s=l.simpleMap(t.range,t.r2l);n=[s[0],.8*s[0]+.2*s[1]]}if(e.range=l.simpleMap(n,t.l2r),e._isMinor=!0,V.prepTicks(e,r),i){var c=a(t.dtick),u=a(e.dtick),f=c?t.dtick:+t.dtick.substring(1),d=u?e.dtick:+e.dtick.substring(1);c&&u?te(f,d)?f===2*k&&d===2*A&&(e.dtick=k):f===2*k&&d===3*A?e.dtick=k:f!==k||(t._input.minor||{}).nticks?re(f/d,2.5)?e.dtick=f/2:e.dtick=f:e.dtick=A:"M"===String(t.dtick).charAt(0)?u?e.dtick="M1":te(f,d)?f>=12&&2===d&&(e.dtick="M3"):e.dtick=t.dtick:"L"===String(e.dtick).charAt(0)?"L"===String(t.dtick).charAt(0)?te(f,d)||(e.dtick=re(f/d,2.5)?t.dtick/2:t.dtick):e.dtick="D1":"D2"===e.dtick&&+t.dtick>1&&(e.dtick=1)}e.range=t.range}void 0===t.minor._tick0Init&&(e.tick0=t.tick0)},V.prepTicks=function(e,t){var r=l.simpleMap(e.range,e.r2l,void 0,void 0,t);if("auto"===e.tickmode||!e.dtick){var n,i=e.nticks;i||("category"===e.type||"multicategory"===e.type?(n=e.tickfont?l.bigFont(e.tickfont.size||12):15,i=e._length/n):(n="y"===e._id.charAt(0)?40:80,i=l.constrain(e._length/n,4,9)+1),"radialaxis"===e._name&&(i*=2)),e.minor&&"array"!==e.minor.tickmode||"array"===e.tickmode&&(i*=100),e._roughDTick=Math.abs(r[1]-r[0])/i,V.autoTicks(e,e._roughDTick),e._minDtick>0&&e.dtick<2*e._minDtick&&(e.dtick=e._minDtick,e.tick0=e.l2r(e._forceTick0))}"period"===e.ticklabelmode&&function(e){var t;function r(){return!(a(e.dtick)||"M"!==e.dtick.charAt(0))}var n=r(),i=V.getTickFormat(e);if(i){var o=e._dtickInit!==e.dtick;/%[fLQsSMX]/.test(i)||(/%[HI]/.test(i)?(t=S,o&&!n&&e.dtick=(I?0:1);R--){var z=!R;R?(e._dtickInit=e.dtick,e._tick0Init=e.tick0):(e.minor._dtickInit=e.minor.dtick,e.minor._tick0Init=e.minor.tick0);var N=R?e:l.extendFlat({},e,e.minor);if(z?V.prepMinorTicks(N,e,t):V.prepTicks(N,t),"array"!==N.tickmode)if("sync"!==N.tickmode){var E=K(u),F=E[0],H=E[1],j=a(N.dtick),B="log"===i&&!(j||"L"===N.dtick.charAt(0)),Y=V.tickFirst(N,t);if(R){if(e._tmin=Y,Y=H:G<=H;G=V.tickIncrement(G,W,f,o)){if(R&&U++,N.rangebreaks&&!f){if(G=h)break}if(D.length>p||G===Z)break;Z=G;var X={value:G};R?(B&&G!==(0|G)&&(X.simpleLabel=!0),s>1&&U%s&&(X.skipLabel=!0),D.push(X)):(X.minor=!0,C.push(X))}}else D=[],v=ie(e);else R?(D=[],v=oe(e)):(C=[],O=oe(e))}if(I&&!("inside"===e.minor.ticks&&"outside"===e.ticks||"outside"===e.minor.ticks&&"inside"===e.ticks)){for(var J=D.map((function(e){return e.value})),Q=[],$=0;$0?(i=n-1,o=n):(i=n,o=n);var l,s=e[i].value,c=e[o].value,u=Math.abs(c-s),f=r||u,d=0;f>=m?d=u>=m&&u<=y?u:g:r===b&&f>=_?d=u>=_&&u<=x?u:b:f>=M?d=u>=M&&u<=w?u:T:r===k&&f>=k?d=k:f>=A?d=A:r===L&&f>=L?d=L:r===S&&f>=S&&(d=S),d>=u&&(d=u,l=!0);var h=a+d;if(t.rangebreaks&&d>0){for(var p=0,v=0;v<84;v++){var O=(v+.5)/84;t.maskBreaks(a*(1-O)+O*h)!==P&&p++}(d*=p/84)||(e[n].drop=!0),l&&u>k&&(d=u)}(d>0||0===n)&&(e[n].periodX=a+d/2)}}(D,e,e._definedDelta),e.rangebreaks){var ae="y"===e._id.charAt(0),le=1;"auto"===e.tickmode&&(le=e.tickfont?e.tickfont.size:12);var se=NaN;for(r=D.length-1;r>-1;r--)if(D[r].drop)D.splice(r,1);else{D[r].value=ze(D[r].value,e);var ce=e.c2p(D[r].value);(ae?se>ce-le:seh||feh&&(ue.periodX=h),fe10||"01-01"!==n.substr(5)?e._tickround="d":e._tickround=+t.substr(1)%12==0?"y":"m";else if(t>=A&&i<=10||t>=15*A)e._tickround="d";else if(t>=O&&i<=16||t>=S)e._tickround="M";else if(t>=D&&i<=19||t>=O)e._tickround="S";else{var o=e.l2r(r+t).replace(/^-/,"").length;e._tickround=Math.max(i,o)-20,e._tickround<0&&(e._tickround=4)}}else if(a(t)||"L"===t.charAt(0)){var l=e.range.map(e.r2d||Number);a(t)||(t=Number(t.substr(1))),e._tickround=2-Math.floor(Math.log(t)/Math.LN10+.01);var s=Math.max(Math.abs(l[0]),Math.abs(l[1])),c=Math.floor(Math.log(s)/Math.LN10+.01),u=void 0===e.minexponent?3:e.minexponent;Math.abs(c)>u&&(me(e.exponentformat)&&!xe(c)?e._tickexponent=3*Math.round((c-1)/3):e._tickexponent=c)}else e._tickround=null}function ye(e,t,r){var n=e.tickfont||{};return{x:t,dx:0,dy:0,text:r||"",fontSize:n.size,font:n.family,fontColor:n.color}}V.autoTicks=function(e,t,r){var n;function i(e){return Math.pow(e,Math.floor(Math.log(t)/Math.LN10))}if("date"===e.type){e.tick0=l.dateTick0(e.calendar,0);var o=2*t;if(o>g)t/=g,n=i(10),e.dtick="M"+12*pe(t,n,le);else if(o>T)t/=T,e.dtick="M"+pe(t,1,se);else if(o>A){if(e.dtick=pe(t,A,e._hasDayOfWeekBreaks?[1,2,7,14]:ue),!r){var s=V.getTickFormat(e),c="period"===e.ticklabelmode;c&&(e._rawTick0=e.tick0),/%[uVW]/.test(s)?e.tick0=l.dateTick0(e.calendar,2):e.tick0=l.dateTick0(e.calendar,1),c&&(e._dowTick0=e.tick0)}}else o>S?e.dtick=pe(t,S,se):o>O?e.dtick=pe(t,O,ce):o>D?e.dtick=pe(t,D,ce):(n=i(10),e.dtick=pe(t,n,le))}else if("log"===e.type){e.tick0=0;var u=l.simpleMap(e.range,e.r2l);if(e._isMinor&&(t*=1.5),t>.7)e.dtick=Math.ceil(t);else if(Math.abs(u[1]-u[0])<1){var f=1.5*Math.abs((u[1]-u[0])/t);t=Math.abs(Math.pow(10,u[1])-Math.pow(10,u[0]))/f,n=i(10),e.dtick="L"+pe(t,n,le)}else e.dtick=t>.3?"D2":"D1"}else"category"===e.type||"multicategory"===e.type?(e.tick0=0,e.dtick=Math.ceil(Math.max(t,1))):Re(e)?(e.tick0=0,n=1,e.dtick=pe(t,n,he)):(e.tick0=0,n=i(10),e.dtick=pe(t,n,le));if(0===e.dtick&&(e.dtick=1),!a(e.dtick)&&"string"!=typeof e.dtick){var d=e.dtick;throw e.dtick=1,"ax.dtick error: "+String(d)}},V.tickIncrement=function(e,t,r,i){var o=r?-1:1;if(a(t))return l.increment(e,o*t);var s=t.charAt(0),c=o*Number(t.substr(1));if("M"===s)return l.incrementMonth(e,c,i);if("L"===s)return Math.log(Math.pow(10,e)+c)/Math.LN10;if("D"===s){var u="D2"===t?de:fe,f=e+.01*o,d=l.roundUp(l.mod(f,1),u,r);return Math.floor(f)+Math.log(n.round(Math.pow(10,d),1))/Math.LN10}throw"unrecognized dtick "+String(t)},V.tickFirst=function(e,t){var r=e.r2l||Number,i=l.simpleMap(e.range,r,void 0,void 0,t),o=i[1] ")}else e._prevDateHead=s,c+="
"+s;t.text=c}(e,o,r,c):"log"===u?function(e,t,r,n,i){var o=e.dtick,s=t.x,c=e.tickformat,u="string"==typeof o&&o.charAt(0);if("never"===i&&(i=""),n&&"L"!==u&&(o="L3",u="L"),c||"L"===u)t.text=be(Math.pow(10,s),e,i,n);else if(a(o)||"D"===u&&l.mod(s+.01,1)<.1){var f=Math.round(s),d=Math.abs(f),h=e.exponentformat;"power"===h||me(h)&&xe(f)?(t.text=0===f?1:1===f?"10":"10"+(f>1?"":C)+d+"",t.fontSize*=1.25):("e"===h||"E"===h)&&d>2?t.text="1"+h+(f>0?"+":C)+d:(t.text=be(Math.pow(10,s),e,"","fakehover"),"D1"===o&&"y"===e._id.charAt(0)&&(t.dy-=t.fontSize/6))}else{if("D"!==u)throw"unrecognized dtick "+String(o);t.text=String(Math.round(Math.pow(10,l.mod(s,1)))),t.fontSize*=.75}if("D1"===e.dtick){var p=String(t.text).charAt(0);"0"!==p&&"1"!==p||("y"===e._id.charAt(0)?t.dx-=t.fontSize/4:(t.dy+=t.fontSize/2,t.dx+=(e.range[1]>e.range[0]?1:-1)*t.fontSize*(s<0?.5:.25)))}}(e,o,0,c,v):"category"===u?function(e,t){var r=e._categories[Math.round(t.x)];void 0===r&&(r=""),t.text=String(r)}(e,o):"multicategory"===u?function(e,t,r){var n=Math.round(t.x),a=e._categories[n]||[],i=void 0===a[1]?"":String(a[1]),o=void 0===a[0]?"":String(a[0]);r?t.text=o+" - "+i:(t.text=i,t.text2=o)}(e,o,r):Re(e)?function(e,t,r,n,a){if("radians"!==e.thetaunit||r)t.text=be(t.x,e,a,n);else{var i=t.x/180;if(0===i)t.text="0";else{var o=function(e){function t(e,t){return Math.abs(e-t)<=1e-6}function r(e,n){return t(n,0)?e:r(n,e%n)}function n(e){for(var r=1;!t(Math.round(e*r)/r,e);)r*=10;return r}var a=n(e),i=e*a,o=Math.abs(r(i,a));return[Math.round(i/o),Math.round(a/o)]}(i);if(o[1]>=100)t.text=be(l.deg2rad(t.x),e,a,n);else{var s=t.x<0;1===o[1]?1===o[0]?t.text="\u03c0":t.text=o[0]+"\u03c0":t.text=["",o[0],"","\u2044","",o[1],"","\u03c0"].join(""),s&&(t.text=C+t.text)}}}}(e,o,r,c,v):function(e,t,r,n,a){"never"===a?a="":"all"===e.showexponent&&Math.abs(t.x/e.dtick)<1e-6&&(a="hide"),t.text=be(t.x,e,a,n)}(e,o,0,c,v),n||(e.tickprefix&&!p(e.showtickprefix)&&(o.text=e.tickprefix+o.text),e.ticksuffix&&!p(e.showticksuffix)&&(o.text+=e.ticksuffix)),e.labelalias&&e.labelalias.hasOwnProperty(o.text)){var y=e.labelalias[o.text];"string"==typeof y&&(o.text=y)}if("boundaries"===e.tickson||e.showdividers){var g=function(t){var r=e.l2p(t);return r>=0&&r<=e._length?t:null};o.xbnd=[g(o.x-.5),g(o.x+e.dtick-.5)]}return o},V.hoverLabelText=function(e,t,r){r&&(e=l.extendFlat({},e,{hoverformat:r}));var n=Array.isArray(t)?t[0]:t,a=Array.isArray(t)?t[1]:void 0;if(void 0!==a&&a!==n)return V.hoverLabelText(e,n,r)+" - "+V.hoverLabelText(e,a,r);var i="log"===e.type&&n<=0,o=V.tickText(e,e.c2l(i?-n:n),"hover").text;return i?0===n?"0":C+o:o};var ge=["f","p","n","\u03bc","m","","k","M","G","T"];function me(e){return"SI"===e||"B"===e}function xe(e){return e>14||e<-15}function be(e,t,r,n){var i=e<0,o=t._tickround,s=r||t.exponentformat||"B",c=t._tickexponent,u=V.getTickFormat(t),f=t.separatethousands;if(n){var d={exponentformat:s,minexponent:t.minexponent,dtick:"none"===t.showexponent?t.dtick:a(e)&&Math.abs(e)||1,range:"none"===t.showexponent?t.range.map(t.r2d):[0,e||1]};ve(d),o=(Number(d._tickround)||0)+4,c=d._tickexponent,t.hoverformat&&(u=t.hoverformat)}if(u)return t._numFormat(u)(e).replace(/-/g,C);var h,p=Math.pow(10,-o)/2;if("none"===s&&(c=0),(e=Math.abs(e))"+h+"":"B"===s&&9===c?e+="B":me(s)&&(e+=ge[c/3+5])),i?C+e:e}function _e(e,t){if(e){var r=Object.keys(F).reduce((function(e,r){return-1!==t.indexOf(r)&&F[r].forEach((function(t){e[t]=1})),e}),{});Object.keys(e).forEach((function(t){r[t]||(1===t.length?e[t]=0:delete e[t])}))}}function we(e,t){for(var r=[],n={},a=0;a1&&r=a.min&&e=0,i=u(e,t[1])<=0;return(r||a)&&(n||i)}if(e.tickformatstops&&e.tickformatstops.length>0)switch(e.type){case"date":case"linear":for(t=0;t=o(a)))){r=n;break}break;case"log":for(t=0;t=0&&a.unshift(a.splice(n,1).shift())}}));var o={false:{left:0,right:0}};return l.syncOrAsync(a.map((function(t){return function(){if(t){var n=V.getFromId(e,t);r||(r={}),r.axShifts=o,r.overlayingShiftedAx=i;var a=V.drawOne(e,n,r);return n._shiftPusher&&Fe(n,n._fullDepth||0,o,!0),n._r=n.range.slice(),n._rl=l.simpleMap(n._r,n.r2l),a}}})))},V.drawOne=function(e,t,r){var n,a,s,c=(r=r||{}).axShifts||{},h=r.overlayingShiftedAx||[];t.setScale();var p=e._fullLayout,v=t._id,y=v.charAt(0),g=V.counterLetter(v),m=p._plots[t._mainSubplot];if(m){if(t._shiftPusher=t.autoshift||-1!==h.indexOf(t._id)||-1!==h.indexOf(t.overlaying),t._shiftPusher&"free"===t.anchor){var x=t.linewidth/2||0;"inside"===t.ticks&&(x+=t.ticklen),Fe(t,x,c,!0),Fe(t,t.shift||0,c,!1)}!0===r.skipTitle&&void 0!==t._shift||(t._shift=function(e,t){return e.autoshift?t[e.overlaying][e.side]:e.shift||0}(t,c));var b=m[y+"axislayer"],_=t._mainLinePosition,w=_+=t._shift,T=t._mainMirrorPosition,M=t._vals=V.calcTicks(t),k=[t.mirror,w,T].join("_");for(n=0;n0?r.bottom-u:0,f))));var d=0,h=0;if(t._shiftPusher&&(d=Math.max(f,r.height>0?"l"===s?u-r.left:r.right-u:0),t.title.text!==p._dfltTitle[y]&&(h=(t._titleStandoff||0)+(t._titleScoot||0),"l"===s&&(h+=ke(t))),t._fullDepth=Math.max(d,h)),t.automargin){n={x:0,y:0,r:0,l:0,t:0,b:0};var v=[0,1],m="number"==typeof t._shift?t._shift:0;if("x"===y){if("b"===s?n[s]=t._depth:(n[s]=t._depth=Math.max(r.width>0?u-r.top:0,f),v.reverse()),r.width>0){var x=r.right-(t._offset+t._length);x>0&&(n.xr=1,n.r=x);var b=t._offset-r.left;b>0&&(n.xl=0,n.l=b)}}else if("l"===s?(t._depth=Math.max(r.height>0?u-r.left:0,f),n[s]=t._depth-m):(t._depth=Math.max(r.height>0?r.right-u:0,f),n[s]=t._depth+m,v.reverse()),r.height>0){var _=r.bottom-(t._offset+t._length);_>0&&(n.yb=0,n.b=_);var w=t._offset-r.top;w>0&&(n.yt=1,n.t=w)}n[g]="free"===t.anchor?t.position:t._anchorAxis.domain[v[0]],t.title.text!==p._dfltTitle[y]&&(n[s]+=ke(t)+(t.title.standoff||0)),t.mirror&&"free"!==t.anchor&&((a={x:0,y:0,r:0,l:0,t:0,b:0})[c]=t.linewidth,t.mirror&&!0!==t.mirror&&(a[c]+=f),!0===t.mirror||"ticks"===t.mirror?a[g]=t._anchorAxis.domain[v[1]]:"all"!==t.mirror&&"allticks"!==t.mirror||(a[g]=[t._counterDomainMin,t._counterDomainMax][v[1]]))}se&&(l=o.getComponentMethod("rangeslider","autoMarginOpts")(e,t)),"string"==typeof t.automargin&&(_e(n,t.automargin),_e(a,t.automargin)),i.autoMargin(e,Se(t),n),i.autoMargin(e,Oe(t),a),i.autoMargin(e,De(t),l)})),l.syncOrAsync(oe)}}function ce(e){var r=v+(e||"tick");return A[r]||(A[r]=function(e,t){var r,n,a,i;return e._selections[t].size()?(r=1/0,n=-1/0,a=1/0,i=-1/0,e._selections[t].each((function(){var e=Le(this),t=d.bBox(e.node().parentNode);r=Math.min(r,t.top),n=Math.max(n,t.bottom),a=Math.min(a,t.left),i=Math.max(i,t.right)}))):(r=0,n=0,a=0,i=0),{top:r,bottom:n,left:a,right:i,height:n-r,width:i-a}}(t,r)),A[r]}},V.getTickSigns=function(e,t){var r=e._id.charAt(0),n={x:"top",y:"right"}[r],a=e.side===n?1:-1,i=[-1,1,a,-a];return"inside"!==(t?(e.minor||{}).ticks:e.ticks)==("x"===r)&&(i=i.map((function(e){return-e}))),e.side&&i.push({l:-1,t:-1,r:1,b:1}[e.side.charAt(0)]),i},V.makeTransTickFn=function(e){return"x"===e._id.charAt(0)?function(t){return s(e._offset+e.l2p(t.x),0)}:function(t){return s(0,e._offset+e.l2p(t.x))}},V.makeTransTickLabelFn=function(e){var t=function(e){var t=e.ticklabelposition||"",r=function(e){return-1!==t.indexOf(e)},n=r("top"),a=r("left"),i=r("right"),o=r("bottom"),l=r("inside"),s=o||a||n||i;if(!s&&!l)return[0,0];var c=e.side,u=s?(e.tickwidth||0)/2:0,f=3,d=e.tickfont?e.tickfont.size:12;return(o||n)&&(u+=d*B,f+=(e.linewidth||0)/2),(a||i)&&(u+=(e.linewidth||0)/2,f+=3),l&&"top"===c&&(f-=d*(1-B)),(a||n)&&(u=-u),"bottom"!==c&&"right"!==c||(f=-f),[s?u:0,l?f:0]}(e),r=t[0],n=t[1];return"x"===e._id.charAt(0)?function(t){return s(r+e._offset+e.l2p(Te(t)),n)}:function(t){return s(n,r+e._offset+e.l2p(Te(t)))}},V.makeTickPath=function(e,t,r,n){n||(n={});var a=n.minor;if(a&&!e.minor)return"";var i=void 0!==n.len?n.len:a?e.minor.ticklen:e.ticklen,o=e._id.charAt(0),l=(e.linewidth||1)/2;return"x"===o?"M0,"+(t+l*r)+"v"+i*r:"M"+(t+l*r)+",0h"+i*r},V.makeLabelFns=function(e,t,r){var n=e.ticklabelposition||"",i=function(e){return-1!==n.indexOf(e)},o=i("top"),s=i("left"),c=i("right"),u=i("bottom")||s||o||c,f=i("inside"),d="inside"===n&&"inside"===e.ticks||!f&&"outside"===e.ticks&&"boundaries"!==e.tickson,h=0,p=0,v=d?e.ticklen:0;if(f?v*=-1:u&&(v=0),d&&(h+=v,r)){var y=l.deg2rad(r);h=v*Math.cos(y)+1,p=v*Math.sin(y)}e.showticklabels&&(d||e.showline)&&(h+=.2*e.tickfont.size);var g,m,x,b,_,w={labelStandoff:h+=(e.linewidth||1)/2*(f?-1:1),labelShift:p},T=0,M=e.side,k=e._id.charAt(0),A=e.tickangle;if("x"===k)b=(_=!f&&"bottom"===M||f&&"top"===M)?1:-1,f&&(b*=-1),g=p*b,m=t+h*b,x=_?1:-.2,90===Math.abs(A)&&(f?x+=j:x=-90===A&&"bottom"===M?B:90===A&&"top"===M?j:.5,T=j/2*(A/90)),w.xFn=function(e){return e.dx+g+T*e.fontSize},w.yFn=function(e){return e.dy+m+e.fontSize*x},w.anchorFn=function(e,t){if(u){if(s)return"end";if(c)return"start"}return a(t)&&0!==t&&180!==t?t*b<0!==f?"end":"start":"middle"},w.heightFn=function(t,r,n){return r<-60||r>60?-.5*n:"top"===e.side!==f?-n:0};else if("y"===k){if(b=(_=!f&&"left"===M||f&&"right"===M)?1:-1,f&&(b*=-1),g=h,m=p*b,x=0,f||90!==Math.abs(A)||(x=-90===A&&"left"===M||90===A&&"right"===M?B:.5),f){var L=a(A)?+A:0;if(0!==L){var S=l.deg2rad(L);T=Math.abs(Math.sin(S))*B*b,x=0}}w.xFn=function(e){return e.dx+t-(g+e.fontSize*x)*b+T*e.fontSize},w.yFn=function(e){return e.dy+m+e.fontSize*j},w.anchorFn=function(e,t){return a(t)&&90===Math.abs(t)?"middle":_?"end":"start"},w.heightFn=function(t,r,n){return"right"===e.side&&(r*=-1),r<-30?-n:r<30?-.5*n:0}}return w},V.drawTicks=function(e,t,r){r=r||{};var a=t._id+"tick",i=[].concat(t.minor&&t.minor.ticks?r.vals.filter((function(e){return e.minor&&!e.noTick})):[]).concat(t.ticks?r.vals.filter((function(e){return!e.minor&&!e.noTick})):[]),o=r.layer.selectAll("path."+a).data(i,Me);o.exit().remove(),o.enter().append("path").classed(a,1).classed("ticks",1).classed("crisp",!1!==r.crisp).each((function(e){return f.stroke(n.select(this),e.minor?t.minor.tickcolor:t.tickcolor)})).style("stroke-width",(function(r){return d.crispRound(e,r.minor?t.minor.tickwidth:t.tickwidth,1)+"px"})).attr("d",r.path).style("display",null),Ee(t,[N]),o.attr("transform",r.transFn)},V.drawGrid=function(e,t,r){if(r=r||{},"sync"!==t.tickmode){var a=t._id+"grid",i=t.minor&&t.minor.showgrid,o=i?r.vals.filter((function(e){return e.minor})):[],l=t.showgrid?r.vals.filter((function(e){return!e.minor})):[],s=r.counterAxis;if(s&&V.shouldShowZeroLine(e,t,s))for(var c="array"===t.tickmode,u=0;u=0;g--){var m=g?v:y;if(m){var x=m.selectAll("path."+a).data(g?l:o,Me);x.exit().remove(),x.enter().append("path").classed(a,1).classed("crisp",!1!==r.crisp),x.attr("transform",r.transFn).attr("d",r.path).each((function(e){return f.stroke(n.select(this),e.minor?t.minor.gridcolor:t.gridcolor||"#ddd")})).style("stroke-dasharray",(function(e){return d.dashStyle(e.minor?t.minor.griddash:t.griddash,e.minor?t.minor.gridwidth:t.gridwidth)})).style("stroke-width",(function(e){return(e.minor?p:t._gw)+"px"})).style("display",null),"function"==typeof r.path&&x.attr("d",r.path)}}Ee(t,[R,z])}},V.drawZeroLine=function(e,t,r){r=r||r;var n=t._id+"zl",a=V.shouldShowZeroLine(e,t,r.counterAxis),i=r.layer.selectAll("path."+n).data(a?[{x:0,id:t._id}]:[]);i.exit().remove(),i.enter().append("path").classed(n,1).classed("zl",1).classed("crisp",!1!==r.crisp).each((function(){r.layer.selectAll("path").sort((function(e,t){return G(e.id,t.id)}))})),i.attr("transform",r.transFn).attr("d",r.path).call(f.stroke,t.zerolinecolor||f.defaultLine).style("stroke-width",d.crispRound(e,t.zerolinewidth,t._gw||1)+"px").style("display",null),Ee(t,[I])},V.drawLabels=function(e,t,r){r=r||{};var i=e._fullLayout,o=t._id,u=o.charAt(0),f=r.cls||o+"tick",h=r.vals.filter((function(e){return e.text})),p=r.labelFns,v=r.secondary?0:t.tickangle,y=(t._prevTickAngles||{})[f],g=r.layer.selectAll("g."+f).data(t.showticklabels?h:[],Me),m=[];function x(e,i){e.each((function(e){var o=n.select(this),l=o.select(".text-math-group"),u=p.anchorFn(e,i),f=r.transFn.call(o.node(),e)+(a(i)&&0!=+i?" rotate("+i+","+p.xFn(e)+","+(p.yFn(e)-e.fontSize/2)+")":""),h=c.lineCount(o),v=Y*e.fontSize,y=p.heightFn(e,a(i)?+i:0,(h-1)*v);if(y&&(f+=s(0,y)),l.empty()){var g=o.select("text");g.attr({transform:f,"text-anchor":u}),g.style("opacity",1),t._adjustTickLabelsOverflow&&t._adjustTickLabelsOverflow()}else{var m=d.bBox(l.node()).width*{end:-.5,start:.5}[u];l.attr("transform",f+s(m,0))}}))}g.enter().append("g").classed(f,1).append("text").attr("text-anchor","middle").each((function(t){var r=n.select(this),a=e._promises.length;r.call(c.positionText,p.xFn(t),p.yFn(t)).call(d.font,t.font,t.fontSize,t.fontColor).text(t.text).call(c.convertToTspans,e),e._promises[a]?m.push(e._promises.pop().then((function(){x(r,v)}))):x(r,v)})),Ee(t,[E]),g.exit().remove(),r.repositionOnUpdate&&g.each((function(e){n.select(this).select("text").call(c.positionText,p.xFn(e),p.yFn(e))})),t._adjustTickLabelsOverflow=function(){var r=t.ticklabeloverflow;if(r&&"allow"!==r){var a=-1!==r.indexOf("hide"),o="x"===t._id.charAt(0),s=0,c=o?e._fullLayout.width:e._fullLayout.height;if(-1!==r.indexOf("domain")){var u=l.simpleMap(t.range,t.r2l);s=t.l2p(u[0])+t._offset,c=t.l2p(u[1])+t._offset}var f=Math.min(s,c),h=Math.max(s,c),p=t.side,v=1/0,y=-1/0;for(var m in g.each((function(e){var r=n.select(this);if(r.select(".text-math-group").empty()){var i=d.bBox(r.node()),l=0;o?(i.right>h||i.lefth||i.top+(t.tickangle?0:e.fontSize/4)t["_visibleLabelMin_"+r._id]?s.style("display","none"):"tick"!==e.K||a||s.style("display",null)}))}))}))}))},x(g,y+1?y:v);var b=null;t._selections&&(t._selections[f]=g);var _=[function(){return m.length&&Promise.all(m)}];t.automargin&&i._redrawFromAutoMarginCount&&90===y?(b=90,_.push((function(){x(g,y)}))):_.push((function(){if(x(g,v),h.length&&"x"===u&&!a(v)&&("log"!==t.type||"D"!==String(t.dtick).charAt(0))){b=0;var e,n=0,i=[];if(g.each((function(e){n=Math.max(n,e.fontSize);var r=t.l2p(e.x),a=Le(this),o=d.bBox(a.node());i.push({top:0,bottom:10,height:10,left:r-o.width/2,right:r+o.width/2+2,width:o.width+2})})),"boundaries"!==t.tickson&&!t.showdividers||r.secondary){var o=h.length,s=Math.abs((h[o-1].x-h[0].x)*t._m)/(o-1),c=t.ticklabelposition||"",f=function(e){return-1!==c.indexOf(e)},p=f("top"),y=f("left"),m=f("right"),_=f("bottom")||y||p||m?(t.tickwidth||0)+6:0,w=s<2.5*n||"multicategory"===t.type||"realaxis"===t._name;for(e=0;e1)for(n=1;n2*o}(a,t))return"date";var y="strict"!==r.autotypenumbers;return function(e,t){for(var r=e.length,n=f(r),a=0,o=0,l={},u=0;u2*a}(a,y)?"category":function(e,t){for(var r=e.length,n=0;n=2){var l,c,u="";if(2===o.length)for(l=0;l<2;l++)if(c=b(o[l])){u=y;break}var f=a("pattern",u);if(f===y)for(l=0;l<2;l++)(c=b(o[l]))&&(t.bounds[l]=o[l]=c-1);if(f)for(l=0;l<2;l++)switch(c=o[l],f){case y:if(!n(c))return void(t.enabled=!1);if((c=+c)!==Math.floor(c)||c<0||c>=7)return void(t.enabled=!1);t.bounds[l]=o[l]=c;break;case g:if(!n(c))return void(t.enabled=!1);if((c=+c)<0||c>24)return void(t.enabled=!1);t.bounds[l]=o[l]=c}if(!1===r.autorange){var d=r.range;if(d[0]d[1])return void(t.enabled=!1)}else if(o[0]>d[0]&&o[1]n?1:-1:+(e.substr(1)||1)-+(t.substr(1)||1)},t.ref2id=function(e){return!!/^[xyz]/.test(e)&&e.split(" ")[0]},t.isLinked=function(e,t){return i(t,e._axisMatchGroups)||i(t,e._axisConstraintGroups)}},5258:function(e){"use strict";e.exports=function(e,t,r,n){if("category"===t.type){var a,i=e.categoryarray,o=Array.isArray(i)&&i.length>0;o&&(a="array");var l,s=r("categoryorder",a);"array"===s&&(l=r("categoryarray")),o||"array"!==s||(s=t.categoryorder="trace"),"trace"===s?t._initialCategories=[]:"array"===s?t._initialCategories=l.slice():(l=function(e,t){var r,n,a,i=t.dataAttr||e._id.charAt(0),o={};if(t.axData)r=t.axData;else for(r=[],n=0;nn?a.substr(n):i.substr(r))+o:a+i+e*t:o}function y(e,t){for(var r=t._size,n=r.h/r.w,a={},i=Object.keys(e),o=0;oc*x)||T)for(r=0;rI&&EC&&(C=E);d/=(C-D)/(2*P),D=s.l2r(D),C=s.l2r(C),s.range=s._input.range=L=0?Math.min(e,.9):1/(1/Math.max(e,-.3)+3.222))}function H(e,t,r,n,a){return e.append("path").attr("class","zoombox").style({fill:t>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("transform",c(r,n)).attr("d",a+"Z")}function j(e,t,r){return e.append("path").attr("class","zoombox-corners").style({fill:f.background,stroke:f.defaultLine,"stroke-width":1,opacity:0}).attr("transform",c(t,r)).attr("d","M0,0Z")}function B(e,t,r,n,a,i){e.attr("d",n+"M"+r.l+","+r.t+"v"+r.h+"h"+r.w+"v-"+r.h+"h-"+r.w+"Z"),Y(e,t,a,i)}function Y(e,t,r,n){r||(e.transition().style("fill",n>.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),t.transition().style("opacity",1).duration(200))}function U(e){n.select(e).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function V(e){P&&e.data&&e._context.showTips&&(a.notifier(a._(e,"Double-click to zoom back out"),"long"),P=!1)}function q(e){var t=Math.floor(Math.min(e.b-e.t,e.r-e.l,C)/2);return"M"+(e.l-3.5)+","+(e.t-.5+t)+"h3v"+-t+"h"+t+"v-3h-"+(t+3)+"ZM"+(e.r+3.5)+","+(e.t-.5+t)+"h-3v"+-t+"h"+-t+"v-3h"+(t+3)+"ZM"+(e.r+3.5)+","+(e.b+.5-t)+"h-3v"+t+"h"+-t+"v3h"+(t+3)+"ZM"+(e.l-3.5)+","+(e.b+.5-t)+"h3v"+t+"h"+t+"v3h-"+(t+3)+"Z"}function Z(e,t,r,n,i){for(var o,l,s,c,u=!1,f={},d={},h=(i||{}).xaHash,p=(i||{}).yaHash,v=0;v=0)a._fullLayout._deactivateShape(a);else{var o=a._fullLayout.clickmode;if(U(a),2!==e||ge||Ve(),ye)o.indexOf("select")>-1&&L(r,a,J,K,t.id,Ce),o.indexOf("event")>-1&&h.click(a,r,t.id);else if(1===e&&ge){var l=v?I:P,c="s"===v||"w"===g?0:1,f=l._name+".range["+c+"]",d=function(e,t){var r,n=e.range[t],a=Math.abs(n-e.range[1-t]);return"date"===e.type?n:"log"===e.type?(r=Math.ceil(Math.max(0,-Math.log(a)/Math.LN10))+3,i("."+r+"g")(Math.pow(10,n))):(r=Math.floor(Math.log(Math.abs(n))/Math.LN10)-Math.floor(Math.log(a)/Math.LN10)+4,i("."+String(r)+"g")(n))}(l,c),p="left",y="middle";if(l.fixedrange)return;v?(y="n"===v?"top":"bottom","right"===l.side&&(p="right")):"e"===g&&(p="right"),a._context.showAxisRangeEntryBoxes&&n.select(be).call(u.makeEditable,{gd:a,immediate:!0,background:a._fullLayout.paper_bgcolor,text:String(d),fill:l.tickfont?l.tickfont.color:"#444",horizontalAlign:p,verticalAlign:y}).on("edit",(function(e){var t=l.d2r(e);void 0!==t&&s.call("_guiRelayout",a,f,t)}))}}}function Re(t,r){if(e._transitioningWithDuration)return!1;var n=Math.max(0,Math.min(ee,he*t+_e)),a=Math.max(0,Math.min(te,pe*r+we)),i=Math.abs(n-_e),o=Math.abs(a-we);function l(){Le="",Te.r=Te.l,Te.t=Te.b,Oe.attr("d","M0,0Z")}if(Te.l=Math.min(_e,n),Te.r=Math.max(_e,n),Te.t=Math.min(we,a),Te.b=Math.max(we,a),re.isSubplotConstrained)i>C||o>C?(Le="xy",i/ee>o/te?(o=i*te/ee,we>a?Te.t=we-o:Te.b=we+o):(i=o*ee/te,_e>n?Te.l=_e-i:Te.r=_e+i),Oe.attr("d",q(Te))):l();else if(ne.isSubplotConstrained)if(i>C||o>C){Le="xy";var s=Math.min(Te.l/ee,(te-Te.b)/te),c=Math.max(Te.r/ee,(te-Te.t)/te);Te.l=s*ee,Te.r=c*ee,Te.b=(1-s)*te,Te.t=(1-c)*te,Oe.attr("d",q(Te))}else l();else!ie||o0){var u;if(ne.isSubplotConstrained||!ae&&1===ie.length){for(u=0;ub[1]-1/4096&&(t.domain=l),a.noneOrAll(e.domain,t.domain,l),"sync"===t.tickmode&&(t.tickmode="auto")}return r("layer"),t}},9426:function(e,t,r){"use strict";var n=r(9652);e.exports=function(e,t,r,a,i){i||(i={});var o=i.tickSuffixDflt,l=n(e);r("tickprefix")&&r("showtickprefix",l),r("ticksuffix",o)&&r("showticksuffix",l)}},2449:function(e,t,r){"use strict";var n=r(8783).FROM_BL;e.exports=function(e,t,r){void 0===r&&(r=n[e.constraintoward||"center"]);var a=[e.r2l(e.range[0]),e.r2l(e.range[1])],i=a[0]+(a[1]-a[0])*r;e.range=e._input.range=[e.l2r(i+(a[0]-i)*t),e.l2r(i+(a[1]-i)*t)],e.setScale()}},1994:function(e,t,r){"use strict";var n=r(9898),a=r(4096).g0,i=r(1828),o=i.numberFormat,l=r(2770),s=i.cleanNumber,c=i.ms2DateTime,u=i.dateTime2ms,f=i.ensureNumber,d=i.isArrayOrTypedArray,h=r(606),p=h.FP_SAFE,v=h.BADNUM,y=h.LOG_CLIP,g=h.ONEWEEK,m=h.ONEDAY,x=h.ONEHOUR,b=h.ONEMIN,_=h.ONESEC,w=r(1675),T=r(5555),M=T.HOUR_PATTERN,k=T.WEEKDAY_PATTERN;function A(e){return Math.pow(10,e)}function L(e){return null!=e}e.exports=function(e,t){t=t||{};var r=e._id||"x",h=r.charAt(0);function S(t,r){if(t>0)return Math.log(t)/Math.LN10;if(t<=0&&r&&e.range&&2===e.range.length){var n=e.range[0],a=e.range[1];return.5*(n+a-2*y*Math.abs(n-a))}return v}function O(t,r,n,a){if((a||{}).msUTC&&l(t))return+t;var o=u(t,n||e.calendar);if(o===v){if(!l(t))return v;t=+t;var s=Math.floor(10*i.mod(t+.05,1)),c=Math.round(t-s/10);o=u(new Date(c))+s/10}return o}function D(t,r,n){return c(t,r,n||e.calendar)}function C(t){return e._categories[Math.round(t)]}function P(t){if(L(t)){if(void 0===e._categoriesMap&&(e._categoriesMap={}),void 0!==e._categoriesMap[t])return e._categoriesMap[t];e._categories.push("number"==typeof t?String(t):t);var r=e._categories.length-1;return e._categoriesMap[t]=r,r}return v}function I(t){if(e._categoriesMap)return e._categoriesMap[t]}function R(e){var t=I(e);return void 0!==t?t:l(e)?+e:void 0}function z(e){return l(e)?+e:I(e)}function N(e,t,r){return n.round(r+t*e,2)}function E(e,t,r){return(e-r)/t}var F=function(t){return l(t)?N(t,e._m,e._b):v},H=function(t){return E(t,e._m,e._b)};if(e.rangebreaks){var j="y"===h;F=function(t){if(!l(t))return v;var r=e._rangebreaks.length;if(!r)return N(t,e._m,e._b);var n=j;e.range[0]>e.range[1]&&(n=!n);for(var a=n?-1:1,i=a*t,o=0,s=0;su)){o=i<(c+u)/2?s:s+1;break}o=s+1}var f=e._B[o]||0;return isFinite(f)?N(t,e._m2,f):0},H=function(t){var r=e._rangebreaks.length;if(!r)return E(t,e._m,e._b);for(var n=0,a=0;ae._rangebreaks[a].pmax&&(n=a+1);return E(t,e._m2,e._B[n])}}e.c2l="log"===e.type?S:f,e.l2c="log"===e.type?A:f,e.l2p=F,e.p2l=H,e.c2p="log"===e.type?function(e,t){return F(S(e,t))}:F,e.p2c="log"===e.type?function(e){return A(H(e))}:H,-1!==["linear","-"].indexOf(e.type)?(e.d2r=e.r2d=e.d2c=e.r2c=e.d2l=e.r2l=s,e.c2d=e.c2r=e.l2d=e.l2r=f,e.d2p=e.r2p=function(t){return e.l2p(s(t))},e.p2d=e.p2r=H,e.cleanPos=f):"log"===e.type?(e.d2r=e.d2l=function(e,t){return S(s(e),t)},e.r2d=e.r2c=function(e){return A(s(e))},e.d2c=e.r2l=s,e.c2d=e.l2r=f,e.c2r=S,e.l2d=A,e.d2p=function(t,r){return e.l2p(e.d2r(t,r))},e.p2d=function(e){return A(H(e))},e.r2p=function(t){return e.l2p(s(t))},e.p2r=H,e.cleanPos=f):"date"===e.type?(e.d2r=e.r2d=i.identity,e.d2c=e.r2c=e.d2l=e.r2l=O,e.c2d=e.c2r=e.l2d=e.l2r=D,e.d2p=e.r2p=function(t,r,n){return e.l2p(O(t,0,n))},e.p2d=e.p2r=function(e,t,r){return D(H(e),t,r)},e.cleanPos=function(t){return i.cleanDate(t,v,e.calendar)}):"category"===e.type?(e.d2c=e.d2l=P,e.r2d=e.c2d=e.l2d=C,e.d2r=e.d2l_noadd=R,e.r2c=function(t){var r=z(t);return void 0!==r?r:e.fraction2r(.5)},e.l2r=e.c2r=f,e.r2l=z,e.d2p=function(t){return e.l2p(e.r2c(t))},e.p2d=function(e){return C(H(e))},e.r2p=e.d2p,e.p2r=H,e.cleanPos=function(e){return"string"==typeof e&&""!==e?e:f(e)}):"multicategory"===e.type&&(e.r2d=e.c2d=e.l2d=C,e.d2r=e.d2l_noadd=R,e.r2c=function(t){var r=R(t);return void 0!==r?r:e.fraction2r(.5)},e.r2c_just_indices=I,e.l2r=e.c2r=f,e.r2l=R,e.d2p=function(t){return e.l2p(e.r2c(t))},e.p2d=function(e){return C(H(e))},e.r2p=e.d2p,e.p2r=H,e.cleanPos=function(e){return Array.isArray(e)||"string"==typeof e&&""!==e?e:f(e)},e.setupMultiCategory=function(n){var a,o,l=e._traceIndices,s=e._matchGroup;if(s&&0===e._categories.length)for(var c in s)if(c!==r){var u=t[w.id2name(c)];l=l.concat(u._traceIndices)}var f=[[0,{}],[0,{}]],p=[];for(a=0;ap&&(o[n]=p),o[0]===o[1]){var c=Math.max(1,Math.abs(1e-6*o[0]));o[0]-=c,o[1]+=c}}else i.nestedProperty(e,t).set(a)},e.setScale=function(r){var n=t._size;if(e.overlaying){var a=w.getFromId({_fullLayout:t},e.overlaying);e.domain=a.domain}var i=r&&e._r?"_r":"range",o=e.calendar;e.cleanRange(i);var l,s,c=e.r2l(e[i][0],o),u=e.r2l(e[i][1],o),f="y"===h;if(f?(e._offset=n.t+(1-e.domain[1])*n.h,e._length=n.h*(e.domain[1]-e.domain[0]),e._m=e._length/(c-u),e._b=-e._m*u):(e._offset=n.l+e.domain[0]*n.w,e._length=n.w*(e.domain[1]-e.domain[0]),e._m=e._length/(u-c),e._b=-e._m*c),e._rangebreaks=[],e._lBreaks=0,e._m2=0,e._B=[],e.rangebreaks&&(e._rangebreaks=e.locateBreaks(Math.min(c,u),Math.max(c,u)),e._rangebreaks.length)){for(l=0;lu&&(d=!d),d&&e._rangebreaks.reverse();var p=d?-1:1;for(e._m2=p*e._length/(Math.abs(u-c)-e._lBreaks),e._B.push(-e._m2*(f?u:c)),l=0;la&&(a+=7,oa&&(a+=24,o=n&&o=n&&t=l.min&&(el.max&&(l.max=n),a=!1)}a&&c.push({min:e,max:n})}};for(n=0;nr.duration?(function(){for(var r={},n=0;n rect").call(o.setTranslate,0,0).call(o.setScale,1,1),e.plot.call(o.setTranslate,t._offset,r._offset).call(o.setScale,1,1);var n=e.plot.selectAll(".scatterlayer .trace");n.selectAll(".point").call(o.setPointGroupScale,1,1),n.selectAll(".textpoint").call(o.setTextPointsScale,1,1),n.call(o.hideOutsideRangePoints,e)}function y(t,r){var n=t.plotinfo,a=n.xaxis,s=n.yaxis,c=a._length,u=s._length,f=!!t.xr1,d=!!t.yr1,h=[];if(f){var p=i.simpleMap(t.xr0,a.r2l),v=i.simpleMap(t.xr1,a.r2l),y=p[1]-p[0],g=v[1]-v[0];h[0]=(p[0]*(1-r)+r*v[0]-p[0])/(p[1]-p[0])*c,h[2]=c*(1-r+r*g/y),a.range[0]=a.l2r(p[0]*(1-r)+r*v[0]),a.range[1]=a.l2r(p[1]*(1-r)+r*v[1])}else h[0]=0,h[2]=c;if(d){var m=i.simpleMap(t.yr0,s.r2l),x=i.simpleMap(t.yr1,s.r2l),b=m[1]-m[0],_=x[1]-x[0];h[1]=(m[1]*(1-r)+r*x[1]-m[1])/(m[0]-m[1])*u,h[3]=u*(1-r+r*_/b),s.range[0]=a.l2r(m[0]*(1-r)+r*x[0]),s.range[1]=s.l2r(m[1]*(1-r)+r*x[1])}else h[1]=0,h[3]=u;l.drawOne(e,a,{skipTitle:!0}),l.drawOne(e,s,{skipTitle:!0}),l.redrawComponents(e,[a._id,s._id]);var w=f?c/h[2]:1,T=d?u/h[3]:1,M=f?h[0]:0,k=d?h[1]:0,A=f?h[0]/h[2]*c:0,L=d?h[1]/h[3]*u:0,S=a._offset-A,O=s._offset-L;n.clipRect.call(o.setTranslate,M,k).call(o.setScale,1/w,1/T),n.plot.call(o.setTranslate,S,O).call(o.setScale,w,T),o.setPointGroupScale(n.zoomScalePts,1/w,1/T),o.setTextPointsScale(n.zoomScaleTxt,1/w,1/T)}l.redrawComponents(e)}},951:function(e,t,r){"use strict";var n=r(3972).traceIs,a=r(4322);function i(e){return{v:"x",h:"y"}[e.orientation||"v"]}function o(e,t){var r=i(e),a=n(e,"box-violin"),o=n(e._fullInput||{},"candlestick");return a&&!o&&t===r&&void 0===e[r]&&void 0===e[r+"0"]}e.exports=function(e,t,r,l){r("autotypenumbers",l.autotypenumbersDflt),"-"===r("type",(l.splomStash||{}).type)&&(function(e,t){if("-"===e.type){var r,l=e._id,s=l.charAt(0);-1!==l.indexOf("scene")&&(l=s);var c=function(e,t,r){for(var n=0;n0&&(a["_"+r+"axes"]||{})[t])return a;if((a[r+"axis"]||r)===t){if(o(a,r))return a;if((a[r]||[]).length||a[r+"0"])return a}}}(t,l,s);if(c)if("histogram"!==c.type||s!=={v:"y",h:"x"}[c.orientation||"v"]){var u=s+"calendar",f=c[u],d={noMultiCategory:!n(c,"cartesian")||n(c,"noMultiCategory")};if("box"===c.type&&c._hasPreCompStats&&s==={h:"x",v:"y"}[c.orientation||"v"]&&(d.noMultiCategory=!0),d.autotypenumbers=e.autotypenumbers,o(c,s)){var h=i(c),p=[];for(r=0;r0?".":"")+i;a.isPlainObject(o)?s(o,t,l,n+1):t(l,i,o)}}))}t.manageCommandObserver=function(e,r,n,o){var l={},s=!0;r&&r._commandObserver&&(l=r._commandObserver),l.cache||(l.cache={}),l.lookupTable={};var c=t.hasSimpleAPICommandBindings(e,n,l.lookupTable);if(r&&r._commandObserver){if(c)return l;if(r._commandObserver.remove)return r._commandObserver.remove(),r._commandObserver=null,l}if(c){i(e,c,l.cache),l.check=function(){if(s){var t=i(e,c,l.cache);return t.changed&&o&&void 0!==l.lookupTable[t.value]&&(l.disable(),Promise.resolve(o({value:t.value,type:c.type,prop:c.prop,traces:c.traces,index:l.lookupTable[t.value]})).then(l.enable,l.enable)),t.changed}};for(var u=["plotly_relayout","plotly_redraw","plotly_restyle","plotly_update","plotly_animatingframe","plotly_afterplot"],f=0;f=t.width-20?(i["text-anchor"]="start",i.x=5):(i["text-anchor"]="end",i.x=t._paper.attr("width")-7),r.attr(i);var o=r.select(".js-link-to-tool"),l=r.select(".js-link-spacer"),s=r.select(".js-sourcelinks");e._context.showSources&&e._context.showSources(e),e._context.showLink&&function(e,t){t.text("");var r=t.append("a").attr({"xlink:xlink:href":"#",class:"link--impt link--embedview","font-weight":"bold"}).text(e._context.linkText+" "+String.fromCharCode(187));if(e._context.sendData)r.on("click",(function(){_.sendDataToCloud(e)}));else{var n=window.location.pathname.split("/"),a=window.location.search;r.attr({"xlink:xlink:show":"new","xlink:xlink:href":"/"+n[2].split(".")[0]+"/"+n[1]+a})}}(e,o),l.text(o.text()&&s.text()?" - ":"")}},_.sendDataToCloud=function(e){var t=(window.PLOTLYENV||{}).BASE_URL||e._context.plotlyServerURL;if(t){e.emit("plotly_beforeexport");var r=n.select(e).append("div").attr("id","hiddenform").style("display","none"),a=r.append("form").attr({action:t+"/external",method:"post",target:"_blank"});return a.append("input").attr({type:"text",name:"data"}).node().value=_.graphJson(e,!1,"keepdata"),a.node().submit(),r.remove(),e.emit("plotly_afterexport"),!1}};var M=["days","shortDays","months","shortMonths","periods","dateTime","date","time","decimal","thousands","grouping","currency"],k=["year","month","dayMonth","dayMonthYear"];function A(e,t){var r=e._context.locale;r||(r="en-US");var n=!1,a={};function i(e){for(var r=!0,i=0;i1&&R.length>1){for(l.getComponentMethod("grid","sizeDefaults")(c,s),o=0;o15&&R.length>15&&0===s.shapes.length&&0===s.images.length,_.linkSubplots(d,s,f,n),_.cleanPlot(d,s,f,n);var H=!(!n._has||!n._has("gl2d")),j=!(!s._has||!s._has("gl2d")),B=!(!n._has||!n._has("cartesian"))||H,Y=!(!s._has||!s._has("cartesian"))||j;B&&!Y?n._bgLayer.remove():Y&&!B&&(s._shouldCreateBgLayer=!0),n._zoomlayer&&!e._dragging&&p({_fullLayout:n}),function(e,t){var r,n=[];t.meta&&(r=t._meta={meta:t.meta,layout:{meta:t.meta}});for(var a=0;a0){var f=1-2*l;n=Math.round(f*n),a=Math.round(f*a)}}var d=_.layoutAttributes.width.min,h=_.layoutAttributes.height.min;n1,v=!t.height&&Math.abs(r.height-a)>1;(v||p)&&(p&&(r.width=n),v&&(r.height=a)),e._initialAutoSize||(e._initialAutoSize={width:n,height:a}),_.sanitizeMargins(r)},_.supplyLayoutModuleDefaults=function(e,t,r,n){var a,i,o,s=l.componentsRegistry,c=t._basePlotModules,f=l.subplotsRegistry.cartesian;for(a in s)(o=s[a]).includeBasePlot&&o.includeBasePlot(e,t);for(var d in c.length||c.push(f),t._has("cartesian")&&(l.getComponentMethod("grid","contentDefaults")(e,t),f.finalizeSubplots(e,t)),t._subplots)t._subplots[d].sort(u.subplotSort);for(i=0;i1&&(r.l/=g,r.r/=g)}if(h){var m=(r.t+r.b)/h;m>1&&(r.t/=m,r.b/=m)}var x=void 0!==r.xl?r.xl:r.x,b=void 0!==r.xr?r.xr:r.x,w=void 0!==r.yt?r.yt:r.y,T=void 0!==r.yb?r.yb:r.y;p[t]={l:{val:x,size:r.l+y},r:{val:b,size:r.r+y},b:{val:T,size:r.b+y},t:{val:w,size:r.t+y}},v[t]=1}else delete p[t],delete v[t];if(!n._replotting)return _.doAutoMargin(e)}},_.doAutoMargin=function(e){var t=e._fullLayout,r=t.width,n=t.height;t._size||(t._size={}),C(t);var a=t._size,i=t.margin,s={t:0,b:0,l:0,r:0},c=u.extendFlat({},a),f=i.l,d=i.r,p=i.t,v=i.b,y=t._pushmargin,g=t._pushmarginIds,m=t.minreducedwidth,x=t.minreducedheight;if(!1!==i.autoexpand){for(var b in y)g[b]||delete y[b];var w=e._fullLayout._reservedMargin;for(var T in w)for(var M in w[T]){var k=w[T][M];s[M]=Math.max(s[M],k)}for(var A in y.base={l:{val:0,size:f},r:{val:1,size:d},t:{val:1,size:p},b:{val:0,size:v}},s){var L=0;for(var S in y)"base"!==S&&o(y[S][A].size)&&(L=y[S][A].size>L?y[S][A].size:L);var O=Math.max(0,i[A]-L);s[A]=Math.max(0,s[A]-O)}for(var D in y){var P=y[D].l||{},I=y[D].b||{},R=P.val,z=P.size,N=I.val,E=I.size,F=r-s.r-s.l,H=n-s.t-s.b;for(var j in y){if(o(z)&&y[j].r){var B=y[j].r.val,Y=y[j].r.size;if(B>R){var U=(z*B+(Y-F)*R)/(B-R),V=(Y*(1-R)+(z-F)*(1-B))/(B-R);U+V>f+d&&(f=U,d=V)}}if(o(E)&&y[j].t){var q=y[j].t.val,Z=y[j].t.size;if(q>N){var G=(E*q+(Z-H)*N)/(q-N),W=(Z*(1-N)+(E-H)*(1-q))/(q-N);G+W>v+p&&(v=G,p=W)}}}}}var X=u.constrain(r-i.l-i.r,2,m),J=u.constrain(n-i.t-i.b,2,x),K=Math.max(0,r-X),Q=Math.max(0,n-J);if(K){var $=(f+d)/K;$>1&&(f/=$,d/=$)}if(Q){var ee=(v+p)/Q;ee>1&&(v/=ee,p/=ee)}if(a.l=Math.round(f)+s.l,a.r=Math.round(d)+s.r,a.t=Math.round(p)+s.t,a.b=Math.round(v)+s.b,a.p=Math.round(i.pad),a.w=Math.round(r)-a.l-a.r,a.h=Math.round(n)-a.t-a.b,!t._replotting&&(_.didMarginChange(c,a)||function(e){if("_redrawFromAutoMarginCount"in e._fullLayout)return!1;var t=h.list(e,"",!0);for(var r in t)if(t[r].autoshift||t[r].shift)return!0;return!1}(e))){"_redrawFromAutoMarginCount"in t?t._redrawFromAutoMarginCount++:t._redrawFromAutoMarginCount=1;var te=3*(1+Object.keys(g).length);if(t._redrawFromAutoMarginCount0&&(e._transitioningWithDuration=!0),e._transitionData._interruptCallbacks.push((function(){n=!0})),r.redraw&&e._transitionData._interruptCallbacks.push((function(){return l.call("redraw",e)})),e._transitionData._interruptCallbacks.push((function(){e.emit("plotly_transitioninterrupted",[])}));var i=0,o=0;function s(){return i++,function(){var t;o++,n||o!==i||(t=a,e._transitionData&&(function(e){if(e)for(;e.length;)e.shift()}(e._transitionData._interruptCallbacks),Promise.resolve().then((function(){if(r.redraw)return l.call("redraw",e)})).then((function(){e._transitioning=!1,e._transitioningWithDuration=!1,e.emit("plotly_transitioned",[])})).then(t)))}}r.runFn(s),setTimeout(s())}))}],i=u.syncOrAsync(a,e);return i&&i.then||(i=Promise.resolve()),i.then((function(){return e}))}_.didMarginChange=function(e,t){for(var r=0;r1)return!0}return!1},_.graphJson=function(e,t,r,n,a,i){(a&&t&&!e._fullData||a&&!t&&!e._fullLayout)&&_.supplyDefaults(e);var o=a?e._fullData:e.data,l=a?e._fullLayout:e.layout,s=(e._transitionData||{})._frames;function c(e,t){if("function"==typeof e)return t?"_function_":null;if(u.isPlainObject(e)){var n,a={};return Object.keys(e).sort().forEach((function(i){if(-1===["_","["].indexOf(i.charAt(0)))if("function"!=typeof e[i]){if("keepdata"===r){if("src"===i.substr(i.length-3))return}else if("keepstream"===r){if("string"==typeof(n=e[i+"src"])&&n.indexOf(":")>0&&!u.isPlainObject(e.stream))return}else if("keepall"!==r&&"string"==typeof(n=e[i+"src"])&&n.indexOf(":")>0)return;a[i]=c(e[i],t)}else t&&(a[i]="_function")})),a}return Array.isArray(e)?e.map((function(e){return c(e,t)})):u.isTypedArray(e)?u.simpleMap(e,u.identity):u.isJSDate(e)?u.ms2DateTimeLocal(+e):e}var f={data:(o||[]).map((function(e){var r=c(e);return t&&delete r.fit,r}))};if(!t&&(f.layout=c(l),a)){var d=l._size;f.layout.computed={margin:{b:d.b,l:d.l,r:d.r,t:d.t}}}return s&&(f.frames=c(s)),i&&(f.config=c(e._context,!0)),"object"===n?f:JSON.stringify(f)},_.modifyFrames=function(e,t){var r,n,a,i=e._transitionData._frames,o=e._transitionData._frameHash;for(r=0;r=0;i--)if(l[i].enabled){r._indexToPoints=l[i]._indexToPoints;break}n&&n.calc&&(o=n.calc(e,r))}Array.isArray(o)&&o[0]||(o=[{x:d,y:d}]),o[0].t||(o[0].t={}),o[0].trace=r,p[t]=o}}for(z(o,c,f),a=0;a0){for(var n=[],a=0;a-1&&(f[h[r]].title={text:""});for(r=0;r")?"":t.html(e).text()}));return t.remove(),r}(w)).replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g,"&")).replace(u,"'"),a.isIE()&&(w=(w=(w=w.replace(/"/gi,"'")).replace(/(\('#)([^']*)('\))/gi,'("#$2")')).replace(/(\\')/gi,'"')),w}},5341:function(e,t,r){"use strict";var n=r(1828);e.exports=function(e,t){for(var r=0;rf+c||!n(u))}for(var h=0;hi))return t}return void 0!==r?r:e.dflt},t.coerceColor=function(e,t,r){return a(t).isValid()?t:void 0!==r?r:e.dflt},t.coerceEnumerated=function(e,t,r){return e.coerceNumber&&(t=+t),-1!==e.values.indexOf(t)?t:void 0!==r?r:e.dflt},t.getValue=function(e,t){var r;return Array.isArray(e)?t0?t+=r:u<0&&(t-=r)}return t}function R(e){var t=u,r=e.b,a=I(e);return n.inbox(r-t,a-t,_+(a-t)/(a-r)-1)}var z=e[f+"a"],N=e[d+"a"];v=Math.abs(z.r2c(z.range[1])-z.r2c(z.range[0]));var E=n.getDistanceFunction(a,h,p,(function(e){return(h(e)+p(e))/2}));if(n.getClosest(y,E,e),!1!==e.index&&y[e.index].p!==c){M||(O=function(e){return Math.min(k(e),e.p-m.bargroupwidth/2)},D=function(e){return Math.max(A(e),e.p+m.bargroupwidth/2)});var F=y[e.index],H=g.base?F.b+F.s:F.s;e[d+"0"]=e[d+"1"]=N.c2p(F[d],!0),e[d+"LabelVal"]=H;var j=m.extents[m.extents.round(F.p)];e[f+"0"]=z.c2p(x?O(F):j[0],!0),e[f+"1"]=z.c2p(x?D(F):j[1],!0);var B=void 0!==F.orig_p;return e[f+"LabelVal"]=B?F.orig_p:F.p,e.labelLabel=s(z,e[f+"LabelVal"],g[f+"hoverformat"]),e.valueLabel=s(N,e[d+"LabelVal"],g[d+"hoverformat"]),e.baseLabel=s(N,F.b,g[d+"hoverformat"]),e.spikeDistance=(function(e){var t=u,r=e.b,a=I(e);return n.inbox(r-t,a-t,w+(a-t)/(a-r)-1)}(F)+function(e){return C(k(e),A(e),w)}(F))/2,e[f+"Spike"]=z.c2p(F.p,!0),o(F,g,e),e.hovertemplate=g.hovertemplate,e}}function f(e,t){var r=t.mcc||e.marker.color,n=t.mlcc||e.marker.line.color,a=l(e,t);return i.opacity(r)?r:i.opacity(n)&&a?n:void 0}e.exports={hoverPoints:function(e,t,r,n,i){var o=u(e,t,r,n,i);if(o){var l=o.cd,s=l[0].trace,c=l[o.index];return o.color=f(s,c),a.getComponentMethod("errorbars","hoverInfo")(c,s,o),[o]}},hoverOnBars:u,getTraceColor:f}},822:function(e,t,r){"use strict";e.exports={attributes:r(1486),layoutAttributes:r(3641),supplyDefaults:r(769).supplyDefaults,crossTraceDefaults:r(769).crossTraceDefaults,supplyLayoutDefaults:r(3957),calc:r(2290),crossTraceCalc:r(1661).crossTraceCalc,colorbar:r(4898),arraysToCalcdata:r(5341),plot:r(7295).plot,style:r(6688).style,styleOnSelect:r(6688).styleOnSelect,hoverPoints:r(5423).hoverPoints,eventData:r(8065),selectPoints:r(1974),moduleType:"trace",name:"bar",basePlotModule:r(3612),categories:["bar-like","cartesian","svg","bar","oriented","errorBarsOK","showLegend","zoomScale"],animatable:!0,meta:{}}},3641:function(e){"use strict";e.exports={barmode:{valType:"enumerated",values:["stack","group","overlay","relative"],dflt:"group",editType:"calc"},barnorm:{valType:"enumerated",values:["","fraction","percent"],dflt:"",editType:"calc"},bargap:{valType:"number",min:0,max:1,editType:"calc"},bargroupgap:{valType:"number",min:0,max:1,dflt:0,editType:"calc"}}},3957:function(e,t,r){"use strict";var n=r(3972),a=r(9298),i=r(1828),o=r(3641);e.exports=function(e,t,r){function l(r,n){return i.coerce(e,t,o,r,n)}for(var s=!1,c=!1,u=!1,f={},d=l("barmode"),h=0;h0}function L(e){return"auto"===e?0:e}function S(e,t){var r=Math.PI/180*t,n=Math.abs(Math.sin(r)),a=Math.abs(Math.cos(r));return{x:e.width*a+e.height*n,y:e.width*n+e.height*a}}function O(e,t,r,n,a,i){var o=!!i.isHorizontal,l=!!i.constrained,s=i.angle||0,c=i.anchor||"end",u="end"===c,f="start"===c,d=((i.leftToRight||0)+1)/2,h=1-d,p=a.width,v=a.height,y=Math.abs(t-e),g=Math.abs(n-r),m=y>2*_&&g>2*_?_:0;y-=2*m,g-=2*m;var x=L(s);"auto"!==s||p<=y&&v<=g||!(p>y||v>g)||(p>g||v>y)&&p.01?q:function(e,t,r){return r&&e===t?e:Math.abs(e-t)>=2?q(e):e>t?Math.ceil(e):Math.floor(e)};H=Z(H,j,N),j=Z(j,H,N),B=Z(B,Y,!N),Y=Z(Y,B,!N)}var G=k(i.ensureSingle(I,"path"),C,y,g);if(G.style("vector-effect",P?"none":"non-scaling-stroke").attr("d",isNaN((j-H)*(Y-B))||U&&e._context.staticPlot?"M0,0Z":"M"+H+","+B+"V"+Y+"H"+j+"V"+B+"Z").call(s.setClipUrl,t.layerClipId,e),!C.uniformtext.mode&&E){var W=s.makePointStyleFns(f);s.singlePointStyle(c,G,f,W,e)}!function(e,t,r,n,a,l,c,f,h,y,g){var w,T=t.xaxis,A=t.yaxis,D=e._fullLayout;function C(t,r,n){return i.ensureSingle(t,"text").text(r).attr({class:"bartext bartext-"+w,"text-anchor":"middle","data-notex":1}).call(s.font,n).call(o.convertToTspans,e)}var P=n[0].trace,I="h"===P.orientation,R=function(e,t,r,n,a){var o,l=t[0].trace,s=l.texttemplate;return o=s?function(e,t,r,n,a){var o=t[0].trace,l=i.castOption(o,r,"texttemplate");if(!l)return"";var s,c,f,d,h="histogram"===o.type,p="waterfall"===o.type,v="funnel"===o.type,y="h"===o.orientation;function g(e){return u(c,c.c2l(e),!0).text}function m(e){return u(d,d.c2l(e),!0).text}y?(s="y",c=a,f="x",d=n):(s="x",c=n,f="y",d=a);var x=t[r],_={};_.label=x.p,_.labelLabel=_[s+"Label"]=g(x.p);var w=i.castOption(o,x.i,"text");(0===w||w)&&(_.text=w),_.value=x.s,_.valueLabel=_[f+"Label"]=m(x.s);var T={};b(T,o,x.i),(h||void 0===T.x)&&(T.x=y?_.value:_.label),(h||void 0===T.y)&&(T.y=y?_.label:_.value),(h||void 0===T.xLabel)&&(T.xLabel=y?_.valueLabel:_.labelLabel),(h||void 0===T.yLabel)&&(T.yLabel=y?_.labelLabel:_.valueLabel),p&&(_.delta=+x.rawS||x.s,_.deltaLabel=m(_.delta),_.final=x.v,_.finalLabel=m(_.final),_.initial=_.final-_.delta,_.initialLabel=m(_.initial)),v&&(_.value=x.s,_.valueLabel=m(_.value),_.percentInitial=x.begR,_.percentInitialLabel=i.formatPercent(x.begR),_.percentPrevious=x.difR,_.percentPreviousLabel=i.formatPercent(x.difR),_.percentTotal=x.sumR,_.percenTotalLabel=i.formatPercent(x.sumR));var M=i.castOption(o,x.i,"customdata");return M&&(_.customdata=M),i.texttemplateString(l,_,e._d3locale,T,_,o._meta||{})}(e,t,r,n,a):l.textinfo?function(e,t,r,n){var a=e[0].trace,o="h"===a.orientation,l="waterfall"===a.type,s="funnel"===a.type;function c(e){return u(o?n:r,e,!0).text}function f(e){return u(o?r:n,+e,!0).text}var d,h=a.textinfo,p=e[t],v=h.split("+"),y=[],g=function(e){return-1!==v.indexOf(e)};if(g("label")&&y.push(c(e[t].p)),g("text")&&(0===(d=i.castOption(a,p.i,"text"))||d)&&y.push(d),l){var m=+p.rawS||p.s,x=p.v,b=x-m;g("initial")&&y.push(f(b)),g("delta")&&y.push(f(m)),g("final")&&y.push(f(x))}if(s){g("value")&&y.push(f(p.s));var _=0;g("percent initial")&&_++,g("percent previous")&&_++,g("percent total")&&_++;var w=_>1;g("percent initial")&&(d=i.formatPercent(p.begR),w&&(d+=" of initial"),y.push(d)),g("percent previous")&&(d=i.formatPercent(p.difR),w&&(d+=" of previous"),y.push(d)),g("percent total")&&(d=i.formatPercent(p.sumR),w&&(d+=" of total"),y.push(d))}return y.join("
")}(t,r,n,a):v.getValue(l.text,r),v.coerceString(m,o)}(D,n,a,T,A);w=function(e,t){var r=v.getValue(e.textposition,t);return v.coerceEnumerated(x,r)}(P,a);var z="stack"===y.mode||"relative"===y.mode,N=n[a],E=!z||N._outmost;if(R&&"none"!==w&&(!N.isBlank&&l!==c&&f!==h||"auto"!==w&&"inside"!==w)){var F=D.font,H=p.getBarColor(n[a],P),j=p.getInsideTextFont(P,a,F,H),B=p.getOutsideTextFont(P,a,F),Y=r.datum();I?"log"===T.type&&Y.s0<=0&&(l=T.range[0]0&&Z>0&&(q<=W&&Z<=X||q<=X&&Z<=W||(I?W>=q*(X/Z):X>=Z*(W/q)))?w="inside":(w="outside",U.remove(),U=null)):w="inside"),!U){var J=(U=C(r,R,G=i.ensureUniformFontSize(e,"outside"===w?B:j))).attr("transform");if(U.attr("transform",""),q=(V=s.bBox(U.node())).width,Z=V.height,U.attr("transform",J),q<=0||Z<=0)return void U.remove()}var K,Q=P.textangle;K="outside"===w?function(e,t,r,n,a,i){var o,l=!!i.isHorizontal,s=!!i.constrained,c=i.angle||0,u=a.width,f=a.height,d=Math.abs(t-e),h=Math.abs(n-r);o=l?h>2*_?_:0:d>2*_?_:0;var p=1;s&&(p=l?Math.min(1,h/f):Math.min(1,d/u));var v=L(c),y=S(a,v),g=(l?y.x:y.y)/2,m=(a.left+a.right)/2,x=(a.top+a.bottom)/2,b=(e+t)/2,w=(r+n)/2,T=0,k=0,A=l?M(t,e):M(r,n);return l?(b=t-A*o,T=A*g):(w=n+A*o,k=-A*g),{textX:m,textY:x,targetX:b,targetY:w,anchorX:T,anchorY:k,scale:p,rotate:v}}(l,c,f,h,V,{isHorizontal:I,constrained:"both"===P.constraintext||"outside"===P.constraintext,angle:Q}):O(l,c,f,h,V,{isHorizontal:I,constrained:"both"===P.constraintext||"inside"===P.constraintext,angle:Q,anchor:P.insidetextanchor}),K.fontSize=G.size,d("histogram"===P.type?"bar":P.type,K,D),N.transform=K;var $=k(U,D,y,g);i.setTransormAndDisplay($,K)}else r.select("text").remove()}(e,t,I,r,h,H,j,B,Y,y,g),t.layerClipId&&s.hideOutsideRangePoint(c,I.select("text"),w,D,f.xcalendar,f.ycalendar)}));var B=!1===f.cliponaxis;s.setClipUrl(c,B?null:t.layerClipId,e)}));c.getComponentMethod("errorbars","plot")(e,I,t,y)},toMoveInsideBar:O}},1974:function(e){"use strict";function t(e,t,r,n,a){var i=t.c2p(n?e.s0:e.p0,!0),o=t.c2p(n?e.s1:e.p1,!0),l=r.c2p(n?e.p0:e.s0,!0),s=r.c2p(n?e.p1:e.s1,!0);return a?[(i+o)/2,(l+s)/2]:n?[o,(l+s)/2]:[(i+o)/2,s]}e.exports=function(e,r){var n,a=e.cd,i=e.xaxis,o=e.yaxis,l=a[0].trace,s="funnel"===l.type,c="h"===l.orientation,u=[];if(!1===r)for(n=0;n1||0===a.bargap&&0===a.bargroupgap&&!e[0].trace.marker.line.width)&&n.select(this).attr("shape-rendering","crispEdges")})),t.selectAll("g.points").each((function(t){p(n.select(this),t[0].trace,e)})),l.getComponentMethod("errorbars","style")(t)},styleTextPoints:v,styleOnSelect:function(e,t,r){var a=t[0].trace;a.selectedpoints?function(e,t,r){i.selectedPointStyle(e.selectAll("path"),t),function(e,t,r){e.each((function(e){var a,l=n.select(this);if(e.selected){a=o.ensureUniformFontSize(r,y(l,e,t,r));var s=t.selected.textfont&&t.selected.textfont.color;s&&(a.color=s),i.font(l,a)}else i.selectedTextStyle(l,t)}))}(e.selectAll("text"),t,r)}(r,a,e):(p(r,a,e),l.getComponentMethod("errorbars","style")(r))},getInsideTextFont:m,getOutsideTextFont:x,getBarColor:_,resizeText:s}},8340:function(e,t,r){"use strict";var n=r(7901),a=r(2869).hasColorscale,i=r(1586),o=r(1828).coercePattern;e.exports=function(e,t,r,l,s){var c=r("marker.color",l),u=a(e,"marker");u&&i(e,t,s,r,{prefix:"marker.",cLetter:"c"}),r("marker.line.color",n.defaultLine),a(e,"marker.line")&&i(e,t,s,r,{prefix:"marker.line.",cLetter:"c"}),r("marker.line.width"),r("marker.opacity"),o(r,"marker.pattern",c,u),r("selected.marker.color"),r("unselected.marker.color")}},2597:function(e,t,r){"use strict";var n=r(9898),a=r(1828);function i(e){return"_"+e+"Text_minsize"}e.exports={recordMinTextSize:function(e,t,r){if(r.uniformtext.mode){var n=i(e),a=r.uniformtext.minsize,o=t.scale*t.fontSize;t.hide=o=0})),("funnelarea"===t.type?g:t.sort)&&i.sort((function(e,t){return t.v-e.v})),i[0]&&(i[0].vTotal=y),i},crossTraceCalc:function(e,t){var r=(t||{}).type;r||(r="pie");var n=e._fullLayout,a=e.calcdata,i=n[r+"colorway"],l=n["_"+r+"colormap"];n["extend"+r+"colors"]&&(i=s(i,o));for(var c=0,u=0;u0){l=!0;break}}l||(o=0)}return{hasLabels:r,hasValues:i,len:o}}function u(e,t,r,n,a){n("marker.line.width")&&n("marker.line.color",a?void 0:r.paper_bgcolor);var i=n("marker.colors");s(n,"marker.pattern",i),e.marker&&!t.marker.pattern.fgcolor&&(t.marker.pattern.fgcolor=e.marker.colors),t.marker.pattern.bgcolor||(t.marker.pattern.bgcolor=r.paper_bgcolor)}e.exports={handleLabelsAndValues:c,handleMarkerDefaults:u,supplyDefaults:function(e,t,r,n){function s(r,n){return a.coerce(e,t,i,r,n)}var f=c(s("labels"),s("values")),d=f.len;if(t._hasLabels=f.hasLabels,t._hasValues=f.hasValues,!t._hasLabels&&t._hasValues&&(s("label0"),s("dlabel")),d){t._length=d,u(e,t,n,s,!0),s("scalegroup");var h,p=s("text"),v=s("texttemplate");if(v||(h=s("textinfo",Array.isArray(p)?"text+percent":"percent")),s("hovertext"),s("hovertemplate"),v||h&&"none"!==h){var y=s("textposition");l(e,t,n,s,y,{moduleHasSelected:!1,moduleHasUnselected:!1,moduleHasConstrain:!1,moduleHasCliponaxis:!1,moduleHasTextangle:!1,moduleHasInsideanchor:!1}),(Array.isArray(y)||"auto"===y||"outside"===y)&&s("automargin"),("inside"===y||"auto"===y||Array.isArray(y))&&s("insidetextorientation")}o(t,n,s);var g=s("hole");if(s("title.text")){var m=s("title.position",g?"middle center":"top center");g||"middle center"!==m||(t.title.position="top center"),a.coerceFont(s,"title.font",n.font)}s("sort"),s("direction"),s("rotation"),s("pull")}else t.visible=!1}}},7:function(e,t,r){"use strict";var n=r(3469).appendArrayMultiPointValues;e.exports=function(e,t){var r={curveNumber:t.index,pointNumbers:e.pts,data:t._input,fullData:t,label:e.label,color:e.color,value:e.v,percent:e.percent,text:e.text,bbox:e.bbox,v:e.v};return 1===e.pts.length&&(r.pointNumber=r.i=e.pts[0]),n(r,t,e.pts),"funnelarea"===t.type&&(delete r.v,delete r.i),r}},2209:function(e,t,r){"use strict";var n=r(1424),a=r(7901);e.exports=function(e,t,r,i){var o=r.marker.pattern;o&&o.shape?n.pointStyle(e,r,i,t):a.fill(e,t.color)}},3581:function(e,t,r){"use strict";var n=r(1828);function a(e){return-1!==e.indexOf("e")?e.replace(/[.]?0+e/,"e"):-1!==e.indexOf(".")?e.replace(/[.]?0+$/,""):e}t.formatPiePercent=function(e,t){var r=a((100*e).toPrecision(3));return n.numSeparate(r,t)+"%"},t.formatPieValue=function(e,t){var r=a(e.toPrecision(10));return n.numSeparate(r,t)},t.getFirstFilled=function(e,t){if(Array.isArray(e))for(var r=0;r"),name:f.hovertemplate||-1!==d.indexOf("name")?f.name:void 0,idealAlign:e.pxmid[0]<0?"left":"right",color:y.castOption(_.bgcolor,e.pts)||e.color,borderColor:y.castOption(_.bordercolor,e.pts),fontFamily:y.castOption(w.family,e.pts),fontSize:y.castOption(w.size,e.pts),fontColor:y.castOption(w.color,e.pts),nameLength:y.castOption(_.namelength,e.pts),textAlign:y.castOption(_.align,e.pts),hovertemplate:y.castOption(f.hovertemplate,e.pts),hovertemplateLabels:e,eventData:[g(e,f)]},{container:r._hoverlayer.node(),outerContainer:r._paper.node(),gd:t,inOut_bbox:T}),e.bbox=T[0],c._hasHoverLabel=!0}c._hasHoverEvent=!0,t.emit("plotly_hover",{points:[g(e,f)],event:n.event})}})),e.on("mouseout",(function(e){var r=t._fullLayout,a=t._fullData[c.index],o=n.select(this).datum();c._hasHoverEvent&&(e.originalEvent=n.event,t.emit("plotly_unhover",{points:[g(o,a)],event:n.event}),c._hasHoverEvent=!1),c._hasHoverLabel&&(i.loneUnhover(r._hoverlayer.node()),c._hasHoverLabel=!1)})),e.on("click",(function(e){var r=t._fullLayout,a=t._fullData[c.index];t._dragging||!1===r.hovermode||(t._hoverdata=[g(e,a)],i.click(t,n.event))}))}function b(e,t,r){var n=y.castOption(e.insidetextfont.color,t.pts);!n&&e._input.textfont&&(n=y.castOption(e._input.textfont.color,t.pts));var a=y.castOption(e.insidetextfont.family,t.pts)||y.castOption(e.textfont.family,t.pts)||r.family,i=y.castOption(e.insidetextfont.size,t.pts)||y.castOption(e.textfont.size,t.pts)||r.size;return{color:n||o.contrast(t.color),family:a,size:i}}function _(e,t){for(var r,n,a=0;at&&t>n||r=-4;y-=2)g(Math.PI*y,"tan");for(y=4;y>=-4;y-=2)g(Math.PI*(y+1),"tan")}if(f||h){for(y=4;y>=-4;y-=2)g(Math.PI*(y+1.5),"rad");for(y=4;y>=-4;y-=2)g(Math.PI*(y+.5),"rad")}}if(l||p||f){var m=Math.sqrt(e.width*e.width+e.height*e.height);if((i={scale:a*n*2/m,rCenter:1-a,rotate:0}).textPosAngle=(t.startangle+t.stopangle)/2,i.scale>=1)return i;v.push(i)}(p||h)&&((i=T(e,n,o,s,c)).textPosAngle=(t.startangle+t.stopangle)/2,v.push(i)),(p||d)&&((i=M(e,n,o,s,c)).textPosAngle=(t.startangle+t.stopangle)/2,v.push(i));for(var x=0,b=0,_=0;_=1)break}return v[x]}function T(e,t,r,n,a){t=Math.max(0,t-2*v);var i=e.width/e.height,o=L(i,n,t,r);return{scale:2*o/e.height,rCenter:k(i,o/t),rotate:A(a)}}function M(e,t,r,n,a){t=Math.max(0,t-2*v);var i=e.height/e.width,o=L(i,n,t,r);return{scale:2*o/e.width,rCenter:k(i,o/t),rotate:A(a+Math.PI/2)}}function k(e,t){return Math.cos(t)-e*t}function A(e){return(180/Math.PI*e+720)%180-90}function L(e,t,r,n){var a=e+1/(2*Math.tan(t));return r*Math.min(1/(Math.sqrt(a*a+.5)+a),n/(Math.sqrt(e*e+n/2)+e))}function S(e,t){return e.v!==t.vTotal||t.trace.hole?Math.min(1/(1+1/Math.sin(e.halfangle)),e.ring/2):1}function O(e,t){var r=t.pxmid[0],n=t.pxmid[1],a=e.width/2,i=e.height/2;return r<0&&(a*=-1),n<0&&(i*=-1),{scale:1,rCenter:1,rotate:0,x:a+Math.abs(i)*(a>0?1:-1)/2,y:i/(1+r*r/(n*n)),outside:!0}}function D(e,t){var r,n,a,i=e.trace,o={x:e.cx,y:e.cy},l={tx:0,ty:0};l.ty+=i.title.font.size,a=P(i),-1!==i.title.position.indexOf("top")?(o.y-=(1+a)*e.r,l.ty-=e.titleBox.height):-1!==i.title.position.indexOf("bottom")&&(o.y+=(1+a)*e.r);var s,c,u=(s=e.r,c=e.trace.aspectratio,s/(void 0===c?1:c)),f=t.w*(i.domain.x[1]-i.domain.x[0])/2;return-1!==i.title.position.indexOf("left")?(f+=u,o.x-=(1+a)*u,l.tx+=e.titleBox.width/2):-1!==i.title.position.indexOf("center")?f*=2:-1!==i.title.position.indexOf("right")&&(f+=u,o.x+=(1+a)*u,l.tx-=e.titleBox.width/2),r=f/e.titleBox.width,n=C(e,t)/e.titleBox.height,{x:o.x,y:o.y,scale:Math.min(r,n),tx:l.tx,ty:l.ty}}function C(e,t){var r=e.trace,n=t.h*(r.domain.y[1]-r.domain.y[0]);return Math.min(e.titleBox.height,n/2)}function P(e){var t,r=e.pull;if(!r)return 0;if(Array.isArray(r))for(r=0,t=0;tr&&(r=e.pull[t]);return r}function I(e,t){for(var r=[],n=0;n1?u=(c=r.r)/a.aspectratio:c=(u=r.r)*a.aspectratio,s=(c*=(1+a.baseratio)/2)*u}o=Math.min(o,s/r.vTotal)}for(n=0;n")}if(i){var x=s.castOption(a,t.i,"texttemplate");if(x){var b=function(e){return{label:e.label,value:e.v,valueLabel:y.formatPieValue(e.v,n.separators),percent:e.v/r.vTotal,percentLabel:y.formatPiePercent(e.v/r.vTotal,n.separators),color:e.color,text:e.text,customdata:s.castOption(a,e.i,"customdata")}}(t),_=y.getFirstFilled(a.text,t.pts);(m(_)||""===_)&&(b.text=_),t.text=s.texttemplateString(x,b,e._fullLayout._d3locale,b,a._meta||{})}else t.text=""}}function N(e,t){var r=e.rotate*Math.PI/180,n=Math.cos(r),a=Math.sin(r),i=(t.left+t.right)/2,o=(t.top+t.bottom)/2;e.textX=i*n-o*a,e.textY=i*a+o*n,e.noCenter=!0}e.exports={plot:function(e,t){var r=e._context.staticPlot,i=e._fullLayout,d=i._size;p("pie",i),_(t,e),I(t,d);var v=s.makeTraceGroups(i._pielayer,t,"trace").each((function(t){var p=n.select(this),v=t[0],g=v.trace;!function(e){var t,r,n,a=e[0],i=a.r,o=a.trace,l=y.getRotationAngle(o.rotation),s=2*Math.PI/a.vTotal,c="px0",u="px1";if("counterclockwise"===o.direction){for(t=0;ta.vTotal/2?1:0,r.halfangle=Math.PI*Math.min(r.v/a.vTotal,.5),r.ring=1-o.hole,r.rInscribed=S(r,a))}(t),p.attr("stroke-linejoin","round"),p.each((function(){var m=n.select(this).selectAll("g.slice").data(t);m.enter().append("g").classed("slice",!0),m.exit().remove();var _=[[[],[]],[[],[]]],T=!1;m.each((function(a,o){if(a.hidden)n.select(this).selectAll("path,g").remove();else{a.pointNumber=a.i,a.curveNumber=g.index,_[a.pxmid[1]<0?0:1][a.pxmid[0]<0?0:1].push(a);var c=v.cx,u=v.cy,d=n.select(this),p=d.selectAll("path.surface").data([a]);if(p.enter().append("path").classed("surface",!0).style({"pointer-events":r?"none":"all"}),d.call(x,e,t),g.pull){var m=+y.castOption(g.pull,a.pts)||0;m>0&&(c+=m*a.pxmid[0],u+=m*a.pxmid[1])}a.cxFinal=c,a.cyFinal=u;var M=g.hole;if(a.v===v.vTotal){var k="M"+(c+a.px0[0])+","+(u+a.px0[1])+C(a.px0,a.pxmid,!0,1)+C(a.pxmid,a.px0,!0,1)+"Z";M?p.attr("d","M"+(c+M*a.px0[0])+","+(u+M*a.px0[1])+C(a.px0,a.pxmid,!1,M)+C(a.pxmid,a.px0,!1,M)+"Z"+k):p.attr("d",k)}else{var A=C(a.px0,a.px1,!0,1);if(M){var L=1-M;p.attr("d","M"+(c+M*a.px1[0])+","+(u+M*a.px1[1])+C(a.px1,a.px0,!1,M)+"l"+L*a.px0[0]+","+L*a.px0[1]+A+"Z")}else p.attr("d","M"+c+","+u+"l"+a.px0[0]+","+a.px0[1]+A+"Z")}z(e,a,v);var S=y.castOption(g.textposition,a.pts),D=d.selectAll("g.slicetext").data(a.text&&"none"!==S?[0]:[]);D.enter().append("g").classed("slicetext",!0),D.exit().remove(),D.each((function(){var r=s.ensureSingle(n.select(this),"text","",(function(e){e.attr("data-notex",1)})),d=s.ensureUniformFontSize(e,"outside"===S?function(e,t,r){var n=y.castOption(e.outsidetextfont.color,t.pts)||y.castOption(e.textfont.color,t.pts)||r.color,a=y.castOption(e.outsidetextfont.family,t.pts)||y.castOption(e.textfont.family,t.pts)||r.family,i=y.castOption(e.outsidetextfont.size,t.pts)||y.castOption(e.textfont.size,t.pts)||r.size;return{color:n,family:a,size:i}}(g,a,i.font):b(g,a,i.font));r.text(a.text).attr({class:"slicetext",transform:"","text-anchor":"middle"}).call(l.font,d).call(f.convertToTspans,e);var p,m=l.bBox(r.node());if("outside"===S)p=O(m,a);else if(p=w(m,a,v),"auto"===S&&p.scale<1){var x=s.ensureUniformFontSize(e,g.outsidetextfont);r.call(l.font,x),p=O(m=l.bBox(r.node()),a)}var _=p.textPosAngle,M=void 0===_?a.pxmid:R(v.r,_);if(p.targetX=c+M[0]*p.rCenter+(p.x||0),p.targetY=u+M[1]*p.rCenter+(p.y||0),N(p,m),p.outside){var k=p.targetY;a.yLabelMin=k-m.height/2,a.yLabelMid=k,a.yLabelMax=k+m.height/2,a.labelExtraX=0,a.labelExtraY=0,T=!0}p.fontSize=d.size,h(g.type,p,i),t[o].transform=p,s.setTransormAndDisplay(r,p)}))}function C(e,t,r,n){var i=n*(t[0]-e[0]),o=n*(t[1]-e[1]);return"a"+n*v.r+","+n*v.r+" 0 "+a.largeArc+(r?" 1 ":" 0 ")+i+","+o}}));var M=n.select(this).selectAll("g.titletext").data(g.title.text?[0]:[]);if(M.enter().append("g").classed("titletext",!0),M.exit().remove(),M.each((function(){var t,r=s.ensureSingle(n.select(this),"text","",(function(e){e.attr("data-notex",1)})),a=g.title.text;g._meta&&(a=s.templateString(a,g._meta)),r.text(a).attr({class:"titletext",transform:"","text-anchor":"middle"}).call(l.font,g.title.font).call(f.convertToTspans,e),t="middle center"===g.title.position?function(e){var t=Math.sqrt(e.titleBox.width*e.titleBox.width+e.titleBox.height*e.titleBox.height);return{x:e.cx,y:e.cy,scale:e.trace.hole*e.r*2/t,tx:0,ty:-e.titleBox.height/2+e.trace.title.font.size}}(v):D(v,d),r.attr("transform",u(t.x,t.y)+c(Math.min(1,t.scale))+u(t.tx,t.ty))})),T&&function(e,t){var r,n,a,i,o,l,s,c,u,f,d,h,p;function v(e,t){return e.pxmid[1]-t.pxmid[1]}function g(e,t){return t.pxmid[1]-e.pxmid[1]}function m(e,r){r||(r={});var a,c,u,d,h=r.labelExtraY+(n?r.yLabelMax:r.yLabelMin),p=n?e.yLabelMin:e.yLabelMax,v=n?e.yLabelMax:e.yLabelMin,g=e.cyFinal+o(e.px0[1],e.px1[1]),m=h-p;if(m*s>0&&(e.labelExtraY=m),Array.isArray(t.pull))for(c=0;c=(y.castOption(t.pull,u.pts)||0)||((e.pxmid[1]-u.pxmid[1])*s>0?(m=u.cyFinal+o(u.px0[1],u.px1[1])-p-e.labelExtraY)*s>0&&(e.labelExtraY+=m):(v+e.labelExtraY-g)*s>0&&(a=3*l*Math.abs(c-f.indexOf(e)),(d=u.cxFinal+i(u.px0[0],u.px1[0])+a-(e.cxFinal+e.pxmid[0])-e.labelExtraX)*l>0&&(e.labelExtraX+=d)))}for(n=0;n<2;n++)for(a=n?v:g,o=n?Math.max:Math.min,s=n?1:-1,r=0;r<2;r++){for(i=r?Math.max:Math.min,l=r?1:-1,(c=e[n][r]).sort(a),u=e[1-n][r],f=u.concat(c),h=[],d=0;dMath.abs(f)?l+="l"+f*e.pxmid[0]/e.pxmid[1]+","+f+"H"+(i+e.labelExtraX+c):l+="l"+e.labelExtraX+","+u+"v"+(f-u)+"h"+c}else l+="V"+(e.yLabelMid+e.labelExtraY)+"h"+c;s.ensureSingle(r,"path","textline").call(o.stroke,t.outsidetextfont.color).attr({"stroke-width":Math.min(2,t.outsidetextfont.size/8),d:l,fill:"none"})}else r.select("path.textline").remove()}))}(m,g),T&&g.automargin){var k=l.bBox(p.node()),A=g.domain,L=d.w*(A.x[1]-A.x[0]),S=d.h*(A.y[1]-A.y[0]),C=(.5*L-v.r)/d.w,P=(.5*S-v.r)/d.h;a.autoMargin(e,"pie."+g.uid+".automargin",{xl:A.x[0]-C,xr:A.x[1]+C,yb:A.y[0]-P,yt:A.y[1]+P,l:Math.max(v.cx-v.r-k.left,0),r:Math.max(k.right-(v.cx+v.r),0),b:Math.max(k.bottom-(v.cy+v.r),0),t:Math.max(v.cy-v.r-k.top,0),pad:5})}}))}));setTimeout((function(){v.selectAll("tspan").each((function(){var e=n.select(this);e.attr("dy")&&e.attr("dy",e.attr("dy"))}))}),0)},formatSliceLabel:z,transformInsideText:w,determineInsideTextFont:b,positionTitleOutside:D,prerenderTitles:_,layoutAreas:I,attachFxHandlers:x,computeTransform:N}},8357:function(e,t,r){"use strict";var n=r(9898),a=r(3463),i=r(2597).resizeText;e.exports=function(e){var t=e._fullLayout._pielayer.selectAll(".trace");i(e,t,"pie"),t.each((function(t){var r=t[0].trace,i=n.select(this);i.style({opacity:r.opacity}),i.selectAll("path.surface").each((function(t){n.select(this).call(a,t,r,e)}))}))}},3463:function(e,t,r){"use strict";var n=r(7901),a=r(3581).castOption,i=r(2209);e.exports=function(e,t,r,o){var l=r.marker.line,s=a(l.color,t.pts)||n.defaultLine,c=a(l.width,t.pts)||0;e.call(i,t,r,o).style("stroke-width",c).call(n.stroke,s)}},5225:function(e,t,r){"use strict";var n=r(1828);e.exports=function(e,t){for(var r=0;rs&&D[g].gap;)g--;for(x=D[g].s,v=D.length-1;v>g;v--)D[v].s=x;for(;sL[f]&&f=0;f--){var d=e[f];if("scatter"===d.type&&d.xaxis===c.xaxis&&d.yaxis===c.yaxis){d.opacity=void 0;break}}}}}},7438:function(e,t,r){"use strict";var n=r(1828),a=r(3972),i=r(2196),o=r(7581),l=r(4098),s=r(7513),c=r(3927),u=r(565),f=r(9508),d=r(1058),h=r(4039),p=r(2410),v=r(8908),y=r(1828).coercePattern;e.exports=function(e,t,r,g){function m(r,a){return n.coerce(e,t,i,r,a)}var x=s(e,t,g,m);if(x||(t.visible=!1),t.visible){c(e,t,g,m),m("xhoverformat"),m("yhoverformat");var b=u(e,t,g,m);"group"===g.scattermode&&void 0===t.orientation&&m("orientation","v");var _=!b&&x=Math.min(t,r)&&p<=Math.max(t,r)?0:1/0}var n=Math.max(3,e.mrc||0),a=1-1/n,i=Math.abs(d.c2p(e.x)-p);return i=Math.min(t,r)&&v<=Math.max(t,r)?0:1/0}var n=Math.max(3,e.mrc||0),a=1-1/n,i=Math.abs(h.c2p(e.y)-v);return iG!=(H=R[P][1])>=G&&(N=R[P-1][0],E=R[P][0],H-F&&(z=N+(E-N)*(G-F)/(H-F),U=Math.min(U,z),V=Math.max(V,z)));U=Math.max(U,0),V=Math.min(V,d._length);var W=l.defaultLine;return l.opacity(f.fillcolor)?W=f.fillcolor:l.opacity((f.line||{}).color)&&(W=f.line.color),n.extendFlat(e,{distance:e.maxHoverDistance,x0:U,x1:V,y0:G,y1:G,color:W,hovertemplate:!1}),delete e.index,f.text&&!Array.isArray(f.text)?e.text=String(f.text):e.text=f.name,[e]}}}},7368:function(e,t,r){"use strict";var n=r(4098);e.exports={hasLines:n.hasLines,hasMarkers:n.hasMarkers,hasText:n.hasText,isBubble:n.isBubble,attributes:r(2196),layoutAttributes:r(1479),supplyDefaults:r(7438),crossTraceDefaults:r(462),supplyLayoutDefaults:r(9334),calc:r(7761).calc,crossTraceCalc:r(2626),arraysToCalcdata:r(5225),plot:r(7399),colorbar:r(4898),formatLabels:r(8225),style:r(6296).style,styleOnSelect:r(6296).styleOnSelect,hoverPoints:r(3720),selectPoints:r(8002),animatable:!0,moduleType:"trace",name:"scatter",basePlotModule:r(3612),categories:["cartesian","svg","symbols","errorBarsOK","showLegend","scatter-like","zoomScale"],meta:{}}},1479:function(e){"use strict";e.exports={scattermode:{valType:"enumerated",values:["group","overlay"],dflt:"overlay",editType:"calc"},scattergap:{valType:"number",min:0,max:1,editType:"calc"}}},9334:function(e,t,r){"use strict";var n=r(1828),a=r(1479);e.exports=function(e,t){var r,i,o="group"===t.barmode;"group"===t.scattermode&&(r="scattergap",i=o?t.bargap:.2,n.coerce(e,t,a,r,i))}},1058:function(e,t,r){"use strict";var n=r(1828).isArrayOrTypedArray,a=r(2869).hasColorscale,i=r(1586);e.exports=function(e,t,r,o,l,s){s||(s={});var c=(e.marker||{}).color;l("line.color",r),a(e,"line")?i(e,t,o,l,{prefix:"line.",cLetter:"c"}):l("line.color",!n(c)&&c||r),l("line.width"),s.noDash||l("line.dash"),s.backoff&&l("line.backoff")}},4621:function(e,t,r){"use strict";var n=r(1424),a=r(606),i=a.BADNUM,o=a.LOG_CLIP,l=o+.5,s=o-.5,c=r(1828),u=c.segmentsIntersect,f=c.constrain,d=r(7581);e.exports=function(e,t){var r,a,o,h,p,v,y,g,m,x,b,_,w,T,M,k,A,L,S=t.trace||{},O=t.xaxis,D=t.yaxis,C="log"===O.type,P="log"===D.type,I=O._length,R=D._length,z=t.backoff,N=S.marker,E=t.connectGaps,F=t.baseTolerance,H=t.shape,j="linear"===H,B=S.fill&&"none"!==S.fill,Y=[],U=d.minTolerance,V=e.length,q=new Array(V),Z=0;function G(r){var n=e[r];if(!n)return!1;var a=t.linearized?O.l2p(n.x):O.c2p(n.x),o=t.linearized?D.l2p(n.y):D.c2p(n.y);if(a===i){if(C&&(a=O.c2p(n.x,!0)),a===i)return!1;P&&o===i&&(a*=Math.abs(O._m*R*(O._m>0?l:s)/(D._m*I*(D._m>0?l:s)))),a*=1e3}if(o===i){if(P&&(o=D.c2p(n.y,!0)),o===i)return!1;o*=1e3}return[a,o]}function W(e,t,r,n){var a=r-e,i=n-t,o=.5-e,l=.5-t,s=a*a+i*i,c=a*o+i*l;if(c>0&&coe||e[1]se)return[f(e[0],ie,oe),f(e[1],le,se)]}function fe(e,t){return e[0]===t[0]&&(e[0]===ie||e[0]===oe)||e[1]===t[1]&&(e[1]===le||e[1]===se)||void 0}function de(e,t,r){return function(n,a){var i=ue(n),o=ue(a),l=[];if(i&&o&&fe(i,o))return l;i&&l.push(i),o&&l.push(o);var s=2*c.constrain((n[e]+a[e])/2,t,r)-((i||n)[e]+(o||a)[e]);return s&&((i&&o?s>0==i[e]>o[e]?i:o:i||o)[e]+=s),l}}function he(e){var t=e[0],r=e[1],n=t===q[Z-1][0],a=r===q[Z-1][1];if(!n||!a)if(Z>1){var i=t===q[Z-2][0],o=r===q[Z-2][1];n&&(t===ie||t===oe)&&i?o?Z--:q[Z-1]=e:a&&(r===le||r===se)&&o?i?Z--:q[Z-1]=e:q[Z++]=e}else q[Z++]=e}function pe(e){q[Z-1][0]!==e[0]&&q[Z-1][1]!==e[1]&&he([$,ee]),he(e),te=null,$=ee=0}"linear"===H||"spline"===H?ne=function(e,t){for(var r=[],n=0,a=0;a<4;a++){var i=ce[a],o=u(e[0],e[1],t[0],t[1],i[0],i[1],i[2],i[3]);o&&(!n||Math.abs(o.x-r[0][0])>1||Math.abs(o.y-r[0][1])>1)&&(o=[o.x,o.y],n&&J(o,e)oe?oe:0,Q=t[1]se?se:0,K||Q){if(Z)if(te){var n=ne(te,t);n.length>1&&(pe(n[0]),q[Z++]=n[1])}else re=ne(q[Z-1],t)[0],q[Z++]=re;else q[Z++]=[K||t[0],Q||t[1]];var a=q[Z-1];K&&Q&&(a[0]!==K||a[1]!==Q)?(te&&($!==K&&ee!==Q?he($&&ee?(i=te,l=(o=t)[0]-i[0],s=(o[1]-i[1])/l,(i[1]*o[0]-o[1]*i[0])/l>0?[s>0?ie:oe,se]:[s>0?oe:ie,le]):[$||K,ee||Q]):$&&ee&&he([$,ee])),he([K,Q])):$-K&&ee-Q&&he([K||$,Q||ee]),te=t,$=K,ee=Q}else te&&pe(ne(te,t)[0]),q[Z++]=t;var i,o,l,s}for(r=0;rX(v,ge))break;o=v,(w=m[0]*g[0]+m[1]*g[1])>b?(b=w,h=v,y=!1):w<_&&(_=w,p=v,y=!0)}if(y?(ye(h),o!==p&&ye(p)):(p!==a&&ye(p),o!==h&&ye(h)),ye(o),r>=e.length||!v)break;ye(v),a=v}}else ye(h)}te&&he([$||te[0],ee||te[1]]),Y.push(q.slice(0,Z))}var me=H.slice(H.length-1);if(z&&"h"!==me&&"v"!==me){for(var xe=!1,be=-1,_e=[],we=0;we=0?s=h:(s=h=d,d++),s0?Math.max(r,i):0}}},4898:function(e){"use strict";e.exports={container:"marker",min:"cmin",max:"cmax"}},9508:function(e,t,r){"use strict";var n=r(7901),a=r(2869).hasColorscale,i=r(1586),o=r(4098);e.exports=function(e,t,r,l,s,c){var u=o.isBubble(e),f=(e.line||{}).color;c=c||{},f&&(r=f),s("marker.symbol"),s("marker.opacity",u?.7:1),s("marker.size"),c.noAngle||(s("marker.angle"),c.noAngleRef||s("marker.angleref"),c.noStandOff||s("marker.standoff")),s("marker.color",r),a(e,"marker")&&i(e,t,l,s,{prefix:"marker.",cLetter:"c"}),c.noSelect||(s("selected.marker.color"),s("unselected.marker.color"),s("selected.marker.size"),s("unselected.marker.size")),c.noLine||(s("marker.line.color",f&&!Array.isArray(f)&&t.marker.color!==f?f:u?n.background:n.defaultLine),a(e,"marker.line")&&i(e,t,l,s,{prefix:"marker.line.",cLetter:"c"}),s("marker.line.width",u?1:0)),u&&(s("marker.sizeref"),s("marker.sizemin"),s("marker.sizemode")),c.gradient&&"none"!==s("marker.gradient.type")&&s("marker.gradient.color")}},3927:function(e,t,r){"use strict";var n=r(1828).dateTick0,a=r(606).ONEWEEK;function i(e,t){return n(t,e%a==0?1:0)}e.exports=function(e,t,r,n,a){if(a||(a={x:!0,y:!0}),a.x){var o=n("xperiod");o&&(n("xperiod0",i(o,t.xcalendar)),n("xperiodalignment"))}if(a.y){var l=n("yperiod");l&&(n("yperiod0",i(l,t.ycalendar)),n("yperiodalignment"))}}},7399:function(e,t,r){"use strict";var n=r(9898),a=r(3972),i=r(1828),o=i.ensureSingle,l=i.identity,s=r(1424),c=r(4098),u=r(4621),f=r(8687),d=r(1082).tester;function h(e,t,r,f,h,p,v){var y,g=e._context.staticPlot;!function(e,t,r,a,o){var l=r.xaxis,s=r.yaxis,u=n.extent(i.simpleMap(l.range,l.r2c)),f=n.extent(i.simpleMap(s.range,s.r2c)),d=a[0].trace;if(c.hasMarkers(d)){var h=d.marker.maxdisplayed;if(0!==h){var p=a.filter((function(e){return e.x>=u[0]&&e.x<=u[1]&&e.y>=f[0]&&e.y<=f[1]})),v=Math.ceil(p.length/h),y=0;o.forEach((function(e,r){var n=e[0].trace;c.hasMarkers(n)&&n.marker.maxdisplayed>0&&r0;function x(e){return m?e.transition():e}var b=r.xaxis,_=r.yaxis,w=f[0].trace,T=w.line,M=n.select(p),k=o(M,"g","errorbars"),A=o(M,"g","lines"),L=o(M,"g","points"),S=o(M,"g","text");if(a.getComponentMethod("errorbars","plot")(e,k,r,v),!0===w.visible){var O,D;x(M).style("opacity",w.opacity);var C=w.fill.charAt(w.fill.length-1);"x"!==C&&"y"!==C&&(C=""),f[0][r.isRangePlot?"nodeRangePlot3":"node3"]=M;var P,I,R="",z=[],N=w._prevtrace;N&&(R=N._prevRevpath||"",D=N._nextFill,z=N._polygons);var E,F,H,j,B,Y,U,V="",q="",Z=[],G=i.noop;if(O=w._ownFill,c.hasLines(w)||"none"!==w.fill){for(D&&D.datum(f),-1!==["hv","vh","hvh","vhv"].indexOf(T.shape)?(E=s.steps(T.shape),F=s.steps(T.shape.split("").reverse().join(""))):E=F="spline"===T.shape?function(e){var t=e[e.length-1];return e.length>1&&e[0][0]===t[0]&&e[0][1]===t[1]?s.smoothclosed(e.slice(1),T.smoothing):s.smoothopen(e,T.smoothing)}:function(e){return"M"+e.join("L")},H=function(e){return F(e.reverse())},Z=u(f,{xaxis:b,yaxis:_,trace:w,connectGaps:w.connectgaps,baseTolerance:Math.max(T.width||1,3)/4,shape:T.shape,backoff:T.backoff,simplify:T.simplify,fill:w.fill}),U=w._polygons=new Array(Z.length),y=0;y0,y=f(e,t,r);(u=a.selectAll("g.trace").data(y,(function(e){return e[0].trace.uid}))).enter().append("g").attr("class",(function(e){return"trace scatter trace"+e[0].trace.uid})).style("stroke-miterlimit",2),u.order(),function(e,t,r){t.each((function(t){var a=o(n.select(this),"g","fills");s.setClipUrl(a,r.layerClipId,e);var i=t[0].trace,c=[];i._ownfill&&c.push("_ownFill"),i._nexttrace&&c.push("_nextFill");var u=a.selectAll("g").data(c,l);u.enter().append("g"),u.exit().each((function(e){i[e]=null})).remove(),u.order().each((function(e){i[e]=o(n.select(this),"path","js-fill")}))}))}(e,u,t),v?(c&&(d=c()),n.transition().duration(i.duration).ease(i.easing).each("end",(function(){d&&d()})).each("interrupt",(function(){d&&d()})).each((function(){a.selectAll("g.trace").each((function(r,n){h(e,n,t,r,y,this,i)}))}))):u.each((function(r,n){h(e,n,t,r,y,this,i)})),p&&u.exit().remove(),a.selectAll("path:not([d])").remove()}},8002:function(e,t,r){"use strict";var n=r(4098);e.exports=function(e,t){var r,a,i,o,l=e.cd,s=e.xaxis,c=e.yaxis,u=[],f=l[0].trace;if(!n.hasMarkers(f)&&!n.hasText(f))return[];if(!1===t)for(r=0;ra&&(a=u,o=c)}}return a?i(o):l};case"rms":return function(e,t){for(var r=0,a=0,o=0;o":return function(e){return d(e)>l};case">=":return function(e){return d(e)>=l};case"[]":return function(e){var t=d(e);return t>=l[0]&&t<=l[1]};case"()":return function(e){var t=d(e);return t>l[0]&&t=l[0]&&tl[0]&&t<=l[1]};case"][":return function(e){var t=d(e);return t<=l[0]||t>=l[1]};case")(":return function(e){var t=d(e);return tl[1]};case"](":return function(e){var t=d(e);return t<=l[0]||t>l[1]};case")[":return function(e){var t=d(e);return t=l[1]};case"{}":return function(e){return-1!==l.indexOf(d(e))};case"}{":return function(e){return-1===l.indexOf(d(e))}}}(r,i.getDataToCoordFunc(e,t,l,a),d),x={},b={},_=0;p?(y=function(e){x[e.astr]=n.extendDeep([],e.get()),e.set(new Array(f))},g=function(e,t){var r=x[e.astr][t];e.get()[t]=r}):(y=function(e){x[e.astr]=n.extendDeep([],e.get()),e.set([])},g=function(e,t){var r=x[e.astr][t];e.get().push(r)}),M(y);for(var w=o(t.transforms,r),T=0;T1?"%{group} (%{trace})":"%{group}");var s=e.styles,c=o.styles=[];if(s)for(i=0;i1&&-1!==a.indexOf("Macintosh")&&-1!==a.indexOf("Safari")&&(i=!0),i}},9898:function(e,t,r){var n,a;(function(){var i={version:"3.8.0"},o=[].slice,l=function(e){return o.call(e)},s=self.document;function c(e){return e&&(e.ownerDocument||e.document||e).documentElement}function u(e){return e&&(e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView)}if(s)try{l(s.documentElement.childNodes)[0].nodeType}catch(gi){l=function(e){for(var t=e.length,r=new Array(t);t--;)r[t]=e[t];return r}}if(Date.now||(Date.now=function(){return+new Date}),s)try{s.createElement("DIV").style.setProperty("opacity",0,"")}catch(mi){var f=this.Element.prototype,d=f.setAttribute,h=f.setAttributeNS,p=this.CSSStyleDeclaration.prototype,v=p.setProperty;f.setAttribute=function(e,t){d.call(this,e,t+"")},f.setAttributeNS=function(e,t,r){h.call(this,e,t,r+"")},p.setProperty=function(e,t,r){v.call(this,e,t+"",r)}}function y(e,t){return et?1:e>=t?0:NaN}function g(e){return null===e?NaN:+e}function m(e){return!isNaN(e)}function x(e){return{left:function(t,r,n,a){for(arguments.length<3&&(n=0),arguments.length<4&&(a=t.length);n>>1;e(t[i],r)<0?n=i+1:a=i}return n},right:function(t,r,n,a){for(arguments.length<3&&(n=0),arguments.length<4&&(a=t.length);n>>1;e(t[i],r)>0?a=i:n=i+1}return n}}}i.ascending=y,i.descending=function(e,t){return te?1:t>=e?0:NaN},i.min=function(e,t){var r,n,a=-1,i=e.length;if(1===arguments.length){for(;++a=n){r=n;break}for(;++an&&(r=n)}else{for(;++a=n){r=n;break}for(;++an&&(r=n)}return r},i.max=function(e,t){var r,n,a=-1,i=e.length;if(1===arguments.length){for(;++a=n){r=n;break}for(;++ar&&(r=n)}else{for(;++a=n){r=n;break}for(;++ar&&(r=n)}return r},i.extent=function(e,t){var r,n,a,i=-1,o=e.length;if(1===arguments.length){for(;++i=n){r=a=n;break}for(;++in&&(r=n),a=n){r=a=n;break}for(;++in&&(r=n),a1)return o/(s-1)},i.deviation=function(){var e=i.variance.apply(this,arguments);return e?Math.sqrt(e):e};var b=x(y);function _(e){return e.length}i.bisectLeft=b.left,i.bisect=i.bisectRight=b.right,i.bisector=function(e){return x(1===e.length?function(t,r){return y(e(t),r)}:e)},i.shuffle=function(e,t,r){(i=arguments.length)<3&&(r=e.length,i<2&&(t=0));for(var n,a,i=r-t;i;)a=Math.random()*i--|0,n=e[i+t],e[i+t]=e[a+t],e[a+t]=n;return e},i.permute=function(e,t){for(var r=t.length,n=new Array(r);r--;)n[r]=e[t[r]];return n},i.pairs=function(e){for(var t=0,r=e.length-1,n=e[0],a=new Array(r<0?0:r);t=0;)for(t=(n=e[a]).length;--t>=0;)r[--o]=n[t];return r};var w=Math.abs;function T(e,t){for(var r in t)Object.defineProperty(e.prototype,r,{value:t[r],enumerable:!1})}function M(){this._=Object.create(null)}i.range=function(e,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=e,e=0)),(t-e)/r==1/0)throw new Error("infinite range");var n,a=[],i=function(e){for(var t=1;e*t%1;)t*=10;return t}(w(r)),o=-1;if(e*=i,t*=i,(r*=i)<0)for(;(n=e+r*++o)>t;)a.push(n/i);else for(;(n=e+r*++o)=n.length)return t?t.call(r,i):e?i.sort(e):i;for(var s,c,u,f,d=-1,h=i.length,p=n[l++],v=new M;++d=n.length)return e;var r=[],i=a[t++];return e.forEach((function(e,n){r.push({key:e,values:l(n,t)})})),i?r.sort((function(e,t){return i(e.key,t.key)})):r}return r.map=function(e,t){return o(t,e,0)},r.entries=function(e){return l(o(i.map,e,0),0)},r.key=function(e){return n.push(e),r},r.sortKeys=function(e){return a[n.length-1]=e,r},r.sortValues=function(t){return e=t,r},r.rollup=function(e){return t=e,r},r},i.set=function(e){var t=new R;if(e)for(var r=0,n=e.length;r=0&&(n=e.slice(r+1),e=e.slice(0,r)),e)return arguments.length<2?this[e].on(n):this[e].on(n,t);if(2===arguments.length){if(null==t)for(e in this)this.hasOwnProperty(e)&&this[e].on(n,null);return this}},i.event=null,i.requote=function(e){return e.replace(q,"\\$&")};var q=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Z={}.__proto__?function(e,t){e.__proto__=t}:function(e,t){for(var r in t)e[r]=t[r]};function G(e){return Z(e,K),e}var W=function(e,t){return t.querySelector(e)},X=function(e,t){return t.querySelectorAll(e)},J=function(e,t){var r=e.matches||e[E(e,"matchesSelector")];return J=function(e,t){return r.call(e,t)},J(e,t)};"function"==typeof Sizzle&&(W=function(e,t){return Sizzle(e,t)[0]||null},X=Sizzle,J=Sizzle.matchesSelector),i.selection=function(){return i.select(s.documentElement)};var K=i.selection.prototype=[];function Q(e){return"function"==typeof e?e:function(){return W(e,this)}}function $(e){return"function"==typeof e?e:function(){return X(e,this)}}K.select=function(e){var t,r,n,a,i=[];e=Q(e);for(var o=-1,l=this.length;++o=0&&"xmlns"!==(r=e.slice(0,t))&&(e=e.slice(t+1)),te.hasOwnProperty(r)?{space:te[r],local:e}:e}},K.attr=function(e,t){if(arguments.length<2){if("string"==typeof e){var r=this.node();return(e=i.ns.qualify(e)).local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}for(t in e)this.each(re(t,e[t]));return this}return this.each(re(e,t))},K.classed=function(e,t){if(arguments.length<2){if("string"==typeof e){var r=this.node(),n=(e=ie(e)).length,a=-1;if(t=r.classList){for(;++a=0;)(r=n[a])&&(i&&i!==r.nextSibling&&i.parentNode.insertBefore(r,i),i=r);return this},K.sort=function(e){e=pe.apply(this,arguments);for(var t=-1,r=this.length;++t0&&(e=e.slice(0,a));var s=xe.get(e);function c(){var t=this[n];t&&(this.removeEventListener(e,t,t.$),delete this[n])}return s&&(e=s,o=_e),a?t?function(){var a=o(t,l(arguments));c.call(this),this.addEventListener(e,this[n]=a,a.$=r),a._=t}:c:t?H:function(){var t,r=new RegExp("^__on([^.]+)"+i.requote(e)+"$");for(var n in this)if(t=n.match(r)){var a=this[n];this.removeEventListener(t[1],a,a.$),delete this[n]}}}i.selection.enter=ye,i.selection.enter.prototype=ge,ge.append=K.append,ge.empty=K.empty,ge.node=K.node,ge.call=K.call,ge.size=K.size,ge.select=function(e){for(var t,r,n,a,i,o=[],l=-1,s=this.length;++l=n&&(n=t+1);!(o=l[n])&&++n1?Ie:e<-1?-Ie:Math.asin(e)}function Ee(e){return((e=Math.exp(e))+1/e)/2}var Fe=Math.SQRT2;i.interpolateZoom=function(e,t){var r,n,a=e[0],i=e[1],o=e[2],l=t[0],s=t[1],c=t[2],u=l-a,f=s-i,d=u*u+f*f;if(d0&&(e=e.transition().duration(v)),e.call(w.event)}function L(){l&&l.domain(o.range().map((function(e){return(e-d.x)/d.k})).map(o.invert)),f&&f.domain(c.range().map((function(e){return(e-d.y)/d.k})).map(c.invert))}function S(e){y++||e({type:"zoomstart"})}function O(e){L(),e({type:"zoom",scale:d.k,translate:[d.x,d.y]})}function D(e){--y||(e({type:"zoomend"}),t=null)}function C(){var e=this,t=_.of(e,arguments),r=0,n=i.select(u(e)).on(m,(function(){r=1,k(i.mouse(e),a),O(t)})).on(x,(function(){n.on(m,null).on(x,null),o(r),D(t)})),a=T(i.mouse(e)),o=Me(e);Qa.call(e),S(t)}function P(){var e,t=this,r=_.of(t,arguments),n={},o=0,l=".zoom-"+i.event.changedTouches[0].identifier,s="touchmove"+l,c="touchend"+l,u=[],f=i.select(t),h=Me(t);function p(){var r=i.touches(t);return e=d.k,r.forEach((function(e){e.identifier in n&&(n[e.identifier]=T(e))})),r}function v(){var e=i.event.target;i.select(e).on(s,y).on(c,m),u.push(e);for(var r=i.event.changedTouches,l=0,f=r.length;l1){g=h[0];var x=h[1],b=g[0]-x[0],_=g[1]-x[1];o=b*b+_*_}}function y(){var l,s,c,u,f=i.touches(t);Qa.call(t);for(var d=0,h=f.length;d360?e-=360:e<0&&(e+=360),e<60?n+(a-n)*e/60:e<180?a:e<240?n+(a-n)*(240-e)/60:n}(e))}return e=isNaN(e)?0:(e%=360)<0?e+360:e,t=isNaN(t)||t<0?0:t>1?1:t,n=2*(r=r<0?0:r>1?1:r)-(a=r<=.5?r*(1+t):r+t-r*t),new ot(i(e+120),i(e),i(e-120))}function Ze(e,t,r){return this instanceof Ze?(this.h=+e,this.c=+t,void(this.l=+r)):arguments.length<2?e instanceof Ze?new Ze(e.h,e.c,e.l):rt(e instanceof Xe?e.l:(e=ht((e=i.rgb(e)).r,e.g,e.b)).l,e.a,e.b):new Ze(e,t,r)}Ve.brighter=function(e){return e=Math.pow(.7,arguments.length?e:1),new Ue(this.h,this.s,this.l/e)},Ve.darker=function(e){return e=Math.pow(.7,arguments.length?e:1),new Ue(this.h,this.s,e*this.l)},Ve.rgb=function(){return qe(this.h,this.s,this.l)},i.hcl=Ze;var Ge=Ze.prototype=new Ye;function We(e,t,r){return isNaN(e)&&(e=0),isNaN(t)&&(t=0),new Xe(r,Math.cos(e*=Re)*t,Math.sin(e)*t)}function Xe(e,t,r){return this instanceof Xe?(this.l=+e,this.a=+t,void(this.b=+r)):arguments.length<2?e instanceof Xe?new Xe(e.l,e.a,e.b):e instanceof Ze?We(e.h,e.c,e.l):ht((e=ot(e)).r,e.g,e.b):new Xe(e,t,r)}Ge.brighter=function(e){return new Ze(this.h,this.c,Math.min(100,this.l+Je*(arguments.length?e:1)))},Ge.darker=function(e){return new Ze(this.h,this.c,Math.max(0,this.l-Je*(arguments.length?e:1)))},Ge.rgb=function(){return We(this.h,this.c,this.l).rgb()},i.lab=Xe;var Je=18,Ke=.95047,Qe=1,$e=1.08883,et=Xe.prototype=new Ye;function tt(e,t,r){var n=(e+16)/116,a=n+t/500,i=n-r/200;return new ot(it(3.2404542*(a=nt(a)*Ke)-1.5371385*(n=nt(n)*Qe)-.4985314*(i=nt(i)*$e)),it(-.969266*a+1.8760108*n+.041556*i),it(.0556434*a-.2040259*n+1.0572252*i))}function rt(e,t,r){return e>0?new Ze(Math.atan2(r,t)*ze,Math.sqrt(t*t+r*r),e):new Ze(NaN,NaN,e)}function nt(e){return e>.206893034?e*e*e:(e-4/29)/7.787037}function at(e){return e>.008856?Math.pow(e,1/3):7.787037*e+4/29}function it(e){return Math.round(255*(e<=.00304?12.92*e:1.055*Math.pow(e,1/2.4)-.055))}function ot(e,t,r){return this instanceof ot?(this.r=~~e,this.g=~~t,void(this.b=~~r)):arguments.length<2?e instanceof ot?new ot(e.r,e.g,e.b):ft(""+e,ot,qe):new ot(e,t,r)}function lt(e){return new ot(e>>16,e>>8&255,255&e)}function st(e){return lt(e)+""}et.brighter=function(e){return new Xe(Math.min(100,this.l+Je*(arguments.length?e:1)),this.a,this.b)},et.darker=function(e){return new Xe(Math.max(0,this.l-Je*(arguments.length?e:1)),this.a,this.b)},et.rgb=function(){return tt(this.l,this.a,this.b)},i.rgb=ot;var ct=ot.prototype=new Ye;function ut(e){return e<16?"0"+Math.max(0,e).toString(16):Math.min(255,e).toString(16)}function ft(e,t,r){var n,a,i,o=0,l=0,s=0;if(n=/([a-z]+)\((.*)\)/.exec(e=e.toLowerCase()))switch(a=n[2].split(","),n[1]){case"hsl":return r(parseFloat(a[0]),parseFloat(a[1])/100,parseFloat(a[2])/100);case"rgb":return t(vt(a[0]),vt(a[1]),vt(a[2]))}return(i=yt.get(e))?t(i.r,i.g,i.b):(null==e||"#"!==e.charAt(0)||isNaN(i=parseInt(e.slice(1),16))||(4===e.length?(o=(3840&i)>>4,o|=o>>4,l=240&i,l|=l>>4,s=15&i,s|=s<<4):7===e.length&&(o=(16711680&i)>>16,l=(65280&i)>>8,s=255&i)),t(o,l,s))}function dt(e,t,r){var n,a,i=Math.min(e/=255,t/=255,r/=255),o=Math.max(e,t,r),l=o-i,s=(o+i)/2;return l?(a=s<.5?l/(o+i):l/(2-o-i),n=e==o?(t-r)/l+(t0&&s<1?0:n),new Ue(n,a,s)}function ht(e,t,r){var n=at((.4124564*(e=pt(e))+.3575761*(t=pt(t))+.1804375*(r=pt(r)))/Ke),a=at((.2126729*e+.7151522*t+.072175*r)/Qe);return Xe(116*a-16,500*(n-a),200*(a-at((.0193339*e+.119192*t+.9503041*r)/$e)))}function pt(e){return(e/=255)<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}function vt(e){var t=parseFloat(e);return"%"===e.charAt(e.length-1)?Math.round(2.55*t):t}ct.brighter=function(e){e=Math.pow(.7,arguments.length?e:1);var t=this.r,r=this.g,n=this.b,a=30;return t||r||n?(t&&t=200&&t<300||304===t){try{e=r.call(a,c)}catch(gi){return void o.error.call(a,gi)}o.load.call(a,e)}else o.error.call(a,c)}return self.XDomainRequest&&!("withCredentials"in c)&&/^(http(s)?:)?\/\//.test(e)&&(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=f:c.onreadystatechange=function(){c.readyState>3&&f()},c.onprogress=function(e){var t=i.event;i.event=e;try{o.progress.call(a,c)}finally{i.event=t}},a.header=function(e,t){return e=(e+"").toLowerCase(),arguments.length<2?s[e]:(null==t?delete s[e]:s[e]=t+"",a)},a.mimeType=function(e){return arguments.length?(t=null==e?null:e+"",a):t},a.responseType=function(e){return arguments.length?(u=e,a):u},a.response=function(e){return r=e,a},["get","post"].forEach((function(e){a[e]=function(){return a.send.apply(a,[e].concat(l(arguments)))}})),a.send=function(r,n,i){if(2===arguments.length&&"function"==typeof n&&(i=n,n=null),c.open(r,e,!0),null==t||"accept"in s||(s.accept=t+",*/*"),c.setRequestHeader)for(var l in s)c.setRequestHeader(l,s[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=u&&(c.responseType=u),null!=i&&a.on("error",i).on("load",(function(e){i(null,e)})),o.beforesend.call(a,c),c.send(null==n?null:n),a},a.abort=function(){return c.abort(),a},i.rebind(a,o,"on"),null==n?a:a.get(function(e){return 1===e.length?function(t,r){e(null==t?r:null)}:e}(n))}yt.forEach((function(e,t){yt.set(e,lt(t))})),i.functor=gt,i.xhr=mt(z),i.dsv=function(e,t){var r=new RegExp('["'+e+"\n]"),n=e.charCodeAt(0);function a(e,r,n){arguments.length<3&&(n=r,r=null);var a=xt(e,t,null==r?i:o(r),n);return a.row=function(e){return arguments.length?a.response(null==(r=e)?i:o(e)):r},a}function i(e){return a.parse(e.responseText)}function o(e){return function(t){return a.parse(t.responseText,e)}}function l(t){return t.map(s).join(e)}function s(e){return r.test(e)?'"'+e.replace(/\"/g,'""')+'"':e}return a.parse=function(e,t){var r;return a.parseRows(e,(function(e,n){if(r)return r(e,n-1);var a=function(t){for(var r={},n=e.length,a=0;a=s)return o;if(a)return a=!1,i;var t=c;if(34===e.charCodeAt(t)){for(var r=t;r++24?(isFinite(t)&&(clearTimeout(Tt),Tt=setTimeout(At,t)),wt=0):(wt=1,Mt(At))}function Lt(){for(var e=Date.now(),t=bt;t;)e>=t.t&&t.c(e-t.t)&&(t.c=null),t=t.n;return e}function St(){for(var e,t=bt,r=1/0;t;)t.c?(t.t1&&(t=e[i[o-2]],r=e[i[o-1]],n=e[l],(r[0]-t[0])*(n[1]-t[1])-(r[1]-t[1])*(n[0]-t[0])<=0);)--o;i[o++]=l}return i.slice(0,o)}function Pt(e,t){return e[0]-t[0]||e[1]-t[1]}i.timer=function(){kt.apply(this,arguments)},i.timer.flush=function(){Lt(),St()},i.round=function(e,t){return t?Math.round(e*(t=Math.pow(10,t)))/t:Math.round(e)},i.geom={},i.geom.hull=function(e){var t=Ot,r=Dt;if(arguments.length)return n(e);function n(e){if(e.length<3)return[];var n,a=gt(t),i=gt(r),o=e.length,l=[],s=[];for(n=0;n=0;--n)h.push(e[l[c[n]][2]]);for(n=+f;nSe)l=l.L;else{if(!((a=i-Jt(l,o))>Se)){n>-Se?(t=l.P,r=l):a>-Se?(t=l,r=l.N):t=r=l;break}if(!l.R){t=l;break}l=l.R}var s=qt(e);if(Ht.insert(t,s),t||r){if(t===r)return tr(t),r=qt(t.site),Ht.insert(s,r),s.edge=r.edge=ar(t.site,s.site),er(t),void er(r);if(r){tr(t),tr(r);var c=t.site,u=c.x,f=c.y,d=e.x-u,h=e.y-f,p=r.site,v=p.x-u,y=p.y-f,g=2*(d*y-h*v),m=d*d+h*h,x=v*v+y*y,b={x:(y*m-h*x)/g+u,y:(d*x-v*m)/g+f};or(r.edge,c,p,b),s.edge=ar(c,e,null,b),r.edge=ar(e,p,null,b),er(t),er(r)}else s.edge=ar(t.site,s.site)}}function Xt(e,t){var r=e.site,n=r.x,a=r.y,i=a-t;if(!i)return n;var o=e.P;if(!o)return-1/0;var l=(r=o.site).x,s=r.y,c=s-t;if(!c)return l;var u=l-n,f=1/i-1/c,d=u/c;return f?(-d+Math.sqrt(d*d-2*f*(u*u/(-2*c)-s+c/2+a-i/2)))/f+n:(n+l)/2}function Jt(e,t){var r=e.N;if(r)return Xt(r,t);var n=e.site;return n.y===t?n.x:1/0}function Kt(e){this.site=e,this.edges=[]}function Qt(e,t){return t.angle-e.angle}function $t(){cr(this),this.x=this.y=this.arc=this.site=this.cy=null}function er(e){var t=e.P,r=e.N;if(t&&r){var n=t.site,a=e.site,i=r.site;if(n!==i){var o=a.x,l=a.y,s=n.x-o,c=n.y-l,u=i.x-o,f=2*(s*(y=i.y-l)-c*u);if(!(f>=-Oe)){var d=s*s+c*c,h=u*u+y*y,p=(y*d-c*h)/f,v=(s*h-u*d)/f,y=v+l,g=Ut.pop()||new $t;g.arc=e,g.site=a,g.x=p+o,g.y=y+Math.sqrt(p*p+v*v),g.cy=y,e.circle=g;for(var m=null,x=Bt._;x;)if(g.y=l)return;if(d>p){if(i){if(i.y>=c)return}else i={x:y,y:s};r={x:y,y:c}}else{if(i){if(i.y1)if(d>p){if(i){if(i.y>=c)return}else i={x:(s-a)/n,y:s};r={x:(c-a)/n,y:c}}else{if(i){if(i.y=l)return}else i={x:o,y:n*o+a};r={x:l,y:n*l+a}}else{if(i){if(i.x0)){if(t/=d,d<0){if(t0){if(t>f)return;t>u&&(u=t)}if(t=a-s,d||!(t<0)){if(t/=d,d<0){if(t>f)return;t>u&&(u=t)}else if(d>0){if(t0)){if(t/=h,h<0){if(t0){if(t>f)return;t>u&&(u=t)}if(t=i-c,h||!(t<0)){if(t/=h,h<0){if(t>f)return;t>u&&(u=t)}else if(h>0){if(t0&&(e.a={x:s+u*d,y:c+u*h}),f<1&&(e.b={x:s+f*d,y:c+f*h}),e}}}}}),s=o.length;s--;)(!rr(t=o[s],e)||!l(t)||w(t.a.x-t.b.x)Se||w(a-r)>Se)&&(l.splice(o,0,new lr(ir(i.site,u,w(n-f)Se?{x:f,y:w(t-f)Se?{x:w(r-p)Se?{x:d,y:w(t-d)Se?{x:w(r-h)=r&&c.x<=a&&c.y>=n&&c.y<=o?[[r,o],[a,o],[a,n],[r,n]]:[]).point=e[l]})),t}function l(e){return e.map((function(e,t){return{x:Math.round(n(e,t)/Se)*Se,y:Math.round(a(e,t)/Se)*Se,i:t}}))}return o.links=function(e){return hr(l(e)).edges.filter((function(e){return e.l&&e.r})).map((function(t){return{source:e[t.l.i],target:e[t.r.i]}}))},o.triangles=function(e){var t=[];return hr(l(e)).cells.forEach((function(r,n){for(var a,i,o,l,s=r.site,c=r.edges.sort(Qt),u=-1,f=c.length,d=c[f-1].edge,h=d.l===s?d.r:d.l;++ui&&(a=t.slice(i,a),l[o]?l[o]+=a:l[++o]=a),(r=r[0])===(n=n[0])?l[o]?l[o]+=n:l[++o]=n:(l[++o]=null,s.push({i:o,x:_r(r,n)})),i=Mr.lastIndex;return iv&&(v=s.x),s.y>y&&(y=s.y),c.push(s.x),u.push(s.y);else for(f=0;fv&&(v=x),b>y&&(y=b),c.push(x),u.push(b)}var _=v-h,T=y-p;function M(e,t,r,n,a,i,o,l){if(!isNaN(r)&&!isNaN(n))if(e.leaf){var s=e.x,c=e.y;if(null!=s)if(w(s-r)+w(c-n)<.01)k(e,t,r,n,a,i,o,l);else{var u=e.point;e.x=e.y=e.point=null,k(e,u,s,c,a,i,o,l),k(e,t,r,n,a,i,o,l)}else e.x=r,e.y=n,e.point=t}else k(e,t,r,n,a,i,o,l)}function k(e,t,r,n,a,i,o,l){var s=.5*(a+o),c=.5*(i+l),u=r>=s,f=n>=c,d=f<<1|u;e.leaf=!1,u?a=s:o=s,f?i=c:l=c,M(e=e.nodes[d]||(e.nodes[d]={leaf:!0,nodes:[],point:null,x:null,y:null}),t,r,n,a,i,o,l)}_>T?y=p+_:v=h+T;var A={leaf:!0,nodes:[],point:null,x:null,y:null,add:function(e){M(A,e,+g(e,++f),+m(e,f),h,p,v,y)},visit:function(e){mr(e,A,h,p,v,y)},find:function(e){return function(e,t,r,n,a,i,o){var l,s=1/0;return function e(c,u,f,d,h){if(!(u>i||f>o||d=_)<<1|t>=b,T=w+4;w=0&&!(r=i.interpolators[n](e,t)););return r}function Ar(e,t){var r,n=[],a=[],i=e.length,o=t.length,l=Math.min(e.length,t.length);for(r=0;r=1)return 1;var t=e*e,r=t*e;return 4*(e<.5?r:3*(e-t)+r-.75)}function zr(e){return 1-Math.cos(e*Ie)}function Nr(e){return Math.pow(2,10*(e-1))}function Er(e){return 1-Math.sqrt(1-e*e)}function Fr(e){return e<1/2.75?7.5625*e*e:e<2/2.75?7.5625*(e-=1.5/2.75)*e+.75:e<2.5/2.75?7.5625*(e-=2.25/2.75)*e+.9375:7.5625*(e-=2.625/2.75)*e+.984375}function Hr(e,t){return t-=e,function(r){return Math.round(e+t*r)}}function jr(e){var t,r,n,a=[e.a,e.b],i=[e.c,e.d],o=Yr(a),l=Br(a,i),s=Yr(((t=i)[0]+=(n=-l)*(r=a)[0],t[1]+=n*r[1],t))||0;a[0]*i[1]=0?e.slice(0,r):e,a=r>=0?e.slice(r+1):"in";return n=Sr.get(n)||Lr,a=Or.get(a)||z,t=a(n.apply(null,o.call(arguments,1))),function(e){return e<=0?0:e>=1?1:t(e)}},i.interpolateHcl=function(e,t){e=i.hcl(e),t=i.hcl(t);var r=e.h,n=e.c,a=e.l,o=t.h-r,l=t.c-n,s=t.l-a;return isNaN(l)&&(l=0,n=isNaN(n)?t.c:n),isNaN(o)?(o=0,r=isNaN(r)?t.h:r):o>180?o-=360:o<-180&&(o+=360),function(e){return We(r+o*e,n+l*e,a+s*e)+""}},i.interpolateHsl=function(e,t){e=i.hsl(e),t=i.hsl(t);var r=e.h,n=e.s,a=e.l,o=t.h-r,l=t.s-n,s=t.l-a;return isNaN(l)&&(l=0,n=isNaN(n)?t.s:n),isNaN(o)?(o=0,r=isNaN(r)?t.h:r):o>180?o-=360:o<-180&&(o+=360),function(e){return qe(r+o*e,n+l*e,a+s*e)+""}},i.interpolateLab=function(e,t){e=i.lab(e),t=i.lab(t);var r=e.l,n=e.a,a=e.b,o=t.l-r,l=t.a-n,s=t.b-a;return function(e){return tt(r+o*e,n+l*e,a+s*e)+""}},i.interpolateRound=Hr,i.transform=function(e){var t=s.createElementNS(i.ns.prefix.svg,"g");return(i.transform=function(e){if(null!=e){t.setAttribute("transform",e);var r=t.transform.baseVal.consolidate()}return new jr(r?r.matrix:Ur)})(e)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var Ur={a:1,b:0,c:0,d:1,e:0,f:0};function Vr(e){return e.length?e.pop()+",":""}function qr(e,t){var r=[],n=[];return e=i.transform(e),t=i.transform(t),function(e,t,r,n){if(e[0]!==t[0]||e[1]!==t[1]){var a=r.push("translate(",null,",",null,")");n.push({i:a-4,x:_r(e[0],t[0])},{i:a-2,x:_r(e[1],t[1])})}else(t[0]||t[1])&&r.push("translate("+t+")")}(e.translate,t.translate,r,n),function(e,t,r,n){e!==t?(e-t>180?t+=360:t-e>180&&(e+=360),n.push({i:r.push(Vr(r)+"rotate(",null,")")-2,x:_r(e,t)})):t&&r.push(Vr(r)+"rotate("+t+")")}(e.rotate,t.rotate,r,n),function(e,t,r,n){e!==t?n.push({i:r.push(Vr(r)+"skewX(",null,")")-2,x:_r(e,t)}):t&&r.push(Vr(r)+"skewX("+t+")")}(e.skew,t.skew,r,n),function(e,t,r,n){if(e[0]!==t[0]||e[1]!==t[1]){var a=r.push(Vr(r)+"scale(",null,",",null,")");n.push({i:a-4,x:_r(e[0],t[0])},{i:a-2,x:_r(e[1],t[1])})}else 1===t[0]&&1===t[1]||r.push(Vr(r)+"scale("+t+")")}(e.scale,t.scale,r,n),e=t=null,function(e){for(var t,a=-1,i=n.length;++a0?r=t:(e.c=null,e.t=NaN,e=null,s.end({type:"end",alpha:r=0})):t>0&&(s.start({type:"start",alpha:r=t}),e=kt(l.tick)),l):r},l.start=function(){var e,t,r,i=g.length,s=m.length,u=c[0],p=c[1];for(e=0;e=0;)r.push(a[n])}function ln(e,t){for(var r=[e],n=[];null!=(e=r.pop());)if(n.push(e),(i=e.children)&&(a=i.length))for(var a,i,o=-1;++o=0;)o.push(u=c[s]),u.parent=i,u.depth=i.depth+1;r&&(i.value=0),i.children=c}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return ln(a,(function(t){var n,a;e&&(n=t.children)&&n.sort(e),r&&(a=t.parent)&&(a.value+=t.value)})),l}return n.sort=function(t){return arguments.length?(e=t,n):e},n.children=function(e){return arguments.length?(t=e,n):t},n.value=function(e){return arguments.length?(r=e,n):r},n.revalue=function(e){return r&&(on(e,(function(e){e.children&&(e.value=0)})),ln(e,(function(e){var t;e.children||(e.value=+r.call(n,e,e.depth)||0),(t=e.parent)&&(t.value+=e.value)}))),e},n},i.layout.partition=function(){var e=i.layout.hierarchy(),t=[1,1];function r(e,t,n,a){var i=e.children;if(e.x=t,e.y=e.depth*a,e.dx=n,e.dy=a,i&&(o=i.length)){var o,l,s,c=-1;for(n=e.value?n/e.value:0;++cl&&(l=n),o.push(n)}for(r=0;ra&&(n=r,a=t);return n}function _n(e){return e.reduce(wn,0)}function wn(e,t){return e+t[1]}function Tn(e,t){return Mn(e,Math.ceil(Math.log(t.length)/Math.LN2+1))}function Mn(e,t){for(var r=-1,n=+e[0],a=(e[1]-n)/t,i=[];++r<=t;)i[r]=a*r+n;return i}function kn(e){return[i.min(e),i.max(e)]}function An(e,t){return e.value-t.value}function Ln(e,t){var r=e._pack_next;e._pack_next=t,t._pack_prev=e,t._pack_next=r,r._pack_prev=t}function Sn(e,t){e._pack_next=t,t._pack_prev=e}function On(e,t){var r=t.x-e.x,n=t.y-e.y,a=e.r+t.r;return.999*a*a>r*r+n*n}function Dn(e){if((t=e.children)&&(s=t.length)){var t,r,n,a,i,o,l,s,c=1/0,u=-1/0,f=1/0,d=-1/0;if(t.forEach(Cn),(r=t[0]).x=-r.r,r.y=0,x(r),s>1&&((n=t[1]).x=n.r,n.y=0,x(n),s>2))for(Rn(r,n,a=t[2]),x(a),Ln(r,a),r._pack_prev=a,Ln(a,n),n=r._pack_next,i=3;i0)for(o=-1;++o=f[0]&&s<=f[1]&&((l=c[i.bisect(d,s,1,p)-1]).y+=v,l.push(a[o]));return c}return a.value=function(e){return arguments.length?(t=e,a):t},a.range=function(e){return arguments.length?(r=gt(e),a):r},a.bins=function(e){return arguments.length?(n="number"==typeof e?function(t){return Mn(t,e)}:gt(e),a):n},a.frequency=function(t){return arguments.length?(e=!!t,a):e},a},i.layout.pack=function(){var e,t=i.layout.hierarchy().sort(An),r=0,n=[1,1];function a(a,i){var o=t.call(this,a,i),l=o[0],s=n[0],c=n[1],u=null==e?Math.sqrt:"function"==typeof e?e:function(){return e};if(l.x=l.y=0,ln(l,(function(e){e.r=+u(e.value)})),ln(l,Dn),r){var f=r*(e?1:Math.max(2*l.r/s,2*l.r/c))/2;ln(l,(function(e){e.r+=f})),ln(l,Dn),ln(l,(function(e){e.r-=f}))}return In(l,s/2,c/2,e?1:1/Math.max(2*l.r/s,2*l.r/c)),o}return a.size=function(e){return arguments.length?(n=e,a):n},a.radius=function(t){return arguments.length?(e=null==t||"function"==typeof t?t:+t,a):e},a.padding=function(e){return arguments.length?(r=+e,a):r},an(a,t)},i.layout.tree=function(){var e=i.layout.hierarchy().sort(null).value(null),t=zn,r=[1,1],n=null;function a(a,i){var c=e.call(this,a,i),u=c[0],f=function(e){for(var t,r={A:null,children:[e]},n=[r];null!=(t=n.pop());)for(var a,i=t.children,o=0,l=i.length;oh.x&&(h=e),e.depth>p.depth&&(p=e)}));var v=t(d,h)/2-d.x,y=r[0]/(h.x+t(h,d)/2+v),g=r[1]/(p.depth||1);on(u,(function(e){e.x=(e.x+v)*y,e.y=e.depth*g}))}return c}function o(e){var r=e.children,n=e.parent.children,a=e.i?n[e.i-1]:null;if(r.length){!function(e){for(var t,r=0,n=0,a=e.children,i=a.length;--i>=0;)(t=a[i]).z+=r,t.m+=r,r+=t.s+(n+=t.c)}(e);var i=(r[0].z+r[r.length-1].z)/2;a?(e.z=a.z+t(e._,a._),e.m=e.z-i):e.z=i}else a&&(e.z=a.z+t(e._,a._));e.parent.A=function(e,r,n){if(r){for(var a,i=e,o=e,l=r,s=i.parent.children[0],c=i.m,u=o.m,f=l.m,d=s.m;l=En(l),i=Nn(i),l&&i;)s=Nn(s),(o=En(o)).a=e,(a=l.z+f-i.z-c+t(l._,i._))>0&&(Fn(Hn(l,e,n),e,a),c+=a,u+=a),f+=l.m,c+=i.m,d+=s.m,u+=o.m;l&&!En(o)&&(o.t=l,o.m+=f-u),i&&!Nn(s)&&(s.t=i,s.m+=c-d,n=e)}return n}(e,a,e.parent.A||n[0])}function l(e){e._.x=e.z+e.parent.m,e.m+=e.parent.m}function s(e){e.x*=r[0],e.y=e.depth*r[1]}return a.separation=function(e){return arguments.length?(t=e,a):t},a.size=function(e){return arguments.length?(n=null==(r=e)?s:null,a):n?null:r},a.nodeSize=function(e){return arguments.length?(n=null==(r=e)?null:s,a):n?r:null},an(a,e)},i.layout.cluster=function(){var e=i.layout.hierarchy().sort(null).value(null),t=zn,r=[1,1],n=!1;function a(a,o){var l,s=e.call(this,a,o),c=s[0],u=0;ln(c,(function(e){var r=e.children;r&&r.length?(e.x=function(e){return e.reduce((function(e,t){return e+t.x}),0)/e.length}(r),e.y=function(e){return 1+i.max(e,(function(e){return e.y}))}(r)):(e.x=l?u+=t(e,l):0,e.y=0,l=e)}));var f=jn(c),d=Bn(c),h=f.x-t(f,d)/2,p=d.x+t(d,f)/2;return ln(c,n?function(e){e.x=(e.x-c.x)*r[0],e.y=(c.y-e.y)*r[1]}:function(e){e.x=(e.x-h)/(p-h)*r[0],e.y=(1-(c.y?e.y/c.y:1))*r[1]}),s}return a.separation=function(e){return arguments.length?(t=e,a):t},a.size=function(e){return arguments.length?(n=null==(r=e),a):n?null:r},a.nodeSize=function(e){return arguments.length?(n=null!=(r=e),a):n?r:null},an(a,e)},i.layout.treemap=function(){var e,t=i.layout.hierarchy(),r=Math.round,n=[1,1],a=null,o=Yn,l=!1,s="squarify",c=.5*(1+Math.sqrt(5));function u(e,t){for(var r,n,a=-1,i=e.length;++a0;)l.push(r=c[a-1]),l.area+=r.area,"squarify"!==s||(n=h(l,v))<=d?(c.pop(),d=n):(l.area-=l.pop().area,p(l,v,i,!1),v=Math.min(i.dx,i.dy),l.length=l.area=0,d=1/0);l.length&&(p(l,v,i,!0),l.length=l.area=0),t.forEach(f)}}function d(e){var t=e.children;if(t&&t.length){var r,n=o(e),a=t.slice(),i=[];for(u(a,n.dx*n.dy/e.value),i.area=0;r=a.pop();)i.push(r),i.area+=r.area,null!=r.z&&(p(i,r.z?n.dx:n.dy,n,!a.length),i.length=i.area=0);t.forEach(d)}}function h(e,t){for(var r,n=e.area,a=0,i=1/0,o=-1,l=e.length;++oa&&(a=r));return t*=t,(n*=n)?Math.max(t*a*c/n,n/(t*i*c)):1/0}function p(e,t,n,a){var i,o=-1,l=e.length,s=n.x,c=n.y,u=t?r(e.area/t):0;if(t==n.dx){for((a||u>n.dy)&&(u=n.dy);++on.dx)&&(u=n.dx);++o1);return e+t*r*Math.sqrt(-2*Math.log(a)/a)}},logNormal:function(){var e=i.random.normal.apply(i,arguments);return function(){return Math.exp(e())}},bates:function(e){var t=i.random.irwinHall(e);return function(){return t()/e}},irwinHall:function(e){return function(){for(var t=0,r=0;r2?Jn:Zn,s=n?Gr:Zr;return a=o(e,t,s,r),i=o(t,e,s,kr),l}function l(e){return a(e)}return l.invert=function(e){return i(e)},l.domain=function(t){return arguments.length?(e=t.map(Number),o()):e},l.range=function(e){return arguments.length?(t=e,o()):t},l.rangeRound=function(e){return l.range(e).interpolate(Hr)},l.clamp=function(e){return arguments.length?(n=e,o()):n},l.interpolate=function(e){return arguments.length?(r=e,o()):r},l.ticks=function(t){return ta(e,t)},l.tickFormat=function(t,r){return d3_scale_linearTickFormat(e,t,r)},l.nice=function(t){return $n(e,t),o()},l.copy=function(){return Kn(e,t,r,n)},o()}function Qn(e,t){return i.rebind(e,t,"range","rangeRound","interpolate","clamp")}function $n(e,t){return Gn(e,Wn(ea(e,t)[2])),Gn(e,Wn(ea(e,t)[2])),e}function ea(e,t){null==t&&(t=10);var r=Vn(e),n=r[1]-r[0],a=Math.pow(10,Math.floor(Math.log(n/t)/Math.LN10)),i=t/n*a;return i<=.15?a*=10:i<=.35?a*=5:i<=.75&&(a*=2),r[0]=Math.ceil(r[0]/a)*a,r[1]=Math.floor(r[1]/a)*a+.5*a,r[2]=a,r}function ta(e,t){return i.range.apply(i,ea(e,t))}function ra(e,t,r,n){function a(e){return(r?Math.log(e<0?0:e):-Math.log(e>0?0:-e))/Math.log(t)}function i(e){return r?Math.pow(t,e):-Math.pow(t,-e)}function o(t){return e(a(t))}return o.invert=function(t){return i(e.invert(t))},o.domain=function(t){return arguments.length?(r=t[0]>=0,e.domain((n=t.map(Number)).map(a)),o):n},o.base=function(r){return arguments.length?(t=+r,e.domain(n.map(a)),o):t},o.nice=function(){var t=Gn(n.map(a),r?Math:na);return e.domain(t),n=t.map(i),o},o.ticks=function(){var e=Vn(n),o=[],l=e[0],s=e[1],c=Math.floor(a(l)),u=Math.ceil(a(s)),f=t%1?2:t;if(isFinite(u-c)){if(r){for(;c0;d--)o.push(i(c)*d);for(c=0;o[c]s;u--);o=o.slice(c,u)}return o},o.copy=function(){return ra(e.copy(),t,r,n)},Qn(o,e)}i.scale.linear=function(){return Kn([0,1],[0,1],kr,!1)},i.scale.log=function(){return ra(i.scale.linear().domain([0,1]),10,!0,[1,10])};var na={floor:function(e){return-Math.ceil(-e)},ceil:function(e){return-Math.floor(-e)}};function aa(e,t,r){var n=ia(t),a=ia(1/t);function i(t){return e(n(t))}return i.invert=function(t){return a(e.invert(t))},i.domain=function(t){return arguments.length?(e.domain((r=t.map(Number)).map(n)),i):r},i.ticks=function(e){return ta(r,e)},i.tickFormat=function(e,t){return d3_scale_linearTickFormat(r,e,t)},i.nice=function(e){return i.domain($n(r,e))},i.exponent=function(o){return arguments.length?(n=ia(t=o),a=ia(1/t),e.domain(r.map(n)),i):t},i.copy=function(){return aa(e.copy(),t,r)},Qn(i,e)}function ia(e){return function(t){return t<0?-Math.pow(-t,e):Math.pow(t,e)}}function oa(e,t){var r,n,a;function o(a){return n[((r.get(a)||("range"===t.t?r.set(a,e.push(a)):NaN))-1)%n.length]}function l(t,r){return i.range(e.length).map((function(e){return t+r*e}))}return o.domain=function(n){if(!arguments.length)return e;e=[],r=new M;for(var a,i=-1,l=n.length;++i0?r[n-1]:e[0],nf?0:1;if(c=Pe)return s(c,h)+(l?s(l,1-h):"")+"Z";var p,v,y,g,m,x,b,_,w,T,M,k,A=0,L=0,S=[];if((g=(+o.apply(this,arguments)||0)/2)&&(y=n===ya?Math.sqrt(l*l+c*c):+n.apply(this,arguments),h||(L*=-1),c&&(L=Ne(y/c*Math.sin(g))),l&&(A=Ne(y/l*Math.sin(g)))),c){m=c*Math.cos(u+L),x=c*Math.sin(u+L),b=c*Math.cos(f-L),_=c*Math.sin(f-L);var O=Math.abs(f-u-2*L)<=De?0:1;if(L&&wa(m,x,b,_)===h^O){var D=(u+f)/2;m=c*Math.cos(D),x=c*Math.sin(D),b=_=null}}else m=x=0;if(l){w=l*Math.cos(f-A),T=l*Math.sin(f-A),M=l*Math.cos(u+A),k=l*Math.sin(u+A);var C=Math.abs(u-f+2*A)<=De?0:1;if(A&&wa(w,T,M,k)===1-h^C){var P=(u+f)/2;w=l*Math.cos(P),T=l*Math.sin(P),M=k=null}}else w=T=0;if(d>Se&&(p=Math.min(Math.abs(c-l)/2,+r.apply(this,arguments)))>.001){v=l0?0:1}function Ta(e,t,r,n,a){var i=e[0]-t[0],o=e[1]-t[1],l=(a?n:-n)/Math.sqrt(i*i+o*o),s=l*o,c=-l*i,u=e[0]+s,f=e[1]+c,d=t[0]+s,h=t[1]+c,p=(u+d)/2,v=(f+h)/2,y=d-u,g=h-f,m=y*y+g*g,x=r-n,b=u*h-d*f,_=(g<0?-1:1)*Math.sqrt(Math.max(0,x*x*m-b*b)),w=(b*g-y*_)/m,T=(-b*y-g*_)/m,M=(b*g+y*_)/m,k=(-b*y+g*_)/m,A=w-p,L=T-v,S=M-p,O=k-v;return A*A+L*L>S*S+O*O&&(w=M,T=k),[[w-s,T-c],[w*r/x,T*r/x]]}function Ma(){return!0}function ka(e){var t=Ot,r=Dt,n=Ma,a=La,i=a.key,o=.7;function l(i){var l,s=[],c=[],u=-1,f=i.length,d=gt(t),h=gt(r);function p(){s.push("M",a(e(c),o))}for(;++u1&&a.push("H",n[0]),a.join("")},"step-before":Oa,"step-after":Da,basis:Ia,"basis-open":function(e){if(e.length<4)return La(e);for(var t,r=[],n=-1,a=e.length,i=[0],o=[0];++n<3;)t=e[n],i.push(t[0]),o.push(t[1]);for(r.push(Ra(Ea,i)+","+Ra(Ea,o)),--n;++n9&&(a=3*t/Math.sqrt(a),o[l]=a*r,o[l+1]=a*n);for(l=-1;++l<=s;)a=(e[Math.min(s,l+1)][0]-e[Math.max(0,l-1)][0])/(6*(1+o[l]*o[l])),i.push([a||0,o[l]*a||0]);return i}(e))}});function La(e){return e.length>1?e.join("L"):e+"Z"}function Sa(e){return e.join("L")+"Z"}function Oa(e){for(var t=0,r=e.length,n=e[0],a=[n[0],",",n[1]];++t1){l=t[1],i=e[s],s++,n+="C"+(a[0]+o[0])+","+(a[1]+o[1])+","+(i[0]-l[0])+","+(i[1]-l[1])+","+i[0]+","+i[1];for(var c=2;cDe)+",1 "+t}function s(e,t,r,n){return"Q 0,0 "+n}return i.radius=function(e){return arguments.length?(r=gt(e),i):r},i.source=function(t){return arguments.length?(e=gt(t),i):e},i.target=function(e){return arguments.length?(t=gt(e),i):t},i.startAngle=function(e){return arguments.length?(n=gt(e),i):n},i.endAngle=function(e){return arguments.length?(a=gt(e),i):a},i},i.svg.diagonal=function(){var e=Ya,t=Ua,r=qa;function n(n,a){var i=e.call(this,n,a),o=t.call(this,n,a),l=(i.y+o.y)/2,s=[i,{x:i.x,y:l},{x:o.x,y:l},o];return"M"+(s=s.map(r))[0]+"C"+s[1]+" "+s[2]+" "+s[3]}return n.source=function(t){return arguments.length?(e=gt(t),n):e},n.target=function(e){return arguments.length?(t=gt(e),n):t},n.projection=function(e){return arguments.length?(r=e,n):r},n},i.svg.diagonal.radial=function(){var e=i.svg.diagonal(),t=qa,r=e.projection;return e.projection=function(e){return arguments.length?r(function(e){return function(){var t=e.apply(this,arguments),r=t[0],n=t[1]-Ie;return[r*Math.cos(n),r*Math.sin(n)]}}(t=e)):t},e},i.svg.symbol=function(){var e=Ga,t=Za;function r(r,n){return(Xa.get(e.call(this,r,n))||Wa)(t.call(this,r,n))}return r.type=function(t){return arguments.length?(e=gt(t),r):e},r.size=function(e){return arguments.length?(t=gt(e),r):t},r};var Xa=i.map({circle:Wa,cross:function(e){var t=Math.sqrt(e/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(e){var t=Math.sqrt(e/(2*Ka)),r=t*Ka;return"M0,"+-t+"L"+r+",0 0,"+t+" "+-r+",0Z"},square:function(e){var t=Math.sqrt(e)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(e){var t=Math.sqrt(e/Ja),r=t*Ja/2;return"M0,"+r+"L"+t+","+-r+" "+-t+","+-r+"Z"},"triangle-up":function(e){var t=Math.sqrt(e/Ja),r=t*Ja/2;return"M0,"+-r+"L"+t+","+r+" "+-t+","+r+"Z"}});i.svg.symbolTypes=Xa.keys();var Ja=Math.sqrt(3),Ka=Math.tan(30*Re);K.transition=function(e){for(var t,r,n=ti||++ai,a=li(e),i=[],o=ri||{time:Date.now(),ease:Rr,delay:0,duration:250},l=-1,s=this.length;++l0;)c[--d].call(e,o);if(i>=1)return f.event&&f.event.end.call(e,e.__data__,t),--u.count?delete u[n]:delete e[r],1}f||(i=a.time,o=kt((function(e){var t=f.delay;if(o.t=t+i,t<=e)return d(e-t);o.c=d}),0,i),f=u[n]={tween:new M,time:i,timer:o,delay:a.delay,duration:a.duration,ease:a.ease,index:t},a=null,++u.count)}ni.call=K.call,ni.empty=K.empty,ni.node=K.node,ni.size=K.size,i.transition=function(e,t){return e&&e.transition?ti?e.transition(t):e:i.selection().transition(e)},i.transition.prototype=ni,ni.select=function(e){var t,r,n,a=this.id,i=this.namespace,o=[];e=Q(e);for(var l=-1,s=this.length;++lrect,.s>rect").attr("width",o[1]-o[0])}function v(e){e.select(".extent").attr("y",l[0]),e.selectAll(".extent,.e>rect,.w>rect").attr("height",l[1]-l[0])}function y(){var f,y,g=this,m=i.select(i.event.target),x=r.of(g,arguments),b=i.select(g),_=m.datum(),w=!/^(n|s)$/.test(_)&&n,T=!/^(e|w)$/.test(_)&&a,M=m.classed("extent"),k=Me(g),A=i.mouse(g),L=i.select(u(g)).on("keydown.brush",(function(){32==i.event.keyCode&&(M||(f=null,A[0]-=o[1],A[1]-=l[1],M=2),Y())})).on("keyup.brush",(function(){32==i.event.keyCode&&2==M&&(A[0]+=o[1],A[1]+=l[1],M=0,Y())}));if(i.event.changedTouches?L.on("touchmove.brush",D).on("touchend.brush",P):L.on("mousemove.brush",D).on("mouseup.brush",P),b.interrupt().selectAll("*").interrupt(),M)A[0]=o[0]-A[0],A[1]=l[0]-A[1];else if(_){var S=+/w$/.test(_),O=+/^n/.test(_);y=[o[1-S]-A[0],l[1-O]-A[1]],A[0]=o[S],A[1]=l[O]}else i.event.altKey&&(f=A.slice());function D(){var e=i.mouse(g),t=!1;y&&(e[0]+=y[0],e[1]+=y[1]),M||(i.event.altKey?(f||(f=[(o[0]+o[1])/2,(l[0]+l[1])/2]),A[0]=o[+(e[0]1?n[0]+n.slice(2):n,+e.slice(r+1)]}r.d(t,{WU:function(){return d},FF:function(){return v}});var a,i=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function o(e){if(!(t=i.exec(e)))throw new Error("invalid format: "+e);var t;return new l({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}function l(e){this.fill=void 0===e.fill?" ":e.fill+"",this.align=void 0===e.align?">":e.align+"",this.sign=void 0===e.sign?"-":e.sign+"",this.symbol=void 0===e.symbol?"":e.symbol+"",this.zero=!!e.zero,this.width=void 0===e.width?void 0:+e.width,this.comma=!!e.comma,this.precision=void 0===e.precision?void 0:+e.precision,this.trim=!!e.trim,this.type=void 0===e.type?"":e.type+""}function s(e,t){var r=n(e,t);if(!r)return e+"";var a=r[0],i=r[1];return i<0?"0."+new Array(-i).join("0")+a:a.length>i+1?a.slice(0,i+1)+"."+a.slice(i+1):a+new Array(i-a.length+2).join("0")}o.prototype=l.prototype,l.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var c={"%":function(e,t){return(100*e).toFixed(t)},b:function(e){return Math.round(e).toString(2)},c:function(e){return e+""},d:function(e){return Math.abs(e=Math.round(e))>=1e21?e.toLocaleString("en").replace(/,/g,""):e.toString(10)},e:function(e,t){return e.toExponential(t)},f:function(e,t){return e.toFixed(t)},g:function(e,t){return e.toPrecision(t)},o:function(e){return Math.round(e).toString(8)},p:function(e,t){return s(100*e,t)},r:s,s:function(e,t){var r=n(e,t);if(!r)return e+"";var i=r[0],o=r[1],l=o-(a=3*Math.max(-8,Math.min(8,Math.floor(o/3))))+1,s=i.length;return l===s?i:l>s?i+new Array(l-s+1).join("0"):l>0?i.slice(0,l)+"."+i.slice(l):"0."+new Array(1-l).join("0")+n(e,Math.max(0,t+l-1))[0]},X:function(e){return Math.round(e).toString(16).toUpperCase()},x:function(e){return Math.round(e).toString(16)}};function u(e){return e}var f,d,h=Array.prototype.map,p=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"];function v(e){var t,r,i=void 0===e.grouping||void 0===e.thousands?u:(t=h.call(e.grouping,Number),r=e.thousands+"",function(e,n){for(var a=e.length,i=[],o=0,l=t[0],s=0;a>0&&l>0&&(s+l+1>n&&(l=Math.max(1,n-s)),i.push(e.substring(a-=l,a+l)),!((s+=l+1)>n));)l=t[o=(o+1)%t.length];return i.reverse().join(r)}),l=void 0===e.currency?"":e.currency[0]+"",s=void 0===e.currency?"":e.currency[1]+"",f=void 0===e.decimal?".":e.decimal+"",d=void 0===e.numerals?u:function(e){return function(t){return t.replace(/[0-9]/g,(function(t){return e[+t]}))}}(h.call(e.numerals,String)),v=void 0===e.percent?"%":e.percent+"",y=void 0===e.minus?"-":e.minus+"",g=void 0===e.nan?"NaN":e.nan+"";function m(e){var t=(e=o(e)).fill,r=e.align,n=e.sign,u=e.symbol,h=e.zero,m=e.width,x=e.comma,b=e.precision,_=e.trim,w=e.type;"n"===w?(x=!0,w="g"):c[w]||(void 0===b&&(b=12),_=!0,w="g"),(h||"0"===t&&"="===r)&&(h=!0,t="0",r="=");var T="$"===u?l:"#"===u&&/[boxX]/.test(w)?"0"+w.toLowerCase():"",M="$"===u?s:/[%p]/.test(w)?v:"",k=c[w],A=/[defgprs%]/.test(w);function L(e){var o,l,s,c=T,u=M;if("c"===w)u=k(e)+u,e="";else{var v=(e=+e)<0||1/e<0;if(e=isNaN(e)?g:k(Math.abs(e),b),_&&(e=function(e){e:for(var t,r=e.length,n=1,a=-1;n0&&(a=0)}return a>0?e.slice(0,a)+e.slice(t+1):e}(e)),v&&0==+e&&"+"!==n&&(v=!1),c=(v?"("===n?n:y:"-"===n||"("===n?"":n)+c,u=("s"===w?p[8+a/3]:"")+u+(v&&"("===n?")":""),A)for(o=-1,l=e.length;++o(s=e.charCodeAt(o))||s>57){u=(46===s?f+e.slice(o+1):e.slice(o))+u,e=e.slice(0,o);break}}x&&!h&&(e=i(e,1/0));var L=c.length+e.length+u.length,S=L>1)+c+e+u+S.slice(L);break;default:e=S+c+e+u}return d(e)}return b=void 0===b?6:/[gprs]/.test(w)?Math.max(1,Math.min(21,b)):Math.max(0,Math.min(20,b)),L.toString=function(){return e+""},L}return{format:m,formatPrefix:function(e,t){var r,a=m(((e=o(e)).type="f",e)),i=3*Math.max(-8,Math.min(8,Math.floor((r=t,((r=n(Math.abs(r)))?r[1]:NaN)/3)))),l=Math.pow(10,-i),s=p[8+i/3];return function(e){return a(l*e)+s}}}}f=v({decimal:".",thousands:",",grouping:[3],currency:["$",""],minus:"-"}),d=f.format,f.formatPrefix},4096:function(e,t,r){"use strict";r.d(t,{i$:function(){return p},Dq:function(){return d},g0:function(){return v}});var n=r(8176),a=r(8480),i=r(9879),o=r(2301),l=r(4823),s=r(9791);function c(e){if(0<=e.y&&e.y<100){var t=new Date(-1,e.m,e.d,e.H,e.M,e.S,e.L);return t.setFullYear(e.y),t}return new Date(e.y,e.m,e.d,e.H,e.M,e.S,e.L)}function u(e){if(0<=e.y&&e.y<100){var t=new Date(Date.UTC(-1,e.m,e.d,e.H,e.M,e.S,e.L));return t.setUTCFullYear(e.y),t}return new Date(Date.UTC(e.y,e.m,e.d,e.H,e.M,e.S,e.L))}function f(e,t,r){return{y:e,m:t,d:r,H:0,M:0,S:0,L:0}}function d(e){var t=e.dateTime,r=e.date,l=e.time,s=e.periods,d=e.days,h=e.shortDays,p=e.months,v=e.shortMonths,g=w(s),m=T(s),x=w(d),b=T(d),_=w(h),Le=T(h),Se=w(p),Oe=T(p),De=w(v),Ce=T(v),Pe={a:function(e){return h[e.getDay()]},A:function(e){return d[e.getDay()]},b:function(e){return v[e.getMonth()]},B:function(e){return p[e.getMonth()]},c:null,d:V,e:V,f:X,H:q,I:Z,j:G,L:W,m:J,M:K,p:function(e){return s[+(e.getHours()>=12)]},q:function(e){return 1+~~(e.getMonth()/3)},Q:ke,s:Ae,S:Q,u:$,U:ee,V:te,w:re,W:ne,x:null,X:null,y:ae,Y:ie,Z:oe,"%":Me},Ie={a:function(e){return h[e.getUTCDay()]},A:function(e){return d[e.getUTCDay()]},b:function(e){return v[e.getUTCMonth()]},B:function(e){return p[e.getUTCMonth()]},c:null,d:le,e:le,f:de,H:se,I:ce,j:ue,L:fe,m:he,M:pe,p:function(e){return s[+(e.getUTCHours()>=12)]},q:function(e){return 1+~~(e.getUTCMonth()/3)},Q:ke,s:Ae,S:ve,u:ye,U:ge,V:me,w:xe,W:be,x:null,X:null,y:_e,Y:we,Z:Te,"%":Me},Re={a:function(e,t,r){var n=_.exec(t.slice(r));return n?(e.w=Le[n[0].toLowerCase()],r+n[0].length):-1},A:function(e,t,r){var n=x.exec(t.slice(r));return n?(e.w=b[n[0].toLowerCase()],r+n[0].length):-1},b:function(e,t,r){var n=De.exec(t.slice(r));return n?(e.m=Ce[n[0].toLowerCase()],r+n[0].length):-1},B:function(e,t,r){var n=Se.exec(t.slice(r));return n?(e.m=Oe[n[0].toLowerCase()],r+n[0].length):-1},c:function(e,r,n){return Ee(e,t,r,n)},d:R,e:R,f:j,H:N,I:N,j:z,L:H,m:I,M:E,p:function(e,t,r){var n=g.exec(t.slice(r));return n?(e.p=m[n[0].toLowerCase()],r+n[0].length):-1},q:P,Q:Y,s:U,S:F,u:k,U:A,V:L,w:M,W:S,x:function(e,t,n){return Ee(e,r,t,n)},X:function(e,t,r){return Ee(e,l,t,r)},y:D,Y:O,Z:C,"%":B};function ze(e,t){return function(r){var n,a,i,o=[],l=-1,s=0,c=e.length;for(r instanceof Date||(r=new Date(+r));++l53)return null;"w"in d||(d.w=1),"Z"in d?(s=(l=u(f(d.y,0,1))).getUTCDay(),l=s>4||0===s?n.l6.ceil(l):(0,n.l6)(l),l=a.Z.offset(l,7*(d.V-1)),d.y=l.getUTCFullYear(),d.m=l.getUTCMonth(),d.d=l.getUTCDate()+(d.w+6)%7):(s=(l=c(f(d.y,0,1))).getDay(),l=s>4||0===s?i.wA.ceil(l):(0,i.wA)(l),l=o.Z.offset(l,7*(d.V-1)),d.y=l.getFullYear(),d.m=l.getMonth(),d.d=l.getDate()+(d.w+6)%7)}else("W"in d||"U"in d)&&("w"in d||(d.w="u"in d?d.u%7:"W"in d?1:0),s="Z"in d?u(f(d.y,0,1)).getUTCDay():c(f(d.y,0,1)).getDay(),d.m=0,d.d="W"in d?(d.w+6)%7+7*d.W-(s+5)%7:d.w+7*d.U-(s+6)%7);return"Z"in d?(d.H+=d.Z/100|0,d.M+=d.Z%100,u(d)):c(d)}}function Ee(e,t,r,n){for(var a,i,o=0,l=t.length,s=r.length;o=s)return-1;if(37===(a=t.charCodeAt(o++))){if(a=t.charAt(o++),!(i=Re[a in y?t.charAt(o++):a])||(n=i(e,r,n))<0)return-1}else if(a!=r.charCodeAt(n++))return-1}return n}return Pe.x=ze(r,Pe),Pe.X=ze(l,Pe),Pe.c=ze(t,Pe),Ie.x=ze(r,Ie),Ie.X=ze(l,Ie),Ie.c=ze(t,Ie),{format:function(e){var t=ze(e+="",Pe);return t.toString=function(){return e},t},parse:function(e){var t=Ne(e+="",!1);return t.toString=function(){return e},t},utcFormat:function(e){var t=ze(e+="",Ie);return t.toString=function(){return e},t},utcParse:function(e){var t=Ne(e+="",!0);return t.toString=function(){return e},t}}}var h,p,v,y={"-":"",_:" ",0:"0"},g=/^\s*\d+/,m=/^%/,x=/[\\^$*+?|[\]().{}]/g;function b(e,t,r){var n=e<0?"-":"",a=(n?-e:e)+"",i=a.length;return n+(i68?1900:2e3),r+n[0].length):-1}function C(e,t,r){var n=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(t.slice(r,r+6));return n?(e.Z=n[1]?0:-(n[2]+(n[3]||"00")),r+n[0].length):-1}function P(e,t,r){var n=g.exec(t.slice(r,r+1));return n?(e.q=3*n[0]-3,r+n[0].length):-1}function I(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.m=n[0]-1,r+n[0].length):-1}function R(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.d=+n[0],r+n[0].length):-1}function z(e,t,r){var n=g.exec(t.slice(r,r+3));return n?(e.m=0,e.d=+n[0],r+n[0].length):-1}function N(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.H=+n[0],r+n[0].length):-1}function E(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.M=+n[0],r+n[0].length):-1}function F(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.S=+n[0],r+n[0].length):-1}function H(e,t,r){var n=g.exec(t.slice(r,r+3));return n?(e.L=+n[0],r+n[0].length):-1}function j(e,t,r){var n=g.exec(t.slice(r,r+6));return n?(e.L=Math.floor(n[0]/1e3),r+n[0].length):-1}function B(e,t,r){var n=m.exec(t.slice(r,r+1));return n?r+n[0].length:-1}function Y(e,t,r){var n=g.exec(t.slice(r));return n?(e.Q=+n[0],r+n[0].length):-1}function U(e,t,r){var n=g.exec(t.slice(r));return n?(e.s=+n[0],r+n[0].length):-1}function V(e,t){return b(e.getDate(),t,2)}function q(e,t){return b(e.getHours(),t,2)}function Z(e,t){return b(e.getHours()%12||12,t,2)}function G(e,t){return b(1+o.Z.count((0,l.Z)(e),e),t,3)}function W(e,t){return b(e.getMilliseconds(),t,3)}function X(e,t){return W(e,t)+"000"}function J(e,t){return b(e.getMonth()+1,t,2)}function K(e,t){return b(e.getMinutes(),t,2)}function Q(e,t){return b(e.getSeconds(),t,2)}function $(e){var t=e.getDay();return 0===t?7:t}function ee(e,t){return b(i.OM.count((0,l.Z)(e)-1,e),t,2)}function te(e,t){var r=e.getDay();return e=r>=4||0===r?(0,i.bL)(e):i.bL.ceil(e),b(i.bL.count((0,l.Z)(e),e)+(4===(0,l.Z)(e).getDay()),t,2)}function re(e){return e.getDay()}function ne(e,t){return b(i.wA.count((0,l.Z)(e)-1,e),t,2)}function ae(e,t){return b(e.getFullYear()%100,t,2)}function ie(e,t){return b(e.getFullYear()%1e4,t,4)}function oe(e){var t=e.getTimezoneOffset();return(t>0?"-":(t*=-1,"+"))+b(t/60|0,"0",2)+b(t%60,"0",2)}function le(e,t){return b(e.getUTCDate(),t,2)}function se(e,t){return b(e.getUTCHours(),t,2)}function ce(e,t){return b(e.getUTCHours()%12||12,t,2)}function ue(e,t){return b(1+a.Z.count((0,s.Z)(e),e),t,3)}function fe(e,t){return b(e.getUTCMilliseconds(),t,3)}function de(e,t){return fe(e,t)+"000"}function he(e,t){return b(e.getUTCMonth()+1,t,2)}function pe(e,t){return b(e.getUTCMinutes(),t,2)}function ve(e,t){return b(e.getUTCSeconds(),t,2)}function ye(e){var t=e.getUTCDay();return 0===t?7:t}function ge(e,t){return b(n.Ox.count((0,s.Z)(e)-1,e),t,2)}function me(e,t){var r=e.getUTCDay();return e=r>=4||0===r?(0,n.hB)(e):n.hB.ceil(e),b(n.hB.count((0,s.Z)(e),e)+(4===(0,s.Z)(e).getUTCDay()),t,2)}function xe(e){return e.getUTCDay()}function be(e,t){return b(n.l6.count((0,s.Z)(e)-1,e),t,2)}function _e(e,t){return b(e.getUTCFullYear()%100,t,2)}function we(e,t){return b(e.getUTCFullYear()%1e4,t,4)}function Te(){return"+0000"}function Me(){return"%"}function ke(e){return+e}function Ae(e){return Math.floor(+e/1e3)}h=d({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),p=h.format,h.parse,v=h.utcFormat,h.utcParse},2301:function(e,t,r){"use strict";r.d(t,{a:function(){return o}});var n=r(52),a=r(4263),i=(0,n.Z)((function(e){e.setHours(0,0,0,0)}),(function(e,t){e.setDate(e.getDate()+t)}),(function(e,t){return(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*a.yB)/a.UD}),(function(e){return e.getDate()-1}));t.Z=i;var o=i.range},4263:function(e,t,r){"use strict";r.d(t,{UD:function(){return o},Y2:function(){return i},Ym:function(){return n},iM:function(){return l},yB:function(){return a}});var n=1e3,a=6e4,i=36e5,o=864e5,l=6048e5},1041:function(e,t,r){"use strict";r.r(t),r.d(t,{timeDay:function(){return g.Z},timeDays:function(){return g.a},timeFriday:function(){return m.mC},timeFridays:function(){return m.b$},timeHour:function(){return v},timeHours:function(){return y},timeInterval:function(){return n.Z},timeMillisecond:function(){return i},timeMilliseconds:function(){return o},timeMinute:function(){return d},timeMinutes:function(){return h},timeMonday:function(){return m.wA},timeMondays:function(){return m.bJ},timeMonth:function(){return b},timeMonths:function(){return _},timeSaturday:function(){return m.EY},timeSaturdays:function(){return m.Ff},timeSecond:function(){return c},timeSeconds:function(){return u},timeSunday:function(){return m.OM},timeSundays:function(){return m.vm},timeThursday:function(){return m.bL},timeThursdays:function(){return m.$t},timeTuesday:function(){return m.sy},timeTuesdays:function(){return m.aU},timeWednesday:function(){return m.zg},timeWednesdays:function(){return m.Ld},timeWeek:function(){return m.OM},timeWeeks:function(){return m.vm},timeYear:function(){return w.Z},timeYears:function(){return w.g},utcDay:function(){return O.Z},utcDays:function(){return O.y},utcFriday:function(){return D.QQ},utcFridays:function(){return D.fz},utcHour:function(){return L},utcHours:function(){return S},utcMillisecond:function(){return i},utcMilliseconds:function(){return o},utcMinute:function(){return M},utcMinutes:function(){return k},utcMonday:function(){return D.l6},utcMondays:function(){return D.$3},utcMonth:function(){return P},utcMonths:function(){return I},utcSaturday:function(){return D.g4},utcSaturdays:function(){return D.Q_},utcSecond:function(){return c},utcSeconds:function(){return u},utcSunday:function(){return D.Ox},utcSundays:function(){return D.SU},utcThursday:function(){return D.hB},utcThursdays:function(){return D.xj},utcTuesday:function(){return D.J1},utcTuesdays:function(){return D.DK},utcWednesday:function(){return D.b3},utcWednesdays:function(){return D.uy},utcWeek:function(){return D.Ox},utcWeeks:function(){return D.SU},utcYear:function(){return R.Z},utcYears:function(){return R.D}});var n=r(52),a=(0,n.Z)((function(){}),(function(e,t){e.setTime(+e+t)}),(function(e,t){return t-e}));a.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?(0,n.Z)((function(t){t.setTime(Math.floor(t/e)*e)}),(function(t,r){t.setTime(+t+r*e)}),(function(t,r){return(r-t)/e})):a:null};var i=a,o=a.range,l=r(4263),s=(0,n.Z)((function(e){e.setTime(e-e.getMilliseconds())}),(function(e,t){e.setTime(+e+t*l.Ym)}),(function(e,t){return(t-e)/l.Ym}),(function(e){return e.getUTCSeconds()})),c=s,u=s.range,f=(0,n.Z)((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*l.Ym)}),(function(e,t){e.setTime(+e+t*l.yB)}),(function(e,t){return(t-e)/l.yB}),(function(e){return e.getMinutes()})),d=f,h=f.range,p=(0,n.Z)((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*l.Ym-e.getMinutes()*l.yB)}),(function(e,t){e.setTime(+e+t*l.Y2)}),(function(e,t){return(t-e)/l.Y2}),(function(e){return e.getHours()})),v=p,y=p.range,g=r(2301),m=r(9879),x=(0,n.Z)((function(e){e.setDate(1),e.setHours(0,0,0,0)}),(function(e,t){e.setMonth(e.getMonth()+t)}),(function(e,t){return t.getMonth()-e.getMonth()+12*(t.getFullYear()-e.getFullYear())}),(function(e){return e.getMonth()})),b=x,_=x.range,w=r(4823),T=(0,n.Z)((function(e){e.setUTCSeconds(0,0)}),(function(e,t){e.setTime(+e+t*l.yB)}),(function(e,t){return(t-e)/l.yB}),(function(e){return e.getUTCMinutes()})),M=T,k=T.range,A=(0,n.Z)((function(e){e.setUTCMinutes(0,0,0)}),(function(e,t){e.setTime(+e+t*l.Y2)}),(function(e,t){return(t-e)/l.Y2}),(function(e){return e.getUTCHours()})),L=A,S=A.range,O=r(8480),D=r(8176),C=(0,n.Z)((function(e){e.setUTCDate(1),e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCMonth(e.getUTCMonth()+t)}),(function(e,t){return t.getUTCMonth()-e.getUTCMonth()+12*(t.getUTCFullYear()-e.getUTCFullYear())}),(function(e){return e.getUTCMonth()})),P=C,I=C.range,R=r(9791)},52:function(e,t,r){"use strict";r.d(t,{Z:function(){return i}});var n=new Date,a=new Date;function i(e,t,r,o){function l(t){return e(t=0===arguments.length?new Date:new Date(+t)),t}return l.floor=function(t){return e(t=new Date(+t)),t},l.ceil=function(r){return e(r=new Date(r-1)),t(r,1),e(r),r},l.round=function(e){var t=l(e),r=l.ceil(e);return e-t0))return o;do{o.push(i=new Date(+r)),t(r,a),e(r)}while(i=t)for(;e(t),!r(t);)t.setTime(t-1)}),(function(e,n){if(e>=e)if(n<0)for(;++n<=0;)for(;t(e,-1),!r(e););else for(;--n>=0;)for(;t(e,1),!r(e););}))},r&&(l.count=function(t,i){return n.setTime(+t),a.setTime(+i),e(n),e(a),Math.floor(r(n,a))},l.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?l.filter(o?function(t){return o(t)%e==0}:function(t){return l.count(0,t)%e==0}):l:null}),l}},8480:function(e,t,r){"use strict";r.d(t,{y:function(){return o}});var n=r(52),a=r(4263),i=(0,n.Z)((function(e){e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCDate(e.getUTCDate()+t)}),(function(e,t){return(t-e)/a.UD}),(function(e){return e.getUTCDate()-1}));t.Z=i;var o=i.range},8176:function(e,t,r){"use strict";r.d(t,{$3:function(){return p},DK:function(){return v},J1:function(){return s},Ox:function(){return o},QQ:function(){return f},Q_:function(){return x},SU:function(){return h},b3:function(){return c},fz:function(){return m},g4:function(){return d},hB:function(){return u},l6:function(){return l},uy:function(){return y},xj:function(){return g}});var n=r(52),a=r(4263);function i(e){return(0,n.Z)((function(t){t.setUTCDate(t.getUTCDate()-(t.getUTCDay()+7-e)%7),t.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCDate(e.getUTCDate()+7*t)}),(function(e,t){return(t-e)/a.iM}))}var o=i(0),l=i(1),s=i(2),c=i(3),u=i(4),f=i(5),d=i(6),h=o.range,p=l.range,v=s.range,y=c.range,g=u.range,m=f.range,x=d.range},9791:function(e,t,r){"use strict";r.d(t,{D:function(){return i}});var n=r(52),a=(0,n.Z)((function(e){e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCFullYear(e.getUTCFullYear()+t)}),(function(e,t){return t.getUTCFullYear()-e.getUTCFullYear()}),(function(e){return e.getUTCFullYear()}));a.every=function(e){return isFinite(e=Math.floor(e))&&e>0?(0,n.Z)((function(t){t.setUTCFullYear(Math.floor(t.getUTCFullYear()/e)*e),t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,r){t.setUTCFullYear(t.getUTCFullYear()+r*e)})):null},t.Z=a;var i=a.range},9879:function(e,t,r){"use strict";r.d(t,{$t:function(){return g},EY:function(){return d},Ff:function(){return x},Ld:function(){return y},OM:function(){return o},aU:function(){return v},b$:function(){return m},bJ:function(){return p},bL:function(){return u},mC:function(){return f},sy:function(){return s},vm:function(){return h},wA:function(){return l},zg:function(){return c}});var n=r(52),a=r(4263);function i(e){return(0,n.Z)((function(t){t.setDate(t.getDate()-(t.getDay()+7-e)%7),t.setHours(0,0,0,0)}),(function(e,t){e.setDate(e.getDate()+7*t)}),(function(e,t){return(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*a.yB)/a.iM}))}var o=i(0),l=i(1),s=i(2),c=i(3),u=i(4),f=i(5),d=i(6),h=o.range,p=l.range,v=s.range,y=c.range,g=u.range,m=f.range,x=d.range},4823:function(e,t,r){"use strict";r.d(t,{g:function(){return i}});var n=r(52),a=(0,n.Z)((function(e){e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,t){e.setFullYear(e.getFullYear()+t)}),(function(e,t){return t.getFullYear()-e.getFullYear()}),(function(e){return e.getFullYear()}));a.every=function(e){return isFinite(e=Math.floor(e))&&e>0?(0,n.Z)((function(t){t.setFullYear(Math.floor(t.getFullYear()/e)*e),t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,r){t.setFullYear(t.getFullYear()+r*e)})):null},t.Z=a;var i=a.range},5398:function(e){"use strict";var t,r="object"==typeof Reflect?Reflect:null,n=r&&"function"==typeof r.apply?r.apply:function(e,t,r){return Function.prototype.apply.call(e,t,r)};t=r&&"function"==typeof r.ownKeys?r.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var a=Number.isNaN||function(e){return e!=e};function i(){i.init.call(this)}e.exports=i,e.exports.once=function(e,t){return new Promise((function(r,n){function a(r){e.removeListener(t,i),n(r)}function i(){"function"==typeof e.removeListener&&e.removeListener("error",a),r([].slice.call(arguments))}v(e,t,i,{once:!0}),"error"!==t&&function(e,t,r){"function"==typeof e.on&&v(e,"error",t,r)}(e,a,{once:!0})}))},i.EventEmitter=i,i.prototype._events=void 0,i.prototype._eventsCount=0,i.prototype._maxListeners=void 0;var o=10;function l(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function s(e){return void 0===e._maxListeners?i.defaultMaxListeners:e._maxListeners}function c(e,t,r,n){var a,i,o,c;if(l(r),void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,r.listener?r.listener:r),i=e._events),o=i[t]),void 0===o)o=i[t]=r,++e._eventsCount;else if("function"==typeof o?o=i[t]=n?[r,o]:[o,r]:n?o.unshift(r):o.push(r),(a=s(e))>0&&o.length>a&&!o.warned){o.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=o.length,c=u,console&&console.warn&&console.warn(c)}return e}function u(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function f(e,t,r){var n={fired:!1,wrapFn:void 0,target:e,type:t,listener:r},a=u.bind(n);return a.listener=r,n.wrapFn=a,a}function d(e,t,r){var n=e._events;if(void 0===n)return[];var a=n[t];return void 0===a?[]:"function"==typeof a?r?[a.listener||a]:[a]:r?function(e){for(var t=new Array(e.length),r=0;r0&&(o=t[0]),o instanceof Error)throw o;var l=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw l.context=o,l}var s=i[e];if(void 0===s)return!1;if("function"==typeof s)n(s,this,t);else{var c=s.length,u=p(s,c);for(r=0;r=0;i--)if(r[i]===t||r[i].listener===t){o=r[i].listener,a=i;break}if(a<0)return this;0===a?r.shift():function(e,t){for(;t+1=0;n--)this.removeListener(e,t[n]);return this},i.prototype.listeners=function(e){return d(this,e,!0)},i.prototype.rawListeners=function(e){return d(this,e,!1)},i.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):h.call(e,t)},i.prototype.listenerCount=h,i.prototype.eventNames=function(){return this._eventsCount>0?t(this._events):[]}},2770:function(e,t,r){"use strict";var n=r(8546);e.exports=function(e){var t=typeof e;if("string"===t){var r=e;if(0==(e=+e)&&n(r))return!1}else if("number"!==t)return!1;return e-e<1}},5400:function(e){e.exports=function(e,t){var r=t[0],n=t[1],a=t[2],i=t[3],o=t[4],l=t[5],s=t[6],c=t[7],u=t[8],f=t[9],d=t[10],h=t[11],p=t[12],v=t[13],y=t[14],g=t[15];return e[0]=l*(d*g-h*y)-f*(s*g-c*y)+v*(s*h-c*d),e[1]=-(n*(d*g-h*y)-f*(a*g-i*y)+v*(a*h-i*d)),e[2]=n*(s*g-c*y)-l*(a*g-i*y)+v*(a*c-i*s),e[3]=-(n*(s*h-c*d)-l*(a*h-i*d)+f*(a*c-i*s)),e[4]=-(o*(d*g-h*y)-u*(s*g-c*y)+p*(s*h-c*d)),e[5]=r*(d*g-h*y)-u*(a*g-i*y)+p*(a*h-i*d),e[6]=-(r*(s*g-c*y)-o*(a*g-i*y)+p*(a*c-i*s)),e[7]=r*(s*h-c*d)-o*(a*h-i*d)+u*(a*c-i*s),e[8]=o*(f*g-h*v)-u*(l*g-c*v)+p*(l*h-c*f),e[9]=-(r*(f*g-h*v)-u*(n*g-i*v)+p*(n*h-i*f)),e[10]=r*(l*g-c*v)-o*(n*g-i*v)+p*(n*c-i*l),e[11]=-(r*(l*h-c*f)-o*(n*h-i*f)+u*(n*c-i*l)),e[12]=-(o*(f*y-d*v)-u*(l*y-s*v)+p*(l*d-s*f)),e[13]=r*(f*y-d*v)-u*(n*y-a*v)+p*(n*d-a*f),e[14]=-(r*(l*y-s*v)-o*(n*y-a*v)+p*(n*s-a*l)),e[15]=r*(l*d-s*f)-o*(n*d-a*f)+u*(n*s-a*l),e}},2331:function(e){e.exports=function(e){var t=new Float32Array(16);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t}},1042:function(e){e.exports=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e}},1902:function(e){e.exports=function(){var e=new Float32Array(16);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},9887:function(e){e.exports=function(e){var t=e[0],r=e[1],n=e[2],a=e[3],i=e[4],o=e[5],l=e[6],s=e[7],c=e[8],u=e[9],f=e[10],d=e[11],h=e[12],p=e[13],v=e[14],y=e[15];return(t*o-r*i)*(f*y-d*v)-(t*l-n*i)*(u*y-d*p)+(t*s-a*i)*(u*v-f*p)+(r*l-n*o)*(c*y-d*h)-(r*s-a*o)*(c*v-f*h)+(n*s-a*l)*(c*p-u*h)}},7812:function(e){e.exports=function(e,t){var r=t[0],n=t[1],a=t[2],i=t[3],o=r+r,l=n+n,s=a+a,c=r*o,u=n*o,f=n*l,d=a*o,h=a*l,p=a*s,v=i*o,y=i*l,g=i*s;return e[0]=1-f-p,e[1]=u+g,e[2]=d-y,e[3]=0,e[4]=u-g,e[5]=1-c-p,e[6]=h+v,e[7]=0,e[8]=d+y,e[9]=h-v,e[10]=1-c-f,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},4045:function(e){e.exports=function(e,t,r){var n,a,i,o=r[0],l=r[1],s=r[2],c=Math.sqrt(o*o+l*l+s*s);return Math.abs(c)<1e-6?null:(o*=c=1/c,l*=c,s*=c,n=Math.sin(t),a=Math.cos(t),i=1-a,e[0]=o*o*i+a,e[1]=l*o*i+s*n,e[2]=s*o*i-l*n,e[3]=0,e[4]=o*l*i-s*n,e[5]=l*l*i+a,e[6]=s*l*i+o*n,e[7]=0,e[8]=o*s*i+l*n,e[9]=l*s*i-o*n,e[10]=s*s*i+a,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e)}},5973:function(e){e.exports=function(e,t,r){var n=t[0],a=t[1],i=t[2],o=t[3],l=n+n,s=a+a,c=i+i,u=n*l,f=n*s,d=n*c,h=a*s,p=a*c,v=i*c,y=o*l,g=o*s,m=o*c;return e[0]=1-(h+v),e[1]=f+m,e[2]=d-g,e[3]=0,e[4]=f-m,e[5]=1-(u+v),e[6]=p+y,e[7]=0,e[8]=d+g,e[9]=p-y,e[10]=1-(u+h),e[11]=0,e[12]=r[0],e[13]=r[1],e[14]=r[2],e[15]=1,e}},1472:function(e){e.exports=function(e,t){return e[0]=t[0],e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=t[1],e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=t[2],e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},4669:function(e){e.exports=function(e,t){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=t[0],e[13]=t[1],e[14]=t[2],e[15]=1,e}},5262:function(e){e.exports=function(e,t){var r=Math.sin(t),n=Math.cos(t);return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=n,e[6]=r,e[7]=0,e[8]=0,e[9]=-r,e[10]=n,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},331:function(e){e.exports=function(e,t){var r=Math.sin(t),n=Math.cos(t);return e[0]=n,e[1]=0,e[2]=-r,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=r,e[9]=0,e[10]=n,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},1049:function(e){e.exports=function(e,t){var r=Math.sin(t),n=Math.cos(t);return e[0]=n,e[1]=r,e[2]=0,e[3]=0,e[4]=-r,e[5]=n,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},5195:function(e){e.exports=function(e,t,r,n,a,i,o){var l=1/(r-t),s=1/(a-n),c=1/(i-o);return e[0]=2*i*l,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=2*i*s,e[6]=0,e[7]=0,e[8]=(r+t)*l,e[9]=(a+n)*s,e[10]=(o+i)*c,e[11]=-1,e[12]=0,e[13]=0,e[14]=o*i*2*c,e[15]=0,e}},1551:function(e){e.exports=function(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}},9576:function(e,t,r){e.exports={create:r(1902),clone:r(2331),copy:r(1042),identity:r(1551),transpose:r(8654),invert:r(5874),adjoint:r(5400),determinant:r(9887),multiply:r(1362),translate:r(1283),scale:r(789),rotate:r(5074),rotateX:r(5545),rotateY:r(4918),rotateZ:r(5692),fromRotation:r(4045),fromRotationTranslation:r(5973),fromScaling:r(1472),fromTranslation:r(4669),fromXRotation:r(5262),fromYRotation:r(331),fromZRotation:r(1049),fromQuat:r(7812),frustum:r(5195),perspective:r(7864),perspectiveFromFieldOfView:r(5279),ortho:r(378),lookAt:r(5551),str:r(6726)}},5874:function(e){e.exports=function(e,t){var r=t[0],n=t[1],a=t[2],i=t[3],o=t[4],l=t[5],s=t[6],c=t[7],u=t[8],f=t[9],d=t[10],h=t[11],p=t[12],v=t[13],y=t[14],g=t[15],m=r*l-n*o,x=r*s-a*o,b=r*c-i*o,_=n*s-a*l,w=n*c-i*l,T=a*c-i*s,M=u*v-f*p,k=u*y-d*p,A=u*g-h*p,L=f*y-d*v,S=f*g-h*v,O=d*g-h*y,D=m*O-x*S+b*L+_*A-w*k+T*M;return D?(D=1/D,e[0]=(l*O-s*S+c*L)*D,e[1]=(a*S-n*O-i*L)*D,e[2]=(v*T-y*w+g*_)*D,e[3]=(d*w-f*T-h*_)*D,e[4]=(s*A-o*O-c*k)*D,e[5]=(r*O-a*A+i*k)*D,e[6]=(y*b-p*T-g*x)*D,e[7]=(u*T-d*b+h*x)*D,e[8]=(o*S-l*A+c*M)*D,e[9]=(n*A-r*S-i*M)*D,e[10]=(p*w-v*b+g*m)*D,e[11]=(f*b-u*w-h*m)*D,e[12]=(l*k-o*L-s*M)*D,e[13]=(r*L-n*k+a*M)*D,e[14]=(v*x-p*_-y*m)*D,e[15]=(u*_-f*x+d*m)*D,e):null}},5551:function(e,t,r){var n=r(1551);e.exports=function(e,t,r,a){var i,o,l,s,c,u,f,d,h,p,v=t[0],y=t[1],g=t[2],m=a[0],x=a[1],b=a[2],_=r[0],w=r[1],T=r[2];return Math.abs(v-_)<1e-6&&Math.abs(y-w)<1e-6&&Math.abs(g-T)<1e-6?n(e):(f=v-_,d=y-w,h=g-T,p=1/Math.sqrt(f*f+d*d+h*h),i=x*(h*=p)-b*(d*=p),o=b*(f*=p)-m*h,l=m*d-x*f,(p=Math.sqrt(i*i+o*o+l*l))?(i*=p=1/p,o*=p,l*=p):(i=0,o=0,l=0),s=d*l-h*o,c=h*i-f*l,u=f*o-d*i,(p=Math.sqrt(s*s+c*c+u*u))?(s*=p=1/p,c*=p,u*=p):(s=0,c=0,u=0),e[0]=i,e[1]=s,e[2]=f,e[3]=0,e[4]=o,e[5]=c,e[6]=d,e[7]=0,e[8]=l,e[9]=u,e[10]=h,e[11]=0,e[12]=-(i*v+o*y+l*g),e[13]=-(s*v+c*y+u*g),e[14]=-(f*v+d*y+h*g),e[15]=1,e)}},1362:function(e){e.exports=function(e,t,r){var n=t[0],a=t[1],i=t[2],o=t[3],l=t[4],s=t[5],c=t[6],u=t[7],f=t[8],d=t[9],h=t[10],p=t[11],v=t[12],y=t[13],g=t[14],m=t[15],x=r[0],b=r[1],_=r[2],w=r[3];return e[0]=x*n+b*l+_*f+w*v,e[1]=x*a+b*s+_*d+w*y,e[2]=x*i+b*c+_*h+w*g,e[3]=x*o+b*u+_*p+w*m,x=r[4],b=r[5],_=r[6],w=r[7],e[4]=x*n+b*l+_*f+w*v,e[5]=x*a+b*s+_*d+w*y,e[6]=x*i+b*c+_*h+w*g,e[7]=x*o+b*u+_*p+w*m,x=r[8],b=r[9],_=r[10],w=r[11],e[8]=x*n+b*l+_*f+w*v,e[9]=x*a+b*s+_*d+w*y,e[10]=x*i+b*c+_*h+w*g,e[11]=x*o+b*u+_*p+w*m,x=r[12],b=r[13],_=r[14],w=r[15],e[12]=x*n+b*l+_*f+w*v,e[13]=x*a+b*s+_*d+w*y,e[14]=x*i+b*c+_*h+w*g,e[15]=x*o+b*u+_*p+w*m,e}},378:function(e){e.exports=function(e,t,r,n,a,i,o){var l=1/(t-r),s=1/(n-a),c=1/(i-o);return e[0]=-2*l,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=-2*s,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=2*c,e[11]=0,e[12]=(t+r)*l,e[13]=(a+n)*s,e[14]=(o+i)*c,e[15]=1,e}},7864:function(e){e.exports=function(e,t,r,n,a){var i=1/Math.tan(t/2),o=1/(n-a);return e[0]=i/r,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=(a+n)*o,e[11]=-1,e[12]=0,e[13]=0,e[14]=2*a*n*o,e[15]=0,e}},5279:function(e){e.exports=function(e,t,r,n){var a=Math.tan(t.upDegrees*Math.PI/180),i=Math.tan(t.downDegrees*Math.PI/180),o=Math.tan(t.leftDegrees*Math.PI/180),l=Math.tan(t.rightDegrees*Math.PI/180),s=2/(o+l),c=2/(a+i);return e[0]=s,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=c,e[6]=0,e[7]=0,e[8]=-(o-l)*s*.5,e[9]=(a-i)*c*.5,e[10]=n/(r-n),e[11]=-1,e[12]=0,e[13]=0,e[14]=n*r/(r-n),e[15]=0,e}},5074:function(e){e.exports=function(e,t,r,n){var a,i,o,l,s,c,u,f,d,h,p,v,y,g,m,x,b,_,w,T,M,k,A,L,S=n[0],O=n[1],D=n[2],C=Math.sqrt(S*S+O*O+D*D);return Math.abs(C)<1e-6?null:(S*=C=1/C,O*=C,D*=C,a=Math.sin(r),i=Math.cos(r),o=1-i,l=t[0],s=t[1],c=t[2],u=t[3],f=t[4],d=t[5],h=t[6],p=t[7],v=t[8],y=t[9],g=t[10],m=t[11],x=S*S*o+i,b=O*S*o+D*a,_=D*S*o-O*a,w=S*O*o-D*a,T=O*O*o+i,M=D*O*o+S*a,k=S*D*o+O*a,A=O*D*o-S*a,L=D*D*o+i,e[0]=l*x+f*b+v*_,e[1]=s*x+d*b+y*_,e[2]=c*x+h*b+g*_,e[3]=u*x+p*b+m*_,e[4]=l*w+f*T+v*M,e[5]=s*w+d*T+y*M,e[6]=c*w+h*T+g*M,e[7]=u*w+p*T+m*M,e[8]=l*k+f*A+v*L,e[9]=s*k+d*A+y*L,e[10]=c*k+h*A+g*L,e[11]=u*k+p*A+m*L,t!==e&&(e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e)}},5545:function(e){e.exports=function(e,t,r){var n=Math.sin(r),a=Math.cos(r),i=t[4],o=t[5],l=t[6],s=t[7],c=t[8],u=t[9],f=t[10],d=t[11];return t!==e&&(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[4]=i*a+c*n,e[5]=o*a+u*n,e[6]=l*a+f*n,e[7]=s*a+d*n,e[8]=c*a-i*n,e[9]=u*a-o*n,e[10]=f*a-l*n,e[11]=d*a-s*n,e}},4918:function(e){e.exports=function(e,t,r){var n=Math.sin(r),a=Math.cos(r),i=t[0],o=t[1],l=t[2],s=t[3],c=t[8],u=t[9],f=t[10],d=t[11];return t!==e&&(e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=i*a-c*n,e[1]=o*a-u*n,e[2]=l*a-f*n,e[3]=s*a-d*n,e[8]=i*n+c*a,e[9]=o*n+u*a,e[10]=l*n+f*a,e[11]=s*n+d*a,e}},5692:function(e){e.exports=function(e,t,r){var n=Math.sin(r),a=Math.cos(r),i=t[0],o=t[1],l=t[2],s=t[3],c=t[4],u=t[5],f=t[6],d=t[7];return t!==e&&(e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15]),e[0]=i*a+c*n,e[1]=o*a+u*n,e[2]=l*a+f*n,e[3]=s*a+d*n,e[4]=c*a-i*n,e[5]=u*a-o*n,e[6]=f*a-l*n,e[7]=d*a-s*n,e}},789:function(e){e.exports=function(e,t,r){var n=r[0],a=r[1],i=r[2];return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e[3]=t[3]*n,e[4]=t[4]*a,e[5]=t[5]*a,e[6]=t[6]*a,e[7]=t[7]*a,e[8]=t[8]*i,e[9]=t[9]*i,e[10]=t[10]*i,e[11]=t[11]*i,e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e}},6726:function(e){e.exports=function(e){return"mat4("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+", "+e[4]+", "+e[5]+", "+e[6]+", "+e[7]+", "+e[8]+", "+e[9]+", "+e[10]+", "+e[11]+", "+e[12]+", "+e[13]+", "+e[14]+", "+e[15]+")"}},1283:function(e){e.exports=function(e,t,r){var n,a,i,o,l,s,c,u,f,d,h,p,v=r[0],y=r[1],g=r[2];return t===e?(e[12]=t[0]*v+t[4]*y+t[8]*g+t[12],e[13]=t[1]*v+t[5]*y+t[9]*g+t[13],e[14]=t[2]*v+t[6]*y+t[10]*g+t[14],e[15]=t[3]*v+t[7]*y+t[11]*g+t[15]):(n=t[0],a=t[1],i=t[2],o=t[3],l=t[4],s=t[5],c=t[6],u=t[7],f=t[8],d=t[9],h=t[10],p=t[11],e[0]=n,e[1]=a,e[2]=i,e[3]=o,e[4]=l,e[5]=s,e[6]=c,e[7]=u,e[8]=f,e[9]=d,e[10]=h,e[11]=p,e[12]=n*v+l*y+f*g+t[12],e[13]=a*v+s*y+d*g+t[13],e[14]=i*v+c*y+h*g+t[14],e[15]=o*v+u*y+p*g+t[15]),e}},8654:function(e){e.exports=function(e,t){if(e===t){var r=t[1],n=t[2],a=t[3],i=t[6],o=t[7],l=t[11];e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=r,e[6]=t[9],e[7]=t[13],e[8]=n,e[9]=i,e[11]=t[14],e[12]=a,e[13]=o,e[14]=l}else e[0]=t[0],e[1]=t[4],e[2]=t[8],e[3]=t[12],e[4]=t[1],e[5]=t[5],e[6]=t[9],e[7]=t[13],e[8]=t[2],e[9]=t[6],e[10]=t[10],e[11]=t[14],e[12]=t[3],e[13]=t[7],e[14]=t[11],e[15]=t[15];return e}},7035:function(e,t,r){"use strict";var n,a=r(4404);n="function"==typeof r.g.matchMedia?!r.g.matchMedia("(hover: none)").matches:a,e.exports=n},8520:function(e,t,r){"use strict";var n=r(4404);e.exports=n&&function(){var e=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e=!0}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(r){e=!1}return e}()},4404:function(e){e.exports=!0},8546:function(e){"use strict";e.exports=function(e){for(var t,r=e.length,n=0;n13)&&32!==t&&133!==t&&160!==t&&5760!==t&&6158!==t&&(t<8192||t>8205)&&8232!==t&&8233!==t&&8239!==t&&8287!==t&&8288!==t&&12288!==t&&65279!==t)return!1;return!0}},8956:function(e){var t={left:0,top:0};e.exports=function(e,r,n){r=r||e.currentTarget||e.srcElement,Array.isArray(n)||(n=[0,0]);var a,i=e.clientX||0,o=e.clientY||0,l=(a=r)===window||a===document||a===document.body?t:a.getBoundingClientRect();return n[0]=i-l.left,n[1]=o-l.top,n}},7417:function(e,t,r){var n,a,i,o;a="Promise",i=void 0!==r.g?r.g:this,o=function(){"use strict";var e,t,r,n=Object.prototype.toString,a="undefined"!=typeof setImmediate?function(e){return setImmediate(e)}:setTimeout;try{Object.defineProperty({},"x",{}),e=function(e,t,r,n){return Object.defineProperty(e,t,{value:r,writable:!0,configurable:!1!==n})}}catch(y){e=function(e,t,r){return e[t]=r,e}}function i(e,n){r.add(e,n),t||(t=a(r.drain))}function o(e){var t,r=typeof e;return null==e||"object"!=r&&"function"!=r||(t=e.then),"function"==typeof t&&t}function l(){for(var e=0;e0&&i(l,r))}catch(y){u.call(new d(r),y)}}}function u(e){var t=this;t.triggered||(t.triggered=!0,t.def&&(t=t.def),t.msg=e,t.state=2,t.chain.length>0&&i(l,t))}function f(e,t,r,n){for(var a=0;a2&&(a.push([r].concat(i.splice(0,2))),o="l",r="m"==r?"l":"L");;){if(i.length==t[o])return i.unshift(r),a.push(i);if(i.lengthi!=h>i&&a<(d-u)*(i-f)/(h-f)+u&&(o=!o)}return o}},2142:function(e,t,r){var n,a=r(9444),i=r(9023),o=r(7263),l=r(1328),s=r(5968),c=r(670),u=!1,f=i();function d(e,t,r){var a=n.segments(e),i=n.segments(t),o=r(n.combine(a,i));return n.polygon(o)}n={buildLog:function(e){return!0===e?u=a():!1===e&&(u=!1),!1!==u&&u.list},epsilon:function(e){return f.epsilon(e)},segments:function(e){var t=o(!0,f,u);return e.regions.forEach(t.addRegion),{segments:t.calculate(e.inverted),inverted:e.inverted}},combine:function(e,t){return{combined:o(!1,f,u).calculate(e.segments,e.inverted,t.segments,t.inverted),inverted1:e.inverted,inverted2:t.inverted}},selectUnion:function(e){return{segments:s.union(e.combined,u),inverted:e.inverted1||e.inverted2}},selectIntersect:function(e){return{segments:s.intersect(e.combined,u),inverted:e.inverted1&&e.inverted2}},selectDifference:function(e){return{segments:s.difference(e.combined,u),inverted:e.inverted1&&!e.inverted2}},selectDifferenceRev:function(e){return{segments:s.differenceRev(e.combined,u),inverted:!e.inverted1&&e.inverted2}},selectXor:function(e){return{segments:s.xor(e.combined,u),inverted:e.inverted1!==e.inverted2}},polygon:function(e){return{regions:l(e.segments,f,u),inverted:e.inverted}},polygonFromGeoJSON:function(e){return c.toPolygon(n,e)},polygonToGeoJSON:function(e){return c.fromPolygon(n,f,e)},union:function(e,t){return d(e,t,n.selectUnion)},intersect:function(e,t){return d(e,t,n.selectIntersect)},difference:function(e,t){return d(e,t,n.selectDifference)},differenceRev:function(e,t){return d(e,t,n.selectDifferenceRev)},xor:function(e,t){return d(e,t,n.selectXor)}},"object"==typeof window&&(window.PolyBool=n),e.exports=n},9444:function(e){e.exports=function(){var e,t=0,r=!1;function n(t,r){return e.list.push({type:t,data:r?JSON.parse(JSON.stringify(r)):void 0}),e}return e={list:[],segmentId:function(){return t++},checkIntersection:function(e,t){return n("check",{seg1:e,seg2:t})},segmentChop:function(e,t){return n("div_seg",{seg:e,pt:t}),n("chop",{seg:e,pt:t})},statusRemove:function(e){return n("pop_seg",{seg:e})},segmentUpdate:function(e){return n("seg_update",{seg:e})},segmentNew:function(e,t){return n("new_seg",{seg:e,primary:t})},segmentRemove:function(e){return n("rem_seg",{seg:e})},tempStatus:function(e,t,r){return n("temp_status",{seg:e,above:t,below:r})},rewind:function(e){return n("rewind",{seg:e})},status:function(e,t,r){return n("status",{seg:e,above:t,below:r})},vert:function(t){return t===r?e:(r=t,n("vert",{x:t}))},log:function(e){return"string"!=typeof e&&(e=JSON.stringify(e,!1," ")),n("log",{txt:e})},reset:function(){return n("reset")},selected:function(e){return n("selected",{segs:e})},chainStart:function(e){return n("chain_start",{seg:e})},chainRemoveHead:function(e,t){return n("chain_rem_head",{index:e,pt:t})},chainRemoveTail:function(e,t){return n("chain_rem_tail",{index:e,pt:t})},chainNew:function(e,t){return n("chain_new",{pt1:e,pt2:t})},chainMatch:function(e){return n("chain_match",{index:e})},chainClose:function(e){return n("chain_close",{index:e})},chainAddHead:function(e,t){return n("chain_add_head",{index:e,pt:t})},chainAddTail:function(e,t){return n("chain_add_tail",{index:e,pt:t})},chainConnect:function(e,t){return n("chain_con",{index1:e,index2:t})},chainReverse:function(e){return n("chain_rev",{index:e})},chainJoin:function(e,t){return n("chain_join",{index1:e,index2:t})},done:function(){return n("done")}}}},9023:function(e){e.exports=function(e){"number"!=typeof e&&(e=1e-10);var t={epsilon:function(t){return"number"==typeof t&&(e=t),e},pointAboveOrOnLine:function(t,r,n){var a=r[0],i=r[1],o=n[0],l=n[1],s=t[0];return(o-a)*(t[1]-i)-(l-i)*(s-a)>=-e},pointBetween:function(t,r,n){var a=t[1]-r[1],i=n[0]-r[0],o=t[0]-r[0],l=n[1]-r[1],s=o*i+a*l;return!(s-e)},pointsSameX:function(t,r){return Math.abs(t[0]-r[0])e!=o-a>e&&(i-c)*(a-u)/(o-u)+c-n>e&&(l=!l),i=c,o=u}return l}};return t}},670:function(e){var t={toPolygon:function(e,t){function r(t){if(t.length<=0)return e.segments({inverted:!1,regions:[]});function r(t){var r=t.slice(0,t.length-1);return e.segments({inverted:!1,regions:[r]})}for(var n=r(t[0]),a=1;a0}))}function u(e,n){var a=e.seg,i=n.seg,o=a.start,l=a.end,c=i.start,u=i.end;r&&r.checkIntersection(a,i);var f=t.linesIntersect(o,l,c,u);if(!1===f){if(!t.pointsCollinear(o,l,c))return!1;if(t.pointsSame(o,u)||t.pointsSame(l,c))return!1;var d=t.pointsSame(o,c),h=t.pointsSame(l,u);if(d&&h)return n;var p=!d&&t.pointBetween(o,c,u),v=!h&&t.pointBetween(l,c,u);if(d)return v?s(n,l):s(e,u),n;p&&(h||(v?s(n,l):s(e,u)),s(n,o))}else 0===f.alongA&&(-1===f.alongB?s(e,c):0===f.alongB?s(e,f.pt):1===f.alongB&&s(e,u)),0===f.alongB&&(-1===f.alongA?s(n,o):0===f.alongA?s(n,f.pt):1===f.alongA&&s(n,l));return!1}for(var f=[];!i.isEmpty();){var d=i.getHead();if(r&&r.vert(d.pt[0]),d.isStart){r&&r.segmentNew(d.seg,d.primary);var h=c(d),p=h.before?h.before.ev:null,v=h.after?h.after.ev:null;function y(){if(p){var e=u(d,p);if(e)return e}return!!v&&u(d,v)}r&&r.tempStatus(d.seg,!!p&&p.seg,!!v&&v.seg);var g,m,x=y();if(x)e?(m=null===d.seg.myFill.below||d.seg.myFill.above!==d.seg.myFill.below)&&(x.seg.myFill.above=!x.seg.myFill.above):x.seg.otherFill=d.seg.myFill,r&&r.segmentUpdate(x.seg),d.other.remove(),d.remove();if(i.getHead()!==d){r&&r.rewind(d.seg);continue}e?(m=null===d.seg.myFill.below||d.seg.myFill.above!==d.seg.myFill.below,d.seg.myFill.below=v?v.seg.myFill.above:a,d.seg.myFill.above=m?!d.seg.myFill.below:d.seg.myFill.below):null===d.seg.otherFill&&(g=v?d.primary===v.primary?v.seg.otherFill.above:v.seg.myFill.above:d.primary?o:a,d.seg.otherFill={above:g,below:g}),r&&r.status(d.seg,!!p&&p.seg,!!v&&v.seg),d.other.status=h.insert(n.node({ev:d}))}else{var b=d.status;if(null===b)throw new Error("PolyBool: Zero-length segment detected; your epsilon is probably too small or too large");if(l.exists(b.prev)&&l.exists(b.next)&&u(b.prev.ev,b.next.ev),r&&r.statusRemove(b.ev.seg),b.remove(),!d.primary){var _=d.seg.myFill;d.seg.myFill=d.seg.otherFill,d.seg.otherFill=_}f.push(d.seg)}i.getHead().remove()}return r&&r.done(),f}return e?{addRegion:function(e){for(var n,a,i,o=e[e.length-1],s=0;s1&&(r-=1),r<1/6?e+6*(t-e)*r:r<.5?t:r<2/3?e+(t-e)*(2/3-r)*6:e}if(e=I(e,360),t=I(t,100),r=I(r,100),0===t)n=a=i=r;else{var l=r<.5?r*(1+t):r+t-r*t,s=2*r-l;n=o(s,l,e+1/3),a=o(s,l,e),i=o(s,l,e-1/3)}return{r:255*n,g:255*a,b:255*i}}(e.h,f,h),p=!0,v="hsl"),e.hasOwnProperty("a")&&(s=e.a)),s=P(s),{ok:p,format:e.format||v,r:c(255,u(l.r,0)),g:c(255,u(l.g,0)),b:c(255,u(l.b,0)),a:s}}(e);this._originalInput=e,this._r=r.r,this._g=r.g,this._b=r.b,this._a=r.a,this._roundA=s(100*this._a)/100,this._format=t.format||r.format,this._gradientType=t.gradientType,this._r<1&&(this._r=s(this._r)),this._g<1&&(this._g=s(this._g)),this._b<1&&(this._b=s(this._b)),this._ok=r.ok,this._tc_id=l++}function h(e,t,r){e=I(e,255),t=I(t,255),r=I(r,255);var n,a,i=u(e,t,r),o=c(e,t,r),l=(i+o)/2;if(i==o)n=a=0;else{var s=i-o;switch(a=l>.5?s/(2-i-o):s/(i+o),i){case e:n=(t-r)/s+(t>1)+720)%360;--t;)n.h=(n.h+a)%360,i.push(d(n));return i}function O(e,t){t=t||6;for(var r=d(e).toHsv(),n=r.h,a=r.s,i=r.v,o=[],l=1/t;t--;)o.push(d({h:n,s:a,v:i})),i=(i+l)%1;return o}d.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,t,r,n=this.toRgb();return e=n.r/255,t=n.g/255,r=n.b/255,.2126*(e<=.03928?e/12.92:a.pow((e+.055)/1.055,2.4))+.7152*(t<=.03928?t/12.92:a.pow((t+.055)/1.055,2.4))+.0722*(r<=.03928?r/12.92:a.pow((r+.055)/1.055,2.4))},setAlpha:function(e){return this._a=P(e),this._roundA=s(100*this._a)/100,this},toHsv:function(){var e=p(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=p(this._r,this._g,this._b),t=s(360*e.h),r=s(100*e.s),n=s(100*e.v);return 1==this._a?"hsv("+t+", "+r+"%, "+n+"%)":"hsva("+t+", "+r+"%, "+n+"%, "+this._roundA+")"},toHsl:function(){var e=h(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=h(this._r,this._g,this._b),t=s(360*e.h),r=s(100*e.s),n=s(100*e.l);return 1==this._a?"hsl("+t+", "+r+"%, "+n+"%)":"hsla("+t+", "+r+"%, "+n+"%, "+this._roundA+")"},toHex:function(e){return v(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){return function(e,t,r,n,a){var i=[N(s(e).toString(16)),N(s(t).toString(16)),N(s(r).toString(16)),N(F(n))];return a&&i[0].charAt(0)==i[0].charAt(1)&&i[1].charAt(0)==i[1].charAt(1)&&i[2].charAt(0)==i[2].charAt(1)&&i[3].charAt(0)==i[3].charAt(1)?i[0].charAt(0)+i[1].charAt(0)+i[2].charAt(0)+i[3].charAt(0):i.join("")}(this._r,this._g,this._b,this._a,e)},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:s(this._r),g:s(this._g),b:s(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+s(this._r)+", "+s(this._g)+", "+s(this._b)+")":"rgba("+s(this._r)+", "+s(this._g)+", "+s(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:s(100*I(this._r,255))+"%",g:s(100*I(this._g,255))+"%",b:s(100*I(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+s(100*I(this._r,255))+"%, "+s(100*I(this._g,255))+"%, "+s(100*I(this._b,255))+"%)":"rgba("+s(100*I(this._r,255))+"%, "+s(100*I(this._g,255))+"%, "+s(100*I(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(C[v(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+y(this._r,this._g,this._b,this._a),r=t,n=this._gradientType?"GradientType = 1, ":"";if(e){var a=d(e);r="#"+y(a._r,a._g,a._b,a._a)}return"progid:DXImageTransform.Microsoft.gradient("+n+"startColorstr="+t+",endColorstr="+r+")"},toString:function(e){var t=!!e;e=e||this._format;var r=!1,n=this._a<1&&this._a>=0;return t||!n||"hex"!==e&&"hex6"!==e&&"hex3"!==e&&"hex4"!==e&&"hex8"!==e&&"name"!==e?("rgb"===e&&(r=this.toRgbString()),"prgb"===e&&(r=this.toPercentageRgbString()),"hex"!==e&&"hex6"!==e||(r=this.toHexString()),"hex3"===e&&(r=this.toHexString(!0)),"hex4"===e&&(r=this.toHex8String(!0)),"hex8"===e&&(r=this.toHex8String()),"name"===e&&(r=this.toName()),"hsl"===e&&(r=this.toHslString()),"hsv"===e&&(r=this.toHsvString()),r||this.toHexString()):"name"===e&&0===this._a?this.toName():this.toRgbString()},clone:function(){return d(this.toString())},_applyModification:function(e,t){var r=e.apply(null,[this].concat([].slice.call(t)));return this._r=r._r,this._g=r._g,this._b=r._b,this.setAlpha(r._a),this},lighten:function(){return this._applyModification(b,arguments)},brighten:function(){return this._applyModification(_,arguments)},darken:function(){return this._applyModification(w,arguments)},desaturate:function(){return this._applyModification(g,arguments)},saturate:function(){return this._applyModification(m,arguments)},greyscale:function(){return this._applyModification(x,arguments)},spin:function(){return this._applyModification(T,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(S,arguments)},complement:function(){return this._applyCombination(M,arguments)},monochromatic:function(){return this._applyCombination(O,arguments)},splitcomplement:function(){return this._applyCombination(L,arguments)},triad:function(){return this._applyCombination(k,arguments)},tetrad:function(){return this._applyCombination(A,arguments)}},d.fromRatio=function(e,t){if("object"==typeof e){var r={};for(var n in e)e.hasOwnProperty(n)&&(r[n]="a"===n?e[n]:E(e[n]));e=r}return d(e,t)},d.equals=function(e,t){return!(!e||!t)&&d(e).toRgbString()==d(t).toRgbString()},d.random=function(){return d.fromRatio({r:f(),g:f(),b:f()})},d.mix=function(e,t,r){r=0===r?0:r||50;var n=d(e).toRgb(),a=d(t).toRgb(),i=r/100;return d({r:(a.r-n.r)*i+n.r,g:(a.g-n.g)*i+n.g,b:(a.b-n.b)*i+n.b,a:(a.a-n.a)*i+n.a})},d.readability=function(e,t){var r=d(e),n=d(t);return(a.max(r.getLuminance(),n.getLuminance())+.05)/(a.min(r.getLuminance(),n.getLuminance())+.05)},d.isReadable=function(e,t,r){var n,a,i,o,l,s=d.readability(e,t);switch(a=!1,(i=r,o=((i=i||{level:"AA",size:"small"}).level||"AA").toUpperCase(),l=(i.size||"small").toLowerCase(),"AA"!==o&&"AAA"!==o&&(o="AA"),"small"!==l&&"large"!==l&&(l="small"),n={level:o,size:l}).level+n.size){case"AAsmall":case"AAAlarge":a=s>=4.5;break;case"AAlarge":a=s>=3;break;case"AAAsmall":a=s>=7}return a},d.mostReadable=function(e,t,r){var n,a,i,o,l=null,s=0;a=(r=r||{}).includeFallbackColors,i=r.level,o=r.size;for(var c=0;cs&&(s=n,l=d(t[c]));return d.isReadable(e,l,{level:i,size:o})||!a?l:(r.includeFallbackColors=!1,d.mostReadable(e,["#fff","#000"],r))};var D=d.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},C=d.hexNames=function(e){var t={};for(var r in e)e.hasOwnProperty(r)&&(t[e[r]]=r);return t}(D);function P(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function I(e,t){(function(e){return"string"==typeof e&&-1!=e.indexOf(".")&&1===parseFloat(e)})(e)&&(e="100%");var r=function(e){return"string"==typeof e&&-1!=e.indexOf("%")}(e);return e=c(t,u(0,parseFloat(e))),r&&(e=parseInt(e*t,10)/100),a.abs(e-t)<1e-6?1:e%t/parseFloat(t)}function R(e){return c(1,u(0,e))}function z(e){return parseInt(e,16)}function N(e){return 1==e.length?"0"+e:""+e}function E(e){return e<=1&&(e=100*e+"%"),e}function F(e){return a.round(255*parseFloat(e)).toString(16)}function H(e){return z(e)/255}var j,B,Y,U=(B="[\\s|\\(]+("+(j="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+j+")[,|\\s]+("+j+")\\s*\\)?",Y="[\\s|\\(]+("+j+")[,|\\s]+("+j+")[,|\\s]+("+j+")[,|\\s]+("+j+")\\s*\\)?",{CSS_UNIT:new RegExp(j),rgb:new RegExp("rgb"+B),rgba:new RegExp("rgba"+Y),hsl:new RegExp("hsl"+B),hsla:new RegExp("hsla"+Y),hsv:new RegExp("hsv"+B),hsva:new RegExp("hsva"+Y),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function V(e){return!!U.CSS_UNIT.exec(e)}e.exports?e.exports=d:void 0===(n=function(){return d}.call(t,r,t,e))||(e.exports=n)}(Math)},3961:function(e,t,r){var n=r(3489),a=r(6131),i=n.instance();function o(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,a(o.prototype,{name:"Chinese",jdEpoch:1721425.5,hasYearZero:!1,minMonth:0,firstMonth:0,minDay:1,regionalOptions:{"":{name:"Chinese",epochs:["BEC","EC"],monthNumbers:function(e,t){if("string"==typeof e){var r=e.match(s);return r?r[0]:""}var n=this._validateYear(e),a=e.month(),i=""+this.toChineseMonth(n,a);return t&&i.length<2&&(i="0"+i),this.isIntercalaryMonth(n,a)&&(i+="i"),i},monthNames:function(e){if("string"==typeof e){var t=e.match(c);return t?t[0]:""}var r=this._validateYear(e),n=e.month(),a=["\u4e00\u6708","\u4e8c\u6708","\u4e09\u6708","\u56db\u6708","\u4e94\u6708","\u516d\u6708","\u4e03\u6708","\u516b\u6708","\u4e5d\u6708","\u5341\u6708","\u5341\u4e00\u6708","\u5341\u4e8c\u6708"][this.toChineseMonth(r,n)-1];return this.isIntercalaryMonth(r,n)&&(a="\u95f0"+a),a},monthNamesShort:function(e){if("string"==typeof e){var t=e.match(u);return t?t[0]:""}var r=this._validateYear(e),n=e.month(),a=["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"][this.toChineseMonth(r,n)-1];return this.isIntercalaryMonth(r,n)&&(a="\u95f0"+a),a},parseMonth:function(e,t){e=this._validateYear(e);var r,n=parseInt(t);if(isNaN(n))"\u95f0"===t[0]&&(r=!0,t=t.substring(1)),"\u6708"===t[t.length-1]&&(t=t.substring(0,t.length-1)),n=1+["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u5341\u4e00","\u5341\u4e8c"].indexOf(t);else{var a=t[t.length-1];r="i"===a||"I"===a}return this.toMonthIndex(e,n,r)},dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:1,isRTL:!1}},_validateYear:function(e,t){if(e.year&&(e=e.year()),"number"!=typeof e||e<1888||e>2111)throw t.replace(/\{0\}/,this.local.name);return e},toMonthIndex:function(e,t,r){var a=this.intercalaryMonth(e);if(r&&t!==a||t<1||t>12)throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return a?!r&&t<=a?t-1:t:t-1},toChineseMonth:function(e,t){e.year&&(t=(e=e.year()).month());var r=this.intercalaryMonth(e);if(t<0||t>(r?12:11))throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return r?t>13},isIntercalaryMonth:function(e,t){e.year&&(t=(e=e.year()).month());var r=this.intercalaryMonth(e);return!!r&&r===t},leapYear:function(e){return 0!==this.intercalaryMonth(e)},weekOfYear:function(e,t,r){var a,o=this._validateYear(e,n.local.invalidyear),l=d[o-d[0]],s=l>>9&4095,c=l>>5&15,u=31&l;(a=i.newDate(s,c,u)).add(4-(a.dayOfWeek()||7),"d");var f=this.toJD(e,t,r)-a.toJD();return 1+Math.floor(f/7)},monthsInYear:function(e){return this.leapYear(e)?13:12},daysInMonth:function(e,t){e.year&&(t=e.month(),e=e.year()),e=this._validateYear(e);var r=f[e-f[0]];if(t>(r>>13?12:11))throw n.local.invalidMonth.replace(/\{0\}/,this.local.name);return r&1<<12-t?30:29},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,l,r,n.local.invalidDate);e=this._validateYear(a.year()),t=a.month(),r=a.day();var o=this.isIntercalaryMonth(e,t),l=this.toChineseMonth(e,t),s=function(e,t,r,n,a){var i,o,l;if("object"==typeof e)o=e,i=t||{};else{var s;if(!("number"==typeof e&&e>=1888&&e<=2111))throw new Error("Lunar year outside range 1888-2111");if(!("number"==typeof t&&t>=1&&t<=12))throw new Error("Lunar month outside range 1 - 12");if(!("number"==typeof r&&r>=1&&r<=30))throw new Error("Lunar day outside range 1 - 30");"object"==typeof n?(s=!1,i=n):(s=!!n,i=a||{}),o={year:e,month:t,day:r,isIntercalary:s}}l=o.day-1;var c,u=f[o.year-f[0]],h=u>>13;c=h&&(o.month>h||o.isIntercalary)?o.month:o.month-1;for(var p=0;p>9&4095,(v>>5&15)-1,(31&v)+l);return i.year=y.getFullYear(),i.month=1+y.getMonth(),i.day=y.getDate(),i}(e,l,r,o);return i.toJD(s.year,s.month,s.day)},fromJD:function(e){var t=i.fromJD(e),r=function(e,t,r,n){var a,i;if("object"==typeof e)a=e,i=t||{};else{if(!("number"==typeof e&&e>=1888&&e<=2111))throw new Error("Solar year outside range 1888-2111");if(!("number"==typeof t&&t>=1&&t<=12))throw new Error("Solar month outside range 1 - 12");if(!("number"==typeof r&&r>=1&&r<=31))throw new Error("Solar day outside range 1 - 31");a={year:e,month:t,day:r},i=n||{}}var o=d[a.year-d[0]],l=a.year<<9|a.month<<5|a.day;i.year=l>=o?a.year:a.year-1,o=d[i.year-d[0]];var s,c=new Date(o>>9&4095,(o>>5&15)-1,31&o),u=new Date(a.year,a.month-1,a.day);s=Math.round((u-c)/864e5);var h,p=f[i.year-f[0]];for(h=0;h<13;h++){var v=p&1<<12-h?30:29;if(s>13;return!y||h=2&&n<=6},extraInfo:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return{century:o[Math.floor((a.year()-1)/100)+1]||""}},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return e=a.year()+(a.year()<0?1:0),t=a.month(),(r=a.day())+(t>1?16:0)+(t>2?32*(t-2):0)+400*(e-1)+this.jdEpoch-1},fromJD:function(e){e=Math.floor(e+.5)-Math.floor(this.jdEpoch)-1;var t=Math.floor(e/400)+1;e-=400*(t-1),e+=e>15?16:0;var r=Math.floor(e/32)+1,n=e-32*(r-1)+1;return this.newDate(t<=0?t-1:t,r,n)}});var o={20:"Fruitbat",21:"Anchovy"};n.calendars.discworld=i},7715:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Ethiopian",jdEpoch:1724220.5,daysPerMonth:[30,30,30,30,30,30,30,30,30,30,30,30,5],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Ethiopian",epochs:["BEE","EE"],monthNames:["Meskerem","Tikemet","Hidar","Tahesas","Tir","Yekatit","Megabit","Miazia","Genbot","Sene","Hamle","Nehase","Pagume"],monthNamesShort:["Mes","Tik","Hid","Tah","Tir","Yek","Meg","Mia","Gen","Sen","Ham","Neh","Pag"],dayNames:["Ehud","Segno","Maksegno","Irob","Hamus","Arb","Kidame"],dayNamesShort:["Ehu","Seg","Mak","Iro","Ham","Arb","Kid"],dayNamesMin:["Eh","Se","Ma","Ir","Ha","Ar","Ki"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return(e=t.year()+(t.year()<0?1:0))%4==3||e%4==-1},monthsInYear:function(e){return this._validate(e,this.minMonth,this.minDay,n.local.invalidYear||n.regionalOptions[""].invalidYear),13},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(13===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return(e=a.year())<0&&e++,a.day()+30*(a.month()-1)+365*(e-1)+Math.floor(e/4)+this.jdEpoch-1},fromJD:function(e){var t=Math.floor(e)+.5-this.jdEpoch,r=Math.floor((t-Math.floor((t+366)/1461))/365)+1;r<=0&&r--,t=Math.floor(e)+.5-this.newDate(r,1,1).toJD();var n=Math.floor(t/30)+1,a=t-30*(n-1)+1;return this.newDate(r,n,a)}}),n.calendars.ethiopian=i},9384:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}function o(e,t){return e-t*Math.floor(e/t)}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Hebrew",jdEpoch:347995.5,daysPerMonth:[30,29,30,29,30,29,30,29,30,29,30,29,29],hasYearZero:!1,minMonth:1,firstMonth:7,minDay:1,regionalOptions:{"":{name:"Hebrew",epochs:["BAM","AM"],monthNames:["Nisan","Iyar","Sivan","Tammuz","Av","Elul","Tishrei","Cheshvan","Kislev","Tevet","Shevat","Adar","Adar II"],monthNamesShort:["Nis","Iya","Siv","Tam","Av","Elu","Tis","Che","Kis","Tev","She","Ada","Ad2"],dayNames:["Yom Rishon","Yom Sheni","Yom Shlishi","Yom Revi'i","Yom Chamishi","Yom Shishi","Yom Shabbat"],dayNamesShort:["Ris","She","Shl","Rev","Cha","Shi","Sha"],dayNamesMin:["Ri","She","Shl","Re","Ch","Shi","Sha"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return this._leapYear(t.year())},_leapYear:function(e){return o(7*(e=e<0?e+1:e)+1,19)<7},monthsInYear:function(e){return this._validate(e,this.minMonth,this.minDay,n.local.invalidYear),this._leapYear(e.year?e.year():e)?13:12},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(e){return e=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear).year(),this.toJD(-1===e?1:e+1,7,1)-this.toJD(e,7,1)},daysInMonth:function(e,t){return e.year&&(t=e.month(),e=e.year()),this._validate(e,t,this.minDay,n.local.invalidMonth),12===t&&this.leapYear(e)||8===t&&5===o(this.daysInYear(e),10)?30:9===t&&3===o(this.daysInYear(e),10)?29:this.daysPerMonth[t-1]},weekDay:function(e,t,r){return 6!==this.dayOfWeek(e,t,r)},extraInfo:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return{yearType:(this.leapYear(a)?"embolismic":"common")+" "+["deficient","regular","complete"][this.daysInYear(a)%10-3]}},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);e=a.year(),t=a.month(),r=a.day();var i=e<=0?e+1:e,o=this.jdEpoch+this._delay1(i)+this._delay2(i)+r+1;if(t<7){for(var l=7;l<=this.monthsInYear(e);l++)o+=this.daysInMonth(e,l);for(l=1;l=this.toJD(-1===t?1:t+1,7,1);)t++;for(var r=ethis.toJD(t,r,this.daysInMonth(t,r));)r++;var n=e-this.toJD(t,r,1)+1;return this.newDate(t,r,n)}}),n.calendars.hebrew=i},3805:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Islamic",jdEpoch:1948439.5,daysPerMonth:[30,29,30,29,30,29,30,29,30,29,30,29],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Islamic",epochs:["BH","AH"],monthNames:["Muharram","Safar","Rabi' al-awwal","Rabi' al-thani","Jumada al-awwal","Jumada al-thani","Rajab","Sha'aban","Ramadan","Shawwal","Dhu al-Qi'dah","Dhu al-Hijjah"],monthNamesShort:["Muh","Saf","Rab1","Rab2","Jum1","Jum2","Raj","Sha'","Ram","Shaw","DhuQ","DhuH"],dayNames:["Yawm al-ahad","Yawm al-ithnayn","Yawm ath-thulaathaa'","Yawm al-arbi'aa'","Yawm al-kham\u012bs","Yawm al-jum'a","Yawm as-sabt"],dayNamesShort:["Aha","Ith","Thu","Arb","Kha","Jum","Sab"],dayNamesMin:["Ah","It","Th","Ar","Kh","Ju","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:6,isRTL:!1}},leapYear:function(e){return(11*this._validate(e,this.minMonth,this.minDay,n.local.invalidYear).year()+14)%30<11},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(e){return this.leapYear(e)?355:354},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return 5!==this.dayOfWeek(e,t,r)},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return e=a.year(),t=a.month(),e=e<=0?e+1:e,(r=a.day())+Math.ceil(29.5*(t-1))+354*(e-1)+Math.floor((3+11*e)/30)+this.jdEpoch-1},fromJD:function(e){e=Math.floor(e)+.5;var t=Math.floor((30*(e-this.jdEpoch)+10646)/10631);t=t<=0?t-1:t;var r=Math.min(12,Math.ceil((e-29-this.toJD(t,1,1))/29.5)+1),n=e-this.toJD(t,r,1)+1;return this.newDate(t,r,n)}}),n.calendars.islamic=i},8874:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Julian",jdEpoch:1721423.5,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Julian",epochs:["BC","AD"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"mm/dd/yyyy",firstDay:0,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return(e=t.year()<0?t.year()+1:t.year())%4==0},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(4-(n.dayOfWeek()||7),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return e=a.year(),t=a.month(),r=a.day(),e<0&&e++,t<=2&&(e--,t+=12),Math.floor(365.25*(e+4716))+Math.floor(30.6001*(t+1))+r-1524.5},fromJD:function(e){var t=Math.floor(e+.5)+1524,r=Math.floor((t-122.1)/365.25),n=Math.floor(365.25*r),a=Math.floor((t-n)/30.6001),i=a-Math.floor(a<14?1:13),o=r-Math.floor(i>2?4716:4715),l=t-n-Math.floor(30.6001*a);return o<=0&&o--,this.newDate(o,i,l)}}),n.calendars.julian=i},3290:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}function o(e,t){return e-t*Math.floor(e/t)}function l(e,t){return o(e-1,t)+1}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Mayan",jdEpoch:584282.5,hasYearZero:!0,minMonth:0,firstMonth:0,minDay:0,regionalOptions:{"":{name:"Mayan",epochs:["",""],monthNames:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17"],monthNamesShort:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17"],dayNames:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],dayNamesShort:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],dayNamesMin:["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"],digits:null,dateFormat:"YYYY.m.d",firstDay:0,isRTL:!1,haabMonths:["Pop","Uo","Zip","Zotz","Tzec","Xul","Yaxkin","Mol","Chen","Yax","Zac","Ceh","Mac","Kankin","Muan","Pax","Kayab","Cumku","Uayeb"],tzolkinMonths:["Imix","Ik","Akbal","Kan","Chicchan","Cimi","Manik","Lamat","Muluc","Oc","Chuen","Eb","Ben","Ix","Men","Cib","Caban","Etznab","Cauac","Ahau"]}},leapYear:function(e){return this._validate(e,this.minMonth,this.minDay,n.local.invalidYear),!1},formatYear:function(e){e=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear).year();var t=Math.floor(e/400);return e%=400,e+=e<0?400:0,t+"."+Math.floor(e/20)+"."+e%20},forYear:function(e){if((e=e.split(".")).length<3)throw"Invalid Mayan year";for(var t=0,r=0;r19||r>0&&n<0)throw"Invalid Mayan year";t=20*t+n}return t},monthsInYear:function(e){return this._validate(e,this.minMonth,this.minDay,n.local.invalidYear),18},weekOfYear:function(e,t,r){return this._validate(e,t,r,n.local.invalidDate),0},daysInYear:function(e){return this._validate(e,this.minMonth,this.minDay,n.local.invalidYear),360},daysInMonth:function(e,t){return this._validate(e,t,this.minDay,n.local.invalidMonth),20},daysInWeek:function(){return 5},dayOfWeek:function(e,t,r){return this._validate(e,t,r,n.local.invalidDate).day()},weekDay:function(e,t,r){return this._validate(e,t,r,n.local.invalidDate),!0},extraInfo:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate).toJD(),i=this._toHaab(a),o=this._toTzolkin(a);return{haabMonthName:this.local.haabMonths[i[0]-1],haabMonth:i[0],haabDay:i[1],tzolkinDayName:this.local.tzolkinMonths[o[0]-1],tzolkinDay:o[0],tzolkinTrecena:o[1]}},_toHaab:function(e){var t=o(8+(e-=this.jdEpoch)+340,365);return[Math.floor(t/20)+1,o(t,20)]},_toTzolkin:function(e){return[l(20+(e-=this.jdEpoch),20),l(e+4,13)]},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return a.day()+20*a.month()+360*a.year()+this.jdEpoch},fromJD:function(e){e=Math.floor(e)+.5-this.jdEpoch;var t=Math.floor(e/360);e%=360,e+=e<0?360:0;var r=Math.floor(e/20),n=e%20;return this.newDate(t,r,n)}}),n.calendars.mayan=i},9108:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar;var o=n.instance("gregorian");a(i.prototype,{name:"Nanakshahi",jdEpoch:2257673.5,daysPerMonth:[31,31,31,31,31,30,30,30,30,30,30,30],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Nanakshahi",epochs:["BN","AN"],monthNames:["Chet","Vaisakh","Jeth","Harh","Sawan","Bhadon","Assu","Katak","Maghar","Poh","Magh","Phagun"],monthNamesShort:["Che","Vai","Jet","Har","Saw","Bha","Ass","Kat","Mgr","Poh","Mgh","Pha"],dayNames:["Somvaar","Mangalvar","Budhvaar","Veervaar","Shukarvaar","Sanicharvaar","Etvaar"],dayNamesShort:["Som","Mangal","Budh","Veer","Shukar","Sanichar","Et"],dayNamesMin:["So","Ma","Bu","Ve","Sh","Sa","Et"],digits:null,dateFormat:"dd-mm-yyyy",firstDay:0,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear||n.regionalOptions[""].invalidYear);return o.leapYear(t.year()+(t.year()<1?1:0)+1469)},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(1-(n.dayOfWeek()||7),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidMonth);(e=a.year())<0&&e++;for(var i=a.day(),l=1;l=this.toJD(t+1,1,1);)t++;for(var r=e-Math.floor(this.toJD(t,1,1)+.5)+1,n=1;r>this.daysInMonth(t,n);)r-=this.daysInMonth(t,n),n++;return this.newDate(t,n,r)}}),n.calendars.nanakshahi=i},5422:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar,a(i.prototype,{name:"Nepali",jdEpoch:1700709.5,daysPerMonth:[31,31,32,32,31,30,30,29,30,29,30,30],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,daysPerYear:365,regionalOptions:{"":{name:"Nepali",epochs:["BBS","ABS"],monthNames:["Baisakh","Jestha","Ashadh","Shrawan","Bhadra","Ashwin","Kartik","Mangsir","Paush","Mangh","Falgun","Chaitra"],monthNamesShort:["Bai","Je","As","Shra","Bha","Ash","Kar","Mang","Pau","Ma","Fal","Chai"],dayNames:["Aaitabaar","Sombaar","Manglbaar","Budhabaar","Bihibaar","Shukrabaar","Shanibaar"],dayNamesShort:["Aaita","Som","Mangl","Budha","Bihi","Shukra","Shani"],dayNamesMin:["Aai","So","Man","Bu","Bi","Shu","Sha"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:1,isRTL:!1}},leapYear:function(e){return this.daysInYear(e)!==this.daysPerYear},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(e){if(e=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear).year(),void 0===this.NEPALI_CALENDAR_DATA[e])return this.daysPerYear;for(var t=0,r=this.minMonth;r<=12;r++)t+=this.NEPALI_CALENDAR_DATA[e][r];return t},daysInMonth:function(e,t){return e.year&&(t=e.month(),e=e.year()),this._validate(e,t,this.minDay,n.local.invalidMonth),void 0===this.NEPALI_CALENDAR_DATA[e]?this.daysPerMonth[t-1]:this.NEPALI_CALENDAR_DATA[e][t]},weekDay:function(e,t,r){return 6!==this.dayOfWeek(e,t,r)},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);e=a.year(),t=a.month(),r=a.day();var i=n.instance(),o=0,l=t,s=e;this._createMissingCalendarData(e);var c=e-(l>9||9===l&&r>=this.NEPALI_CALENDAR_DATA[s][0]?56:57);for(9!==t&&(o=r,l--);9!==l;)l<=0&&(l=12,s--),o+=this.NEPALI_CALENDAR_DATA[s][l],l--;return 9===t?(o+=r-this.NEPALI_CALENDAR_DATA[s][0])<0&&(o+=i.daysInYear(c)):o+=this.NEPALI_CALENDAR_DATA[s][9]-this.NEPALI_CALENDAR_DATA[s][0],i.newDate(c,1,1).add(o,"d").toJD()},fromJD:function(e){var t=n.instance().fromJD(e),r=t.year(),a=t.dayOfYear(),i=r+56;this._createMissingCalendarData(i);for(var o=9,l=this.NEPALI_CALENDAR_DATA[i][0],s=this.NEPALI_CALENDAR_DATA[i][o]-l+1;a>s;)++o>12&&(o=1,i++),s+=this.NEPALI_CALENDAR_DATA[i][o];var c=this.NEPALI_CALENDAR_DATA[i][o]-(s-a);return this.newDate(i,o,c)},_createMissingCalendarData:function(e){var t=this.daysPerMonth.slice(0);t.unshift(17);for(var r=e-1;r0?474:473))%2820+474+38)%2816<682},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-(n.dayOfWeek()+1)%7,"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(12===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return 5!==this.dayOfWeek(e,t,r)},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);e=a.year(),t=a.month(),r=a.day();var i=e-(e>=0?474:473),l=474+o(i,2820);return r+(t<=7?31*(t-1):30*(t-1)+6)+Math.floor((682*l-110)/2816)+365*(l-1)+1029983*Math.floor(i/2820)+this.jdEpoch-1},fromJD:function(e){var t=(e=Math.floor(e)+.5)-this.toJD(475,1,1),r=Math.floor(t/1029983),n=o(t,1029983),a=2820;if(1029982!==n){var i=Math.floor(n/366),l=o(n,366);a=Math.floor((2134*i+2816*l+2815)/1028522)+i+1}var s=a+2820*r+474;s=s<=0?s-1:s;var c=e-this.toJD(s,1,1)+1,u=c<=186?Math.ceil(c/31):Math.ceil((c-6)/30),f=e-this.toJD(s,u,1)+1;return this.newDate(s,u,f)}}),n.calendars.persian=i,n.calendars.jalali=i},1320:function(e,t,r){var n=r(3489),a=r(6131),i=n.instance();function o(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,a(o.prototype,{name:"Taiwan",jdEpoch:2419402.5,yearsOffset:1911,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Taiwan",epochs:["BROC","ROC"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:1,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return e=this._t2gYear(t.year()),i.leapYear(e)},weekOfYear:function(e,t,r){var a=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return e=this._t2gYear(a.year()),i.weekOfYear(e,a.month(),a.day())},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return e=this._t2gYear(a.year()),i.toJD(e,a.month(),a.day())},fromJD:function(e){var t=i.fromJD(e),r=this._g2tYear(t.year());return this.newDate(r,t.month(),t.day())},_t2gYear:function(e){return e+this.yearsOffset+(e>=-this.yearsOffset&&e<=-1?1:0)},_g2tYear:function(e){return e-this.yearsOffset-(e>=1&&e<=this.yearsOffset?1:0)}}),n.calendars.taiwan=o},1367:function(e,t,r){var n=r(3489),a=r(6131),i=n.instance();function o(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}o.prototype=new n.baseCalendar,a(o.prototype,{name:"Thai",jdEpoch:1523098.5,yearsOffset:543,daysPerMonth:[31,28,31,30,31,30,31,31,30,31,30,31],hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Thai",epochs:["BBE","BE"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],digits:null,dateFormat:"dd/mm/yyyy",firstDay:0,isRTL:!1}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return e=this._t2gYear(t.year()),i.leapYear(e)},weekOfYear:function(e,t,r){var a=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return e=this._t2gYear(a.year()),i.weekOfYear(e,a.month(),a.day())},daysInMonth:function(e,t){var r=this._validate(e,t,this.minDay,n.local.invalidMonth);return this.daysPerMonth[r.month()-1]+(2===r.month()&&this.leapYear(r.year())?1:0)},weekDay:function(e,t,r){return(this.dayOfWeek(e,t,r)||7)<6},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate);return e=this._t2gYear(a.year()),i.toJD(e,a.month(),a.day())},fromJD:function(e){var t=i.fromJD(e),r=this._g2tYear(t.year());return this.newDate(r,t.month(),t.day())},_t2gYear:function(e){return e-this.yearsOffset-(e>=1&&e<=this.yearsOffset?1:0)},_g2tYear:function(e){return e+this.yearsOffset+(e>=-this.yearsOffset&&e<=-1?1:0)}}),n.calendars.thai=o},1457:function(e,t,r){var n=r(3489),a=r(6131);function i(e){this.local=this.regionalOptions[e||""]||this.regionalOptions[""]}i.prototype=new n.baseCalendar,a(i.prototype,{name:"UmmAlQura",hasYearZero:!1,minMonth:1,firstMonth:1,minDay:1,regionalOptions:{"":{name:"Umm al-Qura",epochs:["BH","AH"],monthNames:["Al-Muharram","Safar","Rabi' al-awwal","Rabi' Al-Thani","Jumada Al-Awwal","Jumada Al-Thani","Rajab","Sha'aban","Ramadan","Shawwal","Dhu al-Qi'dah","Dhu al-Hijjah"],monthNamesShort:["Muh","Saf","Rab1","Rab2","Jum1","Jum2","Raj","Sha'","Ram","Shaw","DhuQ","DhuH"],dayNames:["Yawm al-Ahad","Yawm al-Ithnain","Yawm al-Thal\u0101th\u0101\u2019","Yawm al-Arba\u2018\u0101\u2019","Yawm al-Kham\u012bs","Yawm al-Jum\u2018a","Yawm al-Sabt"],dayNamesMin:["Ah","Ith","Th","Ar","Kh","Ju","Sa"],digits:null,dateFormat:"yyyy/mm/dd",firstDay:6,isRTL:!0}},leapYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,n.local.invalidYear);return 355===this.daysInYear(t.year())},weekOfYear:function(e,t,r){var n=this.newDate(e,t,r);return n.add(-n.dayOfWeek(),"d"),Math.floor((n.dayOfYear()-1)/7)+1},daysInYear:function(e){for(var t=0,r=1;r<=12;r++)t+=this.daysInMonth(e,r);return t},daysInMonth:function(e,t){for(var r=this._validate(e,t,this.minDay,n.local.invalidMonth).toJD()-24e5+.5,a=0,i=0;ir)return o[a]-o[a-1];a++}return 30},weekDay:function(e,t,r){return 5!==this.dayOfWeek(e,t,r)},toJD:function(e,t,r){var a=this._validate(e,t,r,n.local.invalidDate),i=12*(a.year()-1)+a.month()-15292;return a.day()+o[i-1]-1+24e5-.5},fromJD:function(e){for(var t=e-24e5+.5,r=0,n=0;nt);n++)r++;var a=r+15292,i=Math.floor((a-1)/12),l=i+1,s=a-12*i,c=t-o[r-1]+1;return this.newDate(l,s,c)},isValid:function(e,t,r){var a=n.baseCalendar.prototype.isValid.apply(this,arguments);return a&&(a=(e=null!=e.year?e.year:e)>=1276&&e<=1500),a},_validate:function(e,t,r,a){var i=n.baseCalendar.prototype._validate.apply(this,arguments);if(i.year<1276||i.year>1500)throw a.replace(/\{0\}/,this.local.name);return i}}),n.calendars.ummalqura=i;var o=[20,50,79,109,138,168,197,227,256,286,315,345,374,404,433,463,492,522,551,581,611,641,670,700,729,759,788,818,847,877,906,936,965,995,1024,1054,1083,1113,1142,1172,1201,1231,1260,1290,1320,1350,1379,1409,1438,1468,1497,1527,1556,1586,1615,1645,1674,1704,1733,1763,1792,1822,1851,1881,1910,1940,1969,1999,2028,2058,2087,2117,2146,2176,2205,2235,2264,2294,2323,2353,2383,2413,2442,2472,2501,2531,2560,2590,2619,2649,2678,2708,2737,2767,2796,2826,2855,2885,2914,2944,2973,3003,3032,3062,3091,3121,3150,3180,3209,3239,3268,3298,3327,3357,3386,3416,3446,3476,3505,3535,3564,3594,3623,3653,3682,3712,3741,3771,3800,3830,3859,3889,3918,3948,3977,4007,4036,4066,4095,4125,4155,4185,4214,4244,4273,4303,4332,4362,4391,4421,4450,4480,4509,4539,4568,4598,4627,4657,4686,4716,4745,4775,4804,4834,4863,4893,4922,4952,4981,5011,5040,5070,5099,5129,5158,5188,5218,5248,5277,5307,5336,5366,5395,5425,5454,5484,5513,5543,5572,5602,5631,5661,5690,5720,5749,5779,5808,5838,5867,5897,5926,5956,5985,6015,6044,6074,6103,6133,6162,6192,6221,6251,6281,6311,6340,6370,6399,6429,6458,6488,6517,6547,6576,6606,6635,6665,6694,6724,6753,6783,6812,6842,6871,6901,6930,6960,6989,7019,7048,7078,7107,7137,7166,7196,7225,7255,7284,7314,7344,7374,7403,7433,7462,7492,7521,7551,7580,7610,7639,7669,7698,7728,7757,7787,7816,7846,7875,7905,7934,7964,7993,8023,8053,8083,8112,8142,8171,8201,8230,8260,8289,8319,8348,8378,8407,8437,8466,8496,8525,8555,8584,8614,8643,8673,8702,8732,8761,8791,8821,8850,8880,8909,8938,8968,8997,9027,9056,9086,9115,9145,9175,9205,9234,9264,9293,9322,9352,9381,9410,9440,9470,9499,9529,9559,9589,9618,9648,9677,9706,9736,9765,9794,9824,9853,9883,9913,9943,9972,10002,10032,10061,10090,10120,10149,10178,10208,10237,10267,10297,10326,10356,10386,10415,10445,10474,10504,10533,10562,10592,10621,10651,10680,10710,10740,10770,10799,10829,10858,10888,10917,10947,10976,11005,11035,11064,11094,11124,11153,11183,11213,11242,11272,11301,11331,11360,11389,11419,11448,11478,11507,11537,11567,11596,11626,11655,11685,11715,11744,11774,11803,11832,11862,11891,11921,11950,11980,12010,12039,12069,12099,12128,12158,12187,12216,12246,12275,12304,12334,12364,12393,12423,12453,12483,12512,12542,12571,12600,12630,12659,12688,12718,12747,12777,12807,12837,12866,12896,12926,12955,12984,13014,13043,13072,13102,13131,13161,13191,13220,13250,13280,13310,13339,13368,13398,13427,13456,13486,13515,13545,13574,13604,13634,13664,13693,13723,13752,13782,13811,13840,13870,13899,13929,13958,13988,14018,14047,14077,14107,14136,14166,14195,14224,14254,14283,14313,14342,14372,14401,14431,14461,14490,14520,14550,14579,14609,14638,14667,14697,14726,14756,14785,14815,14844,14874,14904,14933,14963,14993,15021,15051,15081,15110,15140,15169,15199,15228,15258,15287,15317,15347,15377,15406,15436,15465,15494,15524,15553,15582,15612,15641,15671,15701,15731,15760,15790,15820,15849,15878,15908,15937,15966,15996,16025,16055,16085,16114,16144,16174,16204,16233,16262,16292,16321,16350,16380,16409,16439,16468,16498,16528,16558,16587,16617,16646,16676,16705,16734,16764,16793,16823,16852,16882,16912,16941,16971,17001,17030,17060,17089,17118,17148,17177,17207,17236,17266,17295,17325,17355,17384,17414,17444,17473,17502,17532,17561,17591,17620,17650,17679,17709,17738,17768,17798,17827,17857,17886,17916,17945,17975,18004,18034,18063,18093,18122,18152,18181,18211,18241,18270,18300,18330,18359,18388,18418,18447,18476,18506,18535,18565,18595,18625,18654,18684,18714,18743,18772,18802,18831,18860,18890,18919,18949,18979,19008,19038,19068,19098,19127,19156,19186,19215,19244,19274,19303,19333,19362,19392,19422,19452,19481,19511,19540,19570,19599,19628,19658,19687,19717,19746,19776,19806,19836,19865,19895,19924,19954,19983,20012,20042,20071,20101,20130,20160,20190,20219,20249,20279,20308,20338,20367,20396,20426,20455,20485,20514,20544,20573,20603,20633,20662,20692,20721,20751,20780,20810,20839,20869,20898,20928,20957,20987,21016,21046,21076,21105,21135,21164,21194,21223,21253,21282,21312,21341,21371,21400,21430,21459,21489,21519,21548,21578,21607,21637,21666,21696,21725,21754,21784,21813,21843,21873,21902,21932,21962,21991,22021,22050,22080,22109,22138,22168,22197,22227,22256,22286,22316,22346,22375,22405,22434,22464,22493,22522,22552,22581,22611,22640,22670,22700,22730,22759,22789,22818,22848,22877,22906,22936,22965,22994,23024,23054,23083,23113,23143,23173,23202,23232,23261,23290,23320,23349,23379,23408,23438,23467,23497,23527,23556,23586,23616,23645,23674,23704,23733,23763,23792,23822,23851,23881,23910,23940,23970,23999,24029,24058,24088,24117,24147,24176,24206,24235,24265,24294,24324,24353,24383,24413,24442,24472,24501,24531,24560,24590,24619,24648,24678,24707,24737,24767,24796,24826,24856,24885,24915,24944,24974,25003,25032,25062,25091,25121,25150,25180,25210,25240,25269,25299,25328,25358,25387,25416,25446,25475,25505,25534,25564,25594,25624,25653,25683,25712,25742,25771,25800,25830,25859,25888,25918,25948,25977,26007,26037,26067,26096,26126,26155,26184,26214,26243,26272,26302,26332,26361,26391,26421,26451,26480,26510,26539,26568,26598,26627,26656,26686,26715,26745,26775,26805,26834,26864,26893,26923,26952,26982,27011,27041,27070,27099,27129,27159,27188,27218,27248,27277,27307,27336,27366,27395,27425,27454,27484,27513,27542,27572,27602,27631,27661,27691,27720,27750,27779,27809,27838,27868,27897,27926,27956,27985,28015,28045,28074,28104,28134,28163,28193,28222,28252,28281,28310,28340,28369,28399,28428,28458,28488,28517,28547,28577,28607,28636,28665,28695,28724,28754,28783,28813,28843,28872,28901,28931,28960,28990,29019,29049,29078,29108,29137,29167,29196,29226,29255,29285,29315,29345,29375,29404,29434,29463,29492,29522,29551,29580,29610,29640,29669,29699,29729,29759,29788,29818,29847,29876,29906,29935,29964,29994,30023,30053,30082,30112,30141,30171,30200,30230,30259,30289,30318,30348,30378,30408,30437,30467,30496,30526,30555,30585,30614,30644,30673,30703,30732,30762,30791,30821,30850,30880,30909,30939,30968,30998,31027,31057,31086,31116,31145,31175,31204,31234,31263,31293,31322,31352,31381,31411,31441,31471,31500,31530,31559,31589,31618,31648,31676,31706,31736,31766,31795,31825,31854,31884,31913,31943,31972,32002,32031,32061,32090,32120,32150,32180,32209,32239,32268,32298,32327,32357,32386,32416,32445,32475,32504,32534,32563,32593,32622,32652,32681,32711,32740,32770,32799,32829,32858,32888,32917,32947,32976,33006,33035,33065,33094,33124,33153,33183,33213,33243,33272,33302,33331,33361,33390,33420,33450,33479,33509,33539,33568,33598,33627,33657,33686,33716,33745,33775,33804,33834,33863,33893,33922,33952,33981,34011,34040,34069,34099,34128,34158,34187,34217,34247,34277,34306,34336,34365,34395,34424,34454,34483,34512,34542,34571,34601,34631,34660,34690,34719,34749,34778,34808,34837,34867,34896,34926,34955,34985,35015,35044,35074,35103,35133,35162,35192,35222,35251,35280,35310,35340,35370,35399,35429,35458,35488,35517,35547,35576,35605,35635,35665,35694,35723,35753,35782,35811,35841,35871,35901,35930,35960,35989,36019,36048,36078,36107,36136,36166,36195,36225,36254,36284,36314,36343,36373,36403,36433,36462,36492,36521,36551,36580,36610,36639,36669,36698,36728,36757,36786,36816,36845,36875,36904,36934,36963,36993,37022,37052,37081,37111,37141,37170,37200,37229,37259,37288,37318,37347,37377,37406,37436,37465,37495,37524,37554,37584,37613,37643,37672,37701,37731,37760,37790,37819,37849,37878,37908,37938,37967,37997,38027,38056,38085,38115,38144,38174,38203,38233,38262,38292,38322,38351,38381,38410,38440,38469,38499,38528,38558,38587,38617,38646,38676,38705,38735,38764,38794,38823,38853,38882,38912,38941,38971,39001,39030,39059,39089,39118,39148,39178,39208,39237,39267,39297,39326,39355,39385,39414,39444,39473,39503,39532,39562,39592,39621,39650,39680,39709,39739,39768,39798,39827,39857,39886,39916,39946,39975,40005,40035,40064,40094,40123,40153,40182,40212,40241,40271,40300,40330,40359,40389,40418,40448,40477,40507,40536,40566,40595,40625,40655,40685,40714,40744,40773,40803,40832,40862,40892,40921,40951,40980,41009,41039,41068,41098,41127,41157,41186,41216,41245,41275,41304,41334,41364,41393,41422,41452,41481,41511,41540,41570,41599,41629,41658,41688,41718,41748,41777,41807,41836,41865,41894,41924,41953,41983,42012,42042,42072,42102,42131,42161,42190,42220,42249,42279,42308,42337,42367,42397,42426,42456,42485,42515,42545,42574,42604,42633,42662,42692,42721,42751,42780,42810,42839,42869,42899,42929,42958,42988,43017,43046,43076,43105,43135,43164,43194,43223,43253,43283,43312,43342,43371,43401,43430,43460,43489,43519,43548,43578,43607,43637,43666,43696,43726,43755,43785,43814,43844,43873,43903,43932,43962,43991,44021,44050,44080,44109,44139,44169,44198,44228,44258,44287,44317,44346,44375,44405,44434,44464,44493,44523,44553,44582,44612,44641,44671,44700,44730,44759,44788,44818,44847,44877,44906,44936,44966,44996,45025,45055,45084,45114,45143,45172,45202,45231,45261,45290,45320,45350,45380,45409,45439,45468,45498,45527,45556,45586,45615,45644,45674,45704,45733,45763,45793,45823,45852,45882,45911,45940,45970,45999,46028,46058,46088,46117,46147,46177,46206,46236,46265,46295,46324,46354,46383,46413,46442,46472,46501,46531,46560,46590,46620,46649,46679,46708,46738,46767,46797,46826,46856,46885,46915,46944,46974,47003,47033,47063,47092,47122,47151,47181,47210,47240,47269,47298,47328,47357,47387,47417,47446,47476,47506,47535,47565,47594,47624,47653,47682,47712,47741,47771,47800,47830,47860,47890,47919,47949,47978,48008,48037,48066,48096,48125,48155,48184,48214,48244,48273,48303,48333,48362,48392,48421,48450,48480,48509,48538,48568,48598,48627,48657,48687,48717,48746,48776,48805,48834,48864,48893,48922,48952,48982,49011,49041,49071,49100,49130,49160,49189,49218,49248,49277,49306,49336,49365,49395,49425,49455,49484,49514,49543,49573,49602,49632,49661,49690,49720,49749,49779,49809,49838,49868,49898,49927,49957,49986,50016,50045,50075,50104,50133,50163,50192,50222,50252,50281,50311,50340,50370,50400,50429,50459,50488,50518,50547,50576,50606,50635,50665,50694,50724,50754,50784,50813,50843,50872,50902,50931,50960,50990,51019,51049,51078,51108,51138,51167,51197,51227,51256,51286,51315,51345,51374,51403,51433,51462,51492,51522,51552,51582,51611,51641,51670,51699,51729,51758,51787,51816,51846,51876,51906,51936,51965,51995,52025,52054,52083,52113,52142,52171,52200,52230,52260,52290,52319,52349,52379,52408,52438,52467,52497,52526,52555,52585,52614,52644,52673,52703,52733,52762,52792,52822,52851,52881,52910,52939,52969,52998,53028,53057,53087,53116,53146,53176,53205,53235,53264,53294,53324,53353,53383,53412,53441,53471,53500,53530,53559,53589,53619,53648,53678,53708,53737,53767,53796,53825,53855,53884,53913,53943,53973,54003,54032,54062,54092,54121,54151,54180,54209,54239,54268,54297,54327,54357,54387,54416,54446,54476,54505,54535,54564,54593,54623,54652,54681,54711,54741,54770,54800,54830,54859,54889,54919,54948,54977,55007,55036,55066,55095,55125,55154,55184,55213,55243,55273,55302,55332,55361,55391,55420,55450,55479,55508,55538,55567,55597,55627,55657,55686,55716,55745,55775,55804,55834,55863,55892,55922,55951,55981,56011,56040,56070,56100,56129,56159,56188,56218,56247,56276,56306,56335,56365,56394,56424,56454,56483,56513,56543,56572,56601,56631,56660,56690,56719,56749,56778,56808,56837,56867,56897,56926,56956,56985,57015,57044,57074,57103,57133,57162,57192,57221,57251,57280,57310,57340,57369,57399,57429,57458,57487,57517,57546,57576,57605,57634,57664,57694,57723,57753,57783,57813,57842,57871,57901,57930,57959,57989,58018,58048,58077,58107,58137,58167,58196,58226,58255,58285,58314,58343,58373,58402,58432,58461,58491,58521,58551,58580,58610,58639,58669,58698,58727,58757,58786,58816,58845,58875,58905,58934,58964,58994,59023,59053,59082,59111,59141,59170,59200,59229,59259,59288,59318,59348,59377,59407,59436,59466,59495,59525,59554,59584,59613,59643,59672,59702,59731,59761,59791,59820,59850,59879,59909,59939,59968,59997,60027,60056,60086,60115,60145,60174,60204,60234,60264,60293,60323,60352,60381,60411,60440,60469,60499,60528,60558,60588,60618,60648,60677,60707,60736,60765,60795,60824,60853,60883,60912,60942,60972,61002,61031,61061,61090,61120,61149,61179,61208,61237,61267,61296,61326,61356,61385,61415,61445,61474,61504,61533,61563,61592,61621,61651,61680,61710,61739,61769,61799,61828,61858,61888,61917,61947,61976,62006,62035,62064,62094,62123,62153,62182,62212,62242,62271,62301,62331,62360,62390,62419,62448,62478,62507,62537,62566,62596,62625,62655,62685,62715,62744,62774,62803,62832,62862,62891,62921,62950,62980,63009,63039,63069,63099,63128,63157,63187,63216,63246,63275,63305,63334,63363,63393,63423,63453,63482,63512,63541,63571,63600,63630,63659,63689,63718,63747,63777,63807,63836,63866,63895,63925,63955,63984,64014,64043,64073,64102,64131,64161,64190,64220,64249,64279,64309,64339,64368,64398,64427,64457,64486,64515,64545,64574,64603,64633,64663,64692,64722,64752,64782,64811,64841,64870,64899,64929,64958,64987,65017,65047,65076,65106,65136,65166,65195,65225,65254,65283,65313,65342,65371,65401,65431,65460,65490,65520,65549,65579,65608,65638,65667,65697,65726,65755,65785,65815,65844,65874,65903,65933,65963,65992,66022,66051,66081,66110,66140,66169,66199,66228,66258,66287,66317,66346,66376,66405,66435,66465,66494,66524,66553,66583,66612,66641,66671,66700,66730,66760,66789,66819,66849,66878,66908,66937,66967,66996,67025,67055,67084,67114,67143,67173,67203,67233,67262,67292,67321,67351,67380,67409,67439,67468,67497,67527,67557,67587,67617,67646,67676,67705,67735,67764,67793,67823,67852,67882,67911,67941,67971,68e3,68030,68060,68089,68119,68148,68177,68207,68236,68266,68295,68325,68354,68384,68414,68443,68473,68502,68532,68561,68591,68620,68650,68679,68708,68738,68768,68797,68827,68857,68886,68916,68946,68975,69004,69034,69063,69092,69122,69152,69181,69211,69240,69270,69300,69330,69359,69388,69418,69447,69476,69506,69535,69565,69595,69624,69654,69684,69713,69743,69772,69802,69831,69861,69890,69919,69949,69978,70008,70038,70067,70097,70126,70156,70186,70215,70245,70274,70303,70333,70362,70392,70421,70451,70481,70510,70540,70570,70599,70629,70658,70687,70717,70746,70776,70805,70835,70864,70894,70924,70954,70983,71013,71042,71071,71101,71130,71159,71189,71218,71248,71278,71308,71337,71367,71397,71426,71455,71485,71514,71543,71573,71602,71632,71662,71691,71721,71751,71781,71810,71839,71869,71898,71927,71957,71986,72016,72046,72075,72105,72135,72164,72194,72223,72253,72282,72311,72341,72370,72400,72429,72459,72489,72518,72548,72577,72607,72637,72666,72695,72725,72754,72784,72813,72843,72872,72902,72931,72961,72991,73020,73050,73080,73109,73139,73168,73197,73227,73256,73286,73315,73345,73375,73404,73434,73464,73493,73523,73552,73581,73611,73640,73669,73699,73729,73758,73788,73818,73848,73877,73907,73936,73965,73995,74024,74053,74083,74113,74142,74172,74202,74231,74261,74291,74320,74349,74379,74408,74437,74467,74497,74526,74556,74586,74615,74645,74675,74704,74733,74763,74792,74822,74851,74881,74910,74940,74969,74999,75029,75058,75088,75117,75147,75176,75206,75235,75264,75294,75323,75353,75383,75412,75442,75472,75501,75531,75560,75590,75619,75648,75678,75707,75737,75766,75796,75826,75856,75885,75915,75944,75974,76003,76032,76062,76091,76121,76150,76180,76210,76239,76269,76299,76328,76358,76387,76416,76446,76475,76505,76534,76564,76593,76623,76653,76682,76712,76741,76771,76801,76830,76859,76889,76918,76948,76977,77007,77036,77066,77096,77125,77155,77185,77214,77243,77273,77302,77332,77361,77390,77420,77450,77479,77509,77539,77569,77598,77627,77657,77686,77715,77745,77774,77804,77833,77863,77893,77923,77952,77982,78011,78041,78070,78099,78129,78158,78188,78217,78247,78277,78307,78336,78366,78395,78425,78454,78483,78513,78542,78572,78601,78631,78661,78690,78720,78750,78779,78808,78838,78867,78897,78926,78956,78985,79015,79044,79074,79104,79133,79163,79192,79222,79251,79281,79310,79340,79369,79399,79428,79458,79487,79517,79546,79576,79606,79635,79665,79695,79724,79753,79783,79812,79841,79871,79900,79930,79960,79990]},3489:function(e,t,r){var n=r(6131);function a(){this.regionalOptions=[],this.regionalOptions[""]={invalidCalendar:"Calendar {0} not found",invalidDate:"Invalid {0} date",invalidMonth:"Invalid {0} month",invalidYear:"Invalid {0} year",differentCalendars:"Cannot mix {0} and {1} dates"},this.local=this.regionalOptions[""],this.calendars={},this._localCals={}}function i(e,t,r,n){if(this._calendar=e,this._year=t,this._month=r,this._day=n,0===this._calendar._validateLevel&&!this._calendar.isValid(this._year,this._month,this._day))throw(c.local.invalidDate||c.regionalOptions[""].invalidDate).replace(/\{0\}/,this._calendar.local.name)}function o(e,t){return"000000".substring(0,t-(e=""+e).length)+e}function l(){this.shortYearCutoff="+10"}function s(e){this.local=this.regionalOptions[e]||this.regionalOptions[""]}n(a.prototype,{instance:function(e,t){e=(e||"gregorian").toLowerCase(),t=t||"";var r=this._localCals[e+"-"+t];if(!r&&this.calendars[e]&&(r=new this.calendars[e](t),this._localCals[e+"-"+t]=r),!r)throw(this.local.invalidCalendar||this.regionalOptions[""].invalidCalendar).replace(/\{0\}/,e);return r},newDate:function(e,t,r,n,a){return(n=(null!=e&&e.year?e.calendar():"string"==typeof n?this.instance(n,a):n)||this.instance()).newDate(e,t,r)},substituteDigits:function(e){return function(t){return(t+"").replace(/[0-9]/g,(function(t){return e[t]}))}},substituteChineseDigits:function(e,t){return function(r){for(var n="",a=0;r>0;){var i=r%10;n=(0===i?"":e[i]+t[a])+n,a++,r=Math.floor(r/10)}return 0===n.indexOf(e[1]+t[1])&&(n=n.substr(1)),n||e[0]}}}),n(i.prototype,{newDate:function(e,t,r){return this._calendar.newDate(null==e?this:e,t,r)},year:function(e){return 0===arguments.length?this._year:this.set(e,"y")},month:function(e){return 0===arguments.length?this._month:this.set(e,"m")},day:function(e){return 0===arguments.length?this._day:this.set(e,"d")},date:function(e,t,r){if(!this._calendar.isValid(e,t,r))throw(c.local.invalidDate||c.regionalOptions[""].invalidDate).replace(/\{0\}/,this._calendar.local.name);return this._year=e,this._month=t,this._day=r,this},leapYear:function(){return this._calendar.leapYear(this)},epoch:function(){return this._calendar.epoch(this)},formatYear:function(){return this._calendar.formatYear(this)},monthOfYear:function(){return this._calendar.monthOfYear(this)},weekOfYear:function(){return this._calendar.weekOfYear(this)},daysInYear:function(){return this._calendar.daysInYear(this)},dayOfYear:function(){return this._calendar.dayOfYear(this)},daysInMonth:function(){return this._calendar.daysInMonth(this)},dayOfWeek:function(){return this._calendar.dayOfWeek(this)},weekDay:function(){return this._calendar.weekDay(this)},extraInfo:function(){return this._calendar.extraInfo(this)},add:function(e,t){return this._calendar.add(this,e,t)},set:function(e,t){return this._calendar.set(this,e,t)},compareTo:function(e){if(this._calendar.name!==e._calendar.name)throw(c.local.differentCalendars||c.regionalOptions[""].differentCalendars).replace(/\{0\}/,this._calendar.local.name).replace(/\{1\}/,e._calendar.local.name);var t=this._year!==e._year?this._year-e._year:this._month!==e._month?this.monthOfYear()-e.monthOfYear():this._day-e._day;return 0===t?0:t<0?-1:1},calendar:function(){return this._calendar},toJD:function(){return this._calendar.toJD(this)},fromJD:function(e){return this._calendar.fromJD(e)},toJSDate:function(){return this._calendar.toJSDate(this)},fromJSDate:function(e){return this._calendar.fromJSDate(e)},toString:function(){return(this.year()<0?"-":"")+o(Math.abs(this.year()),4)+"-"+o(this.month(),2)+"-"+o(this.day(),2)}}),n(l.prototype,{_validateLevel:0,newDate:function(e,t,r){return null==e?this.today():(e.year&&(this._validate(e,t,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),r=e.day(),t=e.month(),e=e.year()),new i(this,e,t,r))},today:function(){return this.fromJSDate(new Date)},epoch:function(e){return this._validate(e,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear).year()<0?this.local.epochs[0]:this.local.epochs[1]},formatYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear);return(t.year()<0?"-":"")+o(Math.abs(t.year()),4)},monthsInYear:function(e){return this._validate(e,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear),12},monthOfYear:function(e,t){var r=this._validate(e,t,this.minDay,c.local.invalidMonth||c.regionalOptions[""].invalidMonth);return(r.month()+this.monthsInYear(r)-this.firstMonth)%this.monthsInYear(r)+this.minMonth},fromMonthOfYear:function(e,t){var r=(t+this.firstMonth-2*this.minMonth)%this.monthsInYear(e)+this.minMonth;return this._validate(e,r,this.minDay,c.local.invalidMonth||c.regionalOptions[""].invalidMonth),r},daysInYear:function(e){var t=this._validate(e,this.minMonth,this.minDay,c.local.invalidYear||c.regionalOptions[""].invalidYear);return this.leapYear(t)?366:365},dayOfYear:function(e,t,r){var n=this._validate(e,t,r,c.local.invalidDate||c.regionalOptions[""].invalidDate);return n.toJD()-this.newDate(n.year(),this.fromMonthOfYear(n.year(),this.minMonth),this.minDay).toJD()+1},daysInWeek:function(){return 7},dayOfWeek:function(e,t,r){var n=this._validate(e,t,r,c.local.invalidDate||c.regionalOptions[""].invalidDate);return(Math.floor(this.toJD(n))+2)%this.daysInWeek()},extraInfo:function(e,t,r){return this._validate(e,t,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),{}},add:function(e,t,r){return this._validate(e,this.minMonth,this.minDay,c.local.invalidDate||c.regionalOptions[""].invalidDate),this._correctAdd(e,this._add(e,t,r),t,r)},_add:function(e,t,r){if(this._validateLevel++,"d"===r||"w"===r){var n=e.toJD()+t*("w"===r?this.daysInWeek():1),a=e.calendar().fromJD(n);return this._validateLevel--,[a.year(),a.month(),a.day()]}try{var i=e.year()+("y"===r?t:0),o=e.monthOfYear()+("m"===r?t:0);a=e.day(),"y"===r?(e.month()!==this.fromMonthOfYear(i,o)&&(o=this.newDate(i,e.month(),this.minDay).monthOfYear()),o=Math.min(o,this.monthsInYear(i)),a=Math.min(a,this.daysInMonth(i,this.fromMonthOfYear(i,o)))):"m"===r&&(function(e){for(;ot-1+e.minMonth;)i++,o-=t,t=e.monthsInYear(i)}(this),a=Math.min(a,this.daysInMonth(i,this.fromMonthOfYear(i,o))));var l=[i,this.fromMonthOfYear(i,o),a];return this._validateLevel--,l}catch(s){throw this._validateLevel--,s}},_correctAdd:function(e,t,r,n){if(!(this.hasYearZero||"y"!==n&&"m"!==n||0!==t[0]&&e.year()>0==t[0]>0)){var a={y:[1,1,"y"],m:[1,this.monthsInYear(-1),"m"],w:[this.daysInWeek(),this.daysInYear(-1),"d"],d:[1,this.daysInYear(-1),"d"]}[n],i=r<0?-1:1;t=this._add(e,r*a[0]+i*a[1],a[2])}return e.date(t[0],t[1],t[2])},set:function(e,t,r){this._validate(e,this.minMonth,this.minDay,c.local.invalidDate||c.regionalOptions[""].invalidDate);var n="y"===r?t:e.year(),a="m"===r?t:e.month(),i="d"===r?t:e.day();return"y"!==r&&"m"!==r||(i=Math.min(i,this.daysInMonth(n,a))),e.date(n,a,i)},isValid:function(e,t,r){this._validateLevel++;var n=this.hasYearZero||0!==e;if(n){var a=this.newDate(e,t,this.minDay);n=t>=this.minMonth&&t-this.minMonth=this.minDay&&r-this.minDay13.5?13:1),c=a-(s>2.5?4716:4715);return c<=0&&c--,this.newDate(c,s,l)},toJSDate:function(e,t,r){var n=this._validate(e,t,r,c.local.invalidDate||c.regionalOptions[""].invalidDate),a=new Date(n.year(),n.month()-1,n.day());return a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0),a.setHours(a.getHours()>12?a.getHours()+2:0),a},fromJSDate:function(e){return this.newDate(e.getFullYear(),e.getMonth()+1,e.getDate())}});var c=e.exports=new a;c.cdate=i,c.baseCalendar=l,c.calendars.gregorian=s},4338:function(e,t,r){var n=r(6131),a=r(3489);n(a.regionalOptions[""],{invalidArguments:"Invalid arguments",invalidFormat:"Cannot format a date from another calendar",missingNumberAt:"Missing number at position {0}",unknownNameAt:"Unknown name at position {0}",unexpectedLiteralAt:"Unexpected literal at position {0}",unexpectedText:"Additional text found at end"}),a.local=a.regionalOptions[""],n(a.cdate.prototype,{formatDate:function(e,t){return"string"!=typeof e&&(t=e,e=""),this._calendar.formatDate(e||"",this,t)}}),n(a.baseCalendar.prototype,{UNIX_EPOCH:a.instance().newDate(1970,1,1).toJD(),SECS_PER_DAY:86400,TICKS_EPOCH:a.instance().jdEpoch,TICKS_PER_DAY:864e9,ATOM:"yyyy-mm-dd",COOKIE:"D, dd M yyyy",FULL:"DD, MM d, yyyy",ISO_8601:"yyyy-mm-dd",JULIAN:"J",RFC_822:"D, d M yy",RFC_850:"DD, dd-M-yy",RFC_1036:"D, d M yy",RFC_1123:"D, d M yyyy",RFC_2822:"D, d M yyyy",RSS:"D, d M yy",TICKS:"!",TIMESTAMP:"@",W3C:"yyyy-mm-dd",formatDate:function(e,t,r){if("string"!=typeof e&&(r=t,t=e,e=""),!t)return"";if(t.calendar()!==this)throw a.local.invalidFormat||a.regionalOptions[""].invalidFormat;e=e||this.local.dateFormat;for(var n,i,o,l,s=(r=r||{}).dayNamesShort||this.local.dayNamesShort,c=r.dayNames||this.local.dayNames,u=r.monthNumbers||this.local.monthNumbers,f=r.monthNamesShort||this.local.monthNamesShort,d=r.monthNames||this.local.monthNames,h=(r.calculateWeek||this.local.calculateWeek,function(t,r){for(var n=1;w+n1}),p=function(e,t,r,n){var a=""+t;if(h(e,n))for(;a.length1},x=function(e,r){var n=m(e,r),i=[2,3,n?4:2,n?4:2,10,11,20]["oyYJ@!".indexOf(e)+1],o=new RegExp("^-?\\d{1,"+i+"}"),l=t.substring(k).match(o);if(!l)throw(a.local.missingNumberAt||a.regionalOptions[""].missingNumberAt).replace(/\{0\}/,k);return k+=l[0].length,parseInt(l[0],10)},b=this,_=function(){if("function"==typeof s){m("m");var e=s.call(b,t.substring(k));return k+=e.length,e}return x("m")},w=function(e,r,n,i){for(var o=m(e,i)?n:r,l=0;l-1){h=1,p=v;for(var S=this.daysInMonth(d,h);p>S;S=this.daysInMonth(d,h))h++,p-=S}return f>-1?this.fromJD(f):this.newDate(d,h,p)},determineDate:function(e,t,r,n,a){r&&"object"!=typeof r&&(a=n,n=r,r=null),"string"!=typeof n&&(a=n,n="");var i=this;return t=t?t.newDate():null,e=null==e?t:"string"==typeof e?function(e){try{return i.parseDate(n,e,a)}catch(s){}for(var t=((e=e.toLowerCase()).match(/^c/)&&r?r.newDate():null)||i.today(),o=/([+-]?[0-9]+)\s*(d|w|m|y)?/g,l=o.exec(e);l;)t.add(parseInt(l[1],10),l[2]||"d"),l=o.exec(e);return t}(e):"number"==typeof e?isNaN(e)||e===1/0||e===-1/0?t:i.today().add(e,"d"):i.newDate(e)}})}},t={};function r(n){var a=t[n];if(void 0!==a)return a.exports;var i=t[n]={exports:{}};return e[n].call(i.exports,i,i.exports,r),i.exports}return r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r(2576)}()},e.exports=t()},4922:(e,t,r)=>{"use strict";function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}t.Z=function(e){var t=function(t){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&c(e,t)}(l,t);var r,a,o=(r=l,a=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,t=f(r);if(a){var i=f(this).constructor;e=Reflect.construct(t,arguments,i)}else e=t.apply(this,arguments);return function(e,t){if(t&&("object"===n(t)||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return u(e)}(this,e)});function l(e){var t;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,l),(t=o.call(this,e)).p=Promise.resolve(),t.resizeHandler=null,t.handlers={},t.syncWindowResize=t.syncWindowResize.bind(u(t)),t.syncEventHandlers=t.syncEventHandlers.bind(u(t)),t.attachUpdateEvents=t.attachUpdateEvents.bind(u(t)),t.getRef=t.getRef.bind(u(t)),t.handleUpdate=t.handleUpdate.bind(u(t)),t.figureCallback=t.figureCallback.bind(u(t)),t.updatePlotly=t.updatePlotly.bind(u(t)),t}return function(e,t,r){t&&s(e.prototype,t);r&&s(e,r);Object.defineProperty(e,"prototype",{writable:!1})}(l,[{key:"updatePlotly",value:function(t,r,n){var a=this;this.p=this.p.then((function(){if(!a.unmounting){if(!a.el)throw new Error("Missing element reference");return e.react(a.el,{data:a.props.data,layout:a.props.layout,config:a.props.config,frames:a.props.frames})}})).then((function(){a.unmounting||(a.syncWindowResize(t),a.syncEventHandlers(),a.figureCallback(r),n&&a.attachUpdateEvents())})).catch((function(e){a.props.onError&&a.props.onError(e)}))}},{key:"componentDidMount",value:function(){this.unmounting=!1,this.updatePlotly(!0,this.props.onInitialized,!0)}},{key:"componentDidUpdate",value:function(e){this.unmounting=!1;var t=e.frames&&e.frames.length?e.frames.length:0,r=this.props.frames&&this.props.frames.length?this.props.frames.length:0,n=!(e.layout===this.props.layout&&e.data===this.props.data&&e.config===this.props.config&&r===t),a=void 0!==e.revision,i=e.revision!==this.props.revision;(n||a&&(!a||i))&&this.updatePlotly(!1,this.props.onUpdate,!1)}},{key:"componentWillUnmount",value:function(){this.unmounting=!0,this.figureCallback(this.props.onPurge),this.resizeHandler&&p&&(window.removeEventListener("resize",this.resizeHandler),this.resizeHandler=null),this.removeUpdateEvents(),e.purge(this.el)}},{key:"attachUpdateEvents",value:function(){var e=this;this.el&&this.el.removeListener&&h.forEach((function(t){e.el.on(t,e.handleUpdate)}))}},{key:"removeUpdateEvents",value:function(){var e=this;this.el&&this.el.removeListener&&h.forEach((function(t){e.el.removeListener(t,e.handleUpdate)}))}},{key:"handleUpdate",value:function(){this.figureCallback(this.props.onUpdate)}},{key:"figureCallback",value:function(e){if("function"==typeof e){var t=this.el;e({data:t.data,layout:t.layout,frames:this.el._transitionData?this.el._transitionData._frames:null},this.el)}}},{key:"syncWindowResize",value:function(t){var r=this;p&&(this.props.useResizeHandler&&!this.resizeHandler?(this.resizeHandler=function(){return e.Plots.resize(r.el)},window.addEventListener("resize",this.resizeHandler),t&&this.resizeHandler()):!this.props.useResizeHandler&&this.resizeHandler&&(window.removeEventListener("resize",this.resizeHandler),this.resizeHandler=null))}},{key:"getRef",value:function(e){this.el=e,this.props.debug&&p&&(window.gd=this.el)}},{key:"syncEventHandlers",value:function(){var e=this;d.forEach((function(t){var r=e.props["on"+t],n=e.handlers[t],a=Boolean(n);r&&!a?e.addEventHandler(t,r):!r&&a?e.removeEventHandler(t):r&&a&&r!==n&&(e.removeEventHandler(t),e.addEventHandler(t,r))}))}},{key:"addEventHandler",value:function(e,t){this.handlers[e]=t,this.el.on(this.getPlotlyEventName(e),this.handlers[e])}},{key:"removeEventHandler",value:function(e){this.el.removeListener(this.getPlotlyEventName(e),this.handlers[e]),delete this.handlers[e]}},{key:"getPlotlyEventName",value:function(e){return"plotly_"+e.toLowerCase()}},{key:"render",value:function(){return i.default.createElement("div",{id:this.props.divId,style:this.props.style,ref:this.getRef,className:this.props.className})}}]),l}(i.Component);return t.propTypes={data:o.default.arrayOf(o.default.object),config:o.default.object,layout:o.default.object,frames:o.default.arrayOf(o.default.object),revision:o.default.number,onInitialized:o.default.func,onPurge:o.default.func,onError:o.default.func,onUpdate:o.default.func,debug:o.default.bool,style:o.default.object,className:o.default.string,useResizeHandler:o.default.bool,divId:o.default.string},d.forEach((function(e){t.propTypes["on"+e]=o.default.func})),t.defaultProps={debug:!1,useResizeHandler:!1,data:[],style:{position:"relative",display:"inline-block"}},t};var a,i=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==n(e)&&"function"!=typeof e)return{default:e};var r=l(t);if(r&&r.has(e))return r.get(e);var a={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var s=i?Object.getOwnPropertyDescriptor(e,o):null;s&&(s.get||s.set)?Object.defineProperty(a,o,s):a[o]=e[o]}a.default=e,r&&r.set(e,a);return a}(r(7294)),o=(a=r(5697))&&a.__esModule?a:{default:a};function l(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,r=new WeakMap;return(l=function(e){return e?r:t})(e)}function s(e,t){for(var r=0;r{a.d(e,{Zo:()=>m,kt:()=>N});var n=a(7294);function l(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function r(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function i(t){for(var e=1;e=0||(l[a]=t[a]);return l}(t,e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(l[a]=t[a])}return l}var p=n.createContext({}),d=function(t){var e=n.useContext(p),a=e;return t&&(a="function"==typeof t?t(e):i(i({},e),t)),a},m=function(t){var e=d(t.components);return n.createElement(p.Provider,{value:e},t.children)},s="mdxType",k={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},u=n.forwardRef((function(t,e){var a=t.components,l=t.mdxType,r=t.originalType,p=t.parentName,m=o(t,["components","mdxType","originalType","parentName"]),s=d(a),u=l,N=s["".concat(p,".").concat(u)]||s[u]||k[u]||r;return a?n.createElement(N,i(i({ref:e},m),{},{components:a})):n.createElement(N,i({ref:e},m))}));function N(t,e){var a=arguments,l=e&&e.mdxType;if("string"==typeof t||l){var r=a.length,i=new Array(r);i[0]=u;var o={};for(var p in e)hasOwnProperty.call(e,p)&&(o[p]=e[p]);o.originalType=t,o[s]="string"==typeof t?t:l,i[1]=o;for(var d=2;d{a.r(e),a.d(e,{assets:()=>p,contentTitle:()=>i,default:()=>k,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var n=a(7462),l=(a(7294),a(3905));const r={},i="ADR 0014: Signing Runtime Transactions with Hardware Wallet",o={unversionedId:"adrs/0014-runtime-signing-tx-with-hardware-wallet",id:"adrs/0014-runtime-signing-tx-with-hardware-wallet",title:"ADR 0014: Signing Runtime Transactions with Hardware Wallet",description:"Component",source:"@site/docs/adrs/0014-runtime-signing-tx-with-hardware-wallet.md",sourceDirName:"adrs",slug:"/adrs/0014-runtime-signing-tx-with-hardware-wallet",permalink:"/adrs/0014-runtime-signing-tx-with-hardware-wallet",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0014-runtime-signing-tx-with-hardware-wallet.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0013: Runtime Upgrade Improvements",permalink:"/adrs/0013-runtime-upgrades"},next:{title:"ADR 0015: Randomized Paratime Proposer Selection",permalink:"/adrs/0015-vrf-per-block-entropy"}},p={},d=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Test vectors",id:"test-vectors",level:3},{value:"Runtime transaction format",id:"runtime-transaction-format",level:3},{value:"Decision",id:"decision",level:2},{value:"APDUSPEC additions",id:"apduspec-additions",level:3},{value:"GET_ADDR_SECP256K1",id:"get_addr_secp256k1",level:4},{value:"Command",id:"command",level:5},{value:"Response",id:"response",level:5},{value:"GET_ADDR_SR25519",id:"get_addr_sr25519",level:4},{value:"Command",id:"command-1",level:5},{value:"Response",id:"response-1",level:5},{value:"SIGN_RT_ED25519",id:"sign_rt_ed25519",level:4},{value:"Command",id:"command-2",level:5},{value:"Response",id:"response-2",level:5},{value:"SIGN_RT_SECP256K1",id:"sign_rt_secp256k1",level:4},{value:"Command",id:"command-3",level:5},{value:"Response",id:"response-3",level:5},{value:"SIGN_RT_SR25519",id:"sign_rt_sr25519",level:4},{value:"Command",id:"command-4",level:5},{value:"Response",id:"response-4",level:5},{value:"Meta parameter",id:"meta-parameter",level:4},{value:"Changes to Allowance transaction",id:"changes-to-allowance-transaction",level:3},{value:"Signing general runtime transactions",id:"signing-general-runtime-transactions",level:3},{value:"Deposit",id:"deposit",level:4},{value:"Withdraw",id:"withdraw",level:4},{value:"Transfer",id:"transfer",level:4},{value:"Example",id:"example",level:4},{value:"Signing smart contract runtime transactions",id:"signing-smart-contract-runtime-transactions",level:3},{value:"Uploading smart contract",id:"uploading-smart-contract",level:4},{value:"Instantiating smart contract",id:"instantiating-smart-contract",level:4},{value:"Calling smart contract",id:"calling-smart-contract",level:4},{value:"Upgrading smart contracts",id:"upgrading-smart-contracts",level:4},{value:"Example",id:"example-1",level:4},{value:"Signing EVM runtime transactions",id:"signing-evm-runtime-transactions",level:3},{value:"Creating smart contract",id:"creating-smart-contract",level:4},{value:"Calling smart contract",id:"calling-smart-contract-1",level:4},{value:"Signing encrypted runtime transactions",id:"signing-encrypted-runtime-transactions",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"Consideration of roothash.SubmitMsg transactions",id:"consideration-of-roothashsubmitmsg-transactions",level:4},{value:"Signing contract uploads on hardware wallets",id:"signing-contract-uploads-on-hardware-wallets",level:4},{value:"Consideration of adding From screen",id:"consideration-of-adding-from-screen",level:4},{value:"References",id:"references",level:2}],m={toc:d},s="wrapper";function k(t){let{components:e,...a}=t;return(0,l.kt)(s,(0,n.Z)({},m,a,{components:e,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"adr-0014-signing-runtime-transactions-with-hardware-wallet"},"ADR 0014: Signing Runtime Transactions with Hardware Wallet"),(0,l.kt)("h2",{id:"component"},"Component"),(0,l.kt)("p",null,"Oasis SDK"),(0,l.kt)("h2",{id:"changelog"},"Changelog"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"2023-02-24:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"APDU: Define Oasis native and Ethereum-compatible address length."))),(0,l.kt)("li",{parentName:"ul"},"2023-02-09:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"Encode ",(0,l.kt)("inlineCode",{parentName:"li"},"Meta.runtime_id")," and ",(0,l.kt)("inlineCode",{parentName:"li"},"Meta.orig_to")," as Base16."),(0,l.kt)("li",{parentName:"ul"},"Change ",(0,l.kt)("inlineCode",{parentName:"li"},"SIG")," in ",(0,l.kt)("inlineCode",{parentName:"li"},"SIGN_RT_SECP256K1")," to 65-byte encoded R,S,V format."))),(0,l.kt)("li",{parentName:"ul"},"2023-01-23:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"Fix Deoxys-II field description in ",(0,l.kt)("a",{parentName:"li",href:"#signing-encrypted-runtime-transactions"},"Signing encrypted runtime\ntransactions")," section."),(0,l.kt)("li",{parentName:"ul"},"Rename ",(0,l.kt)("inlineCode",{parentName:"li"},"SIGN_PT_")," instructions in APDUSPEC to ",(0,l.kt)("inlineCode",{parentName:"li"},"SIGN_RT_")," for consistency\nwith oasis-core and oasis-sdk codebase."))),(0,l.kt)("li",{parentName:"ul"},"2023-01-03:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"Add Sapphire runtime ID and consensus address on Mainnet."))),(0,l.kt)("li",{parentName:"ul"},"2022-12-13:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"Fix Secp256k1 public key size."))),(0,l.kt)("li",{parentName:"ul"},"2022-10-12:",(0,l.kt)("ul",{parentName:"li"},(0,l.kt)("li",{parentName:"ul"},"Add Sapphire runtime ID and consensus address on Testnet,"),(0,l.kt)("li",{parentName:"ul"},"Remove redundant ",(0,l.kt)("inlineCode",{parentName:"li"},"sig_context")," from ",(0,l.kt)("inlineCode",{parentName:"li"},"Meta"),","),(0,l.kt)("li",{parentName:"ul"},"Require ",(0,l.kt)("inlineCode",{parentName:"li"},"tx.call.format")," to be either ",(0,l.kt)("inlineCode",{parentName:"li"},"0")," or ",(0,l.kt)("inlineCode",{parentName:"li"},"1"),"."))),(0,l.kt)("li",{parentName:"ul"},"2022-07-15: Initial public version")),(0,l.kt)("h2",{id:"status"},"Status"),(0,l.kt)("p",null,"Proposed"),(0,l.kt)("h2",{id:"context"},"Context"),(0,l.kt)("p",null,"This document proposes additions to APDU specification, guidelines for parsing\nruntime transactions and general UI/UX for signing them on a hardware wallet:"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#apduspec-additions"},"APDUSPEC additions")),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#changes-to-allowance-transaction"},"Changes to Allowance transaction")),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#signing-general-runtime-transactions"},"Signing general runtime transactions"),","),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#signing-smart-contract-runtime-transactions"},"Signing smart contract runtime transactions"),","),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#signing-evm-runtime-transactions"},"Signing EVM runtime transactions"),"."),(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("a",{parentName:"li",href:"#signing-encrypted-runtime-transactions"},"Signing encrypted runtime transactions"),",")),(0,l.kt)("h3",{id:"test-vectors"},"Test vectors"),(0,l.kt)("p",null,"Test vectors for all runtime transactions in this ADR can be generated by\nusing ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/tools/gen_runtime_vectors"},"gen_runtime_vectors")," tool as part of the Oasis SDK."),(0,l.kt)("h3",{id:"runtime-transaction-format"},"Runtime transaction format"),(0,l.kt)("p",null,"The format of the ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L86-L96"},"runtime transaction")," to be signed by the\nhardware wallet is the following:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-rust"},'/// Transaction.\n#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]\npub struct Transaction {\n #[cbor(rename = "v")]\n pub version: u16,\n\n pub call: Call,\n\n #[cbor(rename = "ai")]\n pub auth_info: AuthInfo,\n}\n')),(0,l.kt)("p",null,"The transaction ",(0,l.kt)("strong",{parentName:"p"},"can be signed with ",(0,l.kt)("inlineCode",{parentName:"strong"},"Secp256k1"),' ("Ethereum"), ',(0,l.kt)("inlineCode",{parentName:"strong"},"Ed25519")," key,\nor ",(0,l.kt)("inlineCode",{parentName:"strong"},"Sr25519")," key!")," Information on this along with the gas fee is stored inside\n",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L159-L173"},(0,l.kt)("inlineCode",{parentName:"a"},"ai")," field"),"."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"call")," is defined as ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L129-L146"},"follows"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-rust"},'/// Method call.\n#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]\npub struct Call {\n /// Call format.\n #[cbor(optional, default)]\n pub format: CallFormat,\n /// Method name.\n #[cbor(optional, default, skip_serializing_if = "String::is_empty")]\n pub method: String,\n /// Method body.\n pub body: cbor::Value,\n /// Read-only flag.\n ///\n /// A read-only call cannot make any changes to runtime state. Any attempt at modifying state\n /// will result in the call failing.\n #[cbor(optional, default, rename = "ro")]\n pub read_only: bool,\n}\n')),(0,l.kt)("p",null,"If ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L113-L121"},(0,l.kt)("inlineCode",{parentName:"a"},"format"))," is:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"0"),", the transaction is unencrypted,"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"1"),", the transaction is encrypted,"),(0,l.kt)("li",{parentName:"ul"},"any other, the transaction should be rejected with ",(0,l.kt)("inlineCode",{parentName:"li"},"unsupported call format"),"\nerror unless implemented outside the scope of this ADR.")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"method")," contains the name of the runtime module followed by ",(0,l.kt)("inlineCode",{parentName:"p"},".")," and the method\nname. If ",(0,l.kt)("inlineCode",{parentName:"p"},"format")," is ",(0,l.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"method")," is empty."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"body")," contains a CBOR-encoded transaction. If ",(0,l.kt)("inlineCode",{parentName:"p"},"format")," equals ",(0,l.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"body"),"\ncontains CBOR-encoded ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/callformat.rs#L7-L16"},(0,l.kt)("inlineCode",{parentName:"a"},"CallEnvelopeX25519DeoxysII")),"\nwhich contains the encrypted transaction body inside its ",(0,l.kt)("inlineCode",{parentName:"p"},"data")," field."),(0,l.kt)("h2",{id:"decision"},"Decision"),(0,l.kt)("h3",{id:"apduspec-additions"},"APDUSPEC additions"),(0,l.kt)("h4",{id:"get_addr_secp256k1"},"GET_ADDR_SECP256K1"),(0,l.kt)("h5",{id:"command"},"Command"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"CLA"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Application Identifier"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"INS"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Instruction ID"),(0,l.kt)("td",{parentName:"tr",align:null},"0x04")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P1"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Request User confirmation"),(0,l.kt)("td",{parentName:"tr",align:null},"No = 0")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Parameter 2"),(0,l.kt)("td",{parentName:"tr",align:null},"ignored")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"L"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bytes in payload"),(0,l.kt)("td",{parentName:"tr",align:null},"(depends)")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[0]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"44")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[1]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"60")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[2]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[3]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[4]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")))),(0,l.kt)("p",null,"The first three items in the derivation path are hardened."),(0,l.kt)("h5",{id:"response"},"Response"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Note"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"PK"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (33)"),(0,l.kt)("td",{parentName:"tr",align:null},"Public Key"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"ADDR"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (40)"),(0,l.kt)("td",{parentName:"tr",align:null},"Lower-case hex addr"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SW1-SW2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (2)"),(0,l.kt)("td",{parentName:"tr",align:null},"Return code"),(0,l.kt)("td",{parentName:"tr",align:null},"see list of return codes")))),(0,l.kt)("h4",{id:"get_addr_sr25519"},"GET_ADDR_SR25519"),(0,l.kt)("h5",{id:"command-1"},"Command"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"CLA"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Application Identifier"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"INS"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Instruction ID"),(0,l.kt)("td",{parentName:"tr",align:null},"0x03")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P1"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Request User confirmation"),(0,l.kt)("td",{parentName:"tr",align:null},"No = 0")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Parameter 2"),(0,l.kt)("td",{parentName:"tr",align:null},"ignored")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"L"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bytes in payload"),(0,l.kt)("td",{parentName:"tr",align:null},"(depends)")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[0]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"44")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[1]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"474")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[2]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[3]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[4]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")))),(0,l.kt)("p",null,"The first three items in the derivation path are hardened."),(0,l.kt)("h5",{id:"response-1"},"Response"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Note"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"PK"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (32)"),(0,l.kt)("td",{parentName:"tr",align:null},"Public Key"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"ADDR"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (46)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bech32 addr"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SW1-SW2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (2)"),(0,l.kt)("td",{parentName:"tr",align:null},"Return code"),(0,l.kt)("td",{parentName:"tr",align:null},"see list of return codes")))),(0,l.kt)("h4",{id:"sign_rt_ed25519"},"SIGN_RT_ED25519"),(0,l.kt)("h5",{id:"command-2"},"Command"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"CLA"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Application Identifier"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"INS"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Instruction ID"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P1"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Payload desc"),(0,l.kt)("td",{parentName:"tr",align:null},"0 = init")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"1 = add")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"2 = last")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"----"),(0,l.kt)("td",{parentName:"tr",align:null},"not used")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"L"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bytes in payload"),(0,l.kt)("td",{parentName:"tr",align:null},"(depends)")))),(0,l.kt)("p",null,"The first packet/chunk includes only the derivation path."),(0,l.kt)("p",null,"All other packets/chunks should contain message to sign."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"First Packet")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[0]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"44")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[1]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"474")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[2]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[3]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[4]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")))),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Other Chunks/Packets")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Data"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes..."),(0,l.kt)("td",{parentName:"tr",align:null},"Meta+Message"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("p",null,"Data is defined as:"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Meta"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR metadata"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Message"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR data to sign"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("h5",{id:"response-2"},"Response"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Note"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SIG"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (64)"),(0,l.kt)("td",{parentName:"tr",align:null},"Signature"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SW1-SW2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (2)"),(0,l.kt)("td",{parentName:"tr",align:null},"Return code"),(0,l.kt)("td",{parentName:"tr",align:null},"see list of return codes")))),(0,l.kt)("h4",{id:"sign_rt_secp256k1"},"SIGN_RT_SECP256K1"),(0,l.kt)("h5",{id:"command-3"},"Command"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"CLA"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Application Identifier"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"INS"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Instruction ID"),(0,l.kt)("td",{parentName:"tr",align:null},"0x07")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P1"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Payload desc"),(0,l.kt)("td",{parentName:"tr",align:null},"0 = init")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"1 = add")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"2 = last")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"----"),(0,l.kt)("td",{parentName:"tr",align:null},"not used")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"L"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bytes in payload"),(0,l.kt)("td",{parentName:"tr",align:null},"(depends)")))),(0,l.kt)("p",null,"The first packet/chunk includes only the derivation path."),(0,l.kt)("p",null,"All other packets/chunks should contain message to sign."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"First Packet")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[0]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"44")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[1]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"60")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[2]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[3]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[4]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")))),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Other Chunks/Packets")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Data"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes..."),(0,l.kt)("td",{parentName:"tr",align:null},"Meta+Message"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("p",null,"Data is defined as:"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Meta"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR metadata"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Message"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR data to sign"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("h5",{id:"response-3"},"Response"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Note"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SIG"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (65)"),(0,l.kt)("td",{parentName:"tr",align:null},"Signature"),(0,l.kt)("td",{parentName:"tr",align:null},"R,S,V bigendian integers")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SW1-SW2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (2)"),(0,l.kt)("td",{parentName:"tr",align:null},"Return code"),(0,l.kt)("td",{parentName:"tr",align:null},"see list of return codes")))),(0,l.kt)("h4",{id:"sign_rt_sr25519"},"SIGN_RT_SR25519"),(0,l.kt)("h5",{id:"command-4"},"Command"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"CLA"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Application Identifier"),(0,l.kt)("td",{parentName:"tr",align:null},"0x05")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"INS"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Instruction ID"),(0,l.kt)("td",{parentName:"tr",align:null},"0x06")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P1"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Payload desc"),(0,l.kt)("td",{parentName:"tr",align:null},"0 = init")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"1 = add")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null}),(0,l.kt)("td",{parentName:"tr",align:null},"2 = last")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"P2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"----"),(0,l.kt)("td",{parentName:"tr",align:null},"not used")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"L"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (1)"),(0,l.kt)("td",{parentName:"tr",align:null},"Bytes in payload"),(0,l.kt)("td",{parentName:"tr",align:null},"(depends)")))),(0,l.kt)("p",null,"The first packet/chunk includes only the derivation path."),(0,l.kt)("p",null,"All other packets/chunks should contain message to sign."),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"First Packet")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[0]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"44")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[1]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"474")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[2]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[3]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Path","[4]"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (4)"),(0,l.kt)("td",{parentName:"tr",align:null},"Derivation Path Data"),(0,l.kt)("td",{parentName:"tr",align:null},"?")))),(0,l.kt)("p",null,(0,l.kt)("em",{parentName:"p"},"Other Chunks/Packets")),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Data"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes..."),(0,l.kt)("td",{parentName:"tr",align:null},"Meta+Message"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("p",null,"Data is defined as:"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Expected"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Meta"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR metadata"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"Message"),(0,l.kt)("td",{parentName:"tr",align:null},"bytes.."),(0,l.kt)("td",{parentName:"tr",align:null},"CBOR data to sign"),(0,l.kt)("td",{parentName:"tr",align:null})))),(0,l.kt)("h5",{id:"response-4"},"Response"),(0,l.kt)("table",null,(0,l.kt)("thead",{parentName:"table"},(0,l.kt)("tr",{parentName:"thead"},(0,l.kt)("th",{parentName:"tr",align:null},"Field"),(0,l.kt)("th",{parentName:"tr",align:null},"Type"),(0,l.kt)("th",{parentName:"tr",align:null},"Content"),(0,l.kt)("th",{parentName:"tr",align:null},"Note"))),(0,l.kt)("tbody",{parentName:"table"},(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SIG"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (64)"),(0,l.kt)("td",{parentName:"tr",align:null},"Signature"),(0,l.kt)("td",{parentName:"tr",align:null})),(0,l.kt)("tr",{parentName:"tbody"},(0,l.kt)("td",{parentName:"tr",align:null},"SW1-SW2"),(0,l.kt)("td",{parentName:"tr",align:null},"byte (2)"),(0,l.kt)("td",{parentName:"tr",align:null},"Return code"),(0,l.kt)("td",{parentName:"tr",align:null},"see list of return codes")))),(0,l.kt)("h4",{id:"meta-parameter"},"Meta parameter"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"Meta")," is a CBOR-encoded string \u2192 string map with the following fields:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"runtime_id"),": Base16-encoded ",(0,l.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/runtime/identifiers.md"},"runtime ID")," (64-byte string)"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"chain_context"),": ",(0,l.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/genesis.md#genesis-documents-hash"},"chain ID")," (64-byte string)"),(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("inlineCode",{parentName:"li"},"orig_to")," (optional): Base16-encoded ethereum destination address (40-byte\nstring)")),(0,l.kt)("h3",{id:"changes-to-allowance-transaction"},"Changes to Allowance transaction"),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/services/staking.md#allow"},(0,l.kt)("inlineCode",{parentName:"a"},"staking.Allow"))," transaction already exists on the consensus layer. We propose\nthe following improvement to the UI:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To > | < Amount > | < Fee > | < Gas limit > | < Network > | < > | < |\n| Allowance | | ROSE +- | ROSE | | | APPROVE | REJECT |\n| | | | | | | | |\n")),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"IMPROVEMENT:")," The hardware wallet renders the\nfollowing literals in place of ",(0,l.kt)("inlineCode",{parentName:"p"},"TO")," for specific ",(0,l.kt)("inlineCode",{parentName:"p"},"NETWORK")," and addresses:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qrnu9yhwzap7rqh6tdcdcpz0zf86hwhycchkhvt8")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Cipher")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qqdn25n5a2jtet2s5amc7gmchsqqgs4j0qcg5k0t")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Cipher")),(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qzvlg0grjxwgjj58tx2xvmv26era6t2csqn22pte")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Emerald")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qr629x0tg9gm5fyhedgs9lw5eh3d8ycdnsxf0run")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Emerald")),(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qrd3mnzhhgst26hsp96uf45yhq6zlax0cuzdgcfc")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Sapphire")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, To: ",(0,l.kt)("inlineCode",{parentName:"li"},"oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Sapphire"))),(0,l.kt)("p",null,"For more information on how the addresses above are derived from the runtime ID\ncheck the ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/services/staking.md#runtime-accounts"},"runtime accounts")," section."),(0,l.kt)("h3",{id:"signing-general-runtime-transactions"},"Signing general runtime transactions"),(0,l.kt)("h4",{id:"deposit"},"Deposit"),(0,l.kt)("p",null,"We propose the following UI for ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/consensus_accounts/types.rs#L4-L13"},(0,l.kt)("inlineCode",{parentName:"a"},"consensus.Deposit"))," runtime transaction:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Deposit | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"MIXED_TO")," can either be ",(0,l.kt)("inlineCode",{parentName:"p"},"oasis1")," or the Ethereum's ",(0,l.kt)("inlineCode",{parentName:"p"},"0x")," address. If ",(0,l.kt)("inlineCode",{parentName:"p"},"Meta"),"\ndoes not contain ",(0,l.kt)("inlineCode",{parentName:"p"},"orig_to")," field, render the ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.to")," value in\n",(0,l.kt)("inlineCode",{parentName:"p"},"oasis1")," format in place of ",(0,l.kt)("inlineCode",{parentName:"p"},"MIXED_TO"),". If ",(0,l.kt)("inlineCode",{parentName:"p"},"Meta.orig_to")," is set,\nthen:"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},"Check that the ethereum address stored in ",(0,l.kt)("inlineCode",{parentName:"li"},"orig_to")," field maps to the\nnative address in ",(0,l.kt)("inlineCode",{parentName:"li"},"tx.call.body.to")," according to ",(0,l.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/types/address.go#L135-L142"},"the reference\nimplementation of the mapping"),"."),(0,l.kt)("li",{parentName:"ol"},"Render ",(0,l.kt)("inlineCode",{parentName:"li"},"orig_to")," value in ",(0,l.kt)("inlineCode",{parentName:"li"},"0x")," format in place of ",(0,l.kt)("inlineCode",{parentName:"li"},"MIXED_TO"),".")),(0,l.kt)("p",null,"In addition, if ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.to")," is empty, then the deposit is made to the\nsigner's account inside the runtime. In this case ",(0,l.kt)("inlineCode",{parentName:"p"},"Self")," literal is rendered in\nplace of ",(0,l.kt)("inlineCode",{parentName:"p"},"MIXED_TO"),"."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"AMOUNT")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"FEE")," show the amount of tokens transferred in the transaction and\nthe transaction fee. The number must be formatted according to the number of\ndecimal places and showing a corresponding symbol ",(0,l.kt)("inlineCode",{parentName:"p"},"SYM")," beside. These are\ndetermined by the following mapping hardcoded in the hardware wallet:"),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"(Network, Runtime ID, Denomination) \u2192 (Number of decimals, SYM)")),(0,l.kt)("p",null,"Denomination information is stored in ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.part.body.amount[1]")," or\n",(0,l.kt)("inlineCode",{parentName:"p"},"tx.ai.fee.amount[1]")," for the tokens transferred in the transaction or the fee\nrespectively. Empty Denomination is valid and signifies the native token\nfor the known networks and runtime IDs (see below)."),(0,l.kt)("p",null,"The hardware wallet should have at least the following mappings hardcoded:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},'Network: Mainnet, runtime ID: Cipher, Denomination: "" \u2192 9, ',(0,l.kt)("inlineCode",{parentName:"li"},"ROSE")),(0,l.kt)("li",{parentName:"ul"},'Network: Testnet, runtime ID: Cipher, Denomination: "" \u2192 9, ',(0,l.kt)("inlineCode",{parentName:"li"},"TEST")),(0,l.kt)("li",{parentName:"ul"},'Network: Mainnet, runtime ID: Emerald, Denomination: "" \u2192 18, ',(0,l.kt)("inlineCode",{parentName:"li"},"ROSE")),(0,l.kt)("li",{parentName:"ul"},'Network: Testnet, runtime ID: Emerald, Denomination: "" \u2192 18, ',(0,l.kt)("inlineCode",{parentName:"li"},"TEST")),(0,l.kt)("li",{parentName:"ul"},'Network: Mainnet, runtime ID: Sapphire, Denomination: "" \u2192 18, ',(0,l.kt)("inlineCode",{parentName:"li"},"ROSE")),(0,l.kt)("li",{parentName:"ul"},'Network: Testnet, runtime ID: Sapphire, Denomination: "" \u2192 18, ',(0,l.kt)("inlineCode",{parentName:"li"},"TEST"))),(0,l.kt)("p",null,"If the lookup fails, the following policy should be respected:"),(0,l.kt)("ol",null,(0,l.kt)("li",{parentName:"ol"},(0,l.kt)("inlineCode",{parentName:"li"},"SYM")," is rendered as empty string."),(0,l.kt)("li",{parentName:"ol"},"The number of decimals is 18, if runtime ID matches any Emerald or Sapphire\nruntime on any network."),(0,l.kt)("li",{parentName:"ol"},"Otherwise, the number of decimals is 9.")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"RUNTIME")," shows the 32-byte hex encoded runtime ID stored in ",(0,l.kt)("inlineCode",{parentName:"p"},"Meta.runtime_id"),".\nIf ",(0,l.kt)("inlineCode",{parentName:"p"},"NETWORK")," matches Mainnet or Testnet, then human-readable version of\n",(0,l.kt)("inlineCode",{parentName:"p"},"RUNTIME")," is shown:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000e199119c992377cb")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Cipher")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"0000000000000000000000000000000000000000000000000000000000000000")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Cipher")),(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000e2eaa99fc008f87f")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Emerald")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"00000000000000000000000000000000000000000000000072c8215e60d5bca7")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Emerald")),(0,l.kt)("li",{parentName:"ul"},"Network: Mainnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000f80306c9858e7279")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Sapphire")),(0,l.kt)("li",{parentName:"ul"},"Network: Testnet, runtime ID: ",(0,l.kt)("inlineCode",{parentName:"li"},"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c")," \u2192 ",(0,l.kt)("inlineCode",{parentName:"li"},"Sapphire"))),(0,l.kt)("p",null,(0,l.kt)("strong",{parentName:"p"},"SIGNATURE CONTEXT COMPUTATION:")," ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/crypto.md#chain-domain-separation"},"Chain domain separation")," context\nfor ",(0,l.kt)("strong",{parentName:"p"},"runtime")," transactions beginning with\n",(0,l.kt)("inlineCode",{parentName:"p"},"oasis-runtime-sdk/tx: v0 for chain ")," and followed by the hash derived from\n",(0,l.kt)("inlineCode",{parentName:"p"},"Meta.runtime_id")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"Meta.chain_context"),". See ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/crypto/signature/context.go"},"golang implementation")," for the reference implementation."),(0,l.kt)("h4",{id:"withdraw"},"Withdraw"),(0,l.kt)("p",null,"We propose the following UI for ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/consensus_accounts/types.rs#L15-L23"},(0,l.kt)("inlineCode",{parentName:"a"},"consensus.Withdraw"))," method:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Withdraw | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n")),(0,l.kt)("p",null,"If ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.to")," is empty, then the withdrawal is made to the signer's\nconsensus account. In this case ",(0,l.kt)("inlineCode",{parentName:"p"},"Self")," literal is rendered in\nplace of ",(0,l.kt)("inlineCode",{parentName:"p"},"TO"),"."),(0,l.kt)("h4",{id:"transfer"},"Transfer"),(0,l.kt)("p",null,"We propose the following UI for the ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/accounts/types.rs#L8-L13"},(0,l.kt)("inlineCode",{parentName:"a"},"accounts.Transfer"))," method:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Transfer | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n")),(0,l.kt)("h4",{id:"example"},"Example"),(0,l.kt)("p",null,"The user wants to deposit 100 ROSE to\n",(0,l.kt)("inlineCode",{parentName:"p"},"0xDce075E1C39b1ae0b75D554558b6451A226ffe00")," account on Emerald on the Mainnet.\nFirst they sign the deposit allowance transaction for Emerald."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To > | < Amount > | < Gas limit > | < Fee > | < Network > | < > | < |\n| Allowance | Emerald | ROSE +100.0 | 1277 | ROSE 0.0 | Mainnet | APPROVE | REJECT |\n| | Mainnet | | | | | | |\n")),(0,l.kt)("p",null,"Next, they sign the runtime deposit transaction."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/2) > | < To (2/2) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Deposit | 0xDce075E1C39b1 | 451A226ffe00 | ROSE 100.0 | ROSE 0.0 | 11310 | Mainnet | Emerald | APPROVE | REJECT |\n| (ParaTime) | ae0b75D554558b6 | | | | | | | | |\n")),(0,l.kt)("p",null,"Then, they transfer some tokens to another account inside the runtime:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/2) > | < To (2/2) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Transfer | oasis1qpupfu7e2n | m8anj64ytrayne | ROSE 10.0 | ROSE 0.00015 | 11311 | Mainnet | Emerald | APPROVE | REJECT |\n| (ParaTime) | 6pkezeaw0yhj8mce | | | | | | | | |\n")),(0,l.kt)("p",null,"Finally, the user withdraws the remainder of tokens back to the Mainnet."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Type > | < To (1/2) > | < To (2/2) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Withdraw | oasis1qrec770vre | 504k68svq7kzve | ROSE 99.9997 | ROSE 0.00015 | 11311 | Mainnet | Emerald | APPROVE | REJECT |\n| (ParaTime) | k0a9a5lcrv0zvt22 | | | | | | | | |\n")),(0,l.kt)("h3",{id:"signing-smart-contract-runtime-transactions"},"Signing smart contract runtime transactions"),(0,l.kt)("h4",{id:"uploading-smart-contract"},"Uploading smart contract"),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L99-L110"},(0,l.kt)("inlineCode",{parentName:"a"},"contracts.Upload"))," method will not be signed by the hardware wallet\nbecause the size of the Wasm byte code to sign may easily exceed the maximum\nsize of the available encrypted memory."),(0,l.kt)("h4",{id:"instantiating-smart-contract"},"Instantiating smart contract"),(0,l.kt)("p",null,"We propose the following UI for the ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L119-L133"},(0,l.kt)("inlineCode",{parentName:"a"},"contracts.Instantiate"))," method:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Code ID > | < Amount (1/1) > | < Data (1/1) > | ... | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Instantiation | | | | ... | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | ... | | | | | | |\n")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"DATA")," is a JSON-like representation of ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data"),", if the latter\nis a CBOR-encoded map. If ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data")," is empty or not present,\nthen Data screen is hidden. If ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data")," is in some other format,\nrequire ",(0,l.kt)("strong",{parentName:"p"},"blind signing")," mode and hide Data screen."),(0,l.kt)("p",null,"Blind signing means that the user does not see all contract information. In some\ncases - as is this - not even the amount or the contract address! ",(0,l.kt)("strong",{parentName:"p"},"When\nsigning blindly, it is crucial that the user trusts the client application that\nit generated a non-malicious transaction!")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"AMOUNT...")," is the amount of tokens sent. Contract SDK supports sending\nmultiple tokens at once, each with its own denomination symbol. The hardware\nwallet should render all of them, one per page. For rendering rules of each\n",(0,l.kt)("inlineCode",{parentName:"p"},"AMOUNT")," consult the ",(0,l.kt)("a",{parentName:"p",href:"#deposit"},"runtime deposit")," behavior."),(0,l.kt)("p",null,"There can be multiple Data screens Data 1, Data 2, ..., Data N for each key in\n",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data")," map. ",(0,l.kt)("inlineCode",{parentName:"p"},"DATA")," can be one of the following types:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"string"),(0,l.kt)("li",{parentName:"ul"},"number (integer, float)"),(0,l.kt)("li",{parentName:"ul"},"array"),(0,l.kt)("li",{parentName:"ul"},"map"),(0,l.kt)("li",{parentName:"ul"},"boolean"),(0,l.kt)("li",{parentName:"ul"},"null")),(0,l.kt)("p",null,"Strings are rendered as UTF-8 strings and the following characters need to be\nescaped: ",(0,l.kt)("inlineCode",{parentName:"p"},":"),", ",(0,l.kt)("inlineCode",{parentName:"p"},","),", ",(0,l.kt)("inlineCode",{parentName:"p"},"}"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"]"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"\u2026"),"."),(0,l.kt)("p",null,"Numbers are rendered in standard general base-10 encoding. Floats use decimal\nperiod and should be rendered with at least one decimal."),(0,l.kt)("p",null,"For strings and numbers that cannot fit a single page, a pagination is\nactivated."),(0,l.kt)("p",null,"Boolean and null values are rendered as ",(0,l.kt)("inlineCode",{parentName:"p"},"true"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"false")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"null")," respectively\non a single page."),(0,l.kt)("p",null,"Array and map is rendered in form ",(0,l.kt)("inlineCode",{parentName:"p"},"VAL1,VAL2,...")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"KEY1:VAL1,KEY1:VAL1,..."),"\nrespectively. For security, ",(0,l.kt)("strong",{parentName:"p"},"the items of the map must be sorted\nlexicographically by KEY"),". ",(0,l.kt)("inlineCode",{parentName:"p"},"KEY")," and ",(0,l.kt)("inlineCode",{parentName:"p"},"VAL")," can be of any supported type. If it\nis a map or array it is rendered as ",(0,l.kt)("inlineCode",{parentName:"p"},"{DATA}")," or ",(0,l.kt)("inlineCode",{parentName:"p"},"[DATA]")," respectively\nto avoid disambiguation. Otherwise, it is just ",(0,l.kt)("inlineCode",{parentName:"p"},"DATA"),"."),(0,l.kt)("p",null,"If the content of an array or a map cannot fit a single page, no pagination\nis introduced. Instead, the content is trimmed, ellipsis ",(0,l.kt)("inlineCode",{parentName:"p"},"\u2026")," is appended at\nthe end and the screen ",(0,l.kt)("strong",{parentName:"p"},"becomes confirmable"),". If the user double-clicks it, a\nsubscreen for item ",(0,l.kt)("inlineCode",{parentName:"p"},"n")," of an array or a map is shown. There is one subscreen\nfor each item of the array or a map of size ",(0,l.kt)("inlineCode",{parentName:"p"},"N")," titled Data n.1,\nData n.2, ..., Data n.N which renders the item ",(0,l.kt)("inlineCode",{parentName:"p"},"n")," as\n",(0,l.kt)("inlineCode",{parentName:"p"},"DATA")," for an array item or ",(0,l.kt)("inlineCode",{parentName:"p"},"DATA:DATA")," for a map item:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Data 1.1 (1/1) > | < Data 1.2 (1/1) | < Data 1.3 (1/1) | ... | < |\n| | | | | BACK |\n| | | | | |\n")),(0,l.kt)("p",null,"The recursive approach described above allows user to browse through a complete\ntree of data stracture (typically a request name along with the arguments) by\nusing \u2b05\ufe0f and \u27a1\ufe0f buttons, visit a child by double-clicking and returning to a\nparent node by confirming the ",(0,l.kt)("em",{parentName:"p"},"BACK")," screen."),(0,l.kt)("p",null,"The maximum string length, the length of the array, the depth of a map must\nhave reasonable limits on the hardware wallet. If that limit is exceeded, the\nhardware wallet displays an error on the initial screen. Then, if the user\nstill wants to sign such a transaction, they need to enable ",(0,l.kt)("strong",{parentName:"p"},"blind signing"),"."),(0,l.kt)("p",null,"The following UI is shown when blind-signing a non-encrypted transaction due\nto too complex function parameters."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < BLIND > | < Instance ID (1/1) > | < Amount > | < Fee > | < Network > | < ParaTime > | < > | < |\n| Instantiation | SIGNING! | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n")),(0,l.kt)("h4",{id:"calling-smart-contract"},"Calling smart contract"),(0,l.kt)("p",null,"The hardware wallet should show details of the runtime transaction to the\nuser, when this is possible. We propose the following UI for the\n",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L142-L153"},(0,l.kt)("inlineCode",{parentName:"a"},"contracts.Call"))," method:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Instance ID > | < Amount (1/1) > | < Data (1/1) > | ... | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | | | | ... | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | ... | | | | | | |\n")),(0,l.kt)("p",null,"The Data screen behavior is the same as for\n",(0,l.kt)("a",{parentName:"p",href:"#instantiating-smart-contract"},(0,l.kt)("inlineCode",{parentName:"a"},"contracts.Instantiate"))," transaction."),(0,l.kt)("h4",{id:"upgrading-smart-contracts"},"Upgrading smart contracts"),(0,l.kt)("p",null,"We propose the following UI for the ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L160-L174"},(0,l.kt)("inlineCode",{parentName:"a"},"contracts.Upgrade"))," method:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Instance ID (1/1) > | < Amount (1/1) > | < New Code ID (1/1) > | < Data (1/1) > | ... | < ParaTime > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Upgrade | | | | | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | | | | | |\n")),(0,l.kt)("p",null,"The Data screen behavior is the same as for the\n",(0,l.kt)("a",{parentName:"p",href:"#instantiating-smart-contract"},"contract instantiate")," transaction."),(0,l.kt)("h4",{id:"example-1"},"Example"),(0,l.kt)("p",null,"To upload, instantiate and call the ",(0,l.kt)("a",{parentName:"p",href:"/dapp/cipher/hello-world#deploying-the-contract"},"hello world example")," running on Testnet\nCipher the user first signs the contract upload transaction with a file-based\ned25519 keypair. The user obtains the ",(0,l.kt)("inlineCode",{parentName:"p"},"Code ID")," 3 for the uploaded contract."),(0,l.kt)("p",null,"Next, the user instantiates the contract and obtains the ",(0,l.kt)("inlineCode",{parentName:"p"},"Instance ID")," 2."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Code ID > | < Amount > | < Data > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Instantiation | 3 | ROSE 0.0 | {instantiate:{init | ROSE 0.0 | 1348 | Mainnet | Cipher | APPROVE | REJECT |\n| (ParaTime) | | | ial_counter:42}} | | | | | | | |\n")),(0,l.kt)("p",null,"Finally, they perform a call to ",(0,l.kt)("inlineCode",{parentName:"p"},"say_hello")," function on a smart contract\npassing the ",(0,l.kt)("inlineCode",{parentName:"p"},'{"who":"me"}')," object as a function argument."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Instance ID > | < Amount > | < Data > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | 2 | ROSE 0.0 | {say_hello:{who:me | ROSE 0.0 | 1283 | Mainnet | Cipher | APPROVE | REJECT |\n| (ParaTime) | | | }} | | | | | | |\n")),(0,l.kt)("p",null,"For a complete example, the user can provide a more complex object:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-json"},'{\n "who": {\n "username": "alice",\n "client_secret": "e5868ebb4445fc2ad9f949956c1cb9ddefa0d421",\n "last_logins": [1646835046, 1615299046, 1583763046, 1552140646],\n "redirect": null\n }\n}\n')),(0,l.kt)("p",null,"In this case the hardware wallet renders the following UI."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < Instance ID > | < Amount > | < Data > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | 2 | ROSE 0.0 | {say_hello:{who:{u | ROSE 0.15 | 1283 | Mainnet | Cipher | APPROVE | REJECT |\n| (ParaTime) | | | sername:alice,cli\u2026 | | | | | | |\n\n V V\n\n | Data 1 > | < |\n | say_hello:{who:{us | BACK |\n | ername:alice,clie\u2026 | |\n\n V V\n\n | Data 1.1 > | < |\n | who:{username:alic | BACK |\n | e,client_secret:[\u2026 | |\n\n V V\n\n | Data 1.1.1 > | < Data 1.1.2 (1/2) > | < Data 1.1.2 (2/2) > | < Data 1.1.3 > | < Data 1.1.4 > | < |\n | username:alice | client_secret:e5868e | 1cb9ddefa0d421 | last_logins:[1646835 | redirect:null | BACK |\n | | bb4445fc2ad9f949956c | | 046,1615299046,1583\u2026 | | |\n\n V V\n\n | Data 1.1.3.1 > | < Data 1.1.3.2 > | < Data 1.1.3.3 > | < Data 1.1.3.4 | < |\n | 1646835046 | 1615299046 | 1583763046 | 1552140646 | BACK |\n | | | | | |\n")),(0,l.kt)("h3",{id:"signing-evm-runtime-transactions"},"Signing EVM runtime transactions"),(0,l.kt)("h4",{id:"creating-smart-contract"},"Creating smart contract"),(0,l.kt)("p",null,(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/evm/src/types.rs#L3-L8"},(0,l.kt)("inlineCode",{parentName:"a"},"evm.Create"))," method will not be managed by the hardware wallet because the\nsize of the EVM byte code may easily exceed the wallet's encrypted memory size."),(0,l.kt)("h4",{id:"calling-smart-contract-1"},"Calling smart contract"),(0,l.kt)("p",null,"In contrast to ",(0,l.kt)("inlineCode",{parentName:"p"},"contracts.Call"),", ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/evm/src/types.rs#L10-L16"},(0,l.kt)("inlineCode",{parentName:"a"},"evm.Call"))," method requires contract ABI and\nsupport for RLP decoding in order to extract argument names from\n",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data"),". This is outside of the scope of this ADR and the ",(0,l.kt)("strong",{parentName:"p"},"blind\nsigning"),", explicitly allowed by the user, is performed."),(0,l.kt)("p",null,"We propose the following UI:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Contract > | < BLIND > | < Tx hash (1/1) > | < Address (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | SIGNING! | |
| | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | | | |\n")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"TX_HASH")," is a hex representation of sha256 checksum of ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data"),"\nfield."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"ADDRESS")," is a hex-encoded address of the smart contract."),(0,l.kt)("h3",{id:"signing-encrypted-runtime-transactions"},"Signing encrypted runtime transactions"),(0,l.kt)("p",null,"Encrypted transactions (",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.format == 1"),") contain call data inside the\n",(0,l.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/callformat.rs#L7-L16"},"envelope's ",(0,l.kt)("inlineCode",{parentName:"a"},"data")," field")," encrypted with Deoxys-II\nephemeral key and X25519 key derivation."),(0,l.kt)("p",null,"The hardware wallet is not expected to implement any of these decryption\nschemes, neither it is safe to share the ephemeral key with anyone. Instead,\nthe user should enable ",(0,l.kt)("strong",{parentName:"p"},"blind signing")," and the hardware wallet should\nshow the hash of the encrypted call data, the public key and the nonce:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-ledger"},"| Review Encrypted > | < BLIND > | < Tx hash (1/1) > | < Public key (1/1) > | < Nonce (1/1) > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Transaction | SIGNING! | | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | | | |\n")),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"TX_HASH")," is a hex representation of sha256 checksum of ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data"),"\nfield."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"PUBLIC_KEY")," is a hex representation of the 32-byte ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.pk")," field."),(0,l.kt)("p",null,(0,l.kt)("inlineCode",{parentName:"p"},"NONCE")," is a hex representation of the 15-byte ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.nonce")," field."),(0,l.kt)("p",null,"Since the transaction stored inside the ",(0,l.kt)("inlineCode",{parentName:"p"},"tx.call.body.data")," field is encrypted,\nthere is also no way to discriminate between the transactions, for example\n",(0,l.kt)("inlineCode",{parentName:"p"},"contracts.Call"),", ",(0,l.kt)("inlineCode",{parentName:"p"},"contracts.Upgrade")," or ",(0,l.kt)("inlineCode",{parentName:"p"},"evm.Call"),"."),(0,l.kt)("h2",{id:"consequences"},"Consequences"),(0,l.kt)("h3",{id:"positive"},"Positive"),(0,l.kt)("p",null,"Users will have a similar experience for signing runtime transactions on any\nwallet implementing this ADR."),(0,l.kt)("h3",{id:"negative"},"Negative"),(0,l.kt)("p",null,"For some transactions, user will need to trust the client application and use\nblind signing."),(0,l.kt)("h3",{id:"neutral"},"Neutral"),(0,l.kt)("h4",{id:"consideration-of-roothashsubmitmsg-transactions"},"Consideration of ",(0,l.kt)("inlineCode",{parentName:"h4"},"roothash.SubmitMsg")," transactions"),(0,l.kt)("p",null,"This ADR does not propose a UI for ",(0,l.kt)("em",{parentName:"p"},"generic")," runtime calls\n(",(0,l.kt)("inlineCode",{parentName:"p"},"roothash.SubmitMsg"),", see ",(0,l.kt)("a",{parentName:"p",href:"/adrs/0011-incoming-runtime-messages"},"ADR 11"),"). The proposed design in this ADR assumes a\nnew release of the hardware wallet app each time a new runtime transaction type\nis introduced."),(0,l.kt)("h4",{id:"signing-contract-uploads-on-hardware-wallets"},"Signing contract uploads on hardware wallets"),(0,l.kt)("p",null,"In the future perhaps, if only the merkle root hash of the Wasm contract would\nbe contained in the transaction, signing such a contract could be feasible. See\nhow Ethereum 2.x contract deployment is done using this approach."),(0,l.kt)("h4",{id:"consideration-of-adding-from-screen"},"Consideration of adding ",(0,l.kt)("inlineCode",{parentName:"h4"},"From")," screen"),(0,l.kt)("p",null,"None of the proposed UIs and the existing implementation of signing the\nconsensus transactions on Ledger show ",(0,l.kt)("em",{parentName:"p"},"who")," is a signer of the transaction.\nThe signer's ",(0,l.kt)("em",{parentName:"p"},"from")," address can be extracted from\n",(0,l.kt)("inlineCode",{parentName:"p"},"tx.ai.si[0].address_spec.signature."),"\nfor oasis native address and if the signer wants to show the Ethereum address,\n",(0,l.kt)("inlineCode",{parentName:"p"},"Meta.orig_from")," should be populated and the hardware wallet should\nverify it before showing the tx."),(0,l.kt)("h2",{id:"references"},"References"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},(0,l.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-oasis/blob/master/docs/APDUSPEC.md"},"Existing APDU specification"))))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/885a74d0.cc512ea8.js b/assets/js/885a74d0.cc512ea8.js new file mode 100644 index 0000000000..8398c84aa7 --- /dev/null +++ b/assets/js/885a74d0.cc512ea8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2597],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>f});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function s(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var l=r.createContext({}),u=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},p=function(e){var n=u(e.components);return r.createElement(l.Provider,{value:n},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},m=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=u(t),m=o,f=d["".concat(l,".").concat(m)]||d[m]||c[m]||a;return t?r.createElement(f,s(s({ref:n},p),{},{components:t})):r.createElement(f,s({ref:n},p))}));function f(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var a=t.length,s=new Array(a);s[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i[d]="string"==typeof e?e:o,s[1]=i;for(var u=2;u{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>c,frontMatter:()=>a,metadata:()=>i,toc:()=>u});var r=t(7462),o=(t(7294),t(3905));const a={},s="Local Network Runner",i={unversionedId:"core/development-setup/oasis-net-runner",id:"core/development-setup/oasis-net-runner",title:"Local Network Runner",description:"In order to make development easier (and also to facilitate automated E2E",source:"@site/docs/core/development-setup/oasis-net-runner.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/oasis-net-runner",permalink:"/core/development-setup/oasis-net-runner",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/oasis-net-runner.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Running Tests",permalink:"/core/development-setup/running-tests"},next:{title:"Single Validator Node Network",permalink:"/core/development-setup/single-validator-node-network"}},l={},u=[{value:"Unsafe Non-SGX Environment",id:"unsafe-non-sgx-environment",level:2},{value:"SGX Environment",id:"sgx-environment",level:2},{value:"Common Issues",id:"common-issues",level:2},{value:"User Namespace Permission Issues",id:"user-namespace-permission-issues",level:3}],p={toc:u},d="wrapper";function c(e){let{components:n,...t}=e;return(0,o.kt)(d,(0,r.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"local-network-runner"},"Local Network Runner"),(0,o.kt)("p",null,"In order to make development easier (and also to facilitate automated E2E\ntests), the Oasis Core repository provides a utility called ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-net-runner"),"\nthat enables developers to quickly set up local networks."),(0,o.kt)("p",null,"Before proceeding, make sure to look at the ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites"},"prerequisites")," required for running\nan Oasis Core environment followed by ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/building"},"build instructions")," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."),(0,o.kt)("h2",{id:"unsafe-non-sgx-environment"},"Unsafe Non-SGX Environment"),(0,o.kt)("p",null,"To start a simple Oasis network as defined by ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-net-runner/fixtures/default.go"},"the default network fixture"),"\nrunning the ",(0,o.kt)("inlineCode",{parentName:"p"},"simple-keyvalue")," test runtime, do:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"./go/oasis-net-runner/oasis-net-runner \\\n --fixture.default.node.binary go/oasis-node/oasis-node \\\n --fixture.default.runtime.binary target/default/debug/simple-keyvalue \\\n --fixture.default.runtime.loader target/default/debug/oasis-core-runtime-loader \\\n --fixture.default.keymanager.binary target/default/debug/simple-keymanager\n")),(0,o.kt)("p",null,"Wait for the network to start, there should be messages about nodes being\nstarted and at the end the following message should appear:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'level=info module=oasis/net-runner caller=oasis.go:319 ts=2019-10-03T10:47:30.776566482Z msg="network started"\nlevel=info module=net-runner caller=root.go:145 ts=2019-10-03T10:47:30.77662061Z msg="client node socket available" path=/tmp/oasis-net-runner530668299/net-runner/network/client-0/internal.sock\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"simple-keyvalue")," runtime implements a key-value hash map in the enclave\nand supports reading, writing, and fetching string values associated with the\ngiven key. To learn how to create your own runtime, see the sources of the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue"},"simple-keyvalue example")," and ",(0,o.kt)("a",{parentName:"p",href:"/paratime/"},"Building a runtime")," chapter in the Oasis SDK."),(0,o.kt)("p",null,"Finally, to test Oasis node, we will run a test client written specifically\nfor the ",(0,o.kt)("inlineCode",{parentName:"p"},"simple-keyvalue")," runtime. The client sends a few keys with associated\nvalues and fetches them back over RPC defined in the runtime's API. Execute the\nclient as follows (substituting the socket path from your log output) in a\ndifferent terminal:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"./target/default/debug/simple-keyvalue-client \\\n --runtime-id 8000000000000000000000000000000000000000000000000000000000000000 \\\n --node-address unix:/tmp/oasis-net-runner530668299/net-runner/network/client-0/internal.sock\n")),(0,o.kt)("p",null,"By default, Oasis node is configured with a 30-second epoch, so you may\ninitially need to wait for the first epoch to pass before the test client will\nmake any progress. For more information on writing your own client, see the\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk"},"Oasis SDK"),"."),(0,o.kt)("h2",{id:"sgx-environment"},"SGX Environment"),(0,o.kt)("p",null,"To run an Oasis node under SGX follow the same steps as for non-SGX, except the\n",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-net-runner")," invocation:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"./go/oasis-net-runner/oasis-net-runner \\\n --fixture.default.tee_hardware intel-sgx \\\n --fixture.default.node.binary go/oasis-node/oasis-node \\\n --fixture.default.runtime.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keyvalue.sgxs \\\n --fixture.default.runtime.loader target/default/debug/oasis-core-runtime-loader \\\n --fixture.default.keymanager.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keymanager.sgxs\n")),(0,o.kt)("h2",{id:"common-issues"},"Common Issues"),(0,o.kt)("p",null,"If the above does not appear to work (e.g., when you run the client, it appears\nto hang and not make any progress) usually the best place to start debugging is\nlooking at the various node logs which are stored under a directory starting\nwith ",(0,o.kt)("inlineCode",{parentName:"p"},"/tmp/oasis-net-runner")," (unless overriden via ",(0,o.kt)("inlineCode",{parentName:"p"},"--basedir")," options)."),(0,o.kt)("p",null,"Specifically look at ",(0,o.kt)("inlineCode",{parentName:"p"},"node.log")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"console.log")," files located in directories\nfor each of the nodes comprising the local network."),(0,o.kt)("h3",{id:"user-namespace-permission-issues"},"User Namespace Permission Issues"),(0,o.kt)("p",null,"The Oasis Core compute nodes use ",(0,o.kt)("a",{parentName:"p",href:"/core/runtime/#runtimes"},"sandboxing")," to execute runtime binaries and\nthe sandbox implementation requires that the process is able to create\nnon-privileged user namespaces."),(0,o.kt)("p",null,"In case this is not available, the following error message may appear in\n",(0,o.kt)("inlineCode",{parentName:"p"},"console.log")," of any compute or key manager nodes:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"bwrap: No permissions to creating new namespace, likely because the kernel does\nnot allow non-privileged user namespaces. On e.g. debian this can be enabled\nwith 'sysctl kernel.unprivileged_userns_clone=1'\n")),(0,o.kt)("p",null,"In this case do as indicated in the message and run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"sysctl kernel.unprivileged_userns_clone=1\n")),(0,o.kt)("p",null,"This could also happen if you are running in a Docker container without\nspecifying additional options at startup. See the ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites#using-the-development-docker-image"},"Using the Development Docker\nImage")," section for details."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/886d3d06.d3a244a5.js b/assets/js/886d3d06.d3a244a5.js new file mode 100644 index 0000000000..e39fc37c28 --- /dev/null +++ b/assets/js/886d3d06.d3a244a5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1022],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),m=o,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||r;return n?a.createElement(f,i(i({ref:t},c),{},{components:n})):a.createElement(f,i({ref:t},c))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>r,metadata:()=>l,toc:()=>p});var a=n(7462),o=(n(7294),n(3905));const r={},i="Setup",l={unversionedId:"general/manage-tokens/cli/setup",id:"general/manage-tokens/cli/setup",title:"Setup",description:"Download and Run",source:"@site/docs/general/manage-tokens/cli/setup.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/setup",permalink:"/general/manage-tokens/cli/setup",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/setup.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{},sidebar:"general",previous:{title:"Oasis CLI",permalink:"/general/manage-tokens/cli/"},next:{title:"Network",permalink:"/general/manage-tokens/cli/network"}},s={},p=[{value:"Download and Run",id:"download-and-run",level:2},{value:"Configuration",id:"configuration",level:2},{value:"Multiple Profiles",id:"multiple-profiles",level:2},{value:"Back Up Your Wallet",id:"back-up-your-wallet",level:2}],c={toc:p},u="wrapper";function d(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"setup"},"Setup"),(0,o.kt)("h2",{id:"download-and-run"},"Download and Run"),(0,o.kt)("p",null,"Download the latest release ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/releases"},"here")," and extract it to your\nfavorite application folder."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Oasis is currently providing official amd64 for Linux and ARM builds for MacOS.\nIf you want to run it on another platform, you will have to\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli"},"build it from source"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We suggest that you update your system path to include a directory containing\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis")," binary or create a symbolic link to ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis")," in your\nsystem path, so you can access it globally.")),(0,o.kt)("p",null,"Run the Oasis CLI by typing ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},'CLI for interacting with the Oasis network\n\nUsage:\n oasis [command]\n\nAvailable Commands:\n account Account operations\n addressbook Manage addresses in the local address book\n completion Generate the autocompletion script for the specified shell\n contract WebAssembly smart contracts operations\n help Help about any command\n network Consensus layer operations\n paratime ParaTime layer operations\n transaction Raw transaction operations\n wallet Manage accounts in the local wallet\n\nFlags:\n --config string config file to use\n -h, --help help for oasis\n -v, --version version for oasis\n\nUse "oasis [command] --help" for more information about a command.\n')),(0,o.kt)("p",null,"When running the Oasis CLI for the first time, it will generate a configuration\nfile and populate it with the current Mainnet and Testnet networks. It will also\nconfigure all ",(0,o.kt)("a",{parentName:"p",href:"/dapp/"},"ParaTimes supported by the Oasis Foundation"),"."),(0,o.kt)("h2",{id:"configuration"},"Configuration"),(0,o.kt)("p",null,"The configuration folder of Oasis CLI is located:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"on Windows:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"%USERPROFILE%\\AppData\\Roaming\\oasis\\")))),(0,o.kt)("li",{parentName:"ul"},"on macOS:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"/Users/$USER/Library/Application Support/oasis/")))),(0,o.kt)("li",{parentName:"ul"},"on Linux:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"$HOME/.config/oasis/"))))),(0,o.kt)("p",null,"There, you will find ",(0,o.kt)("inlineCode",{parentName:"p"},"cli.toml")," which contains the configuration of the\nnetworks, ParaTimes and your wallet. Additionally, each file-based account in\nyour wallet will have a separate, password-encrypted JSON file in the same\nfolder named after the name of the account with the ",(0,o.kt)("inlineCode",{parentName:"p"},".wallet")," extension."),(0,o.kt)("h2",{id:"multiple-profiles"},"Multiple Profiles"),(0,o.kt)("p",null,"You can utilize multiple profiles of your Oasis CLI. To create a new profile,\nmove your existing configuration folder to another place, for example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"mv $HOME/.config/oasis $HOME/.config/oasis_dev\n")),(0,o.kt)("p",null,"Then, invoke ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis")," with arbitrary command to set up a fresh configuration\nfolder under ",(0,o.kt)("inlineCode",{parentName:"p"},"~/.config/oasis"),". For example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS \n")),(0,o.kt)("p",null,"Now you can switch between the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis_dev")," and the new profile by passing\n",(0,o.kt)("inlineCode",{parentName:"p"},"--config")," parameter pointing to ",(0,o.kt)("inlineCode",{parentName:"p"},"cli.toml")," in the desired configuration folder."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"oasis wallet list --config ~/.config/oasis_dev/cli.toml\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"ACCOUNT KIND ADDRESS\noscar file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n")),(0,o.kt)("h2",{id:"back-up-your-wallet"},"Back Up Your Wallet"),(0,o.kt)("p",null,"To back up your complete Oasis CLI configuration including your wallet, archive\nthe configuration folder containing ",(0,o.kt)("inlineCode",{parentName:"p"},"cli.toml")," and ",(0,o.kt)("inlineCode",{parentName:"p"},".wallet")," files."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8b083473.e672c389.js b/assets/js/8b083473.e672c389.js new file mode 100644 index 0000000000..58e771f93b --- /dev/null +++ b/assets/js/8b083473.e672c389.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4540],{3905:(e,t,o)=>{o.d(t,{Zo:()=>p,kt:()=>h});var n=o(7294);function a(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function r(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function i(e){for(var t=1;t=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var c=n.createContext({}),l=function(e){var t=n.useContext(c),o=t;return e&&(o="function"==typeof e?e(t):i(i({},t),e)),o},p=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var o=e.components,a=e.mdxType,r=e.originalType,c=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=l(o),m=a,h=d["".concat(c,".").concat(m)]||d[m]||u[m]||r;return o?n.createElement(h,i(i({ref:t},p),{},{components:o})):n.createElement(h,i({ref:t},p))}));function h(e,t){var o=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=o.length,i=new Array(r);i[0]=m;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[d]="string"==typeof e?e:a,i[1]=s;for(var l=2;l{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var n=o(7462),a=(o(7294),o(3905));const r={},i="RPC",s={unversionedId:"core/oasis-node/rpc",id:"core/oasis-node/rpc",title:"RPC",description:"Oasis Node exposes an RPC interface to enable external applications to query",source:"@site/docs/core/oasis-node/rpc.md",sourceDirName:"core/oasis-node",slug:"/core/oasis-node/rpc",permalink:"/core/oasis-node/rpc",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/rpc.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Oasis Node",permalink:"/core/oasis-node"},next:{title:"Metrics",permalink:"/core/oasis-node/metrics"}},c={},l=[{value:"Protocol",id:"protocol",level:2},{value:"Errors",id:"errors",level:2},{value:"Services",id:"services",level:2}],p={toc:l},d="wrapper";function u(e){let{components:t,...o}=e;return(0,a.kt)(d,(0,n.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"rpc"},"RPC"),(0,a.kt)("p",null,"Oasis Node exposes an RPC interface to enable external applications to query\ncurrent ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus")," and ",(0,a.kt)("a",{parentName:"p",href:"/core/runtime/"},"runtime")," states, ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/transactions#submission"},"submit transactions"),", etc."),(0,a.kt)("p",null,"The RPC interface is ONLY exposed via an AF_LOCAL socket called ",(0,a.kt)("inlineCode",{parentName:"p"},"internal.sock"),"\nlocated in the node's data directory. ",(0,a.kt)("strong",{parentName:"p"},"This interface should NEVER be directly\nexposed over the network as it has no authentication and allows full control,\nincluding shutdown, of a node.")),(0,a.kt)("p",null,"In order to support remote clients and different protocols (e.g. REST), a\ngateway that handles things like authentication and rate limiting should be\nused."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"An example of such a gateway is the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-rosetta-gateway"},"Oasis Core Rosetta Gateway")," which exposes\na subset of the consensus layer via the ",(0,a.kt)("a",{parentName:"p",href:"https://www.rosetta-api.org"},"Rosetta API"),".")),(0,a.kt)("h2",{id:"protocol"},"Protocol"),(0,a.kt)("p",null,"Like other parts of Oasis Core, the RPC interface exposed by Oasis Node uses the\n",(0,a.kt)("a",{parentName:"p",href:"https://grpc.io"},"gRPC protocol")," with the ",(0,a.kt)("a",{parentName:"p",href:"/core/authenticated-grpc#cbor-codec"},"CBOR codec (instead of Protocol Buffers)"),". If your\napplication is written in Go, you can use the convenience gRPC wrappers provided\nby Oasis Core to create clients. Check the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk"},"Oasis SDK")," for more information."),(0,a.kt)("p",null,"For example to create a gRPC client connected to the Oasis Node endpoint exposed\nby your local node at ",(0,a.kt)("inlineCode",{parentName:"p"},"/path/to/datadir/internal.sock")," you can do:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'import (\n // ...\n oasisGrpc "github.com/oasisprotocol/oasis-core/go/common/grpc"\n)\n\n// ...\n\nconn, err := oasisGrpc.Dial("unix:/path/to/datadir/internal.sock")\n')),(0,a.kt)("p",null,"This will automatically handle setting up the required gRPC dial options for\nsetting up the CBOR codec and error mapping interceptors. For more detail about\nthe gRPC helpers see the ",(0,a.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc"},"API documentation"),"."),(0,a.kt)("h2",{id:"errors"},"Errors"),(0,a.kt)("p",null,"We use a specific convention to provide more information about the exact error\nthat occurred when processing a gRPC request. See the ",(0,a.kt)("a",{parentName:"p",href:"/core/authenticated-grpc#errors"},"gRPC specifics")," section\nfor details."),(0,a.kt)("h2",{id:"services"},"Services"),(0,a.kt)("p",null,"We use the same service method namespacing convention as gRPC over Protocol\nBuffers. All Oasis Core services have unique identifiers starting with\n",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-core.")," followed by the service identifier. A single slash (",(0,a.kt)("inlineCode",{parentName:"p"},"/"),") is used\nas the separator in method names, e.g., ",(0,a.kt)("inlineCode",{parentName:"p"},"/oasis-core.NodeControl/IsSynced"),"."),(0,a.kt)("p",null,"The following gRPC services are exposed (with links to API documentation):"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"General"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/control/api?tab=doc#NodeController"},"Node Control")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.NodeController"),")"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"Consensus Layer"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend"},"Consensus (client subset)")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Consensus"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#LightClientBackend"},"Consensus (light client subset)")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.ConsensusLight"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Backend"},"Staking")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Staking"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Backend"},"Registry")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Registry"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/scheduler/api?tab=doc#Backend"},"Scheduler")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Scheduler"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc#Backend"},"RootHash")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.RootHash"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/governance/api?tab=doc#Backend"},"Governance")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Governance"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/beacon/api?tab=doc#Backend"},"Beacon")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Beacon"),")"))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"Runtime Layer"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/storage/api?tab=doc#Backend"},"Storage")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.Storage"),")"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/client/api?tab=doc#RuntimeClient"},"Runtime Client")," (",(0,a.kt)("inlineCode",{parentName:"li"},"oasis-core.RuntimeClient"),")")))),(0,a.kt)("p",null,"For more details about what the exposed services do see the respective\ndocumentation sections. The Go API also provides gRPC client implementations for\nall of the services which can be used after establishing a gRPC connection via\nthe internal socket (multiple clients can share the same gRPC connection). For\nexample in case of the consensus service using the connection we established in\nthe previous example:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'import (\n // ...\n consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"\n)\n\n// ...\n\ncc := consensus.NewConsensusClient(conn)\nerr := cc.SubmitTx(ctx, &tx)\n')))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8f21ad56.498c5d2f.js b/assets/js/8f21ad56.498c5d2f.js new file mode 100644 index 0000000000..fdef7a1d22 --- /dev/null +++ b/assets/js/8f21ad56.498c5d2f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7050],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>h});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},d=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},g=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),m=p(a),g=o,h=m["".concat(l,".").concat(g)]||m[g]||u[g]||r;return a?n.createElement(h,i(i({ref:t},d),{},{components:a})):n.createElement(h,i({ref:t},d))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[m]="string"==typeof e?e:o,i[1]=s;for(var p=2;p{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var n=a(7462),o=(a(7294),a(3905));const r={},i="Upgrade Log",s={unversionedId:"node/testnet/upgrade-log",id:"node/testnet/upgrade-log",title:"Upgrade Log",description:"For each upgrade of the Testnet network, we are tracking important changes for",source:"@site/docs/node/testnet/upgrade-log.md",sourceDirName:"node/testnet",slug:"/node/testnet/upgrade-log",permalink:"/node/testnet/upgrade-log",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/testnet/upgrade-log.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Testnet",permalink:"/node/testnet/"},next:{title:"Genesis Document",permalink:"/node/genesis-doc"}},l={},p=[{value:"2023-10-05 Upgrade",id:"2023-10-05-upgrade",level:2},{value:"Instructions",id:"instructions",level:3},{value:"Configuration Changes",id:"configuration-changes",level:3},{value:"State Changes",id:"state-changes",level:3},{value:"General",id:"general",level:4},{value:"Registry",id:"registry",level:4},{value:"Staking",id:"staking",level:4},{value:"Key Manager",id:"key-manager",level:4},{value:"Random Beacon",id:"random-beacon",level:4},{value:"Governance",id:"governance",level:4},{value:"Other",id:"other",level:4},{value:"2022-04-04 Upgrade",id:"2022-04-04-upgrade",level:2},{value:"Instructions",id:"instructions-1",level:3},{value:"Before Upgrade",id:"before-upgrade",level:3},{value:"2022-03-03 Upgrade",id:"2022-03-03-upgrade",level:2},{value:"Instructions",id:"instructions-2",level:3},{value:"Configuration Changes",id:"configuration-changes-1",level:3},{value:"State Changes",id:"state-changes-1",level:3},{value:"General",id:"general-1",level:3},{value:"Registry",id:"registry-1",level:3},{value:"Root Hash",id:"root-hash",level:3},{value:"Staking",id:"staking-1",level:3},{value:"Random Beacon",id:"random-beacon-1",level:3},{value:"Governance",id:"governance-1",level:3},{value:"Consensus",id:"consensus",level:3},{value:"2021-08-11 Upgrade",id:"2021-08-11-upgrade",level:2},{value:"Proposed Parameter Changes",id:"proposed-parameter-changes",level:3},{value:"Instructions - Before Upgrade System Preparation",id:"instructions---before-upgrade-system-preparation",level:3},{value:"2021-06-23 Upgrade",id:"2021-06-23-upgrade",level:2},{value:"Instructions",id:"instructions-3",level:3},{value:"Before upgrade",id:"before-upgrade-1",level:3},{value:"Extra storage requirements",id:"extra-storage-requirements",level:4},{value:"Extra memory requirements",id:"extra-memory-requirements",level:4},{value:"2021-04-13 Upgrade",id:"2021-04-13-upgrade",level:2},{value:"Instructions",id:"instructions-4",level:3},{value:"Before upgrade",id:"before-upgrade-2",level:3},{value:"2021-03-24 Upgrade",id:"2021-03-24-upgrade",level:2},{value:"Instructions",id:"instructions-5",level:3},{value:"Additional steps",id:"additional-steps",level:3}],d={toc:p},m="wrapper";function u(e){let{components:t,...a}=e;return(0,o.kt)(m,(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"upgrade-log"},"Upgrade Log"),(0,o.kt)("p",null,"For each upgrade of the Testnet network, we are tracking important changes for\nnode operators' deployments."),(0,o.kt)("p",null,"They are enumerated and explained in this document."),(0,o.kt)("h2",{id:"2023-10-05-upgrade"},"2023-10-05 Upgrade"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Note that some of the software releases mentioned below have not yet been\npublished. They are expected to become available as we get closer to the\nupgrade window.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"XXX"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2023-10-05 8:00 UTC.")),(0,o.kt)("h3",{id:"instructions"},"Instructions"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"(optional) Vote for the upgrade. On 2023-10-02, an upgrade proposal will be\nproposed which (if accepted) will schedule the upgrade on epoch ",(0,o.kt)("strong",{parentName:"li"},"XXX"),". See\nthe ",(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"Governance documentation")," for details on voting for proposals.")),(0,o.kt)("p",null,"The following steps should be performed only after the network has reached the\nupgrade epoch and has halted:"),(0,o.kt)("ol",{start:2},(0,o.kt)("li",{parentName:"ol"},"Download the Testnet genesis file published in the\n",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2023-10-05"},"Testnet 2023-10-05 release"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Testnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"XXX")," will be exported and migrated to a 23.0\ncompatible genesis file."),(0,o.kt)("p",{parentName:"admonition"},"The new genesis file will be published on the above link soon after reaching the\nupgrade epoch.")),(0,o.kt)("ol",{start:3},(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Verify the provided Testnet upgrade genesis file by comparing it to the\nlocal network state dump."),(0,o.kt)("p",{parentName:"li"},"The state changes are described in the ",(0,o.kt)("a",{parentName:"p",href:"#state-changes"},"State Changes"),"\nsection below.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Replace the old genesis file with the new Testnet genesis file.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Ensure your node will remain stopped by disabling auto-starting via your\nprocess manager (e.g., ",(0,o.kt)("a",{parentName:"p",href:"https://systemd.io/"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org/"},"Supervisor"),")")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),". This must be performed ",(0,o.kt)("em",{parentName:"p"},"before")," replacing the Oasis Node\nbinary."))),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"State of ParaTimes/runtimes is not affected by this upgrade and MUST NOT be\nwiped. Wiping state for confidential ParaTimes will prevent your compute or\nkey manager node from transitioning to the new network."),(0,o.kt)("p",{parentName:"admonition"},"Transitioning confidential ParaTimes to the new network requires local state\nthat is sealed to the CPU. This also means that bootstrapping a new node on a\nseparate CPU immediately after the network upgrade will not be possible until\nan updated ParaTime containing new trust roots is released and adopted.")),(0,o.kt)("ol",{start:7},(0,o.kt)("li",{parentName:"ol"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v23.0"},"23.0"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Oasis Core 23.0 binary in our published releases is built only for Ubuntu\n22.04. You'll have to build it yourself if you're using prior Ubuntu versions\n(or other distributions using older system libraries).")),(0,o.kt)("ol",{start:8},(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Perform any needed ",(0,o.kt)("a",{parentName:"p",href:"#configuration-changes"},"configuration changes")," described\nbelow.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"(only Web3 Gateway operators) Replace old version of Oasis Web3 Gateway with\nversion ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/emerald-web3-gateway/releases/tag/v4.0.0-rc1"},"4.0.0-rc1"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"(only Rosetta Gateway operators) Replace old version of Oasis Rosetta\nGateway with version ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v3.0.0-rc1"},"3.0.0-rc1"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Start your node and re-enable auto-starting via your process manager."))),(0,o.kt)("h3",{id:"configuration-changes"},"Configuration Changes"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"To see the full extent of the changes examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v23.0/CHANGELOG.md"},"Change Log")," of the 23.0\nrelease.")),(0,o.kt)("p",null,"The node configuration has been refactored so that everything is now configured\nvia a YAML configuration file and ",(0,o.kt)("strong",{parentName:"p"},"configuring via command-line options is no\nlonger supported"),"."),(0,o.kt)("p",null,"Some configuration options have changed and so the configuration file needs to\nbe updated. To make this step easier, a command-line tool has been provided that\nwill perform most of the changes automatically. You can run it with:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node config migrate --in config.yml --out new-config.yml\n")),(0,o.kt)("p",null,"The migration subcommand logs the various changes it makes and warns you if a\nconfig option is no longer supported, etc. At the end, any unknown sections of\nthe input config file are printed to the terminal to give you a chance to review\nthem and make manual changes if required."),(0,o.kt)("p",null,"Note that the migration subcommand does not preserve comments and order of\nsections from the input YAML config file. You should always carefully read the\noutput of this command, as well as compare the generated config file with the\noriginal before using it."),(0,o.kt)("p",null,"After you are satisfied with the new configuration file, replace the old file\nwith the new one as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"mv new-config.yml config.yml\n")),(0,o.kt)("h3",{id:"state-changes"},"State Changes"),(0,o.kt)("p",null,"The following parts of the genesis document will be updated:"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For a more detailed explanation of the parameters below, see the\n",(0,o.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"Genesis Document")," docs.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"All state changes will be done automatically with the migration command provided\nby the new version of ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node"),". It can be used as follows to derive the same\ngenesis file from an existing state dump at the correct height:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"oasis-node genesis migrate --genesis.new_chain_id testnet-2023-10-05\n"))),(0,o.kt)("h4",{id:"general"},(0,o.kt)("strong",{parentName:"h4"},"General")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"chain_id"))," will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-2023-10-05"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"halt_epoch"))," will be removed as it is no longer used."))),(0,o.kt)("h4",{id:"registry"},(0,o.kt)("strong",{parentName:"h4"},"Registry")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.prove_freshness"))," specifies the cost of the\nfreshness proof transaction. It will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"1000"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.params.gas_costs.update_keymanager"))," specifies the cost of the\nkeymanager policy update transaction. It will be removed as the parameter has\nbeen moved under ",(0,o.kt)("inlineCode",{parentName:"p"},"keymanager.params.gas_costs.update_policy"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.params.tee_features"))," specify various TEE features supported by\nthe consensus layer registry service. These will be set to the following\nvalues to activate the new features:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"tee_features": {\n "sgx": {\n "pcs": true,\n "signed_attestations": true,\n "max_attestation_age": 1200\n },\n "freshness_proofs": true\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.params.max_runtime_deployments"))," specifies the maximum number of\nruntime deployments that can be specified in the runtime descriptor. It will\nbe set to ",(0,o.kt)("inlineCode",{parentName:"p"},"5"),"."))),(0,o.kt)("h4",{id:"staking"},(0,o.kt)("strong",{parentName:"h4"},"Staking")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.commission_schedule_rules.min_commission_rate"))," specifies\nthe minimum commission rate. It will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"0")," to maintain the existing\nbehavior.")),(0,o.kt)("h4",{id:"key-manager"},(0,o.kt)("strong",{parentName:"h4"},"Key Manager")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"keymanager.params.gas_costs"))," specify the cost of key manager\ntransactions. These will be set to the following values:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"gas_costs": {\n "publish_ephemeral_secret": 1000,\n "publish_master_secret": 1000,\n "update_policy": 1000\n}\n')))),(0,o.kt)("h4",{id:"random-beacon"},(0,o.kt)("strong",{parentName:"h4"},"Random Beacon")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.base"))," is the network's starting epoch. It will be set to the epoch\nof Testnet's state dump + 1, ",(0,o.kt)("inlineCode",{parentName:"li"},"XXX"),".")),(0,o.kt)("h4",{id:"governance"},(0,o.kt)("strong",{parentName:"h4"},"Governance")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.enable_change_parameters_proposal"))," specifies whether\nparameter change governance proposals are allowed. It will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"true"),".")),(0,o.kt)("h4",{id:"other"},"Other"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"extra_data"))," will be set back to the value in the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18"},"Mainnet genesis file"),"\nto include the Oasis Network's genesis quote:"),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("em",{parentName:"p"},"\u201d"),(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F"},(0,o.kt)("em",{parentName:"a"},"Quis custodiet ipsos custodes?")),(0,o.kt)("em",{parentName:"p"},"\u201d ","[","submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:")),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n')))),(0,o.kt)("h2",{id:"2022-04-04-upgrade"},"2022-04-04 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"15056"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2022-04-04 7:45 UTC.")),(0,o.kt)("h3",{id:"instructions-1"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"See ",(0,o.kt)("a",{parentName:"p",href:"/node/testnet/upgrade-log#before-upgrade"},"Before upgrade")," section for required steps\nto be done before upgrade.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"(optional) Vote for the upgrade. On 2022-04-01, an upgrade proposal will be\nproposed which (if accepted) will schedule the upgrade on epoch ",(0,o.kt)("strong",{parentName:"p"},"15056"),".\nSee the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"Governance documentation"),"\nfor details on voting for proposals."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The upgrade proposal contains the ",(0,o.kt)("inlineCode",{parentName:"p"},'"empty"')," upgrade handler whose only purpose\nis allow specifying a no-op handler when submitting an upgrade proposal.")),(0,o.kt)("admonition",{title:"This is not dump & restore upgrade",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"For this upgrade, ",(0,o.kt)("strong",{parentName:"p"},"do NOT wipe state"),". The new Oasis Core version expects\nthe synced state using Oasis Core 22.0.x all the way until the upgrade epoch.\nRead ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"Handling Network Upgrades")," for more info.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Once reaching the designated upgrade epoch, your node will stop and needs to\nbe upgraded to Oasis Core ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1"},"22.1"),".\nAfter your node is upgraded to Oasis Core 22.1, restart it and wait for more\nthan 2/3+ of nodes by stake to do the same and the network starts again.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Testnet's genesis file and the genesis document's hash will remain the same.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"If the nodes are running any ParaTimes, make sure you upgrade to the versions\npublished on the ",(0,o.kt)("a",{parentName:"li",href:"/node/testnet/"},"Testnet network parameters page"),".")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"ParaTime binaries for the Cipher ParaTime will be published at a later time due\nto the additional offline signing step. If you are running ",(0,o.kt)("em",{parentName:"p"},"multiple")," ParaTimes\non the same node, you should ",(0,o.kt)("em",{parentName:"p"},"disable")," the Cipher ParaTime until the new version\nis published.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"If you are running a Rosetta gateway, upgrade it to version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.2.0"},"2.2.0"),".")),(0,o.kt)("h3",{id:"before-upgrade"},"Before Upgrade"),(0,o.kt)("p",null,"This upgrade will upgrade ",(0,o.kt)("strong",{parentName:"p"},"Oasis Core")," to ",(0,o.kt)("strong",{parentName:"p"},"version ",(0,o.kt)("a",{parentName:"strong",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1"},"22.1"))," which ",(0,o.kt)("strong",{parentName:"p"},"no longer\nallows running Oasis Node")," (i.e. the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary) ",(0,o.kt)("strong",{parentName:"p"},"as root"),"\n(effective user ID of 0)."),(0,o.kt)("p",null,'Running network accessible services as the root user is extremely bad for\nsystem security as a general rule. While it would be "ok" if we could drop\nprivileges, ',(0,o.kt)("inlineCode",{parentName:"p"},"syscall.AllThreadsSyscall")," does not work if the binary uses ",(0,o.kt)("inlineCode",{parentName:"p"},"cgo"),"\nat all."),(0,o.kt)("p",null,"Nothing in Oasis Node will ever require elevated privileges.\nAttempting to run the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," process as the root user will now terminate\nimmediately on startup."),(0,o.kt)("p",null,"While there may be specific circumstances where it is safe to run network\nservices with the effective user ID set to 0, the overwhelming majority of cases\nwhere this is done is a misconfiguration."),(0,o.kt)("p",null,"If the previous behavior is required, the binary must be run in unsafe/debug\nmode (via the intentionally undocumented flag), and ",(0,o.kt)("inlineCode",{parentName:"p"},"debug.allow_root")," must also\nbe set."),(0,o.kt)("h2",{id:"2022-03-03-upgrade"},"2022-03-03 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"14209."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2022-03-03 12:45 UTC.")),(0,o.kt)("h3",{id:"instructions-2"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"(optional) Vote for the upgrade. On 2022-03-02, an upgrade proposal will be proposed which (if accepted) will schedule the upgrade on epoch ",(0,o.kt)("strong",{parentName:"li"},"14209.")," See the ",(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"Governance documentation")," for details on voting for proposals.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The upgrade proposal contains a non-existing upgrade handler and will be used to\ncoordinate the network shutdown, the rest of the upgrade is manual.")),(0,o.kt)("p",null,"The following steps should be performed only after the network has reached the\nupgrade network and has halted:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Download the Testnet genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2022-03-03"},"Testnet 2022-03-03 release"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Testnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"14209")," will be exported and migrated to a 22.0\ncompatible genesis file. The new genesis file will be published on the above\nlink soon after reaching the upgrade epoch.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Replace the old genesis file with the new Testnet genesis file.\nThe ",(0,o.kt)("a",{parentName:"li",href:"#state-changes"},"state changes")," are described and explained below."),(0,o.kt)("li",{parentName:"ul"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.0"},"22.0"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Perform any needed ",(0,o.kt)("a",{parentName:"li",href:"#configuration-changes"},"configuration changes")," described below."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("h3",{id:"configuration-changes-1"},"Configuration Changes"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"To see the full extent of the changes examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.0/CHANGELOG.md#220-2022-03-01"},"Change Log")," of the 22.0 release.")),(0,o.kt)("p",null,"If your node is currently configured to run a ParaTime, you need to perform some\nadditional steps."),(0,o.kt)("p",null,"The way ParaTime binaries are distributed has changed so that all required\nartifacts are contained in a single archive called the Oasis Runtime Container\nand have the ",(0,o.kt)("inlineCode",{parentName:"p"},".orc")," extension. Links to updated ParaTime binaries will be\npublished on the ",(0,o.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet network parameters page")," for their respective\nParaTimes."),(0,o.kt)("p",null,"The configuration is simplified as the ",(0,o.kt)("inlineCode",{parentName:"p"},"runtime.paths")," now only needs to list\nall of the supported ",(0,o.kt)("inlineCode",{parentName:"p"},".orc")," files (see below for an example)."),(0,o.kt)("p",null,"Instead of separately configuring various roles for a node, there is now a\nsingle configuration flag called ",(0,o.kt)("inlineCode",{parentName:"p"},"runtime.mode")," which enables the correct roles\nas needed. It should be set to one of the following values:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"none")," (runtime support is disabled, only consensus layer is enabled)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"compute")," (node is participating as a runtime compute node for all the\nconfigured runtimes)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"keymanager")," (node is participating as a keymanager node)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"client")," (node is a stateful runtime client)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"client-stateless")," (node is a stateless runtime client and connects to\nremote nodes for any state queries)")),(0,o.kt)("p",null,"Nodes that have so far been participating as compute nodes should set the mode\nto ",(0,o.kt)("inlineCode",{parentName:"p"},"compute")," and nodes that have been participating as clients for querying\nand transaction submission should set it to ",(0,o.kt)("inlineCode",{parentName:"p"},"client"),"."),(0,o.kt)("p",null,"The following configuration flags have been removed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"runtime.supported")," (existing ",(0,o.kt)("inlineCode",{parentName:"li"},"runtime.paths")," is used instead)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.p2p.enabled")," (now automatically set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.compute.enabled")," (now set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.keymanager.enabled")," (now set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.storage.enabled")," (no longer needed)")),(0,o.kt)("p",null,"Also the ",(0,o.kt)("inlineCode",{parentName:"p"},"worker.client")," option is no longer needed unless you are providing\nconsensus layer RPC services."),(0,o.kt)("p",null,"For example if your ",(0,o.kt)("em",{parentName:"p"},"previous")," configuration looked like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'runtime:\n supported:\n - "000000000000000000000000000000000000000000000000000000000000beef"\n\n paths:\n "000000000000000000000000000000000000000000000000000000000000beef": /path/to/runtime\n\nworker:\n # ... other settings omitted ...\n\n storage:\n enabled: true\n\n compute:\n enabled: true\n\n client:\n port: 12345\n addresses:\n - "xx.yy.zz.vv:12345"\n\n p2p:\n enabled: true\n port: 12346\n addresses:\n - "xx.yy.zz.vv:12346"\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("em",{parentName:"p"},"new")," configuration should look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'runtime:\n mode: compute\n paths:\n - /path/to/runtime.orc\n\nworker:\n # ... other settings omitted ...\n\n p2p:\n port: 12346\n addresses:\n - "xx.yy.zz.vv:12346"\n')),(0,o.kt)("h3",{id:"state-changes-1"},"State Changes"),(0,o.kt)("p",null,"The following parts of the genesis document will be updated:"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For a more detailed explanation of the parameters below, see the ",(0,o.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"Genesis Document")," docs.")),(0,o.kt)("h3",{id:"general-1"},(0,o.kt)("strong",{parentName:"h3"},"General")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"height"))," will be set to the height of the Testnet state dump + 1, i.e. ",(0,o.kt)("inlineCode",{parentName:"li"},"8535081"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"genesis_time"))," will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"2022-03-03T13:00:00Z"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"chain_id"))," will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"testnet-2022-03-03"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"halt_epoch"))," will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"24210")," (more than 1 year from the upgrade).")),(0,o.kt)("h3",{id:"registry-1"},(0,o.kt)("strong",{parentName:"h3"},"Registry")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.runtimes"))," list contains the registered runtimes' descriptors. In\nthis upgrade, all runtime descriptors will be migrated from version ",(0,o.kt)("inlineCode",{parentName:"li"},"2")," to\nversion ",(0,o.kt)("inlineCode",{parentName:"li"},"3"),".\nThe migration will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis"),"\ncommand."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.suspended_runtimes"))," list contains the suspended registered\nruntimes' descriptors. In this upgrade, all runtime descriptors will be\nmigrated from version ",(0,o.kt)("inlineCode",{parentName:"li"},"2")," to version ",(0,o.kt)("inlineCode",{parentName:"li"},"3"),".\nThe migration will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis"),"\ncommand."),(0,o.kt)("li",{parentName:"ul"},"Inactive registered entities in ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.entities"))," (and their\ncorresponding nodes in ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"registry.nodes")),") that don't pass the\n",(0,o.kt)("a",{parentName:"li",href:"/node/genesis-doc#node-and-paratime-token-thresholds"},"minimum staking thresholds")," will be removed.\nThe removal will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("h3",{id:"root-hash"},(0,o.kt)("strong",{parentName:"h3"},"Root Hash")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"roothash.params.gas_costs.submit_msg"))," is a new parameter that specifies\nthe cost for an submit message transaction. It will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"1000"),".\nThis will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_in_runtime_messages"))," is a new parameter that that\nspecifies the maximum number of incoming messages that can be queued for\nprocessing by a runtime. It will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"128"),"."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"roothash.runtime_state"))," contains the state roots of the runtimes.\nEmpty fields will be omitted.\nThis will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command."))),(0,o.kt)("h3",{id:"staking-1"},(0,o.kt)("strong",{parentName:"h3"},"Staking")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.thresholds"))," specifies the minimum number of tokens that\nneed to be staked in order for a particular entity or a particular type of node\nto participate in the network.\nThe ",(0,o.kt)("inlineCode",{parentName:"li"},"node-storage")," key is removed since Oasis Core 22.0+ removes separate\nstorage nodes (for more details, see: ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/pull/4308"},"#4308"),").\nThis will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis")," command."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.min_transfer"))," specifies the minimum number of tokens one\ncan transfer.\nThe value is set to 10,000,000 base units, or 0.01 TEST tokens.\nThis will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis")," command."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.min_transact_balance"))," specifies the minimum general balance\nan account must have to be able to perform transactions on the network.\nThe value is set to 0 base units meaning this requirement is currently not\nenforced.\nThis will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node debug fix-genesis")," command."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.reward_schedule"))," specifies the staking reward schedule\nas an array with elements of the form:",(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},'{\n "until": 14226,\n "scale": "1229"\n}\n')),"For example, this element specifies that the staking reward is 0.001229% per\nepoch until epoch ",(0,o.kt)("inlineCode",{parentName:"li"},"14226"),".\nIt will be set to the same schedule that is currently on used on the Mainnet.")),(0,o.kt)("h3",{id:"random-beacon-1"},(0,o.kt)("strong",{parentName:"h3"},"Random Beacon")),(0,o.kt)("p",null,"The ",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon"))," object contains parameters controlling the new\n",(0,o.kt)("a",{parentName:"p",href:"../../adrs/0010-vrf-elections"},"improved VRF-based random beacon")," introduced in the Damask upgrade."),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.base"))," is the network's starting epoch. It will be set to the\n",(0,o.kt)("inlineCode",{parentName:"p"},"14209"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.backend"))," configures the random beacon backend to use. It\nwill be set to ",(0,o.kt)("inlineCode",{parentName:"p"},'"vrf"')," indicating that the beacon implementing a\n",(0,o.kt)("a",{parentName:"p",href:"../../adrs/0010-vrf-elections"},"VRF-based random beacon")," should be used.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.alpha_hq_threshold"))," is minimal number of\nnodes that need to contribute a VRF proof for the beacon's output to be valid.\nIt will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"3"),"."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.interval"))," is the duration of an epoch.\nIt will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"600"),"."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.proof_delay"))," is number of blocks since the\nbeginning of an epoch after a node can still submit its VRF proof.\nIt will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"300"),"."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.gas_costs.vrf_prove"))," specifies the cost for\na VRF prove transaction.\nIt will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"1000"),"."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,o.kt)("p",null,"The ",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters"))," control the behavior of the\n",(0,o.kt)("a",{parentName:"p",href:"/adrs/0007-improved-random-beacon"},"previous random beacon implementing a PVSS scheme"),"."),(0,o.kt)("p",null,"Since PVSS is no longer supported, all its configuration options are removed\nas well."),(0,o.kt)("h3",{id:"governance-1"},(0,o.kt)("strong",{parentName:"h3"},"Governance")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.stake_threshold"))," is a new parameter specifying the\nsingle unified stake threshold representing the percentage of ",(0,o.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes\nin terms of total voting power for a governance proposal to pass.\nIt will be set to ",(0,o.kt)("inlineCode",{parentName:"p"},"68")," (i.e. 68%)."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.quorum"))," is the minimum percentage of voting power that\nneeds to be cast on a proposal for the result to be valid."),(0,o.kt)("p",{parentName:"li"},"It will be removed since it is being replaced by the single\n",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.staking_threshold"))," parameter."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.threshold"))," is the minimum percentage of ",(0,o.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes\nin order for a proposal to be accepted."),(0,o.kt)("p",{parentName:"li"},"It will be removed since it is being replaced by the single\n",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.staking_threshold"))," parameter."),(0,o.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,o.kt)("h3",{id:"consensus"},(0,o.kt)("strong",{parentName:"h3"},"Consensus")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_interval"))," parameter controls the\ninterval (in blocks) on which state checkpoints should be taken. It will be\nincreased from ",(0,o.kt)("inlineCode",{parentName:"li"},"10000")," to ",(0,o.kt)("inlineCode",{parentName:"li"},"100000")," to improve nodes' performance since\ncomputing checkpoints is I/O intensive.")),(0,o.kt)("h2",{id:"2021-08-11-upgrade"},"2021-08-11 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"8844."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2021-08-11 08:50 UTC.")),(0,o.kt)("h3",{id:"proposed-parameter-changes"},"Proposed Parameter Changes"),(0,o.kt)("p",null,"The ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"Oasis Core 21.2.8")," release contains the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.2.8/go/upgrade/migrations/consensus_parameters.go"},(0,o.kt)("inlineCode",{parentName:"a"},"consensus-params-update-2021-08")," upgrade handler")," which will update the following parameters in the consensus layer:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.max_allowances")," ")," specifies the maximum number of allowances on account can store. It will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"16")," (default value is ",(0,o.kt)("inlineCode",{parentName:"li"},"0"),") to enable support for beneficiary allowances which are required to transfer tokens into a ParaTime. ",(0,o.kt)("em",{parentName:"li"},"Note that this has already been the case on Testnet since the")," ",(0,o.kt)("a",{parentName:"li",href:"/node/testnet/upgrade-log#2021-06-23-upgrade"},(0,o.kt)("em",{parentName:"a"},"2021-06-23 upgrade")),(0,o.kt)("em",{parentName:"li"},".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs")," ")," , ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.gas_costs"))," and ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"roothash.params.gas_costs"))," specify gas costs for various types of staking, governance and roothash transactions. Gas costs for transactions that were missing gas costs will be added."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators"))," is the maximum size of the consensus committee (i.e. the validator set). It will be increased to",(0,o.kt)("inlineCode",{parentName:"li"},"110")," (it was set to ",(0,o.kt)("inlineCode",{parentName:"li"},"100")," previously).")),(0,o.kt)("h3",{id:"instructions---before-upgrade-system-preparation"},"Instructions - Before Upgrade System Preparation"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"This upgrade will upgrade ",(0,o.kt)("strong",{parentName:"li"},"Oasis Core")," to version ",(0,o.kt)("strong",{parentName:"li"},"21.2.8")," which:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Has a check that makes sure the ",(0,o.kt)("strong",{parentName:"li"},"file descriptor limit")," is set to an appropriately high value (at least 50000). While previous versions only warned in case the limit was set too low, this version will refuse to start. Follow the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/system-configuration#file-descriptor-limit"},"File Descriptor Limit")," documentation page for details on how to increase the limit on your system."))),(0,o.kt)("li",{parentName:"ul"},"Stop your node, replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"21.2.8")," and restart your node.")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Since Oasis Core 21.2.8 is otherwise compatible with the current consensus layer protocol, you may upgrade your Testnet node to this version at any time.")),(0,o.kt)("admonition",{title:"This is not dump & restore upgrade",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"For this upgrade, ",(0,o.kt)("strong",{parentName:"p"},"do NOT wipe state"),".")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"21.2.8"),".",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If you upgraded your node to Oasis Core 21.2.8 before the upgrade epoch was reached, you only need to restart your node for the upgrade to proceed."),(0,o.kt)("li",{parentName:"ul"},"Otherwise, you need to upgrade your node to Oasis Core 21.2.8 first and then restart it.")))),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you use a process manager like ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/systemd/systemd"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org"},"Supervisor"),", you can configure it to restart the Oasis Node automatically.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Testnet's genesis file and the genesis document's hash will remain the same.")),(0,o.kt)("h2",{id:"2021-06-23-upgrade"},"2021-06-23 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"7553."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2021-06-23 14:30 UTC.")),(0,o.kt)("h3",{id:"instructions-3"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"See ",(0,o.kt)("a",{parentName:"li",href:"/node/testnet/upgrade-log#before-upgrade"},"Before upgrade")," section for required steps to be done before upgrade."),(0,o.kt)("li",{parentName:"ul"},"(optional) Vote for the upgrade. On 2021-06-21, an upgrade proposal will be proposed which (if accepted) will schedule the upgrade on epoch ",(0,o.kt)("strong",{parentName:"li"},"7553.")," See the ",(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"Governance documentation")," for details on voting for proposals.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The upgrade proposal contains the ",(0,o.kt)("inlineCode",{parentName:"p"},'"consensus-max-allowances-16"')," upgrade handler whose only purpose is to set the",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.min_delegation"))," consensus parameter to 16 (default value is 0) to enable support for beneficiary allowances which are required to transfer tokens into a ParaTime.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Stop your node, replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.4"},"21.2.4")," and restart your node.")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Since Oasis Core 21.2.4 is otherwise compatible with the current consensus layer protocol, you may upgrade your Testnet node to this version at any time.")),(0,o.kt)("admonition",{title:"This is not dump & restore upgrade",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"For this upgrade, ",(0,o.kt)("strong",{parentName:"p"},"do NOT wipe state"),".")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.4"},"21.2.4"),".",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If you upgraded your node to Oasis Core 21.2.4 before the upgrade epoch was reached, you only need to restart your node for the upgrade to proceed."),(0,o.kt)("li",{parentName:"ul"},"Otherwise, you need to upgrade your node to Oasis Core 21.2.4 first and then restart it.")))),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you use a process manager like ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/systemd/systemd"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org"},"Supervisor"),", you can configure it to restart the Oasis Node automatically.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Testnet's genesis file and the genesis document's hash will remain the same.")),(0,o.kt)("h3",{id:"before-upgrade-1"},"Before upgrade"),(0,o.kt)("p",null,"This upgrade will upgrade Oasis Core to version ",(0,o.kt)("strong",{parentName:"p"},"21.2.x")," which includes the new ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/dgraph-io/badger"},(0,o.kt)("strong",{parentName:"a"},"BadgerDB"))," ",(0,o.kt)("strong",{parentName:"p"},"v3"),"."),(0,o.kt)("p",null,"Since BadgerDB's on-disk format changed in v3, it requires on-disk state migration. The migration process is done automatically and makes the following steps:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Upon startup, Oasis Node will start migrating all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")," files (Badger v2 files) and start writing Badger v3 DB to files with the ",(0,o.kt)("inlineCode",{parentName:"p"},".migrate")," suffix.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the migration fails in the middle, Oasis Node will delete all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.migrate")," files the next time it starts and start the migration (of the remaining ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")),(0,o.kt)("p",{parentName:"li"},"files) again.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the migration succeeds, Oasis Node will append the ",(0,o.kt)("inlineCode",{parentName:"p"},".backup")," suffix to all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")," files (Badger v2 files) and remove the ",(0,o.kt)("inlineCode",{parentName:"p"},".migrate")," suffix from all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.migrate")," files (Badger v3 files)."))),(0,o.kt)("h4",{id:"extra-storage-requirements"},"Extra storage requirements"),(0,o.kt)("p",null,"Your node will thus need to have extra storage space to store both the old and the new BadgerDB files."),(0,o.kt)("p",null,"To see estimate how much extra space the migration will need, use the ",(0,o.kt)("inlineCode",{parentName:"p"},"du")," tool:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"shopt -s globstar\ndu -h /**/*.badger.db | sort -h -r\n")),(0,o.kt)("p",null,"This is an example output from a Testnet node that uses ",(0,o.kt)("inlineCode",{parentName:"p"},"/srv/oasis/node")," as the ",(0,o.kt)("inlineCode",{parentName:"p"},""),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"6.3G /srv/oasis/node/tendermint/data/blockstore.badger.db\n2.7G /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db\n1.4G /srv/oasis/node/tendermint/data/state.badger.db\n158M /srv/oasis/node/persistent-store.badger.db\n164K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints\n80K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334\n80K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334\n76K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334/fc815694d8219acb97fc0207a2159601df76df4d96802c147252ad0f2fd8a3f3\n76K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334/613e734e4ee4999bf71c3a190df13ea9d9b7d65af6a7fd8b2c9a477f2d052313\n68K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334/fc815694d8219acb97fc0207a2159601df76df4d96802c147252ad0f2fd8a3f3/chunks\n68K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334/613e734e4ee4999bf71c3a190df13ea9d9b7d65af6a7fd8b2c9a477f2d052313/chunks\n20K /srv/oasis/node/tendermint/data/evidence.badger.db\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"After you've confirmed your node is up and running, you can safely delete all the ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.backup")," files.")),(0,o.kt)("h4",{id:"extra-memory-requirements"},"Extra memory requirements"),(0,o.kt)("p",null,"BadgerDB v2 to v3 migration can use a number of Go routines to migrate different database files in parallel."),(0,o.kt)("p",null,"However, this comes with a memory cost. For larger database files, it might need up to 4 GB of RAM per database, so we recommend lowering the number of Go routines BadgerDB uses during migration (",(0,o.kt)("inlineCode",{parentName:"p"},"badger.migrate.num_go_routines"),") if your node has less than 8 GB of RAM."),(0,o.kt)("p",null,"If your node has less than 8 GB of RAM, set the number of Go routines BadgerDB uses during migration to 2 (default is 8) by adding the following to your node's ",(0,o.kt)("inlineCode",{parentName:"p"},"config.yml"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"# BadgerDB configuration.\nbadger:\n migrate:\n # Set the number of Go routines BadgerDB uses during migration to 2 to lower\n # the memory pressure during migration (at the expense of a longer migration\n # time).\n num_go_routines: 2\n")),(0,o.kt)("h2",{id:"2021-04-13-upgrade"},"2021-04-13 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"5662."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2021-04-13 12:00 UTC.")),(0,o.kt)("h3",{id:"instructions-4"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Runtime operators see ",(0,o.kt)("a",{parentName:"li",href:"/node/testnet/upgrade-log#before-upgrade"},"Before upgrade")," section for required steps to be done before upgrade."),(0,o.kt)("li",{parentName:"ul"},"(optional) Vote for the upgrade. On 2021-04-12 an upgrade proposal will be proposed which (if accepted) will schedule a network shutdown on epoch ",(0,o.kt)("strong",{parentName:"li"},"5662.")," See the ",(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"Governance documentation")," for details on voting for proposals.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The upgrade proposal contains a non-existing upgrade handler and will be used to coordinate the network shutdown, the rest of the upgrade is manual.")),(0,o.kt)("p",null,"Following steps should be performed only after the network has reached the upgrade network and has halted:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Download the Testnet genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2021-04-13"},"Testnet 2021-04-13 release"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Testnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"5662")," will be exported and migrated to a 21.1.x compatible genesis file. Upgrade genesis file will be published on the above link soon after reaching the upgrade epoch.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Replace the old genesis file with the new Testnet genesis file."),(0,o.kt)("li",{parentName:"ul"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1"},"21.1"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("h3",{id:"before-upgrade-2"},"Before upgrade"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Runtime operators")),(0,o.kt)("p",null,"This upgrade requires a runtime storage node migration to be performed ",(0,o.kt)("strong",{parentName:"p"},"before the upgrade genesis is published"),". This can be done before the upgrade epoch is reached by stopping all runtime nodes and running the migration."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Backup your node's data directory")),(0,o.kt)("p",{parentName:"admonition"},"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."),(0,o.kt)("p",{parentName:"admonition"},"For example, to backup the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," directory using the rsync tool, run:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n"))),(0,o.kt)("p",null,"The storage database on all storage nodes needs to be migrated with the following command (using the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1"},"21.1")," binary):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n")),(0,o.kt)("p",null,"After the migration to v5 completes, you will see an output similar to:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"...\n- migrating from v4 to v5...\n- migrating version 24468...\n- migrated root state-root:195cf7a9a103e7300b2bb4e537cb9935cbebd83e448e67aa55433861a6ad7426 -> state-root:cea105a5d701deab935b94af9e8e0c5af5dcdb61c242bf434da9f11aa8d110ba\n- migrated root io-root:0850c5a33ee7f45aa92724b7d5f28c9ac9ae8799b88cc5be9773e8aba9526ca7 -> io-root:19713a2b44e1bf868ebee43c36872baa3058870bb890a5e25d1c4cea2622be77\n- migrated root io-root:477391131f60ac2c22bce9167c7e3783a13d4fb81fddd2d388b4ead6a586fe52 -> io-root:f29f86d491303c5fd7b3572e97cbd65b7487b6b4ac519623afd161cc2e4678b7\n")),(0,o.kt)("p",null,"Take note of the displayed ",(0,o.kt)("inlineCode",{parentName:"p"},"state-root")," and report it to the Foundation, as it needs to be included in the upgrade's new genesis file. Keep the runtime nodes stopped until the upgrade epoch is reached. At upgrade epoch, upgrade the nodes by following the remaining steps above."),(0,o.kt)("h2",{id:"2021-03-24-upgrade"},"2021-03-24 Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"5128."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Testnet network to reach this epoch at around 2021-03-24 11:30 UTC.")),(0,o.kt)("h3",{id:"instructions-5"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"(optional) To ensure your node will stop at epoch ",(0,o.kt)("strong",{parentName:"p"},"5128")," ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades#stop-the-node-at-specific-epoch"},"submit the following upgrade descriptor")," at any time before the upgrade:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},'{\n "name": "testnet-upgrade-2021-03-24",\n "method": "internal",\n "identifier": "testnet-upgrade-2021-03-24",\n "epoch": 5128\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Download the Testnet genesis file published in the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2021-03-24"},"Testnet 2021-03-24 release"),"."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Testnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"5128")," will be exported and migrated to a 21.0.x compatible genesis file. Upgrade genesis file will be published on the above link soon after reaching the upgrade epoch.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"(optional) Verify the provided Testnet genesis file by comparing it to network state dump. See instructions in the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/handling-network-upgrades#download-and-verify-the-provided-genesis-file"},"Handling Network Upgrades")," guide."),(0,o.kt)("li",{parentName:"ul"},"Replace the old genesis file with the new Testnet genesis file."),(0,o.kt)("li",{parentName:"ul"},"Stop your node (if you haven't stopped it already by submitting the upgrade descriptor)."),(0,o.kt)("li",{parentName:"ul"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.0.1"},"21.0.1"),"."),(0,o.kt)("li",{parentName:"ul"},"Update your node's configuration or perform any additional needed steps as per ",(0,o.kt)("a",{parentName:"li",href:"/node/testnet/#additional-steps"},"Additional Steps")," below."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For more detailed instructions, see the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"Handling Network Upgrades")," guide.")),(0,o.kt)("h3",{id:"additional-steps"},"Additional steps"),(0,o.kt)("p",null,"Examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.0.1/CHANGELOG.md#210-2021-03-18"},"Changelog")," of the 21.0 release."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Runtime operators")),(0,o.kt)("p",null,"In addition to some ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.0.1/CHANGELOG.md#configuration-changes"},"configuration changes"),", this upgrade contains breaking runtime API changes. Make sure any runtime code is updated and compatible with the 21.0.x runtime API version."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Backup your node's data directory")),(0,o.kt)("p",{parentName:"admonition"},"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."),(0,o.kt)("p",{parentName:"admonition"},"For example, to backup the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," directory using the rsync tool, run:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n"))),(0,o.kt)("p",null,"For this upgrade, the runtime node operators need to perform an additional migration of the storage nodes. ",(0,o.kt)("strong",{parentName:"p"},"Before starting the upgraded node and before wiping state"),", the storage database on all storage nodes needs to be migrated with the following command (using the 21.0.1 binary):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Storage access policy changes")),(0,o.kt)("p",{parentName:"admonition"},"Due to the changes in the default access policy on storage nodes, at least one of the storage nodes should be configured with the ",(0,o.kt)("inlineCode",{parentName:"p"},"worker.storage.public_rpc.enabled")," flag set to ",(0,o.kt)("inlineCode",{parentName:"p"},"true"),"."),(0,o.kt)("p",{parentName:"admonition"},"Otherwise, external runtime clients wont be able to connect to any storage nodes.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8fa03331.e9642f26.js b/assets/js/8fa03331.e9642f26.js new file mode 100644 index 0000000000..618a6ea7ef --- /dev/null +++ b/assets/js/8fa03331.e9642f26.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2459],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var d=o.createContext({}),l=function(e){var t=o.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=l(e.components);return o.createElement(d.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,s=e.originalType,d=e.parentName,p=r(e,["components","mdxType","originalType","parentName"]),c=l(n),h=a,m=c["".concat(d,".").concat(h)]||c[h]||u[h]||s;return n?o.createElement(m,i(i({ref:t},p),{},{components:n})):o.createElement(m,i({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var s=n.length,i=new Array(s);i[0]=h;var r={};for(var d in t)hasOwnProperty.call(t,d)&&(r[d]=t[d]);r.originalType=e,r[c]="string"==typeof e?e:a,i[1]=r;for(var l=2;l{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var o=n(7462),a=(n(7294),n(3905));const s={},i="Using State Sync for Quick Bootstraping",r={unversionedId:"node/run-your-node/advanced/sync-node-using-state-sync",id:"node/run-your-node/advanced/sync-node-using-state-sync",title:"Using State Sync for Quick Bootstraping",description:"The State Sync is a way to quickly bootstrap a full Oasis node (either a validator node or a non-validator node) by using Tendermint's Light Client protocol. It allows one to initialize a node from a trusted height, its corresponding block's header and a trusted validator set (given in the genesis document). It does so by securely updating the node's trusted state by requesting and verifying a minimal set of data from the network's full nodes.",source:"@site/docs/node/run-your-node/advanced/sync-node-using-state-sync.md",sourceDirName:"node/run-your-node/advanced",slug:"/node/run-your-node/advanced/sync-node-using-state-sync",permalink:"/node/run-your-node/advanced/sync-node-using-state-sync",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/advanced/sync-node-using-state-sync.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Advanced",permalink:"/node/run-your-node/advanced"},next:{title:"Copy State from One Node to the Other",permalink:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other"}},d={},l=[{value:"Obtaining Trusted Height and Hash",id:"obtaining-trusted-height-and-hash",level:3},{value:"Block Explorers",id:"block-explorers",level:4},{value:"A Trusted Node",id:"a-trusted-node",level:4},{value:"Public Rosetta Gateway",id:"public-rosetta-gateway",level:4},{value:"Oasis Node's gRPC Endpoint",id:"oasis-nodes-grpc-endpoint",level:4},{value:"Obtaining Addresses of Oasis Nodes' Publicly Exposed gRPC Endpoints",id:"obtaining-addresses-of-oasis-nodes-publicly-exposed-grpc-endpoints",level:3},{value:"List Registered Nodes' Descriptors via Oasis CLI from the Local Oasis Node",id:"list-registered-nodes-descriptors-via-oasis-cli-from-the-local-oasis-node",level:4}],p={toc:l},c="wrapper";function u(e){let{components:t,...n}=e;return(0,a.kt)(c,(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"using-state-sync-for-quick-bootstraping"},"Using State Sync for Quick Bootstraping"),(0,a.kt)("p",null,"The State Sync is a way to ",(0,a.kt)("strong",{parentName:"p"},"quickly bootstrap")," a ",(0,a.kt)("strong",{parentName:"p"},"full Oasis node")," (either a ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"validator node")," or a ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"non-validator node"),") by using ",(0,a.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/main/tendermint-core/light-client.html"},"Tendermint's Light Client protocol"),". It allows one to initialize a node from a trusted height, its corresponding block's header and a trusted validator set (given in the ",(0,a.kt)("a",{parentName:"p",href:"/node/genesis-doc"},"genesis document"),"). It does so by securely updating the node's trusted state by requesting and verifying a minimal set of data from the network's full nodes."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"If you have access to an Oasis Node that is synced with the latest height, another option to speed bootstraping a new Oasis Node is to ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other"},"copy state from one node to the other"),".")),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Tendermint's Light Client protocol requires at least 1 full node to be correct to be able to ",(0,a.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/main/tendermint-core/light-client.html#where-to-obtain-trusted-height-hash"},"detect and submit evidence for a light client attack"),".")),(0,a.kt)("p",null,"To configure your node to use the state sync, amend your node's configuration (i.e. ",(0,a.kt)("inlineCode",{parentName:"p"},"config.yml"),") with (non-relevant fields omitted):"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},'... trimmed ...\n\n# Consensus.\nconsensus:\n\n ... trimmed ...\n\n # Tendermint backend configuration.\n tendermint:\n\n ... trimmed ...\n\n # Enable consensus state sync (i.e. Tendermint light client sync).\n state_sync:\n enabled: true\n trust_height: {{ trusted_height }}\n trust_hash: "{{ trusted_height_hash }}"\n # List of consensus nodes to use for syncing.\n consensus_node:\n - "{{ node1_grpc_endpoint }}"\n - "{{ node2_grpc_endpoint }}"\n \n .. trimmed ...\n \n - "{{ noden_grpc_endpoint }}"\n\n... trimmed ...\n\n')),(0,a.kt)("p",null,"and replace the following variables in the configuration snippet:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"{{ trusted_height }}"),": Trusted height defines the height at which your node should trust the chain.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"{{ trusted_height_hash }}"),": Trusted height hash defines the hash of the block header corresponding to the trusted height.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"{{ node1_grpc_endpoint }}"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"{{ node2_grpc_endpoint }}")," , ...,"),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"{{ noden_grpc_endpoint }}"),": Addresses of a Oasis Nodes' publicly exposed gRPC endpoints of the form: ",(0,a.kt)("inlineCode",{parentName:"p"},"xAMjfJDcUFUcwgZGEQuOdux8gAdc+IFEqccB2LHdGjU=@34.86.145.181:9001"),"."))),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"You need to provide publicly exposed gRPC endpoints for ",(0,a.kt)("strong",{parentName:"p"},"at least 2 different consensus nodes")," for the state sync to work.")),(0,a.kt)("admonition",{type:"danger"},(0,a.kt)("p",{parentName:"admonition"},"You need to ",(0,a.kt)("strong",{parentName:"p"},"delete any existing node state")," (if it exists), otherwise state sync will be skipped. To do that, follow the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wiping Node State")," instructions."),(0,a.kt)("p",{parentName:"admonition"},"If existing node state is found and state sync is skipped, you will see something like the following in your node's logs:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre"},'{"caller":"full.go:1233","level":"info","module":"tendermint","msg":"state sync enabled","ts":"2021-06-21T14:40:55.033642763Z"}\n{"caller":"node.go:692","level":"info","module":"tendermint:base","msg":"Found local state with non-zero height, skipping state sync","ts":"2021-06-21T14:40:55.838955955Z"}\n'))),(0,a.kt)("h3",{id:"obtaining-trusted-height-and-hash"},"Obtaining Trusted Height and Hash"),(0,a.kt)("p",null,"To obtain the trusted height and the corresponding block header's hash, use one of the following options."),(0,a.kt)("h4",{id:"block-explorers"},"Block Explorers"),(0,a.kt)("p",null,"Browse to one of our block explorers (e.g. ",(0,a.kt)("a",{parentName:"p",href:"https://www.oasisscan.com"},"OASIS SCAN"),", ",(0,a.kt)("a",{parentName:"p",href:"https://oasismonitor.com"},"Oasis Monitor"),") and obtain the trusted height and hash there:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Obtain the current block height from the main page, e.g. 4819139."),(0,a.kt)("li",{parentName:"ol"},"Click on block height's number to view the block's details and obtain its hash, e.g. ",(0,a.kt)("inlineCode",{parentName:"li"},"377520acaf7b8011b95686b548504a973aa414abba2db070b6a85725dec7bd21"),".")),(0,a.kt)("h4",{id:"a-trusted-node"},"A Trusted Node"),(0,a.kt)("p",null,"If you have an existing node that you trust, you can use its status output to retrieve the current block height and hash by running:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"oasis-node control status -a $ADDR\n")),(0,a.kt)("p",null,"replacing ",(0,a.kt)("inlineCode",{parentName:"p"},"$ADDR")," with the path to your node's internal UNIX socket (e.g. ",(0,a.kt)("inlineCode",{parentName:"p"},"/srv/oasis/node/internal.sock"),")."),(0,a.kt)("p",null,"This will give you output like the following (non-relevant fields omitted):"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-json"},'{\n "software_version": "21.3.1",\n "identity": {\n ...\n },\n "consensus": {\n ...\n "latest_height": 6388075,\n "latest_hash": "d9f57b806917b6d3131925f7c987a785ea90f62b3a6987aedd1abdc371d84403",\n "latest_time": "2021-10-19T12:01:55+02:00",\n "latest_epoch": 10636,\n ...\n },\n ...\n}\n')),(0,a.kt)("p",null,"The values you need are ",(0,a.kt)("inlineCode",{parentName:"p"},"latest_height")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"latest_hash")," ."),(0,a.kt)("h4",{id:"public-rosetta-gateway"},"Public Rosetta Gateway"),(0,a.kt)("p",null,"Query our public Rosetta Gateway instance and obtain the trusted height and hash there:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("em",{parentName:"li"},"TODO."))),(0,a.kt)("h4",{id:"oasis-nodes-grpc-endpoint"},"Oasis Node's gRPC Endpoint"),(0,a.kt)("p",null,"Query our public Oasis Node's gRPC endpoint and obtain the trusted height and hash there:"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("em",{parentName:"li"},"TODO."))),(0,a.kt)("h3",{id:"obtaining-addresses-of-oasis-nodes-publicly-exposed-grpc-endpoints"},"Obtaining Addresses of Oasis Nodes' Publicly Exposed gRPC Endpoints"),(0,a.kt)("p",null,"To find the addresses of Oasis Node's publicly exposed gRPC endpoints, use one of the following options."),(0,a.kt)("h4",{id:"list-registered-nodes-descriptors-via-oasis-cli-from-the-local-oasis-node"},"List Registered Nodes' Descriptors via Oasis CLI from the Local Oasis Node"),(0,a.kt)("p",null,"If you already have a local Oasis Node set up, you can list the descriptors of all registered nodes via Oasis CLI."),(0,a.kt)("p",null,"You need to search for the nodes that implement the ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus-rpc")," role."),(0,a.kt)("p",null,"The publicly exposed gRPC endpoint addresses are found under the node descriptor's ",(0,a.kt)("inlineCode",{parentName:"p"},"tls.addresses")," key."),(0,a.kt)("p",null,"You can list the relevant addresses by running:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"oasis-node registry node list -v -a $ADDR | \\\n jq 'select(.roles | contains(\"consensus-rpc\")) | .tls.addresses'\n")),(0,a.kt)("p",null,"replacing ",(0,a.kt)("inlineCode",{parentName:"p"},"$ADDR")," with the path to your node's internal UNIX socket (e.g. ",(0,a.kt)("inlineCode",{parentName:"p"},"/srv/oasis/node/internal.sock"),")."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/904dacd1.b45ea161.js b/assets/js/904dacd1.b45ea161.js new file mode 100644 index 0000000000..3624793402 --- /dev/null +++ b/assets/js/904dacd1.b45ea161.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9572],{3905:(e,n,a)=>{a.d(n,{Zo:()=>d,kt:()=>m});var i=a(7294);function t(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function r(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,i)}return a}function o(e){for(var n=1;n=0||(t[a]=e[a]);return t}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(t[a]=e[a])}return t}var l=i.createContext({}),p=function(e){var n=i.useContext(l),a=n;return e&&(a="function"==typeof e?e(n):o(o({},n),e)),a},d=function(e){var n=p(e.components);return i.createElement(l.Provider,{value:n},e.children)},y="mdxType",g={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},c=i.forwardRef((function(e,n){var a=e.components,t=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),y=p(a),c=t,m=y["".concat(l,".").concat(c)]||y[c]||g[c]||r;return a?i.createElement(m,o(o({ref:n},d),{},{components:a})):i.createElement(m,o({ref:n},d))}));function m(e,n){var a=arguments,t=n&&n.mdxType;if("string"==typeof e||t){var r=a.length,o=new Array(r);o[0]=c;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[y]="string"==typeof e?e:t,o[1]=s;for(var p=2;p{a.r(n),a.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>g,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var i=a(7462),t=(a(7294),a(3905));const r={},o="Signing Key Manager Policy",s={unversionedId:"node/run-your-node/keymanager-node/signing-key-manager-policy",id:"node/run-your-node/keymanager-node/signing-key-manager-policy",title:"Signing Key Manager Policy",description:"This guide will describe how to print and sign an Oasis [key manager policy].",source:"@site/docs/node/run-your-node/keymanager-node/signing-key-manager-policy.md",sourceDirName:"node/run-your-node/keymanager-node",slug:"/node/run-your-node/keymanager-node/signing-key-manager-policy",permalink:"/node/run-your-node/keymanager-node/signing-key-manager-policy",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/keymanager-node/signing-key-manager-policy.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Key Manager Node",permalink:"/node/run-your-node/keymanager-node/"},next:{title:"Upgrading Key Managers",permalink:"/node/run-your-node/keymanager-node/key-manager-upgrade"}},l={},p=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Oasis Node Binary",id:"oasis-node-binary",level:3},{value:"Entity",id:"entity",level:3},{value:"Define Variables",id:"define-variables",level:2},{value:"Printing a Policy",id:"printing-a-policy",level:2},{value:"Signing a Policy",id:"signing-a-policy",level:2}],d={toc:p},y="wrapper";function g(e){let{components:n,...a}=e;return(0,t.kt)(y,(0,i.Z)({},d,a,{components:n,mdxType:"MDXLayout"}),(0,t.kt)("h1",{id:"signing-key-manager-policy"},"Signing Key Manager Policy"),(0,t.kt)("p",null,"This guide will describe how to print and sign an Oasis ",(0,t.kt)("a",{parentName:"p",href:"/core/consensus/services/keymanager#policies"},"key manager policy"),"."),(0,t.kt)("admonition",{type:"info"},(0,t.kt)("p",{parentName:"admonition"},"These instructions are only applicable if you are part of a key manager policy\nsigner set.")),(0,t.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,t.kt)("h3",{id:"oasis-node-binary"},"Oasis Node Binary"),(0,t.kt)("p",null,"Make sure you have followed the ",(0,t.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node binary installation guide")," and have\nthe Oasis Node binary installed on your system."),(0,t.kt)("h3",{id:"entity"},"Entity"),(0,t.kt)("p",null,"Similarly to other things, an entity's private key is used to sign a key manager\npolicy."),(0,t.kt)("p",null,"The trusted key manager policy signer set (i.e. the authorized public keys) and\nthe threshold of keys that need to sign the policy are hard-coded in the key\nmanager's source code.\nThe trusted signer set for the Oasis Key Manager is defined in ",(0,t.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/keymanager-paratime/blob/main/src/lib.rs"},"its source code\n"),"."),(0,t.kt)("admonition",{type:"danger"},(0,t.kt)("p",{parentName:"admonition"},"We strongly recommend using a dedicated (single-purpose) entity for signing key\nmanager policies for production key managers, i.e. the ones deployed on\nMainnet and connected to a production ParaTime.")),(0,t.kt)("p",null,"To provision a new entity, follow the ",(0,t.kt)("a",{parentName:"p",href:"../validator-node/#initializing-an-entity"},"instructions in our Validator Node\nguide"),"."),(0,t.kt)("admonition",{type:"caution"},(0,t.kt)("p",{parentName:"admonition"},"Currently, Ledger-based signers do not support signing key manager policies.")),(0,t.kt)("admonition",{type:"danger"},(0,t.kt)("p",{parentName:"admonition"},"In case a file-based signer needs to be used, we strongly recommend using an\n",(0,t.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Air_gap_(networking)"},"offline/air-gapped machine")," for this purpose and never exposing the entity's\nprivate key to an online machine."),(0,t.kt)("p",{parentName:"admonition"},"Gaining access to the entity's private key can compromise the trusted key\nmanager policy signer set and hence the key manager itself.")),(0,t.kt)("h2",{id:"define-variables"},"Define Variables"),(0,t.kt)("p",null,"For easier handling of key manager policy files, define the following variables:"),(0,t.kt)("pre",null,(0,t.kt)("code",{parentName:"pre"},"POLICY=path/to/policy.cbor\nKEY=path/to/entity/key.pem\nNAME=your_name\n")),(0,t.kt)("h2",{id:"printing-a-policy"},"Printing a Policy"),(0,t.kt)("p",null,"To print and inspect a key manager policy, use the following command:"),(0,t.kt)("pre",null,(0,t.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node keymanager verify_policy \\\n --keymanager.policy.file $POLICY \\\n --keymanager.policy.ignore.signature \\\n --verbose\n")),(0,t.kt)("p",null,"This should output something like the following:"),(0,t.kt)("pre",null,(0,t.kt)("code",{parentName:"pre",className:"language-json",metastring:'title="Example of an actual Oasis Testnet Key Manager policy"',title:'"Example',of:!0,an:!0,actual:!0,Oasis:!0,Testnet:!0,Key:!0,Manager:!0,'policy"':!0},'{\n "serial": 8,\n "id": "4000000000000000000000000000000000000000000000004a1a53dff2ae482d",\n "enclaves": {\n "ZhD5ufyc/MReZD1qMSKNCRxnkNiZ3BtxqcYdx4+M0N9AJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ==": {\n "may_query": {\n "0000000000000000000000000000000000000000000000000000000000000000": [\n "c0SidcKhBx3iuonmtXURnFB+qIVkg+nAiaAozAh16ltAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="\n ],\n "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c": [\n "LwbLEQ6dv+R5wv5q5CGRZWiEBWGxgCi/gpphcJFQ5zVAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="\n ]\n },\n "may_replicate": [\n "jTX8etUcGSQBq3C4WbLlexga7dhQFnwzSJOEmRCPvfRAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="\n ]\n },\n "jTX8etUcGSQBq3C4WbLlexga7dhQFnwzSJOEmRCPvfRAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ==": {\n "may_query": {\n "0000000000000000000000000000000000000000000000000000000000000000": [\n "c0SidcKhBx3iuonmtXURnFB+qIVkg+nAiaAozAh16ltAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="\n ],\n "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c": [\n "LwbLEQ6dv+R5wv5q5CGRZWiEBWGxgCi/gpphcJFQ5zVAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="\n ]\n },\n "may_replicate": []\n }\n }\n}\n')),(0,t.kt)("p",null,"The ",(0,t.kt)("inlineCode",{parentName:"p"},'"serial"')," key, e.g. ",(0,t.kt)("inlineCode",{parentName:"p"},"8"),", represents the key manager policy's serial number\nthat must increase with every update of the key manager policy."),(0,t.kt)("p",null,"The ",(0,t.kt)("inlineCode",{parentName:"p"},'"id"')," key, e.g.\n",(0,t.kt)("inlineCode",{parentName:"p"},'"4000000000000000000000000000000000000000000000004a1a53dff2ae482d"'),", represents\nthe key manager ParaTime's runtime ID."),(0,t.kt)("p",null,"The keys below ",(0,t.kt)("inlineCode",{parentName:"p"},'"enclaves"'),", e.g.\n",(0,t.kt)("inlineCode",{parentName:"p"},'"ZhD5ufyc/MReZD1qMSKNCRxnkNiZ3BtxqcYdx4+M0N9AJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'),"\nand ",(0,t.kt)("inlineCode",{parentName:"p"},'"jTX8etUcGSQBq3C4WbLlexga7dhQFnwzSJOEmRCPvfRAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'),",\nrepresent the identities of the key manager enclaves.\nEach key manager enclave ID is comprised of two parts: its ",(0,t.kt)("inlineCode",{parentName:"p"},"MRENCLAVE")," and its\n",(0,t.kt)("inlineCode",{parentName:"p"},"MRSIGNER"),"."),(0,t.kt)("p",null,"Each key manager enclave identity has two lists: ",(0,t.kt)("inlineCode",{parentName:"p"},'"may_query"')," and\n",(0,t.kt)("inlineCode",{parentName:"p"},'"may_replicate"'),"."),(0,t.kt)("p",null,"Items in ",(0,t.kt)("inlineCode",{parentName:"p"},'"may_query"')," list, e.g.\n",(0,t.kt)("inlineCode",{parentName:"p"},'"0000000000000000000000000000000000000000000000000000000000000000"')," and\n",(0,t.kt)("inlineCode",{parentName:"p"},'"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c"'),",\nrepresent the runtime IDs of the ParaTimes that are allowed to query the key\nmanager (in this example, the Cipher and the Sapphire ParaTimes running on the\nTestnet)."),(0,t.kt)("p",null,"The items under runtime IDs of the ParaTimes, e.g.\n",(0,t.kt)("inlineCode",{parentName:"p"},'"c0SidcKhBx3iuonmtXURnFB+qIVkg+nAiaAozAh16ltAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'),"\nand\n",(0,t.kt)("inlineCode",{parentName:"p"},'"LwbLEQ6dv+R5wv5q5CGRZWiEBWGxgCi/gpphcJFQ5zVAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'),",\nrepresent the identities of the runtime enclaves.\nSimilarly to the key manager enclave ID, each runtime enclave ID is comprised of\ntwo parts: its ",(0,t.kt)("inlineCode",{parentName:"p"},"MRENCLAVE")," and its ",(0,t.kt)("inlineCode",{parentName:"p"},"MRSIGNER"),"."),(0,t.kt)("p",null,"Items in ",(0,t.kt)("inlineCode",{parentName:"p"},'"may_replicate"')," list, e.g.\n",(0,t.kt)("inlineCode",{parentName:"p"},'"jTX8etUcGSQBq3C4WbLlexga7dhQFnwzSJOEmRCPvfRAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'),",\nrepresent the key manager enclave IDs to which an existing key manager enclave is\nallowed to replicate itself to.\nThis is used for key manager upgrades when an old key manager enclave (i.e. its\nmaster secret) is allowed to replicate itself to a new key manager enclave."),(0,t.kt)("admonition",{type:"tip"},(0,t.kt)("p",{parentName:"admonition"},"To see what has changed between two key manager policies, diff the outputs\nof the ",(0,t.kt)("inlineCode",{parentName:"p"},"oasis-node keymanager verify_policy")," commands for the corresponding key\nmanager policy files.")),(0,t.kt)("h2",{id:"signing-a-policy"},"Signing a Policy"),(0,t.kt)("p",null,"Once a key manager policy has been inspected, use the following command to sign\nit:"),(0,t.kt)("pre",null,(0,t.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node keymanager sign_policy \\\n --keymanager.policy.file $POLICY \\\n --keymanager.policy.key.file $KEY \\\n --keymanager.policy.signature.file $POLICY.$NAME.signed\n")))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/917d8c1f.80838eb9.js b/assets/js/917d8c1f.80838eb9.js new file mode 100644 index 0000000000..d72a40b3c5 --- /dev/null +++ b/assets/js/917d8c1f.80838eb9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8060],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>m});var o=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=o.createContext({}),d=function(e){var n=o.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},p=function(e){var n=d(e.components);return o.createElement(l.Provider,{value:n},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},g=o.forwardRef((function(e,n){var t=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=d(t),g=i,m=u["".concat(l,".").concat(g)]||u[g]||c[g]||r;return t?o.createElement(m,a(a({ref:n},p),{},{components:t})):o.createElement(m,a({ref:n},p))}));function m(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var r=t.length,a=new Array(r);a[0]=g;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[u]="string"==typeof e?e:i,a[1]=s;for(var d=2;d{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>c,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var o=t(7462),i=(t(7294),t(3905));const r={},a="Single Validator Node Network",s={unversionedId:"core/development-setup/single-validator-node-network",id:"core/development-setup/single-validator-node-network",title:"Single Validator Node Network",description:'It is possible to provision a local "network" consisting of a single validator',source:"@site/docs/core/development-setup/single-validator-node-network.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/single-validator-node-network",permalink:"/core/development-setup/single-validator-node-network",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/single-validator-node-network.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Local Network Runner",permalink:"/core/development-setup/oasis-net-runner"},next:{title:"Deploying a Runtime",permalink:"/core/development-setup/deploying-a-runtime"}},l={},d=[{value:"Provisioning an Entity",id:"provisioning-an-entity",level:2},{value:"Provisioning a Node",id:"provisioning-a-node",level:2},{value:"Creating a Test Genesis Document",id:"creating-a-test-genesis-document",level:2},{value:"Running the Node",id:"running-the-node",level:2},{value:"Using the Node CLI",id:"using-the-node-cli",level:2}],p={toc:d},u="wrapper";function c(e){let{components:n,...t}=e;return(0,i.kt)(u,(0,o.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"single-validator-node-network"},"Single Validator Node Network"),(0,i.kt)("p",null,'It is possible to provision a local "network" consisting of a single validator\nnode. This may be useful for specific development use cases.'),(0,i.kt)("p",null,"Before proceeding, make sure to look at the ",(0,i.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites"},"prerequisites")," required for running\nan Oasis Core environment followed by ",(0,i.kt)("a",{parentName:"p",href:"/core/development-setup/building"},"build instructions")," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."),(0,i.kt)("admonition",{type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"These instructions are for a development-only instance, do not use them\nfor setting up any kind of production instances as they are unsafe and will\nresult in insecure configurations leading to node compromise.")),(0,i.kt)("h2",{id:"provisioning-an-entity"},"Provisioning an Entity"),(0,i.kt)("p",null,"To provision an ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#entities-and-nodes"},"entity")," we first prepare an empty directory under\n",(0,i.kt)("inlineCode",{parentName:"p"},"/path/to/entity")," and then initialize the entity:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"mkdir -p /path/to/entity\ncd /path/to/entity\noasis-node registry entity init --signer.backend file --signer.dir .\n")),(0,i.kt)("h2",{id:"provisioning-a-node"},"Provisioning a Node"),(0,i.kt)("p",null,"To provision a ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#entities-and-nodes"},"node")," we first prepare an empty directory under ",(0,i.kt)("inlineCode",{parentName:"p"},"/path/to/node"),"\nand the initialize the node. The node is provisioned as a validator."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"mkdir -p /path/to/node\ncd /path/to/node\noasis-node registry node init \\\n --signer.backend file \\\n --signer.dir /path/to/entity \\\n --node.consensus_address 127.0.0.1:26656 \\\n --node.is_self_signed \\\n --node.role validator\n")),(0,i.kt)("p",null,"After the node is provisioned we proceed with updating the ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#register-node"},"entity whitelist"),"\nso that the node will be able to register itself:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-node registry entity update \\\n --signer.backend file \\\n --signer.dir /path/to/entity \\\n --entity.node.descriptor /path/to/node/node_genesis.json\n")),(0,i.kt)("h2",{id:"creating-a-test-genesis-document"},"Creating a Test Genesis Document"),(0,i.kt)("p",null,'To create a test genesis document for your development "network" use the\nfollowing commands:'),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"mkdir -p /path/to/genesis\ncd /path/to/genesis\noasis-node genesis init \\\n --chain.id test \\\n --entity /path/to/entity/entity_genesis.json \\\n --node /path/to/node/node_genesis.json \\\n --debug.dont_blame_oasis \\\n --debug.test_entity \\\n --debug.allow_test_keys \\\n --registry.debug.allow_unroutable_addresses \\\n --staking.token_symbol TEST\n")),(0,i.kt)("admonition",{type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"This enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise.")),(0,i.kt)("h2",{id:"running-the-node"},"Running the Node"),(0,i.kt)("p",null,"To run the single validator node, use the following command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-node \\\n --datadir /path/to/node \\\n --genesis.file /path/to/genesis/genesis.json \\\n --worker.registration.entity /path/to/entity/entity.json \\\n --consensus.validator \\\n --debug.dont_blame_oasis \\\n --debug.allow_test_keys \\\n --log.level debug\n")),(0,i.kt)("admonition",{type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"This enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise.")),(0,i.kt)("h2",{id:"using-the-node-cli"},"Using the Node CLI"),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"oasis-node")," exposes ",(0,i.kt)("a",{parentName:"p",href:"/core/oasis-node/rpc"},"an RPC interface")," via a UNIX socket located in its\ndata directory (e.g., under ",(0,i.kt)("inlineCode",{parentName:"p"},"/path/to/node/internal.sock"),"). To simplify the\nfollowing instructions set up an ",(0,i.kt)("inlineCode",{parentName:"p"},"ADDR")," environment variable pointing to it:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"export ADDR=unix:/path/to/node/internal.sock\n")),(0,i.kt)("p",null,"This can then be used to execute CLI commands against the running node (in a\nseparate terminal). For example to show all registered entities:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-node registry entity list -a $ADDR -v\n")),(0,i.kt)("p",null,"Giving output similar to:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'{"v":1,"id":"UcxpyD0kSo/5keRqv8pLypM/Mg5S5iULRbt7Uf73vKQ=","nodes":["jo+quvaFYAP4Chyf1PRqCZZObqpDeJCxfBzTyghiXxs="]}\n{"v":1,"id":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","allow_entity_signed_nodes":true}\n')),(0,i.kt)("p",null,"Or getting a list of all staking accounts:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-node stake list -a $ADDR\n")),(0,i.kt)("p",null,"Giving output similar to:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\noasis1qz3xllj0kktskjzlk0qacadgwpfe8v7sy5kztvly\noasis1qrh4wqfknrlvv7whjm7mjsjlvka2h35ply289pp2\n")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/919a9404.d2e59cbf.js b/assets/js/919a9404.d2e59cbf.js new file mode 100644 index 0000000000..f3575e75a1 --- /dev/null +++ b/assets/js/919a9404.d2e59cbf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1728],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>h});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=i.createContext({}),d=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=d(e.components);return i.createElement(l.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},p=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=d(n),p=a,h=u["".concat(l,".").concat(p)]||u[p]||m[p]||r;return n?i.createElement(h,o(o({ref:t},c),{},{components:n})):i.createElement(h,o({ref:t},c))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,o=new Array(r);o[0]=p;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:a,o[1]=s;for(var d=2;d{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>m,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var i=n(7462),a=(n(7294),n(3905));const r={},o="ADR 0005: Runtime Compute Node Slashing",s={unversionedId:"adrs/0005-runtime-compute-slashing",id:"adrs/0005-runtime-compute-slashing",title:"ADR 0005: Runtime Compute Node Slashing",description:"Component",source:"@site/docs/adrs/0005-runtime-compute-slashing.md",sourceDirName:"adrs",slug:"/adrs/0005-runtime-compute-slashing",permalink:"/adrs/0005-runtime-compute-slashing",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0005-runtime-compute-slashing.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0004: Runtime Governance",permalink:"/adrs/0004-runtime-governance"},next:{title:"ADR 0006: Consensus Governance",permalink:"/adrs/0006-consensus-governance"}},l={},d=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Runtime Descriptor",id:"runtime-descriptor",level:3},{value:"Slashing Parameters",id:"slashing-parameters",level:3},{value:"Executor Commitments",id:"executor-commitments",level:3},{value:"Root Hash Commitment Processing",id:"root-hash-commitment-processing",level:3},{value:"State",id:"state",level:3},{value:"Transaction Methods",id:"transaction-methods",level:3},{value:"Evidence",id:"evidence",level:4},{value:"Evidence Expiry",id:"evidence-expiry",level:3},{value:"Evidence Collection",id:"evidence-collection",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Roothash",id:"roothash",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],c={toc:d},u="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,i.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"adr-0005-runtime-compute-node-slashing"},"ADR 0005: Runtime Compute Node Slashing"),(0,a.kt)("h2",{id:"component"},"Component"),(0,a.kt)("p",null,"Oasis Core"),(0,a.kt)("h2",{id:"changelog"},"Changelog"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"2020-10-14: Evidence expiry, duplicate evidence detection"),(0,a.kt)("li",{parentName:"ul"},"2020-09-28: Initial draft")),(0,a.kt)("h2",{id:"status"},"Status"),(0,a.kt)("p",null,"Accepted"),(0,a.kt)("h2",{id:"context"},"Context"),(0,a.kt)("p",null,"The runtime compute nodes make updates to the runtime state by submitting\ncommitment messages to the roothash service in the consensus layer where\ndiscrepancy detection and resolution are performed."),(0,a.kt)("p",null,"Currently, the compute nodes are never slashed even if they commit incorrect\nresults. While integrity is guarded by discrepancy detection and resolution,\ncompute nodes should be disincentivized to behave incorrectly."),(0,a.kt)("h2",{id:"decision"},"Decision"),(0,a.kt)("p",null,"This proposal introduces a slashing mechanism for punishing misbehaving compute\nnodes as follows:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Per-runtime configurable slashing parameters")," are added to the runtime\ndescriptor similar to the global slashing configuration that currently exists\nin the staking service.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"New runtime-specific slashing reasons")," are introduced: (i) submitting\nincorrect compute results and (ii) signing two different executor commits or\nproposed batches for the same round.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Failure-indicating executor commits")," are introduced in order to give the\ncompute nodes a possibility to vote for failure when they cannot execute the\ngiven batch (e.g., due to unavailability of storage or key manager) without\ngetting slashed. Such commits will always trigger a discrepancy during\ndiscrepancy detection and will vote for failing the round in discrepancy\nresolution phase."))),(0,a.kt)("h3",{id:"runtime-descriptor"},"Runtime Descriptor"),(0,a.kt)("p",null,"This proposal updates the runtime staking parameters (stored under the ",(0,a.kt)("inlineCode",{parentName:"p"},"staking"),"\nfield of the runtime descriptor) as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type RuntimeStakingParameters struct {\n // ... existing fields omitted ...\n\n // Slashing are the per-runtime misbehavior slashing parameters.\n Slashing map[staking.SlashReason]staking.Slash `json:"slashing,omitempty"`\n\n // RewardSlashEquvocationRuntimePercent is the percentage of the reward obtained when slashing\n // for equivocation that is transferred to the runtime\'s account.\n RewardSlashEquvocationRuntimePercent uint8 `json:"reward_equivocation,omitempty"`\n\n // RewardSlashBadResultsRuntimePercent is the percentage of the reward obtained when slashing\n // for incorrect results that is transferred to the runtime\'s account.\n RewardSlashBadResultsRuntimePercent uint8 `json:"reward_bad_results,omitempty"`\n}\n')),(0,a.kt)("h3",{id:"slashing-parameters"},"Slashing Parameters"),(0,a.kt)("p",null,"The slash reason type in the staking module is changed from ",(0,a.kt)("inlineCode",{parentName:"p"},"int")," to ",(0,a.kt)("inlineCode",{parentName:"p"},"uint8"),"."),(0,a.kt)("p",null,"The slash reason definitions are updated as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},"const (\n // SlashConsensusEquivocation is slashing due to equivocation in the\n // consensus layer.\n SlashConsensusEquivocation SlashReason = 0x00\n\n // SlashRuntimeIncorrectResults is slashing due to submission of incorrect\n // results in runtime executor commitments.\n SlashRuntimeIncorrectResults SlashReason = 0x80\n // SlashRuntimeEquivocation is slashing due to signing two different\n // executor commits or proposed batches for the same round.\n SlashRuntimeEquivocation SlashReason = 0x81\n)\n")),(0,a.kt)("h3",{id:"executor-commitments"},"Executor Commitments"),(0,a.kt)("p",null,"The executor commitment body structures are updated to make certain fields\noptional and to introduce the ",(0,a.kt)("inlineCode",{parentName:"p"},"failure")," field as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type ExecutorCommitmentFailure uint8\n\nconst (\n // FailureNone indicates that no failure has occurred.\n FailureNone ExecutorCommitmentFailure = 0\n // FailureUnknown indicates a generic failure.\n FailureUnknown ExecutorCommitmentFailure = 1\n // FailureStorageUnavailable indicates that batch processing failed due to\n // storage being unavailable.\n FailureStorageUnavailable ExecutorCommitmentFailure = 2\n // FailureKeyManagerUnavailable indicates that batch processing failed due\n // to key manager being unavailable.\n FailureKeyManagerUnavailable ExecutorCommitmentFailure = 3\n)\n\ntype ExecutorCommitmentHeader struct {\n // Required fields.\n\n Round uint64 `json:"round"`\n PreviousHash hash.Hash `json:"previous_hash"`\n\n // Optional fields (may be absent for failure indication).\n\n IORoot *hash.Hash `json:"io_root,omitempty"`\n StateRoot *hash.Hash `json:"state_root,omitempty"`\n MessageHash *hash.Hash `json:"messages_hash,omitempty"`\n}\n\ntype ExecutorCommitmentBody struct {\n Header ExecutorCommitmentHeader `json:"header"`\n Failure ExecutorCommitmentFailure `json:"failure,omitempty"`\n\n TxnSchedSig signature.Signature `json:"txn_sched_sig"`\n InputRoot hash.Hash `json:"input_root"`\n InputStorageSigs []signature.Signature `json:"input_storage_sigs"`\n\n // Optional fields (may be absent for failure indication).\n\n StorageSignatures []signature.Signature `json:"storage_signatures,omitempty"`\n RakSig *signature.RawSignature `json:"rak_sig,omitempty"`\n}\n')),(0,a.kt)("p",null,"The notion of an ",(0,a.kt)("em",{parentName:"p"},"failure-indicating")," executor commitment is introduced as being\nan executor commitment with the following field values:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"failure")," field must be present and non-zero. The code can indicate a\nreason for the failure but currently the reason is ignored during processing.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"header.round"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"header.previous_hash"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"txn_sched_sig"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"input_root")," and\n",(0,a.kt)("inlineCode",{parentName:"p"},"input_storage_sigs")," are set as for usual commitments (e.g., they must be\nvalid).")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"All other fields must be omitted or set to nil."))),(0,a.kt)("h3",{id:"root-hash-commitment-processing"},"Root Hash Commitment Processing"),(0,a.kt)("p",null,"The processing of executor commitments by the commitment pool is modified as\nfollows:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Adding new commitments (",(0,a.kt)("inlineCode",{parentName:"strong"},"AddExecutorCommitment"),")")),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"If a commitment for a node already exists the existing commitment is\nchecked for evidence of equivocation. Any evidence of misbehavior is\nprocessed as described in the ",(0,a.kt)("em",{parentName:"li"},"Evidence")," subsection below."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Discrepancy detection (",(0,a.kt)("inlineCode",{parentName:"strong"},"DetectDiscrepancy"),")")),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"If any executor commitment indicates failure, the discrepancy detection\nprocess signals a discrepancy (which implies that discrepancy resolution is\ntriggered)."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Discrepancy resolution (",(0,a.kt)("inlineCode",{parentName:"strong"},"ResolveDiscrepancy"),")")),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"When tallying votes, any executor commitments indicating failure are tallied\ninto its own bucket. If the failure bucket receives 1/2+ votes, the round\nfails.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If after discrepancy resolution a non-failure option receives 1/2+ votes,\nthis is considered the correct result. Executor commitments for any other\nresult (excluding failure indication) are considered incorrect and are\nsubject to slashing (based on the configured slashing instructions for the\n",(0,a.kt)("inlineCode",{parentName:"p"},"SlashRuntimeIncorrectResults")," reason)."))))),(0,a.kt)("p",null,"A portion of slashed funds is disbursed equally to the compute nodes which\nparticipated in discrepancy resolution for the round. The remainder of slashed\nfunds is transferred to the runtime account."),(0,a.kt)("p",null,"Any slashing instructions related to freezing nodes are currently ignored."),(0,a.kt)("h3",{id:"state"},"State"),(0,a.kt)("p",null,"This proposal introduces/updates the following consensus state in the roothash\nmodule:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"List of past valid evidence (",(0,a.kt)("inlineCode",{parentName:"strong"},"0x24"),")")),(0,a.kt)("p",{parentName:"li"},"A hash uniquely identifying the evidence is stored for each successfully\nprocessed evidence that has not yet expired using the following key format:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"0x24 \n")),(0,a.kt)("p",{parentName:"li"},"The value is empty as we only need to detect duplicate evidence."))),(0,a.kt)("h3",{id:"transaction-methods"},"Transaction Methods"),(0,a.kt)("p",null,"This proposal updates the following transaction methods in the roothash module:"),(0,a.kt)("h4",{id:"evidence"},"Evidence"),(0,a.kt)("p",null,"The evidence method allows anyone to submit evidence of runtime node\nmisbehavior."),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Method name:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"roothash.Evidence\n")),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Body:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-golang"},'type EvidenceKind uint8\n\nconst (\n // EvidenceKindEquivocation is the evidence kind for equivocation.\n EvidenceKindEquivocation = 1\n)\n\ntype Evidence struct {\n ID common.Namespace `json:"id"`\n\n EquivocationExecutor *EquivocationExecutorEvidence `json:"equivocation_executor,omitempty"`\n EquivocationBatch *EquivocationBatchEvidence `json:"equivocation_batch,omitempty"`\n}\n\ntype EquivocationExecutorEvidence struct {\n CommitA commitment.ExecutorCommitment `json:"commit_a"`\n CommitB commitment.ExecutorCommitment `json:"commit_b"`\n}\n\ntype EquivocationBatchEvidence struct {\n BatchA commitment.SignedProposedBatch `json:"batch_a"`\n BatchB commitment.SignedProposedBatch `json:"batch_b"`\n}\n')),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"Fields:")),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"id")," specifies the runtime identifier of a runtime this evidence is for."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"equivocation_executor")," (optional) specifies evidence of an executor node\nequivocating when signing commitments."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"equivocation_batch")," (optional) specifies evidence of an executor node\nequivocating when signing proposed batches.")),(0,a.kt)("p",null,"If no evidence is specified (e.g., all evidence fields are ",(0,a.kt)("inlineCode",{parentName:"p"},"nil"),") the method\ncall is invalid and must fail with ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),"."),(0,a.kt)("p",null,"For all kinds of evidence, the following steps are performed to verify evidence\nvalidity:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Current state for the runtime identified by ",(0,a.kt)("inlineCode",{parentName:"p"},"id")," is fetched. If the runtime\ndoes not exist, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If no slashing instructions for ",(0,a.kt)("inlineCode",{parentName:"p"},"SlashRuntimeEquivocation")," are configured for\nthe given runtime, there is no point in collecting evidence so the method call\nmust fail with ",(0,a.kt)("inlineCode",{parentName:"p"},"ErrRuntimeDoesNotSlash"),"."))),(0,a.kt)("p",null,"When processing ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"EquivocationExecutor"))," evidence, the following steps are\nperformed to verify evidence validity:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"header.round")," fields of both commitments are compared. If they are not the\nsame, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Both executor commitments are checked for basic validity. If either is\ninvalid, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"header.previous_hash"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"header.io_root"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"header.state_root")," and\n",(0,a.kt)("inlineCode",{parentName:"p"},"header.messages_hash")," fields of both commitments are compared. If they are\nthe same, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The failure indication fields of both commitments are compared. If they are\nthe same, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"header.round")," field is compared with the runtime's current state. If it is\nmore than ",(0,a.kt)("inlineCode",{parentName:"p"},"max_evidence_age")," (consensus parameter) rounds behind, the evidence\nis invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Public keys of signers of both commitments are compared. If they are not the\nsame, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Signatures of both commitments are verified. If either is invalid, the\nevidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Otherwise the evidence is valid."))),(0,a.kt)("p",null,"When processing ",(0,a.kt)("strong",{parentName:"p"},(0,a.kt)("inlineCode",{parentName:"strong"},"EquivocationBatch"))," evidence, the following steps are\nperformed to verify evidence validity:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"header.round")," fields of both proposed batches are compared. If they are\nnot the same, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"header")," fields of both proposed batches are checked for basic validity.\nIf any is invalid, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The ",(0,a.kt)("inlineCode",{parentName:"p"},"io_root")," fields of both proposed batches are compared. If they are the\nsame, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Public keys of signers of both commitments are compared. If they are not the\nsame, the evidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Signatures of both proposed batches are validated. If either is invalid, the\nevidence is invalid.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Otherwise the evidence is valid."))),(0,a.kt)("p",null,"For all kinds of valid evidence, the following steps are performed after\nvalidation:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The evidence hash is derived by hashing the evidence kind and the public key\nof the signer and the evidence is looked up in the ",(0,a.kt)("em",{parentName:"p"},"list of past valid\nevidence"),". If evidence already exists there, the method fails with\n",(0,a.kt)("inlineCode",{parentName:"p"},"ErrDuplicateEvidence"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"The valid evidence hash is stored in the ",(0,a.kt)("em",{parentName:"p"},"list of past valid evidence"),"."))),(0,a.kt)("p",null,"If the evidence is deemed valid by the above procedure, the misbehaving compute\nnode is slashed based on the runtime slashing parameters for the\n",(0,a.kt)("inlineCode",{parentName:"p"},"SlashRuntimeEquivocation")," reason."),(0,a.kt)("p",null,"Any slashing instructions related to freezing nodes are currently ignored."),(0,a.kt)("p",null,"The node submitting the evidence may be rewarded from part of the slashed\namount to incentivize evidence submission. The remainder of slashed funds is\ntransferred to the runtime account."),(0,a.kt)("h3",{id:"evidence-expiry"},"Evidence Expiry"),(0,a.kt)("p",null,"On each epoch transition, for each runtime, expired evidence (as defined by the\n",(0,a.kt)("inlineCode",{parentName:"p"},"max_evidence_age")," and the current runtime's round) must be pruned from the\n",(0,a.kt)("em",{parentName:"p"},"list of past valid evidence"),"."),(0,a.kt)("h3",{id:"evidence-collection"},"Evidence Collection"),(0,a.kt)("p",null,"Nodes collect commitment messages distributed via the P2P gossip network and\ncheck for any signs of misbehavior. In case valid evidence can be constructed,\nit is submitted to the consensus layer. Any evidence parts that have expired\nshould be discarded."),(0,a.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,a.kt)("h4",{id:"roothash"},"Roothash"),(0,a.kt)("p",null,"This proposal introduces the following new consensus parameters in the roothash\nmodule:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"max_evidence_age")," (uint64) specifies the maximum age of submitted evidence in\nthe number of rounds.")),(0,a.kt)("h2",{id:"consequences"},"Consequences"),(0,a.kt)("h3",{id:"positive"},"Positive"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Compute nodes can be disincentivized to submit incorrect results by runtimes\nconfiguring slashing parameters.")),(0,a.kt)("h3",{id:"negative"},"Negative"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Checking for duplicate evidence requires additional state in the consensus\nlayer to store the evidence hashes (73 bytes per evidence).")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Expiring old evidence requires additional per-runtime state lookups and\nupdates that happen on each epoch transition.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"If a runtime exhibits non-determinism, this can result in a compute node being\nslashed. While we specify that runtimes should be deterministic, for non-SGX\nruntimes we have no way determining whether a discrepancy is due to runtime\nnon-determinism or a faulty compute node."))),(0,a.kt)("h3",{id:"neutral"},"Neutral"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"This proposal does not introduce any kind of slashing for liveness.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"This proposal does not introduce freezing misbehaving nodes."))),(0,a.kt)("h2",{id:"references"},"References"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/issues/2078"},"oasis-core#2078"))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.96abaa7a.js b/assets/js/935f2afb.96abaa7a.js new file mode 100644 index 0000000000..40cde5b72e --- /dev/null +++ b/assets/js/935f2afb.96abaa7a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"general":[{"type":"link","label":"Overview","href":"/general/","docId":"general/README"},{"type":"category","label":"Oasis Network","collapsible":false,"items":[{"type":"link","label":"Why Oasis?","href":"/general/oasis-network/why-oasis","docId":"general/oasis-network/why-oasis"},{"type":"link","label":"Token Metrics and Distribution","href":"/general/oasis-network/token-metrics-and-distribution","docId":"general/oasis-network/token-metrics-and-distribution"},{"type":"link","label":"Papers","href":"https://oasisprotocol.org/papers"},{"type":"link","label":"Frequently Asked Questions","href":"/general/oasis-network/faq","docId":"general/oasis-network/faq"}],"collapsed":false,"href":"/general/oasis-network/"},{"type":"category","label":"Manage your Tokens","collapsible":false,"items":[{"type":"link","label":"Terminology","href":"/general/manage-tokens/terminology","docId":"general/manage-tokens/terminology"},{"type":"link","label":"Staking and Delegating","href":"/general/manage-tokens/staking-and-delegating","docId":"general/manage-tokens/staking-and-delegating"},{"type":"category","label":"Oasis Wallets","items":[{"type":"link","label":"Web","href":"/general/manage-tokens/oasis-wallets/web","docId":"general/manage-tokens/oasis-wallets/web"},{"type":"link","label":"Browser Extension","href":"/general/manage-tokens/oasis-wallets/browser-extension","docId":"general/manage-tokens/oasis-wallets/browser-extension"}],"collapsed":true,"collapsible":true,"href":"/general/manage-tokens/oasis-wallets/"},{"type":"category","label":"3rd Party Custody & Wallets","items":[{"type":"link","label":"Custody Providers","href":"/general/manage-tokens/holding-rose-tokens/custody-providers","docId":"general/manage-tokens/holding-rose-tokens/custody-providers"},{"type":"link","label":"Self-Custody With Ledger Hardware Wallet","href":"/general/manage-tokens/holding-rose-tokens/ledger-wallet","docId":"general/manage-tokens/holding-rose-tokens/ledger-wallet"}],"collapsed":true,"collapsible":true,"href":"/general/manage-tokens/holding-rose-tokens"},{"type":"link","label":"How to Transfer ROSE into a ParaTime","href":"/general/manage-tokens/how-to-transfer-rose-into-paratime","docId":"general/manage-tokens/how-to-transfer-rose-into-paratime"},{"type":"link","label":"How to Transfer ETH/ERC20 to Emerald ParaTime","href":"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","docId":"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime"},{"type":"category","label":"Oasis CLI","items":[{"type":"link","label":"Setup","href":"/general/manage-tokens/cli/setup","docId":"general/manage-tokens/cli/setup"},{"type":"link","label":"Network","href":"/general/manage-tokens/cli/network","docId":"general/manage-tokens/cli/network"},{"type":"link","label":"ParaTime","href":"/general/manage-tokens/cli/paratime","docId":"general/manage-tokens/cli/paratime"},{"type":"link","label":"Wallet","href":"/general/manage-tokens/cli/wallet","docId":"general/manage-tokens/cli/wallet"},{"type":"link","label":"Account","href":"/general/manage-tokens/cli/account","docId":"general/manage-tokens/cli/account"},{"type":"link","label":"Transaction","href":"/general/manage-tokens/cli/transaction","docId":"general/manage-tokens/cli/transaction"},{"type":"link","label":"Address book","href":"/general/manage-tokens/cli/addressbook","docId":"general/manage-tokens/cli/addressbook"}],"collapsed":true,"collapsible":true,"href":"/general/manage-tokens/cli/"},{"type":"link","label":"Frequently Asked Questions","href":"/general/manage-tokens/faq","docId":"general/manage-tokens/faq"}],"collapsed":false,"href":"/general/manage-tokens/"}],"operators":[{"type":"link","label":"Overview","href":"/node/","docId":"node/README"},{"type":"category","label":"Mainnet","collapsible":false,"items":[{"type":"link","label":"E* Upgrade","href":"/node/mainnet/e-upgrade","docId":"node/mainnet/e-upgrade"},{"type":"link","label":"Damask Upgrade","href":"/node/mainnet/damask-upgrade","docId":"node/mainnet/damask-upgrade"},{"type":"category","label":"Previous Upgrades","items":[{"type":"link","label":"Cobalt Upgrade","href":"/node/mainnet/previous-upgrades/cobalt-upgrade","docId":"node/mainnet/previous-upgrades/cobalt-upgrade"},{"type":"link","label":"Upgrade to Mainnet","href":"/node/mainnet/previous-upgrades/mainnet-upgrade","docId":"node/mainnet/previous-upgrades/mainnet-upgrade"}],"collapsed":true,"collapsible":true,"href":"/node/mainnet/previous-upgrades"},{"type":"link","label":"Upgrade Log","href":"/node/mainnet/upgrade-log","docId":"node/mainnet/upgrade-log"}],"collapsed":false,"href":"/node/mainnet/"},{"type":"category","label":"Testnet","collapsible":false,"items":[{"type":"link","label":"Upgrade Log","href":"/node/testnet/upgrade-log","docId":"node/testnet/upgrade-log"}],"collapsed":false,"href":"/node/testnet/"},{"type":"link","label":"Genesis Document","href":"/node/genesis-doc","docId":"node/genesis-doc"},{"type":"category","label":"Run Your Node","collapsible":false,"items":[{"type":"category","label":"Prerequisites","items":[{"type":"link","label":"Hardware Requirements","href":"/node/run-your-node/prerequisites/hardware-recommendations","docId":"node/run-your-node/prerequisites/hardware-recommendations"},{"type":"link","label":"Stake Requirements","href":"/node/run-your-node/prerequisites/stake-requirements","docId":"node/run-your-node/prerequisites/stake-requirements"},{"type":"link","label":"Install Oasis Node Binary","href":"/node/run-your-node/prerequisites/oasis-node","docId":"node/run-your-node/prerequisites/oasis-node"},{"type":"link","label":"System Configuration","href":"/node/run-your-node/prerequisites/system-configuration","docId":"node/run-your-node/prerequisites/system-configuration"},{"type":"link","label":"Set up Trusted Execution Environment (TEE)","href":"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","docId":"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"}],"collapsed":true,"collapsible":true,"href":"/node/run-your-node/prerequisites"},{"type":"link","label":"Validator Node","href":"/node/run-your-node/validator-node","docId":"node/run-your-node/validator-node"},{"type":"link","label":"Non-validator Node","href":"/node/run-your-node/non-validator-node","docId":"node/run-your-node/non-validator-node"},{"type":"link","label":"Seed Node","href":"/node/run-your-node/seed-node","docId":"node/run-your-node/seed-node"},{"type":"link","label":"Archive Node","href":"/node/run-your-node/archive-node","docId":"node/run-your-node/archive-node"},{"type":"link","label":"ParaTime Node","href":"/node/run-your-node/paratime-node","docId":"node/run-your-node/paratime-node"},{"type":"link","label":"ParaTime Client Node","href":"/node/run-your-node/paratime-client-node","docId":"node/run-your-node/paratime-client-node"},{"type":"category","label":"Key Manager Node","items":[{"type":"link","label":"Signing Key Manager Policy","href":"/node/run-your-node/keymanager-node/signing-key-manager-policy","docId":"node/run-your-node/keymanager-node/signing-key-manager-policy"},{"type":"link","label":"Upgrading Key Managers","href":"/node/run-your-node/keymanager-node/key-manager-upgrade","docId":"node/run-your-node/keymanager-node/key-manager-upgrade"}],"collapsed":true,"collapsible":true,"href":"/node/run-your-node/keymanager-node/"},{"type":"link","label":"IAS Proxy","href":"/node/run-your-node/ias-proxy","docId":"node/run-your-node/ias-proxy"},{"type":"link","label":"Sentry Node","href":"/node/run-your-node/sentry-node","docId":"node/run-your-node/sentry-node"},{"type":"category","label":"Maintenance","items":[{"type":"link","label":"Wiping Node State","href":"/node/run-your-node/maintenance/wiping-node-state","docId":"node/run-your-node/maintenance/wiping-node-state"},{"type":"link","label":"Handling Network Upgrades","href":"/node/run-your-node/maintenance/handling-network-upgrades","docId":"node/run-your-node/maintenance/handling-network-upgrades"},{"type":"link","label":"Adding or Removing Nodes","href":"/node/run-your-node/maintenance/adding-or-removing-nodes","docId":"node/run-your-node/maintenance/adding-or-removing-nodes"},{"type":"link","label":"Refreshing Node Certificates","href":"/node/run-your-node/maintenance/refreshing-certificates","docId":"node/run-your-node/maintenance/refreshing-certificates"},{"type":"link","label":"Shutting Down a Node","href":"/node/run-your-node/maintenance/shutting-down-a-node","docId":"node/run-your-node/maintenance/shutting-down-a-node"}],"collapsed":true,"collapsible":true,"href":"/node/run-your-node/maintenance"},{"type":"category","label":"Advanced","items":[{"type":"link","label":"Using State Sync for Quick Bootstraping","href":"/node/run-your-node/advanced/sync-node-using-state-sync","docId":"node/run-your-node/advanced/sync-node-using-state-sync"},{"type":"link","label":"Copy State from One Node to the Other","href":"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other","docId":"node/run-your-node/advanced/copy-state-from-one-node-to-the-other"},{"type":"link","label":"Install Oasis Remote Signer Binary","href":"/node/run-your-node/advanced/install-oasis-remote-signer-binary","docId":"node/run-your-node/advanced/install-oasis-remote-signer-binary"},{"type":"link","label":"Using Ledger-backed Consensus Key with a Remote Signer","href":"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer","docId":"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer"}],"collapsed":true,"collapsible":true,"href":"/node/run-your-node/advanced"},{"type":"link","label":"Troubleshooting","href":"/node/run-your-node/troubleshooting","docId":"node/run-your-node/troubleshooting"}],"collapsed":false,"href":"/node/run-your-node"},{"type":"link","label":"Web3 Gateway","href":"/node/web3","docId":"node/web3"}],"developers":[{"type":"link","label":"Overview","href":"/dapp/","docId":"dapp/README"},{"type":"category","label":"Sapphire","items":[{"type":"link","label":"Quickstart","href":"/dapp/sapphire/quickstart","docId":"dapp/sapphire/quickstart"},{"type":"link","label":"Guide","href":"/dapp/sapphire/guide","docId":"dapp/sapphire/guide"},{"type":"link","label":"Browser Support","href":"/dapp/sapphire/browser","docId":"dapp/sapphire/browser"},{"type":"link","label":"Gasless Transactions","href":"/dapp/sapphire/gasless","docId":"dapp/sapphire/gasless"},{"type":"link","label":"Precompiles","href":"/dapp/sapphire/precompiles","docId":"dapp/sapphire/precompiles"},{"type":"link","label":"Standard Contract Addresses","href":"/dapp/sapphire/addresses","docId":"dapp/sapphire/addresses"}],"collapsed":true,"collapsible":true,"href":"/dapp/sapphire/"},{"type":"category","label":"Oasis Privacy Layer","items":[{"type":"link","label":"Overview","href":"/dapp/opl/introduction","docId":"dapp/opl/introduction"},{"type":"link","label":"Setup","href":"/dapp/opl/setup","docId":"dapp/opl/setup"},{"type":"link","label":"DAO Contract","href":"/dapp/opl/host","docId":"dapp/opl/host"},{"type":"link","label":"Ballot Contract","href":"/dapp/opl/enclave","docId":"dapp/opl/enclave"},{"type":"link","label":"Build","href":"/dapp/opl/build","docId":"dapp/opl/build"},{"type":"link","label":"Frontend Application","href":"/dapp/opl/frontend","docId":"dapp/opl/frontend"}],"collapsed":true,"collapsible":true,"href":"/dapp/opl/"},{"type":"category","label":"Emerald","items":[{"type":"link","label":"Writing dApps on Emerald","href":"/dapp/emerald/writing-dapps-on-emerald","docId":"dapp/emerald/writing-dapps-on-emerald"},{"type":"link","label":"Integrating BAND oracle smart contract","href":"/dapp/emerald/integrating-band-oracle-smart-contract","docId":"dapp/emerald/integrating-band-oracle-smart-contract"}],"collapsed":true,"collapsible":true,"href":"/dapp/emerald/"},{"type":"category","label":"Cipher","items":[{"type":"link","label":"Prerequisites","href":"/dapp/cipher/prerequisites","docId":"dapp/cipher/prerequisites"},{"type":"link","label":"Hello World","href":"/dapp/cipher/hello-world","docId":"dapp/cipher/hello-world"},{"type":"link","label":"Confidential Hello World","href":"/dapp/cipher/confidential-smart-contract","docId":"dapp/cipher/confidential-smart-contract"},{"type":"link","label":"Rust API","href":"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk"},{"type":"link","label":"Go API","href":"https://pkg.go.dev/github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"}],"collapsed":true,"collapsible":true,"href":"/dapp/cipher/"}],"paratime":[{"type":"link","label":"Overview","href":"/paratime/","docId":"paratime/README"},{"type":"link","label":"Prerequisites","href":"/paratime/prerequisites","docId":"paratime/prerequisites"},{"type":"link","label":"Minimal Runtime","href":"/paratime/minimal-runtime","docId":"paratime/minimal-runtime"},{"type":"link","label":"Modules","href":"/paratime/modules","docId":"paratime/modules"},{"type":"link","label":"Reproducibility","href":"/paratime/reproducibility","docId":"paratime/reproducibility"},{"type":"link","label":"Rust API","href":"https://api.docs.oasis.io/oasis-sdk/oasis_runtime_sdk"}],"oasisCore":[{"type":"link","label":"Overview","href":"/core/","docId":"core/README"},{"type":"category","label":"Development Setup","collapsible":false,"items":[{"type":"category","label":"Build Environment Setup and Building","items":[{"type":"link","label":"Prerequisites","href":"/core/development-setup/prerequisites","docId":"core/development-setup/prerequisites"},{"type":"link","label":"Building","href":"/core/development-setup/building","docId":"core/development-setup/building"}],"collapsed":true,"collapsible":true,"href":"/core/development-setup/build-environment-setup-and-building"},{"type":"category","label":"Running Tests and Development Networks","items":[{"type":"link","label":"Running Tests","href":"/core/development-setup/running-tests","docId":"core/development-setup/running-tests"},{"type":"link","label":"Local Network Runner","href":"/core/development-setup/oasis-net-runner","docId":"core/development-setup/oasis-net-runner"},{"type":"link","label":"Single Validator Node Network","href":"/core/development-setup/single-validator-node-network","docId":"core/development-setup/single-validator-node-network"},{"type":"link","label":"Deploying a Runtime","href":"/core/development-setup/deploying-a-runtime","docId":"core/development-setup/deploying-a-runtime"}],"collapsed":true,"collapsible":true,"href":"/core/development-setup/running-tests-and-development-networks"}],"collapsed":false,"href":"/core/development-setup"},{"type":"category","label":"High-Level Components","collapsible":false,"items":[{"type":"category","label":"Consensus Layer","items":[{"type":"link","label":"Transactions","href":"/core/consensus/transactions","docId":"core/consensus/transactions"},{"type":"category","label":"Services","items":[{"type":"link","label":"Epoch Time","href":"/core/consensus/services/epochtime","docId":"core/consensus/services/epochtime"},{"type":"link","label":"Random Beacon","href":"/core/consensus/services/beacon","docId":"core/consensus/services/beacon"},{"type":"link","label":"Staking","href":"/core/consensus/services/staking","docId":"core/consensus/services/staking"},{"type":"link","label":"Registry","href":"/core/consensus/services/registry","docId":"core/consensus/services/registry"},{"type":"link","label":"Committee Scheduler","href":"/core/consensus/services/scheduler","docId":"core/consensus/services/scheduler"},{"type":"link","label":"Governance","href":"/core/consensus/services/governance","docId":"core/consensus/services/governance"},{"type":"link","label":"Root Hash","href":"/core/consensus/services/roothash","docId":"core/consensus/services/roothash"},{"type":"link","label":"Key Manager","href":"/core/consensus/services/keymanager","docId":"core/consensus/services/keymanager"}],"collapsed":true,"collapsible":true,"href":"/core/consensus/services"},{"type":"link","label":"Genesis Document","href":"/core/consensus/genesis","docId":"core/consensus/genesis"},{"type":"link","label":"Transaction Test Vectors","href":"/core/consensus/test-vectors","docId":"core/consensus/test-vectors"}],"collapsed":true,"collapsible":true,"href":"/core/consensus/"},{"type":"category","label":"Runtime Layer","items":[{"type":"link","label":"Runtime Host Protocol","href":"/core/runtime/runtime-host-protocol","docId":"core/runtime/runtime-host-protocol"},{"type":"link","label":"Runtime IDs","href":"/core/runtime/identifiers","docId":"core/runtime/identifiers"},{"type":"link","label":"Runtime Messages","href":"/core/runtime/messages","docId":"core/runtime/messages"}],"collapsed":true,"collapsible":true,"href":"/core/runtime/"},{"type":"category","label":"Oasis Node","items":[{"type":"link","label":"RPC","href":"/core/oasis-node/rpc","docId":"core/oasis-node/rpc"},{"type":"link","label":"Metrics","href":"/core/oasis-node/metrics","docId":"core/oasis-node/metrics"},{"type":"link","label":"oasis-node CLI","href":"/core/oasis-node/cli","docId":"core/oasis-node/cli"}],"collapsed":true,"collapsible":true,"href":"/core/oasis-node"}],"collapsed":false,"href":"/core/high-level-components"},{"type":"category","label":"Common Functionality","collapsible":false,"items":[{"type":"link","label":"Encoding","href":"/core/encoding","docId":"core/encoding"},{"type":"link","label":"Cryptography","href":"/core/crypto","docId":"core/crypto"},{"type":"category","label":"Protocols","items":[{"type":"link","label":"Authenticated gRPC","href":"/core/authenticated-grpc","docId":"core/authenticated-grpc"}],"collapsed":true,"collapsible":true},{"type":"link","label":"Merklized Key-Value Store (MKVS)","href":"/core/mkvs","docId":"core/mkvs"}],"collapsed":false,"href":"/core/common-functionality"},{"type":"category","label":"Processes","collapsible":false,"items":[{"type":"link","label":"Release Process","href":"/core/release-process","docId":"core/release-process"},{"type":"link","label":"Versioning","href":"/core/versioning","docId":"core/versioning"},{"type":"link","label":"Security","href":"/core/SECURITY","docId":"core/SECURITY"}],"collapsed":false,"href":"/core/processes"},{"type":"link","label":"Oasis Core Ledger","href":"/oasis-core-ledger"},{"type":"link","label":"ADRs","href":"/adrs"}],"oasisSdk":[{"type":"link","label":"Introduction to Oasis Core Ledger","href":"/oasis-core-ledger/","docId":"oasis-core-ledger/README"},{"type":"category","label":"Usage","collapsible":false,"items":[{"type":"link","label":"Setup","href":"/oasis-core-ledger/usage/setup","docId":"oasis-core-ledger/usage/setup"},{"type":"link","label":"Obtaining Account Address","href":"/oasis-core-ledger/usage/address","docId":"oasis-core-ledger/usage/address"},{"type":"link","label":"Exporting Public Key to Entity","href":"/oasis-core-ledger/usage/entity","docId":"oasis-core-ledger/usage/entity"},{"type":"link","label":"Generating and Signing Transactions","href":"/oasis-core-ledger/usage/transactions","docId":"oasis-core-ledger/usage/transactions"},{"type":"link","label":"Identifying Wallets","href":"/oasis-core-ledger/usage/wallets","docId":"oasis-core-ledger/usage/wallets"}],"collapsed":false},{"type":"category","label":"Processes","collapsible":false,"items":[{"type":"link","label":"Versioning","href":"/oasis-core-ledger/versioning","docId":"oasis-core-ledger/versioning"},{"type":"link","label":"Release Process","href":"/oasis-core-ledger/release-process","docId":"oasis-core-ledger/release-process"}],"collapsed":false}],"adrs":[{"type":"category","label":"Architectural Decision Records","items":[{"type":"link","label":"ADR 0001: Multiple Roots Under the Tendermint Application Hash","href":"/adrs/0001-tm-multi-root-apphash","docId":"adrs/0001-tm-multi-root-apphash"},{"type":"link","label":"ADR 0002: Go Modules Compatible Git Tags","href":"/adrs/0002-go-modules-compatible-git-tags","docId":"adrs/0002-go-modules-compatible-git-tags"},{"type":"link","label":"ADR 0003: Consensus/Runtime Token Transfer","href":"/adrs/0003-consensus-runtime-token-transfer","docId":"adrs/0003-consensus-runtime-token-transfer"},{"type":"link","label":"ADR 0004: Runtime Governance","href":"/adrs/0004-runtime-governance","docId":"adrs/0004-runtime-governance"},{"type":"link","label":"ADR 0005: Runtime Compute Node Slashing","href":"/adrs/0005-runtime-compute-slashing","docId":"adrs/0005-runtime-compute-slashing"},{"type":"link","label":"ADR 0006: Consensus Governance","href":"/adrs/0006-consensus-governance","docId":"adrs/0006-consensus-governance"},{"type":"link","label":"ADR 0007: Improved Random Beacon","href":"/adrs/0007-improved-random-beacon","docId":"adrs/0007-improved-random-beacon"},{"type":"link","label":"ADR 0008: Standard Account Key Generation","href":"/adrs/0008-standard-account-key-generation","docId":"adrs/0008-standard-account-key-generation"},{"type":"link","label":"ADR 0009: Ed25519 Signature Verification Semantics","href":"/adrs/0009-ed25519-semantics","docId":"adrs/0009-ed25519-semantics"},{"type":"link","label":"ADR 0010: VRF-based Committee Elections","href":"/adrs/0010-vrf-elections","docId":"adrs/0010-vrf-elections"},{"type":"link","label":"ADR 0011: Incoming Runtime Messages","href":"/adrs/0011-incoming-runtime-messages","docId":"adrs/0011-incoming-runtime-messages"},{"type":"link","label":"ADR 0012: Runtime Message Results","href":"/adrs/0012-runtime-message-results","docId":"adrs/0012-runtime-message-results"},{"type":"link","label":"ADR 0013: Runtime Upgrade Improvements","href":"/adrs/0013-runtime-upgrades","docId":"adrs/0013-runtime-upgrades"},{"type":"link","label":"ADR 0014: Signing Runtime Transactions with Hardware Wallet","href":"/adrs/0014-runtime-signing-tx-with-hardware-wallet","docId":"adrs/0014-runtime-signing-tx-with-hardware-wallet"},{"type":"link","label":"ADR 0015: Randomized Paratime Proposer Selection","href":"/adrs/0015-vrf-per-block-entropy","docId":"adrs/0015-vrf-per-block-entropy"},{"type":"link","label":"ADR 0016: Consensus Parameters Change Proposal","href":"/adrs/0016-consensus-parameters-change-proposal","docId":"adrs/0016-consensus-parameters-change-proposal"},{"type":"link","label":"ADR 0017: ParaTime Application Standard Proposal Process","href":"/adrs/0017-app-standards","docId":"adrs/0017-app-standards"},{"type":"link","label":"ADR 0020: Governance Support for Delegator Votes","href":"/adrs/0020-governance-delegator-votes","docId":"adrs/0020-governance-delegator-votes"},{"type":"link","label":"ADR 0021: Forward-Secret Ephemeral Secrets","href":"/adrs/0021-keymanager-ephemeral-secrets","docId":"adrs/0021-keymanager-ephemeral-secrets"},{"type":"link","label":"ADR 0022: Forward-Secret Master Secrets","href":"/adrs/0022-keymanager-master-secrets","docId":"adrs/0022-keymanager-master-secrets"}],"collapsed":true,"collapsible":true,"href":"/adrs"}],"getInvolved":[{"type":"link","label":"Join our Community","href":"/get-involved/","docId":"get-involved/README"},{"type":"link","label":"Become our Ambassador","href":"https://oasisprotocol.org/ambassador-program"},{"type":"link","label":"Become our Influencer","href":"https://oasisprotocol.org/influencer"},{"type":"link","label":"Apply for Grant","href":"https://oasisprotocol.org/grant-programs"},{"type":"link","label":"Join our University Program","href":"https://oasisprotocol.org/university-program"},{"type":"link","label":"Follow Community Portal","href":"https://oasisrose.garden"},{"type":"category","label":"Run a Node","collapsible":false,"items":[{"type":"link","label":"Consensus Validator Node","href":"/get-involved/run-node/validator-node","docId":"get-involved/run-node/validator-node"},{"type":"link","label":"ParaTime Node","href":"/get-involved/run-node/paratime-node","docId":"get-involved/run-node/paratime-node"}],"collapsed":false,"href":"/get-involved/run-node"},{"type":"link","label":"Develop Oasis Core","href":"/get-involved/oasis-core","docId":"get-involved/oasis-core"},{"type":"link","label":"Network Governance","href":"/get-involved/network-governance","docId":"get-involved/network-governance"},{"type":"link","label":"Delegation Policy","href":"/get-involved/delegation-policy","docId":"get-involved/delegation-policy"},{"type":"link","label":"Token Delivery & KYC Guide","href":"/get-involved/token-delivery-and-kyc","docId":"get-involved/token-delivery-and-kyc"}]},"docs":{"adrs/0001-tm-multi-root-apphash":{"id":"adrs/0001-tm-multi-root-apphash","title":"ADR 0001: Multiple Roots Under the Tendermint Application Hash","description":"Component","sidebar":"adrs"},"adrs/0002-go-modules-compatible-git-tags":{"id":"adrs/0002-go-modules-compatible-git-tags","title":"ADR 0002: Go Modules Compatible Git Tags","description":"Component","sidebar":"adrs"},"adrs/0003-consensus-runtime-token-transfer":{"id":"adrs/0003-consensus-runtime-token-transfer","title":"ADR 0003: Consensus/Runtime Token Transfer","description":"Component","sidebar":"adrs"},"adrs/0004-runtime-governance":{"id":"adrs/0004-runtime-governance","title":"ADR 0004: Runtime Governance","description":"Component","sidebar":"adrs"},"adrs/0005-runtime-compute-slashing":{"id":"adrs/0005-runtime-compute-slashing","title":"ADR 0005: Runtime Compute Node Slashing","description":"Component","sidebar":"adrs"},"adrs/0006-consensus-governance":{"id":"adrs/0006-consensus-governance","title":"ADR 0006: Consensus Governance","description":"Component","sidebar":"adrs"},"adrs/0007-improved-random-beacon":{"id":"adrs/0007-improved-random-beacon","title":"ADR 0007: Improved Random Beacon","description":"Component","sidebar":"adrs"},"adrs/0008-standard-account-key-generation":{"id":"adrs/0008-standard-account-key-generation","title":"ADR 0008: Standard Account Key Generation","description":"Component","sidebar":"adrs"},"adrs/0009-ed25519-semantics":{"id":"adrs/0009-ed25519-semantics","title":"ADR 0009: Ed25519 Signature Verification Semantics","description":"Component","sidebar":"adrs"},"adrs/0010-vrf-elections":{"id":"adrs/0010-vrf-elections","title":"ADR 0010: VRF-based Committee Elections","description":"Component","sidebar":"adrs"},"adrs/0011-incoming-runtime-messages":{"id":"adrs/0011-incoming-runtime-messages","title":"ADR 0011: Incoming Runtime Messages","description":"Component","sidebar":"adrs"},"adrs/0012-runtime-message-results":{"id":"adrs/0012-runtime-message-results","title":"ADR 0012: Runtime Message Results","description":"Component","sidebar":"adrs"},"adrs/0013-runtime-upgrades":{"id":"adrs/0013-runtime-upgrades","title":"ADR 0013: Runtime Upgrade Improvements","description":"Component","sidebar":"adrs"},"adrs/0014-runtime-signing-tx-with-hardware-wallet":{"id":"adrs/0014-runtime-signing-tx-with-hardware-wallet","title":"ADR 0014: Signing Runtime Transactions with Hardware Wallet","description":"Component","sidebar":"adrs"},"adrs/0015-vrf-per-block-entropy":{"id":"adrs/0015-vrf-per-block-entropy","title":"ADR 0015: Randomized Paratime Proposer Selection","description":"Component","sidebar":"adrs"},"adrs/0016-consensus-parameters-change-proposal":{"id":"adrs/0016-consensus-parameters-change-proposal","title":"ADR 0016: Consensus Parameters Change Proposal","description":"Component","sidebar":"adrs"},"adrs/0017-app-standards":{"id":"adrs/0017-app-standards","title":"ADR 0017: ParaTime Application Standard Proposal Process","description":"Component","sidebar":"adrs"},"adrs/0020-governance-delegator-votes":{"id":"adrs/0020-governance-delegator-votes","title":"ADR 0020: Governance Support for Delegator Votes","description":"Component","sidebar":"adrs"},"adrs/0021-keymanager-ephemeral-secrets":{"id":"adrs/0021-keymanager-ephemeral-secrets","title":"ADR 0021: Forward-Secret Ephemeral Secrets","description":"Component","sidebar":"adrs"},"adrs/0022-keymanager-master-secrets":{"id":"adrs/0022-keymanager-master-secrets","title":"ADR 0022: Forward-Secret Master Secrets","description":"Component","sidebar":"adrs"},"core/authenticated-grpc":{"id":"core/authenticated-grpc","title":"Authenticated gRPC","description":"Oasis Core nodes communicate between themselves over various protocols. One of","sidebar":"oasisCore"},"core/bigint":{"id":"core/bigint","title":"Big Integer Quantities","description":"Arbitrary-precision positive integer quantities are represented by the"},"core/consensus/genesis":{"id":"core/consensus/genesis","title":"Genesis Document","description":"The genesis document contains a set of parameters that outline the initial state","sidebar":"oasisCore"},"core/consensus/README":{"id":"core/consensus/README","title":"Consensus Layer","description":"Oasis Core is designed around the principle of modularity. The consensus layer","sidebar":"oasisCore"},"core/consensus/services/beacon":{"id":"core/consensus/services/beacon","title":"Random Beacon","description":"The random beacon service is responsible for providing a source of unbiased","sidebar":"oasisCore"},"core/consensus/services/epochtime":{"id":"core/consensus/services/epochtime","title":"Epoch Time","description":"","sidebar":"oasisCore"},"core/consensus/services/governance":{"id":"core/consensus/services/governance","title":"Governance","description":"The governance service is responsible for providing an on-chain governance","sidebar":"oasisCore"},"core/consensus/services/keymanager":{"id":"core/consensus/services/keymanager","title":"Key Manager","description":"The key manager service is responsible for coordinating the SGX-based key","sidebar":"oasisCore"},"core/consensus/services/registry":{"id":"core/consensus/services/registry","title":"Registry","description":"The registry service is responsible for managing a registry of runtime, entity","sidebar":"oasisCore"},"core/consensus/services/roothash":{"id":"core/consensus/services/roothash","title":"Root Hash","description":"The roothash service is responsible for runtime commitment processing and","sidebar":"oasisCore"},"core/consensus/services/scheduler":{"id":"core/consensus/services/scheduler","title":"Committee Scheduler","description":"The committee scheduler service is responsible for periodically scheduling all","sidebar":"oasisCore"},"core/consensus/services/staking":{"id":"core/consensus/services/staking","title":"Staking","description":"The staking service is responsible for managing the staking ledger in the","sidebar":"oasisCore"},"core/consensus/test-vectors":{"id":"core/consensus/test-vectors","title":"Transaction Test Vectors","description":"In order to test transaction generation, parsing and signing, we provide a set","sidebar":"oasisCore"},"core/consensus/transactions":{"id":"core/consensus/transactions","title":"Transactions","description":"The consensus layer uses a common transaction format for all transactions. As","sidebar":"oasisCore"},"core/crypto":{"id":"core/crypto","title":"Cryptography","description":"Hash Functions","sidebar":"oasisCore"},"core/development-setup/building":{"id":"core/development-setup/building","title":"Building","description":"This section contains a description of steps required to build Oasis Core.","sidebar":"oasisCore"},"core/development-setup/deploying-a-runtime":{"id":"core/development-setup/deploying-a-runtime","title":"Deploying a Runtime","description":"Before proceeding, make sure to look at the [prerequisites] required for running","sidebar":"oasisCore"},"core/development-setup/oasis-net-runner":{"id":"core/development-setup/oasis-net-runner","title":"Local Network Runner","description":"In order to make development easier (and also to facilitate automated E2E","sidebar":"oasisCore"},"core/development-setup/prerequisites":{"id":"core/development-setup/prerequisites","title":"Prerequisites","description":"The following is a list of prerequisites required to start developing on Oasis","sidebar":"oasisCore"},"core/development-setup/running-tests":{"id":"core/development-setup/running-tests","title":"Running Tests","description":"Before proceeding, make sure to look at the [prerequisites] required for running","sidebar":"oasisCore"},"core/development-setup/single-validator-node-network":{"id":"core/development-setup/single-validator-node-network","title":"Single Validator Node Network","description":"It is possible to provision a local \\"network\\" consisting of a single validator","sidebar":"oasisCore"},"core/encoding":{"id":"core/encoding","title":"Encoding","description":"All messages exchanged by different components in Oasis Core are encoded using","sidebar":"oasisCore"},"core/mkvs":{"id":"core/mkvs","title":"Merklized Key-Value Store (MKVS)","description":"For all places that require an [authenticated data structure (ADS)] we provide","sidebar":"oasisCore"},"core/oasis-node/cli":{"id":"core/oasis-node/cli","title":"oasis-node CLI","description":"control","sidebar":"oasisCore"},"core/oasis-node/metrics":{"id":"core/oasis-node/metrics","title":"Metrics","description":"oasis-node can report a number of metrics to Prometheus server. By default,","sidebar":"oasisCore"},"core/oasis-node/rpc":{"id":"core/oasis-node/rpc","title":"RPC","description":"Oasis Node exposes an RPC interface to enable external applications to query","sidebar":"oasisCore"},"core/README":{"id":"core/README","title":"Oasis Core Developer Documentation","description":"Architecture","sidebar":"oasisCore"},"core/release-process":{"id":"core/release-process","title":"Release Process","description":"The following steps should be followed when preparing a release.","sidebar":"oasisCore"},"core/runtime/identifiers":{"id":"core/runtime/identifiers","title":"Runtime IDs","description":"Identifiers for runtimes are represented by the [common.Namespace] type.","sidebar":"oasisCore"},"core/runtime/messages":{"id":"core/runtime/messages","title":"Runtime Messages","description":"In order to enable runtimes to perform actions in the consensus layer on their","sidebar":"oasisCore"},"core/runtime/README":{"id":"core/runtime/README","title":"Runtime Layer","description":"Runtime Layer","sidebar":"oasisCore"},"core/runtime/runtime-host-protocol":{"id":"core/runtime/runtime-host-protocol","title":"Runtime Host Protocol","description":"The Runtime Host Protocol (RHP) is a simple RPC protocol which is used to","sidebar":"oasisCore"},"core/SECURITY":{"id":"core/SECURITY","title":"Security","description":"At [Oasis Foundation], we take security very seriously and we deeply appreciate","sidebar":"oasisCore"},"core/versioning":{"id":"core/versioning","title":"Versioning","description":"Oasis Core","sidebar":"oasisCore"},"dapp/cipher/confidential-smart-contract":{"id":"dapp/cipher/confidential-smart-contract","title":"Confidential Hello World","description":"Confidential smart contract execution on Oasis is assured by three mechanisms:","sidebar":"developers"},"dapp/cipher/hello-world":{"id":"dapp/cipher/hello-world","title":"Hello World","description":"This section will show you how to quickly create, build and test a minimal","sidebar":"developers"},"dapp/cipher/prerequisites":{"id":"dapp/cipher/prerequisites","title":"Prerequisites","description":"How to build your first smart contract on Oasis","sidebar":"developers"},"dapp/cipher/README":{"id":"dapp/cipher/README","title":"Cipher ParaTime","description":"The Cipher ParaTime is a Confidential ParaTime for executing Wasm smart contracts.","sidebar":"developers"},"dapp/emerald/integrating-band-oracle-smart-contract":{"id":"dapp/emerald/integrating-band-oracle-smart-contract","title":"Integrating BAND oracle smart contract","description":"This guide will explain how to query the Band Protocol reference data smart","sidebar":"developers"},"dapp/emerald/README":{"id":"dapp/emerald/README","title":"Emerald ParaTime","description":"The Emerald ParaTime is our official EVM Compatible ParaTime providing smart contract environment with full EVM compatibility.","sidebar":"developers"},"dapp/emerald/writing-dapps-on-emerald":{"id":"dapp/emerald/writing-dapps-on-emerald","title":"Writing dApps on Emerald","description":"This tutorial will show you how to set up dApp development environment for","sidebar":"developers"},"dapp/opl/build":{"id":"dapp/opl/build","title":"Build","description":"Now that we have written our two smart contracts, let\'s compile and deploy them!","sidebar":"developers"},"dapp/opl/enclave":{"id":"dapp/opl/enclave","title":"Ballot Contract","description":"Next, we will write a smart contract that holds private data. This smart","sidebar":"developers"},"dapp/opl/frontend":{"id":"dapp/opl/frontend","title":"Frontend Application","description":"We will need a Pinata development API","sidebar":"developers"},"dapp/opl/host":{"id":"dapp/opl/host","title":"DAO Contract","description":"Let\'s start with a smart contract that describes a basic DAO, DAOV1.sol, with a","sidebar":"developers"},"dapp/opl/introduction":{"id":"dapp/opl/introduction","title":"Overview","description":"How to build your first dApp on OPL","sidebar":"developers"},"dapp/opl/README":{"id":"dapp/opl/README","title":"Oasis Privacy Layer","description":"The Oasis Privacy Layer (OPL) is an EVM-compatible privacy solution that","sidebar":"developers"},"dapp/opl/setup":{"id":"dapp/opl/setup","title":"Setup","description":"Let\'s get started and make our new project. You will need Node.js","sidebar":"developers"},"dapp/README":{"id":"dapp/README","title":"Create dApp","description":"Home of the Oasis dApp developer resources","sidebar":"developers"},"dapp/sapphire/addresses":{"id":"dapp/sapphire/addresses","title":"Standard Contract Addresses","description":"List of Standard Contract Addresses","sidebar":"developers"},"dapp/sapphire/browser":{"id":"dapp/sapphire/browser","title":"Browser Support","description":"Writing Sapphire dApp for browser and Metamask","sidebar":"developers"},"dapp/sapphire/gasless":{"id":"dapp/sapphire/gasless","title":"Gasless Transactions","description":"Submitting transactions without paying for fees","sidebar":"developers"},"dapp/sapphire/guide":{"id":"dapp/sapphire/guide","title":"Guide","description":"Guide to creating secure dApps on Sapphire","sidebar":"developers"},"dapp/sapphire/precompiles":{"id":"dapp/sapphire/precompiles","title":"Precompiles","description":"Additional Sapphire precompiles for encryption and confidentiality","sidebar":"developers"},"dapp/sapphire/quickstart":{"id":"dapp/sapphire/quickstart","title":"Quickstart","description":"In this tutorial, you\'ll port an Eth project in under 10 minutes, and then go on","sidebar":"developers"},"dapp/sapphire/README":{"id":"dapp/sapphire/README","title":"Sapphire ParaTime","description":"The Sapphire ParaTime is our official confidential EVM Compatible ParaTime","sidebar":"developers"},"general/manage-tokens/cli/account":{"id":"general/manage-tokens/cli/account","title":"Account","description":"Using CLI for performing account-related tasks","sidebar":"general"},"general/manage-tokens/cli/addressbook":{"id":"general/manage-tokens/cli/addressbook","title":"Address book","description":"Storing your blockchain contacts for future use","sidebar":"general"},"general/manage-tokens/cli/network":{"id":"general/manage-tokens/cli/network","title":"Network","description":"Managing Mainnet, Testnet or Localnet endpoints","sidebar":"general"},"general/manage-tokens/cli/paratime":{"id":"general/manage-tokens/cli/paratime","title":"ParaTime","description":"Managing ParaTimes","sidebar":"general"},"general/manage-tokens/cli/README":{"id":"general/manage-tokens/cli/README","title":"Oasis CLI","description":"Powerful CLI for managing Oasis network, nodes, tokens and dapps","sidebar":"general"},"general/manage-tokens/cli/setup":{"id":"general/manage-tokens/cli/setup","title":"Setup","description":"Download and Run","sidebar":"general"},"general/manage-tokens/cli/transaction":{"id":"general/manage-tokens/cli/transaction","title":"Transaction","description":"Using CLI to submit or decode a transaction","sidebar":"general"},"general/manage-tokens/cli/wallet":{"id":"general/manage-tokens/cli/wallet","title":"Wallet","description":"Manage accounts in your CLI wallet","sidebar":"general"},"general/manage-tokens/faq":{"id":"general/manage-tokens/faq","title":"Frequently Asked Questions","description":"This documents answers frequently asked questions about Oasis Wallets and 3rd","sidebar":"general"},"general/manage-tokens/holding-rose-tokens/custody-providers":{"id":"general/manage-tokens/holding-rose-tokens/custody-providers","title":"Custody Providers","description":"Another way to hold your ROSE tokens is by using a custody provider.","sidebar":"general"},"general/manage-tokens/holding-rose-tokens/ledger-wallet":{"id":"general/manage-tokens/holding-rose-tokens/ledger-wallet","title":"Self-Custody With Ledger Hardware Wallet","description":"This is a general documentation that will help users setup [Ledger] hadware","sidebar":"general"},"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime":{"id":"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","title":"How to Transfer ETH/ERC20 to Emerald ParaTime","description":"This guide will walk you through bringing your assets, i.e. ETH, USDC, USDT,","sidebar":"general"},"general/manage-tokens/how-to-transfer-rose-into-paratime":{"id":"general/manage-tokens/how-to-transfer-rose-into-paratime","title":"How to Transfer ROSE into a ParaTime","description":"This guide will walk you through transferring ROSE tokens from an Oasis","sidebar":"general"},"general/manage-tokens/oasis-wallets/browser-extension":{"id":"general/manage-tokens/oasis-wallets/browser-extension","title":"Browser Extension","description":"Oasis Foundation-managed official non-custodial browser extension wallet for the","sidebar":"general"},"general/manage-tokens/oasis-wallets/README":{"id":"general/manage-tokens/oasis-wallets/README","title":"Oasis Wallets","description":"This document provides an overview of how to use the official Oasis Wallets: a","sidebar":"general"},"general/manage-tokens/oasis-wallets/web":{"id":"general/manage-tokens/oasis-wallets/web","title":"Web","description":"Oasis Foundation-managed official non-custodial web wallet for the Oasis","sidebar":"general"},"general/manage-tokens/README":{"id":"general/manage-tokens/README","title":"Overview","description":"This documentation will guide you on how to use your ROSE tokens, where to keep them, how to transfer them, how to stake/delegate them, and more.","sidebar":"general"},"general/manage-tokens/staking-and-delegating":{"id":"general/manage-tokens/staking-and-delegating","title":"Staking and Delegating","description":"Staking and Delegation on the Oasis Network is a wonderful way to hold your ROSE","sidebar":"general"},"general/manage-tokens/terminology":{"id":"general/manage-tokens/terminology","title":"Terminology","description":"Account","sidebar":"general"},"general/oasis-network/faq":{"id":"general/oasis-network/faq","title":"Frequently Asked Questions","description":"This page tries to answer some of the most frequently asked questions about the","sidebar":"general"},"general/oasis-network/README":{"id":"general/oasis-network/README","title":"Oasis Network","description":"The Oasis Network is a Layer 1 decentralized blockchain network designed to be uniquely scalable, privacy-first and versatile.","sidebar":"general"},"general/oasis-network/token-metrics-and-distribution":{"id":"general/oasis-network/token-metrics-and-distribution","title":"Token Metrics and Distribution","description":"Background illustration","sidebar":"general"},"general/oasis-network/why-oasis":{"id":"general/oasis-network/why-oasis","title":"Why Oasis?","description":"Network Overview","sidebar":"general"},"general/README":{"id":"general/README","title":"Use Oasis","description":"This chapter provides general overview of the Oasis Network and introduces","sidebar":"general"},"get-involved/delegation-policy":{"id":"get-involved/delegation-policy","title":"Delegation Policy","description":"Oasis Protocol Foundation delegates ROSE tokens to node operators based on their","sidebar":"getInvolved"},"get-involved/network-governance":{"id":"get-involved/network-governance","title":"Network Governance","description":"If you have a general question on how to use and deploy our software, please","sidebar":"getInvolved"},"get-involved/oasis-core":{"id":"get-involved/oasis-core","title":"Develop Oasis Core","description":"This document outlines our guidelines for contributing to the Oasis Network\'s","sidebar":"getInvolved"},"get-involved/README":{"id":"get-involved/README","title":"Join our Community","description":"Welcome to the Oasis Community","sidebar":"getInvolved"},"get-involved/run-node/paratime-node":{"id":"get-involved/run-node/paratime-node","title":"ParaTime Node","description":"This guide provides an overview of the requirements to become a compute node for","sidebar":"getInvolved"},"get-involved/run-node/validator-node":{"id":"get-involved/run-node/validator-node","title":"Consensus Validator Node","description":"This guide provides an overview of the technical setup and stake requirements to","sidebar":"getInvolved"},"get-involved/token-delivery-and-kyc":{"id":"get-involved/token-delivery-and-kyc","title":"Token Delivery & KYC Guide","description":"If you\'re visiting this page, you may have recently earned ROSE tokens via the Community Cup program, the Ambassador Rewards program, or a recent hackathon. Congratulations!","sidebar":"getInvolved"},"node/genesis-doc":{"id":"node/genesis-doc","title":"Genesis Document","description":"A genesis document contains a set of parameters that outline the initial state","sidebar":"operators"},"node/mainnet/damask-upgrade":{"id":"node/mainnet/damask-upgrade","title":"Damask Upgrade","description":"This document provides an overview of the changes for the Damask Mainnet","sidebar":"operators"},"node/mainnet/e-upgrade":{"id":"node/mainnet/e-upgrade","title":"E* Upgrade","description":"This document is a work in progress and details around when the upgrade will be","sidebar":"operators"},"node/mainnet/previous-upgrades/cobalt-upgrade":{"id":"node/mainnet/previous-upgrades/cobalt-upgrade","title":"Cobalt Upgrade","description":"This document provides an overview of the proposed criteria and changes for the Cobalt Mainnet upgrade. This has been reviewed and approved by community members and validators of the Oasis Network and is being reproduced and summarized here for easy access.","sidebar":"operators"},"node/mainnet/previous-upgrades/mainnet-upgrade":{"id":"node/mainnet/previous-upgrades/mainnet-upgrade","title":"Upgrade to Mainnet","description":"This document provides an overview of the proposed criteria and changes to upgrade from Mainnet Beta to Mainnet. This has been reviewed and approved by community members and validators of the Oasis Network and is being reproduced and summarized here for easy access.","sidebar":"operators"},"node/mainnet/README":{"id":"node/mainnet/README","title":"Mainnet","description":"These are the current parameters for the Mainnet:","sidebar":"operators"},"node/mainnet/upgrade-log":{"id":"node/mainnet/upgrade-log","title":"Upgrade Log","description":"For each upgrade of the Oasis Network, we are tracking important changes for","sidebar":"operators"},"node/README":{"id":"node/README","title":"Run Node","description":"The following documentation is intended to assist any individual or","sidebar":"operators"},"node/run-your-node/advanced/copy-state-from-one-node-to-the-other":{"id":"node/run-your-node/advanced/copy-state-from-one-node-to-the-other","title":"Copy State from One Node to the Other","description":"A network that\'s been running for some time can accrue significant amount of state. This means bootstraping a new Oasis Node would take quite some time and resources (bandwidth, CPU) since it would need to fetch (download) and validate (replay) all the blocks from the genesis height onwards.","sidebar":"operators"},"node/run-your-node/advanced/install-oasis-remote-signer-binary":{"id":"node/run-your-node/advanced/install-oasis-remote-signer-binary","title":"Install Oasis Remote Signer Binary","description":"You only need to install the Oasis Remote Signer binary if you intend to configure your Oasis node with a remote signer setup.","sidebar":"operators"},"node/run-your-node/advanced/sync-node-using-state-sync":{"id":"node/run-your-node/advanced/sync-node-using-state-sync","title":"Using State Sync for Quick Bootstraping","description":"The State Sync is a way to quickly bootstrap a full Oasis node (either a validator node or a non-validator node) by using Tendermint\'s Light Client protocol. It allows one to initialize a node from a trusted height, its corresponding block\'s header and a trusted validator set (given in the genesis document). It does so by securely updating the node\'s trusted state by requesting and verifying a minimal set of data from the network\'s full nodes.","sidebar":"operators"},"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer":{"id":"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer","title":"Using Ledger-backed Consensus Key with a Remote Signer","description":"This guide will describe how you can set up your validator node with a detached consensus key stored on a Ledger wallet connected via Oasis Core\'s Remote Signer.","sidebar":"operators"},"node/run-your-node/archive-node":{"id":"node/run-your-node/archive-node","title":"Archive Node","description":"This page describes how to run an archive node on the Oasis Network.","sidebar":"operators"},"node/run-your-node/ias-proxy":{"id":"node/run-your-node/ias-proxy","title":"IAS Proxy","description":"This guide will cover setting up an Intel Attestation Service (IAS)","sidebar":"operators"},"node/run-your-node/keymanager-node/key-manager-upgrade":{"id":"node/run-your-node/keymanager-node/key-manager-upgrade","title":"Upgrading Key Managers","description":"This guide will describe how to upgrade a key manager node.","sidebar":"operators"},"node/run-your-node/keymanager-node/README":{"id":"node/run-your-node/keymanager-node/README","title":"Key Manager Node","description":"These instructions are for setting up a key manager node. Key manager nodes run a special runtime that provides confidentiality to other ParaTimes. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a ParaTime node instead, see the instructions for running a ParaTime node.","sidebar":"operators"},"node/run-your-node/keymanager-node/signing-key-manager-policy":{"id":"node/run-your-node/keymanager-node/signing-key-manager-policy","title":"Signing Key Manager Policy","description":"This guide will describe how to print and sign an Oasis [key manager policy].","sidebar":"operators"},"node/run-your-node/maintenance/adding-or-removing-nodes":{"id":"node/run-your-node/maintenance/adding-or-removing-nodes","title":"Adding or Removing Nodes","description":"At some point you may wish to add or remove nodes from your entity. In order to","sidebar":"operators"},"node/run-your-node/maintenance/handling-network-upgrades":{"id":"node/run-your-node/maintenance/handling-network-upgrades","title":"Handling Network Upgrades","description":"Changes between the major consensus network versions are backward and forward","sidebar":"operators"},"node/run-your-node/maintenance/refreshing-certificates":{"id":"node/run-your-node/maintenance/refreshing-certificates","title":"Refreshing Node Certificates","description":"Refreshing Sentry Client TLS Certificate on the Validator Node","sidebar":"operators"},"node/run-your-node/maintenance/shutting-down-a-node":{"id":"node/run-your-node/maintenance/shutting-down-a-node","title":"Shutting Down a Node","description":"When a node registers for an epoch, it is committing to being available","sidebar":"operators"},"node/run-your-node/maintenance/wiping-node-state":{"id":"node/run-your-node/maintenance/wiping-node-state","title":"Wiping Node State","description":"In some cases you might want (or need) to do a full redeploy with clean state before deploying a new version of the network. This should never actually be used during a Mainnet unless there is some serious corruption, but your node will have to spend time catching up to the rest of the network.","sidebar":"operators"},"node/run-your-node/non-validator-node":{"id":"node/run-your-node/non-validator-node","title":"Non-validator Node","description":"These instructions are for setting up a non-validator node. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a ParaTime node instead, see the instructions for running a ParaTime node.","sidebar":"operators"},"node/run-your-node/paratime-client-node":{"id":"node/run-your-node/paratime-client-node","title":"ParaTime Client Node","description":"These instructions are for setting up a ParaTime client node which only observes ParaTime activity and can submit transactions. If you want to run a ParaTime node instead, see the instructions for running a ParaTime node. Similarly, if you want to run a validator or a non-validator node instead, see the instructions for running a validator node or instructions for running a non-validator node.","sidebar":"operators"},"node/run-your-node/paratime-node":{"id":"node/run-your-node/paratime-node","title":"ParaTime Node","description":"These instructions are for setting up a ParaTime node which participates in one or more ParaTime compute committees. If you want to run a ParaTime client node instead, see the instructions for running a ParaTime client node. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a non-validator node instead, see the instructions for running a non-validator node.","sidebar":"operators"},"node/run-your-node/prerequisites/hardware-recommendations":{"id":"node/run-your-node/prerequisites/hardware-recommendations","title":"Hardware Requirements","description":"The Oasis Network is composed of multiple classes of nodes and services such","sidebar":"operators"},"node/run-your-node/prerequisites/oasis-node":{"id":"node/run-your-node/prerequisites/oasis-node","title":"Install Oasis Node Binary","description":"The Oasis Node is a binary that is created from the Oasis Core repository\'s go/ path.","sidebar":"operators"},"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee":{"id":"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","title":"Set up Trusted Execution Environment (TEE)","description":"In case the ParaTime you want to run does not require the use of a TEE (e.g.","sidebar":"operators"},"node/run-your-node/prerequisites/stake-requirements":{"id":"node/run-your-node/prerequisites/stake-requirements","title":"Stake Requirements","description":"This page provides an overview of the stake requirements to become a validator","sidebar":"operators"},"node/run-your-node/prerequisites/system-configuration":{"id":"node/run-your-node/prerequisites/system-configuration","title":"System Configuration","description":"This page describes changes that should be made to the configuration of the","sidebar":"operators"},"node/run-your-node/seed-node":{"id":"node/run-your-node/seed-node","title":"Seed Node","description":"This guide will cover setting up a seed node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools.","sidebar":"operators"},"node/run-your-node/sentry-node":{"id":"node/run-your-node/sentry-node","title":"Sentry Node","description":"This guide provides instructions for a deployment using the Sentry node architecture to protect validator nodes from being directly exposed on the public network.","sidebar":"operators"},"node/run-your-node/troubleshooting":{"id":"node/run-your-node/troubleshooting","title":"Troubleshooting","description":"Before you begin troubleshooting we suggest you check all of the following:","sidebar":"operators"},"node/run-your-node/validator-node":{"id":"node/run-your-node/validator-node","title":"Validator Node","description":"This guide will walk you through the process of setting up your validator node","sidebar":"operators"},"node/testnet/README":{"id":"node/testnet/README","title":"Testnet","description":"These are the current parameters for the Testnet, a test-only network for","sidebar":"operators"},"node/testnet/upgrade-log":{"id":"node/testnet/upgrade-log","title":"Upgrade Log","description":"For each upgrade of the Testnet network, we are tracking important changes for","sidebar":"operators"},"node/web3":{"id":"node/web3","title":"Oasis Web3 Gateway for your EVM ParaTime","description":"Web3 gateway for Emerald and Sapphire ParaTimes","sidebar":"operators"},"oasis-core-ledger/README":{"id":"oasis-core-ledger/README","title":"Oasis Core Ledger Documentation","description":"This projects aims to provide support for using a [Ledger] hardware wallet with","sidebar":"oasisSdk"},"oasis-core-ledger/release-process":{"id":"oasis-core-ledger/release-process","title":"Release Process","description":"The following steps should be followed when preparing a release.","sidebar":"oasisSdk"},"oasis-core-ledger/SUMMARY":{"id":"oasis-core-ledger/SUMMARY","title":"Table of Contents","description":"Usage"},"oasis-core-ledger/usage/address":{"id":"oasis-core-ledger/usage/address","title":"Obtaining Account Address","description":"Before following the instructions below, make sure your Ledger wallet is","sidebar":"oasisSdk"},"oasis-core-ledger/usage/entity":{"id":"oasis-core-ledger/usage/entity","title":"Exporting Public Key to Entity","description":"Before following the instructions below, make sure your Ledger wallet is","sidebar":"oasisSdk"},"oasis-core-ledger/usage/setup":{"id":"oasis-core-ledger/usage/setup","title":"Setup","description":"Oasis Core Ledger is currently only supported on x86_64 Linux and macOS systems.","sidebar":"oasisSdk"},"oasis-core-ledger/usage/transactions":{"id":"oasis-core-ledger/usage/transactions","title":"Generating and Signing Transactions","description":"Before following the instructions below, make sure your Ledger wallet is","sidebar":"oasisSdk"},"oasis-core-ledger/usage/wallets":{"id":"oasis-core-ledger/usage/wallets","title":"Identifying Wallets","description":"Before following the instructions below, make sure your Ledger wallet is","sidebar":"oasisSdk"},"oasis-core-ledger/versioning":{"id":"oasis-core-ledger/versioning","title":"Versioning","description":"Oasis Core Ledger uses [Semantic Versioning 2.0.0] with the following format:","sidebar":"oasisSdk"},"paratime/minimal-runtime":{"id":"paratime/minimal-runtime","title":"Minimal Runtime","description":"This section will show you how to quickly create, build and test a minimal","sidebar":"paratime"},"paratime/modules":{"id":"paratime/modules","title":"Modules","description":"As we saw in the [minimal runtime example], creating an Oasis runtime is very","sidebar":"paratime"},"paratime/prerequisites":{"id":"paratime/prerequisites","title":"Prerequisites","description":"How to build your first runtime","sidebar":"paratime"},"paratime/README":{"id":"paratime/README","title":"Build ParaTime","description":"Build your own ParaTime using Oasis Runtime SDK","sidebar":"paratime"},"paratime/reproducibility":{"id":"paratime/reproducibility","title":"Reproducibility","description":"If you wish to build paratime binaries yourself, you can use the","sidebar":"paratime"},"README":{"id":"README","title":"Getting Started","description":"Use Oasis"}}}')}}]); \ No newline at end of file diff --git a/assets/js/94ed66ea.721bef3f.js b/assets/js/94ed66ea.721bef3f.js new file mode 100644 index 0000000000..890dad6f41 --- /dev/null +++ b/assets/js/94ed66ea.721bef3f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9008],{3905:(e,t,o)=>{o.d(t,{Zo:()=>d,kt:()=>h});var r=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function s(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function a(e){for(var t=1;t=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var i=r.createContext({}),l=function(e){var t=r.useContext(i),o=t;return e&&(o="function"==typeof e?e(t):a(a({},t),e)),o},d=function(e){var t=l(e.components);return r.createElement(i.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var o=e.components,n=e.mdxType,s=e.originalType,i=e.parentName,d=c(e,["components","mdxType","originalType","parentName"]),m=l(o),p=n,h=m["".concat(i,".").concat(p)]||m[p]||u[p]||s;return o?r.createElement(h,a(a({ref:t},d),{},{components:o})):r.createElement(h,a({ref:t},d))}));function h(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var s=o.length,a=new Array(s);a[0]=p;var c={};for(var i in t)hasOwnProperty.call(t,i)&&(c[i]=t[i]);c.originalType=e,c[m]="string"==typeof e?e:n,a[1]=c;for(var l=2;l{o.r(t),o.d(t,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var r=o(7462),n=(o(7294),o(3905));const s={},a="Committee Scheduler",c={unversionedId:"core/consensus/services/scheduler",id:"core/consensus/services/scheduler",title:"Committee Scheduler",description:"The committee scheduler service is responsible for periodically scheduling all",source:"@site/docs/core/consensus/services/scheduler.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/scheduler",permalink:"/core/consensus/services/scheduler",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/scheduler.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Registry",permalink:"/core/consensus/services/registry"},next:{title:"Governance",permalink:"/core/consensus/services/governance"}},i={},l=[{value:"Events",id:"events",level:2},{value:"Validator Committee",id:"validator-committee",level:2}],d={toc:l},m="wrapper";function u(e){let{components:t,...o}=e;return(0,n.kt)(m,(0,r.Z)({},d,o,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"committee-scheduler"},"Committee Scheduler"),(0,n.kt)("p",null,"The committee scheduler service is responsible for periodically scheduling all\ncommittees (validator, compute, key manager) based on ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/epochtime"},"epoch-based time")," and\nentropy provided by the ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/beacon"},"random beacon"),"."),(0,n.kt)("p",null,"The service interface definition lives in ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/scheduler/api"},(0,n.kt)("inlineCode",{parentName:"a"},"go/scheduler/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/scheduler/api?tab=doc"},"consensus service API documentation"),"."),(0,n.kt)("h2",{id:"events"},"Events"),(0,n.kt)("h2",{id:"validator-committee"},"Validator Committee"),(0,n.kt)("p",null,"To schedule the validator committee, the committee scheduler selects among\nnodes ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#register-node"},"registered")," with the ",(0,n.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#RoleValidator"},(0,n.kt)("inlineCode",{parentName:"a"},"RoleValidator"))," role.\nEach node's entity must have an ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#escrow"},"escrow account balance")," meeting the total\nthresholds for the nodes and runtimes that it has registered.\nIf an entity's escrow account balance is too low to meet the total threshold,\nthe committee scheduler does not consider that entity's nodes."),(0,n.kt)("p",null,"From these qualifying nodes, the committee scheduler selects at most one node\nfrom each entity, up to a maximum validator committee size.\nThe maximum validator committee size is configured in the genesis document,\nunder the path ",(0,n.kt)("inlineCode",{parentName:"p"},".scheduler.params.max_validators")," (consult the ",(0,n.kt)("a",{parentName:"p",href:"/node/genesis-doc#committee-scheduler"},"genesis\ndocument")," for details).\nUnlike how the committee scheduler schedules other committees, it schedules the\nvalidator committee by choosing nodes from the entities that have the highest\nescrow account balances."),(0,n.kt)("p",null,"When the committee scheduler schedules the validator committee, it additionally\nassigns each member a ",(0,n.kt)("em",{parentName:"p"},"voting power"),", which controls (i) the weight of its\nvotes in the consensus protocol and (ii) how often it serves as the proposer in\nthe consensus protocol."),(0,n.kt)("p",null,"The committee scheduler assigns a validator's voting power proportional to its\nentity's ",(0,n.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#escrow"},"escrow account balance"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9645557e.26563459.js b/assets/js/9645557e.26563459.js new file mode 100644 index 0000000000..caf11cae2a --- /dev/null +++ b/assets/js/9645557e.26563459.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6097],{3905:(e,t,a)=>{a.d(t,{Zo:()=>i,kt:()=>s});var l=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,l)}return a}function c(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var g=l.createContext({}),o=function(e){var t=l.useContext(g),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},i=function(e){var t=o(e.components);return l.createElement(g.Provider,{value:t},e.children)},m="mdxType",I={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},C=l.forwardRef((function(e,t){var a=e.components,n=e.mdxType,r=e.originalType,g=e.parentName,i=d(e,["components","mdxType","originalType","parentName"]),m=o(a),C=n,s=m["".concat(g,".").concat(C)]||m[C]||I[C]||r;return a?l.createElement(s,c(c({ref:t},i),{},{components:a})):l.createElement(s,c({ref:t},i))}));function s(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=a.length,c=new Array(r);c[0]=C;var d={};for(var g in t)hasOwnProperty.call(t,g)&&(d[g]=t[g]);d.originalType=e,d[m]="string"==typeof e?e:n,c[1]=d;for(var o=2;o{a.r(t),a.d(t,{assets:()=>g,contentTitle:()=>c,default:()=>I,frontMatter:()=>r,metadata:()=>d,toc:()=>o});var l=a(7462),n=(a(7294),a(3905));const r={},c="Integrating BAND oracle smart contract",d={unversionedId:"dapp/emerald/integrating-band-oracle-smart-contract",id:"dapp/emerald/integrating-band-oracle-smart-contract",title:"Integrating BAND oracle smart contract",description:"This guide will explain how to query the Band Protocol reference data smart",source:"@site/docs/dapp/emerald/integrating-band-oracle-smart-contract.md",sourceDirName:"dapp/emerald",slug:"/dapp/emerald/integrating-band-oracle-smart-contract",permalink:"/dapp/emerald/integrating-band-oracle-smart-contract",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/emerald/integrating-band-oracle-smart-contract.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Writing dApps on Emerald",permalink:"/dapp/emerald/writing-dapps-on-emerald"},next:{title:"Cipher ParaTime",permalink:"/dapp/cipher/"}},g={},o=[{value:"What is the Band Protocol?",id:"what-is-the-band-protocol",level:3},{value:"Deploy Oracle",id:"deploy-oracle",level:3},{value:"Get Rates",id:"get-rates",level:3},{value:"Mainnet Reference Data Contract",id:"mainnet-reference-data-contract",level:3},{value:"Available Reference Data",id:"available-reference-data",level:3},{value:"Example of DemoOracle.sol contract",id:"example-of-demooraclesol-contract",level:3},{value:"Bandchain.js",id:"bandchain",level:3}],i={toc:o},m="wrapper";function I(e){let{components:t,...r}=e;return(0,n.kt)(m,(0,l.Z)({},i,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"integrating-band-oracle-smart-contract"},"Integrating BAND oracle smart contract"),(0,n.kt)("p",null,"This guide will explain how to query the Band Protocol reference data smart\ncontract from another Solidity smart contract on Emerald."),(0,n.kt)("h3",{id:"what-is-the-band-protocol"},"What is the Band Protocol?"),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://bandprotocol.com"},"Band Protocol")," is a cross-chain data oracle\nplatform that aggregates and connects real-world data and APIs to smart\ncontracts. You can read more about the specific details of the protocol\n",(0,n.kt)("a",{parentName:"p",href:"https://docs.bandchain.org"},"here"),"."),(0,n.kt)("h3",{id:"deploy-oracle"},"Deploy Oracle"),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"Follow ",(0,n.kt)("a",{parentName:"li",href:"https://remix.ethereum.org/?#code=cHJhZ21hIHNvbGlkaXR5IDAuNi4xMTsKcHJhZ21hIGV4cGVyaW1lbnRhbCBBQklFbmNvZGVyVjI7CgppbnRlcmZhY2UgSVN0ZFJlZmVyZW5jZSB7CiAgICAvLy8gQSBzdHJ1Y3R1cmUgcmV0dXJuZWQgd2hlbmV2ZXIgc29tZW9uZSByZXF1ZXN0cyBmb3Igc3RhbmRhcmQgcmVmZXJlbmNlIGRhdGEuCiAgICBzdHJ1Y3QgUmVmZXJlbmNlRGF0YSB7CiAgICAgICAgdWludDI1NiByYXRlOyAvLyBiYXNlL3F1b3RlIGV4Y2hhbmdlIHJhdGUsIG11bHRpcGxpZWQgYnkgMWUxOC4KICAgICAgICB1aW50MjU2IGxhc3RVcGRhdGVkQmFzZTsgLy8gVU5JWCBlcG9jaCBvZiB0aGUgbGFzdCB0aW1lIHdoZW4gYmFzZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICAgICAgdWludDI1NiBsYXN0VXBkYXRlZFF1b3RlOyAvLyBVTklYIGVwb2NoIG9mIHRoZSBsYXN0IHRpbWUgd2hlbiBxdW90ZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICB9CgogICAgLy8vIFJldHVybnMgdGhlIHByaWNlIGRhdGEgZm9yIHRoZSBnaXZlbiBiYXNlL3F1b3RlIHBhaXIuIFJldmVydCBpZiBub3QgYXZhaWxhYmxlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YShzdHJpbmcgbWVtb3J5IF9iYXNlLCBzdHJpbmcgbWVtb3J5IF9xdW90ZSkKICAgICAgICBleHRlcm5hbAogICAgICAgIHZpZXcKICAgICAgICByZXR1cm5zIChSZWZlcmVuY2VEYXRhIG1lbW9yeSk7CgogICAgLy8vIFNpbWlsYXIgdG8gZ2V0UmVmZXJlbmNlRGF0YSwgYnV0IHdpdGggbXVsdGlwbGUgYmFzZS9xdW90ZSBwYWlycyBhdCBvbmNlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoc3RyaW5nW10gbWVtb3J5IF9iYXNlcywgc3RyaW5nW10gbWVtb3J5IF9xdW90ZXMpCiAgICAgICAgZXh0ZXJuYWwKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAoUmVmZXJlbmNlRGF0YVtdIG1lbW9yeSk7Cn0KCmNvbnRyYWN0IERlbW9PcmFjbGUgewogICAgSVN0ZFJlZmVyZW5jZSByZWY7CgogICAgdWludDI1NiBwdWJsaWMgcHJpY2U7CgogICAgY29uc3RydWN0b3IoSVN0ZFJlZmVyZW5jZSBfcmVmKSBwdWJsaWMgewogICAgICAgIHJlZiA9IF9yZWY7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UHJpY2UoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKCJXQlRDIiwiVVNEIik7CiAgICAgICAgcmV0dXJuIGRhdGEucmF0ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRNdWx0aVByaWNlcygpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludDI1NltdIG1lbW9yeSl7CiAgICAgICAgc3RyaW5nW10gbWVtb3J5IGJhc2VTeW1ib2xzID0gbmV3IHN0cmluZ1tdKDIpOwogICAgICAgIGJhc2VTeW1ib2xzWzBdID0gIldCVEMiOwogICAgICAgIGJhc2VTeW1ib2xzWzFdID0gIkVUSCI7CgogICAgICAgIHN0cmluZ1tdIG1lbW9yeSBxdW90ZVN5bWJvbHMgPSBuZXcgc3RyaW5nW10oMik7CiAgICAgICAgcXVvdGVTeW1ib2xzWzBdID0gIlVTRCI7CiAgICAgICAgcXVvdGVTeW1ib2xzWzFdID0gIlVTRCI7CiAgICAgICAgSVN0ZFJlZmVyZW5jZS5SZWZlcmVuY2VEYXRhW10gbWVtb3J5IGRhdGEgPSByZWYuZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoYmFzZVN5bWJvbHMscXVvdGVTeW1ib2xzKTsKCiAgICAgICAgdWludDI1NltdIG1lbW9yeSBwcmljZXMgPSBuZXcgdWludDI1NltdKDIpOwogICAgICAgIHByaWNlc1swXSA9IGRhdGFbMF0ucmF0ZTsKICAgICAgICBwcmljZXNbMV0gPSBkYXRhWzFdLnJhdGU7CgogICAgICAgIHJldHVybiBwcmljZXM7CiAgICB9CgogICAgZnVuY3Rpb24gc2F2ZVByaWNlKHN0cmluZyBtZW1vcnkgYmFzZSwgc3RyaW5nIG1lbW9yeSBxdW90ZSkgZXh0ZXJuYWwgewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKGJhc2UscXVvdGUpOwogICAgICAgIHByaWNlID0gZGF0YS5yYXRlOwogICAgfQp9Cg=="},"this link")," to Remix. The link contains an encoded example ",(0,n.kt)("inlineCode",{parentName:"li"},"DemoOracle.sol")," contract."),(0,n.kt)("li",{parentName:"ol"},"Compile the contract with compiler version ",(0,n.kt)("inlineCode",{parentName:"li"},"0.6.11"),"."),(0,n.kt)("li",{parentName:"ol"},"Switch to the Deploy tab of Remix.",(0,n.kt)("ol",{parentName:"li"},(0,n.kt)("li",{parentName:"ol"},'Select "Injected Web3" in the Environment dropdown in the top left to connect Metamask.'),(0,n.kt)("li",{parentName:"ol"},"Make sure that Metamask is connected to the Emerald (Testnet/Mainnet) network. You can read about adding Emerald network to Metamask ",(0,n.kt)("a",{parentName:"li",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime#metamask"},"here"),".")))),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Setting up the environment in Remix",src:a(467).Z,width:"756",height:"558"})),(0,n.kt)("ol",{start:4},(0,n.kt)("li",{parentName:"ol"},"Enter the Emerald Testnet Band reference data aggregator contract address (",(0,n.kt)("inlineCode",{parentName:"li"},"0x61704EFB8b8120c03C210cAC5f5193BF8c80852a"),") to the ",(0,n.kt)("inlineCode",{parentName:"li"},"DemoOracle")," constructor and deploy the contract. You can access the reference data aggregator contract on mainnet at ",(0,n.kt)("inlineCode",{parentName:"li"},"0xDA7a001b254CD22e46d3eAB04d937489c93174C3"),".")),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Deploying DemoOracle",src:a(7855).Z,width:"1314",height:"1439"})),(0,n.kt)("p",null,"An interface to interact with the contract will appear in the bottom left corner of Remix."),(0,n.kt)("h3",{id:"get-rates"},"Get Rates"),(0,n.kt)("p",null,"Clicking the ",(0,n.kt)("inlineCode",{parentName:"p"},"getPrice")," button will return the current price of WBTC in USD. This function calls ",(0,n.kt)("inlineCode",{parentName:"p"},"getReferenceData(string memory _base, string memory _quote)"),' on the Band reference data contract, passing "WBTC" and "USD", indicating WBTC as the base and USD as the quote. The rate returned is base/quote multiplied by 1e18.'),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Get Rates",src:a(6437).Z,width:"1690",height:"1234"})),(0,n.kt)("p",null,"Note that the ",(0,n.kt)("inlineCode",{parentName:"p"},"DemoOracle")," contract only returns the latest rate, but the reference contract also returns values of the last time the base and quote references were updated."),(0,n.kt)("p",null,"The price is offset by 1e18. The returned value at the time of testing is ",(0,n.kt)("inlineCode",{parentName:"p"},"39567000000000000000000"),". Multiplying by 1e-18 gives the current USD price given by the reference contract, 39567.00 WBTC/USD."),(0,n.kt)("p",null,"Clicking the ",(0,n.kt)("inlineCode",{parentName:"p"},"getMultiPrices")," button returns multiple quotes in the same call, WBTC/USD and ETH/USD in this case. This function calls ",(0,n.kt)("inlineCode",{parentName:"p"},"getReferenceDataBulk(string[] memory _bases, string[] memory _quotes)"),' on the Band reference data contract, passing "WBTC" and "ETH" as the base and "USD" for the quote. This will return the current WBTC and ETH prices in USD, as an array of integers. The call also returns just the exchange rates (multipilied by 1e18), but can be modified to return the last updated times for the bases and quotes.'),(0,n.kt)("p",null,"The ",(0,n.kt)("inlineCode",{parentName:"p"},"savePrice")," function will save any base/quote rate that is passed to it in the storage variable named ",(0,n.kt)("inlineCode",{parentName:"p"},"price"),". This storage data will only be updated when the \u201csavePrice\u201d function is called, so the saved ",(0,n.kt)("inlineCode",{parentName:"p"},"price")," value will go stale unless this function is called repeatedly."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Save Price",src:a(3252).Z,width:"343",height:"447"})),(0,n.kt)("h3",{id:"mainnet-reference-data-contract"},"Mainnet Reference Data Contract"),(0,n.kt)("p",null,"You can access the reference data aggregator contract on mainnet at ",(0,n.kt)("a",{parentName:"p",href:"https://explorer.emerald.oasis.dev/address/0xDA7a001b254CD22e46d3eAB04d937489c93174C3/transactions"},"0xDA7a001b254CD22e46d3eAB04d937489c93174C3"),"."),(0,n.kt)("h3",{id:"available-reference-data"},"Available Reference Data"),(0,n.kt)("p",null,"You can view the available reference data on the ",(0,n.kt)("a",{parentName:"p",href:"https://data.bandprotocol.com/"},"Band Standard Dataset site here"),"."),(0,n.kt)("h3",{id:"example-of-demooraclesol-contract"},"Example of DemoOracle.sol contract"),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://remix.ethereum.org/?#code=cHJhZ21hIHNvbGlkaXR5IDAuNi4xMTsKcHJhZ21hIGV4cGVyaW1lbnRhbCBBQklFbmNvZGVyVjI7CgppbnRlcmZhY2UgSVN0ZFJlZmVyZW5jZSB7CiAgICAvLy8gQSBzdHJ1Y3R1cmUgcmV0dXJuZWQgd2hlbmV2ZXIgc29tZW9uZSByZXF1ZXN0cyBmb3Igc3RhbmRhcmQgcmVmZXJlbmNlIGRhdGEuCiAgICBzdHJ1Y3QgUmVmZXJlbmNlRGF0YSB7CiAgICAgICAgdWludDI1NiByYXRlOyAvLyBiYXNlL3F1b3RlIGV4Y2hhbmdlIHJhdGUsIG11bHRpcGxpZWQgYnkgMWUxOC4KICAgICAgICB1aW50MjU2IGxhc3RVcGRhdGVkQmFzZTsgLy8gVU5JWCBlcG9jaCBvZiB0aGUgbGFzdCB0aW1lIHdoZW4gYmFzZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICAgICAgdWludDI1NiBsYXN0VXBkYXRlZFF1b3RlOyAvLyBVTklYIGVwb2NoIG9mIHRoZSBsYXN0IHRpbWUgd2hlbiBxdW90ZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICB9CgogICAgLy8vIFJldHVybnMgdGhlIHByaWNlIGRhdGEgZm9yIHRoZSBnaXZlbiBiYXNlL3F1b3RlIHBhaXIuIFJldmVydCBpZiBub3QgYXZhaWxhYmxlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YShzdHJpbmcgbWVtb3J5IF9iYXNlLCBzdHJpbmcgbWVtb3J5IF9xdW90ZSkKICAgICAgICBleHRlcm5hbAogICAgICAgIHZpZXcKICAgICAgICByZXR1cm5zIChSZWZlcmVuY2VEYXRhIG1lbW9yeSk7CgogICAgLy8vIFNpbWlsYXIgdG8gZ2V0UmVmZXJlbmNlRGF0YSwgYnV0IHdpdGggbXVsdGlwbGUgYmFzZS9xdW90ZSBwYWlycyBhdCBvbmNlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoc3RyaW5nW10gbWVtb3J5IF9iYXNlcywgc3RyaW5nW10gbWVtb3J5IF9xdW90ZXMpCiAgICAgICAgZXh0ZXJuYWwKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAoUmVmZXJlbmNlRGF0YVtdIG1lbW9yeSk7Cn0KCmNvbnRyYWN0IERlbW9PcmFjbGUgewogICAgSVN0ZFJlZmVyZW5jZSByZWY7CgogICAgdWludDI1NiBwdWJsaWMgcHJpY2U7CgogICAgY29uc3RydWN0b3IoSVN0ZFJlZmVyZW5jZSBfcmVmKSBwdWJsaWMgewogICAgICAgIHJlZiA9IF9yZWY7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UHJpY2UoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKCJXQlRDIiwiVVNEIik7CiAgICAgICAgcmV0dXJuIGRhdGEucmF0ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRNdWx0aVByaWNlcygpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludDI1NltdIG1lbW9yeSl7CiAgICAgICAgc3RyaW5nW10gbWVtb3J5IGJhc2VTeW1ib2xzID0gbmV3IHN0cmluZ1tdKDIpOwogICAgICAgIGJhc2VTeW1ib2xzWzBdID0gIldCVEMiOwogICAgICAgIGJhc2VTeW1ib2xzWzFdID0gIkVUSCI7CgogICAgICAgIHN0cmluZ1tdIG1lbW9yeSBxdW90ZVN5bWJvbHMgPSBuZXcgc3RyaW5nW10oMik7CiAgICAgICAgcXVvdGVTeW1ib2xzWzBdID0gIlVTRCI7CiAgICAgICAgcXVvdGVTeW1ib2xzWzFdID0gIlVTRCI7CiAgICAgICAgSVN0ZFJlZmVyZW5jZS5SZWZlcmVuY2VEYXRhW10gbWVtb3J5IGRhdGEgPSByZWYuZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoYmFzZVN5bWJvbHMscXVvdGVTeW1ib2xzKTsKCiAgICAgICAgdWludDI1NltdIG1lbW9yeSBwcmljZXMgPSBuZXcgdWludDI1NltdKDIpOwogICAgICAgIHByaWNlc1swXSA9IGRhdGFbMF0ucmF0ZTsKICAgICAgICBwcmljZXNbMV0gPSBkYXRhWzFdLnJhdGU7CgogICAgICAgIHJldHVybiBwcmljZXM7CiAgICB9CgogICAgZnVuY3Rpb24gc2F2ZVByaWNlKHN0cmluZyBtZW1vcnkgYmFzZSwgc3RyaW5nIG1lbW9yeSBxdW90ZSkgZXh0ZXJuYWwgewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKGJhc2UscXVvdGUpOwogICAgICAgIHByaWNlID0gZGF0YS5yYXRlOwogICAgfQp9Cg=="},"DemoOracle.sol contract example in Remix")),(0,n.kt)("h3",{id:"bandchain"},"Bandchain.js"),(0,n.kt)("p",null,"Band also has a JavaScript library that makes it easy to interact with BandChain directly from JavaScript or TypeScript applications. The library provides classes and methods for convenient to send transactions, query data, OBI encoding, and wallet management. You can read more about it ",(0,n.kt)("a",{parentName:"p",href:"https://docs.bandchain.org/develop/developer-tools/bandchain.js/getting-started"},"here"),"."))}I.isMDXComponent=!0},467:(e,t,a)=>{a.d(t,{Z:()=>l});const l=a.p+"assets/images/band_demooracle_smartcontract-33de5c1550770b2f65357831fc13c6e1.png"},7855:(e,t,a)=>{a.d(t,{Z:()=>l});const l=a.p+"assets/images/band_deploy_demooracle_smartcontact-bcfd8510f590412a0eb3af8025b8a9dc.png"},6437:(e,t,a)=>{a.d(t,{Z:()=>l});const l=a.p+"assets/images/band_get_rates-1172d264b2dcff4f0841da0e3f8a9d53.png"},3252:(e,t,a)=>{a.d(t,{Z:()=>l});const l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVcAAAG/CAMAAADb+GTFAAAC9FBMVEX////+/v/9/f38+/v9+ff6+fv4+Pr89vT29vj19fj68ezx8/bz8vTv8PP47OTs7vLs6+7n6/D2593p6Ov149ng5uzk4+fy283b4eje3+ng3+PY3+bc3OPZ2uXb2t7S2+Lu0b7V1uHV1dnrzLbL1N3Q0dzR0dbpx63MzdjE0NnMy9G8ytXGxs/mvJ+6yNPBws7Cwce0xNDitJO8vMSsvcu3t8Gzs7zdqIGjtsSvr7jaoXedscCrq7OXrb2lprCVq7zXmWuioquQp7meoK7UkWGNpLaenqibm6bTjVqIobSamqSVmq2UmazRiVaTmKuTl6qXlqGDnbCRlqnQh1GQlKePlKfPhE2Ok6aSkp1+ma2KkrCNkqWMkaTOgEiLkKOKj6KOjpmGjqyKjqGJjaCNjJd3k6iIjJ+Hi57Lej6Fi52EipyHiZmIiZSBiaWCh5rJdTh+hqKBhpiFhZBujKLGcziAhJd+g5V9gpTBcTiBgYx7gZR3gJxoh596gJN5f5G7bjh4fpFkhZy3bTl3fI96eoezazl1eo12eYlfgZlxeJRzeIt1doRydoludZBvdIdzc4CpZTlvc4dYe5RucoWkYzlub3xpb4lrboJTd5FqbYBmbIebXzpoa31ma35panhlan1lanxiaYNMcY1jaHthZ4BiZnpiZnllZXRhZXmOWjpgY3ddYntfYnVhYXBEa4heYXSHVjpaX3hAaIVbXnFaXW+BUztbXWtWXHRYXG5VXHNVW3NWWm15UDtVWWo6YoFUV2tTVWo2X35UVGNSVGg0Xn1QU2Y0XXtPUmROUWRrSTtLUGROT19LT2JJTWFJTWBkRTxKS1xIS19hRDxGSV1HSVlFSFtbQjxGRldERllCRFtCRFgwSmVDQ1RBQ1dBQ1Y/Q1RQPT0+QVQ9QFJMOz47PlI6PU84O083OU04OUpCNj43OUs1N0s1N0o0NkkzNUcyNEY3Mj8wMkUvMUQuL0MxLj8tLkIsLUErKz8pKz8oKT0kJDgiIzaxBVQFAAAeS0lEQVR42uzYb0gbZxzA8ecSLlxBIXCQF0HyIi/yQvpCCApCKPjGFxqSECyVq2y1lRaLFSt04krLoFJopx0isUxat7CVjpYwSosdQnGkFEudYNHRP9iJYkxomxwazntyvzf73V2txfSP6xJIyvMF77x77nmSfDgOEkK3WwLW/2iJvhNhrsy1tGOuzLWcYq7MtZxirsy1nPo814lYbFqDvFJx+GBaPLN11fc4t+zTHk1OJgvtSiw8RxwzsKOQDT4c3wF68QrCE1tkx+C9GOSX689CyTZ6OhptTxba9QcEEq3yf3dd4asyoHobdgxWuyC/NJmB0mw5OiYNRaM9p6M3C+4KWd6L80O+OEDHTG/99TeuT5oaZiDeCgCLjZoWqT+kASRC+xZMV59VBSO5yzcOMN0V39evQa+9sjESGY948co6XAi03rrWOR+pa8zqK+SgxFrrGZ00OlEEV3A7YMIiurgY2HjBQXyG63Wu0k764yQGUG0Hj9UjVOFNyjutnOHqcoNRSuCdxAshjq/iRagTeE/IbeXcry0Oj7UeQCRVlU43cXrSTmGv3Q2l1tCs9gzkJPSsFsG1pgJED+5qwGYH8HGa7iq68IwNRDcoXNc4WYR1TvbyGvQTw7VyLxjVGqeWQug/TmTjOeC2ZNEboLESR+L4r/4c0MgAQBpKraHZDQkmo8VxdTnBIojiHgFs9QAzJK67cq0AESL3c5kmXvMRURS5DocbIGferx4XGJmnekM8gEomTFd9qNXtECxQZ3v7fK3mnE0l9xwoqusK5wOrd2FhYRFse3XMFd2VR+JDRNNs+yrrocEyh+NZtwOvJoZrA5cCTDNPRXCG6epEV6QeJ4emGywQ4nTKDInjNt4guKDUKpZrvzzXYavIgVuYgFgH2PjrK04BYmQGPEJ8zi4C+CxcGmZI/bpav97EDcjVpqtSWRHJxJzeVv2URd1yDVkXc7prL1lM2S2wQLxyvBdstZrakINaAUqtYrliQk0WIO0knKUJbC4LEe4BOEit4iTEntBvNg8AdFkJEZegmiNOvgv0Ui6ecI4FqOGIbRy2XGWR7NFdVVyvyoK+eJEPmnjSJHIWYQBKrUK75pdDQ7C1Qgb0MiraKIBNkLjpqBpXrcN2CQ0wLQPvJqtgtP5mn9L0a1I4NQWl19AsJEHNFs8VM1135hbhC27sQtSoPV1U14En+adK9btSQdqYmjSaZ79n7agkf89iMdedMddyjrky13KKuTLXcoq5Mtdyirky13Jq165ajrI+WE77XFfG+nHYz3WlrI/GXJlrOcVcmWs5xVyZaznFXJlrOcVcd9mopNceVeinY667blkau3VrTBqShnYBy1x33TPpmbG5L92in4y57v4ZYLjiTdtzgX6yAri+2t4ZvQwGg4dHNig9HMSWhy9TLBGkNHvpQODkPB781R04OLJJp3C4+w+KXTxPMWW4zd82RQdvU8ycTM25K/Rx0EgfWjvqb/tHPf4LTui8oR+3JOkxY9CcJFOzwSA2vfptsO0KvuR+/0mZKoMt4fOyuQLVWz5CD4fDLRcTdOoc1btxxH/UeJH8Z8CY7ppsR9/3uz66jxv17osCud6UblLsrvQrNVvzb8r3vjm4QcPGUueaX+K2r5mqnWdeKn8G5+nD4ANl7dRJerubbs4Hn1OaDgSTFMdPrWYfD9Kz1yhmTjaBwsiuKD9+pygqHn516fXP4c3VwAN6tlM/PtacwFFlzb9Mw8/pduY6x4c3EvsfpQN3kn199Grna7lv5M0KFOu7QsPLNDPSrb8Z7HLbi82nB67RZDjvGWD8GV14r+srSbpL1VHpRIFcT0sIi6xSz1tXirX9ju/YcD2Kd8Lzr5vpbFD/KFeO0yO/4T7rf2p8lLb7+GkGR4YpnQ0o2x7GZLP1wGogg/ur5h2VDOBm/9/0gX8wrJ/+6WwgYdzzZ3DSizzXU5fpesvDO/hS6WZ6o1NRzwxvrYD5V+m/7NxPSBtZHAfw6UYI5DAHEUIOgYRQ9KAIljbUgxQUKjuzeWUatdQ/CwrZxFKnQqtQ0F0IWLCtsHgosi0IhdItQg4R1kVKBRF70AUJAVewRakGfLGShJjfcX8vY6Z142ICydbB94WZ0Zn3h/fh8UtyGTbR64DmmpLY6iMyIHSxrqxU/IHHnyVyjd1DWGS9u3vMdWwClM7e3gAEQ20fIbAsQbgPMAttQFYA0/k23PF6ekBJQZrs7pEkhHu/9tA6s7wMwviLL65RL9ujCwBPpHUA2PAmsq4xJAKly+d7qLt6fT7f/o5MpAeZF6zQSAfpLtmjfNZHgISUBqXH55U2NdcdKZO9+3lksnjXDKIiLZTAVYfVWXXXkWegzEUiUQiG5wZWekGCZQ8wnQD0sKp4KEfC3l+H5H3AJaVSQ2+057qr1hmTUdZTH8ih7rqpsOq7DCmvBzd5quMvyLoG2VMlvLoa1V3HV1dX08OB+Zdk7dUoziilQ95QuOtFbgRckox95qNLg0d1IClt4TkqZSYGi3eF9N3bt59CyVwRVmfVXQ+Vd7k6EIYOsoqucekDAAQmIDiI14iUZEsZHwLokGRZ9uLz9ZPqwAJ7Ks3prvtSCoB8gPHAjhyBabm/X/Ktwyd5F06sAzKiTzx56wPY9kB/CGC5MzcCYC9toriUyrqCl5WoqR6Yk7/9fmWwyHrMdX+k7fCL69IwoCsMPkjhpvwIUc8aJPpHgS1lX95caQNM5xIMDBzA1ti/XfvmGW6X7gq9b2BBgfdyDEJKYmtxcVEO7cPDMci57kUgsocnbZy+WUj/NHUgb8D4KEwGMzAZOBoBk5YS2YnCSkZzfdW2C5+8YfisfPP6ypJMwFfKEvGQkTiA4iGEbKMrhrkmh4mn6z1T6iTklzTMsqVMDg68BsxMIPucvIRRyePxzGmdAdZZCYAMieium15C1g7ILAAMsFusDmzJe7prmAAJ4UlzXfuRkOEkzHo8PXsQ7yck8FEbAVhIFBSikMAKzLJZx+CZQrzTALCd56r93mK5+7TM3weKT0K/npwDKCQHRc+pX9LpYyNMTP5X83xX3JBa7v19+vfXc/57a6cLCkleDTg159wVUlBI8mrAqTnvroUlrwacGu5abLjrqeGuRgx35a5GCnflrkYKd+WuRgp35a5GCnflrkYKd+WuRgp35a5GCnflrkYKd+WuRgp35a5GCnflrkYKd+WuRgp35a5GCnflrkYKd+WuRgp35a5GCnflrkZKCVx/u6+WO8k4PYOJJ8vp+vvPatlzJlkRtpyu99Xyh57RlNNV5a7clbtyV+7KXbkrd+WuZ8S1ymQyVbpVFrODu5bMVRSvNVqFdhVT11hi19gGPTFRWvLorvrl/3JtES9UuP1VJqFKNbtwn1pvWgTzNVWsVNVWwW1xmK2WarWhQrC0us2C2F2Y6/X6mjv11yldsy1T2lf73OZ0Ou802+02u71psxbPj1gLrd2TGuzQfIXewNvNtAYb1S7S2lu2SOlc89/RWH7XSktrg1u1uhsFt7VCbUdKscVaqYqWumqLSTUL1a1YB0xio+OHC9YWJC7I9c7l+kfBi8hla6K0Zvg5/jlni1Fqo/hv/Xs685i10Nodua7bFunGEK15RJeu2D9dGrLHSuea/47G8rtaBVcLbs06l8nRIjRWm/xClct6QRWFigrrNdVcxepro9Cqqm7B4RLFwlyf32gOx2xL1PnASSO2XXTdGbTTrOu27V2uhXY+ct20TVEMutId2+PvX12ipXPNf0dj+V39LotQ1y6IDpNDtVjNLnR1OBx+sTL3mYVHg9DOXPF+XRH19XLTvJM6w9cvUVYHbM2a6wweXyeeqwPDTnv9TNaVXrxV2vqa/47G8ru6u9VKETdkq+BQGwQEFCu7uxvUY643BYe/wf9dtb/FXYTrtPNqE22+enGK/sOuHYW0ccdxAP/nsssswYbAAoYQ8pI+OFiGI4NsWZsRJkMScijKkLoJFafzwSFBfMlkItQwSsD0YQ46lJTtYYwTMh8EIRr6TzeKLcgQxNIFi42wGEMqxt/j/v/cCSZrKdJEvPL7gob7+Tvu7uPx4y78+RzY4gPTym/G5eq2JTv/H3D17Of2Pe761Hq7zq4qLGc9vzkgvPXx8GWiZ/frsMA0P71MCJuv75xy/fY9geg/++BtQl4xX6tjt/6VX7cyNu66bc0o8/Xd9zP5X2fyLOubShsbqfbMo/F8ftGaY66rH9qf1d2VwzLW83Ll+fLk10mGh1/edBbXTxhn/spH7M7lzwPqHMhn+fPArcosvZbnmbliZ3/M8CeBAeV5IJNvgCs8L73h71t7WeXz2oxaeKqUt17c/ka9F5zHe+zOmbrR9WIFXdEVXdEVXdEVXdEVXbXniuuIcN3by3IR173hOk1cV/y/XOR1xRh0PRV01WLQFV21FHRFVy2lDq6P79OG5v5j0F5e35WzImz9XRlrw2FBc3l9V3oOAc0FXdFVS0FXdNVS0BVdtZSGuiZkSh0tlCWsn1NKnWKlHBc6pvR6vdEl86JXSKLrGVyNrZRayCCl1ETiSqmdVMqyOx4hnRG/2MqLU+4Uur7CtVUQHc00YdI1RUyECFGLaOR3KYk7bZSKHcyVlyNCOMKpW5o7DW7iF2myRRDcaYcg+mjULIid6Eqr0k7cfsFATeaowzLVZAunLE7Rn27ykLjDTKnOz1x5WSaDEeK+6tR52om510+oR/B2elxi+KqetpjmfOha4+psotRhSBFbm1NIV+aA0yt6muRTrpSVk9xVNJi8qXYyR1nRzMdwc3NbGwk7dW1RnAO1rgbumtTZXC5XSnFNG4gvWXFNkSrXuDpw+c8lR8WV7RVNtZmIF11pVTqIy6szUItFln3UZkqyOUD95jRzdesTbJJGSJiX5VpXhziV6HUb4mlvulemLRZ0pdVxX2q2NdGIRUcsdFAkPubKwlznjMRI2qmJ+FjZW+sqmwhplR0CuZRw6gTDILrSqsieVMLYyiVTlCVBTyWpdKR5uTbqDinek5bxOavWNWokOjO/EfF9q46uPKkUpeiK3w+gq5aCruiqpaArumop6IquWgquI7qorrjuDddpVuWiu2LQ9VTQVYtBV3TVUtAVXbUUdEVXLQVd0VVLQVdNuJZWlgpQk7FVUFI4hNKtLmnyAJ5ILItwPCuFpovQ3/1Tt6Tu9vBGsH8ZYP16cGQfYEGSZgFgbywGAL/1S+NP4HeJJQsPRkJDaycNh5Oh7hW2U09wrHiykfs62PdP/RpAPXX1+MrJqNfReNdyn8SFqvPnLigZugc7dwoH47dhq7tcLgPMju4XF55BVxYgqO41v3H0IFgsBteKPwxApntju28RikPffA+wKWWPfrkB89N818PQWnkjdKA2xEZ210I7hdDS3sSEugFfxfYXusp1awD11JXjqyejXkfjXVeDpfIXd45yyrGOJYDlaRhf3xwaDX33fCQQlIAlFoOtntK9fxnm/qONMqiuOSkHlfwdPNoOsY/A/uRdgJURALjLXLOhAiz2w/zNXKYEID2EnWBJbejaBrj589IoQCGgbuyFAKBns24NSmIx5fjqyajX0XjXHwcAJic2A7uKa+AY/hhnt+lGYLFw/T/2ziAkjisO46PFYAml9BAI5OolFAKBHAo9CEIO5T3m4TKyiIuFlQR2D4IEDQSVhgUJIkKyh0kgYkhJECkIcQ+CJBpcUYIVZBEWwUhC1gVxHSbLzn7HOs6/1alMwcxYZtr3gbj/N9/y3vzQcf4y+75l2L+4QFktosg6EmzN4OkE7wNxNXQDAF7E2RwsVS+meTE9D2x0EVeMMsGKmFQTQuxhmcXYFMjAKoA+OjECgBlOsakBhxMGZgAtneZ3FkPncf5cx/qBh2mzUIObqwDGsocvANR6ssCnkSqyqQM2DoO/J65wVFrLqgfY6NamY6W+HPCum7h+4BML/WksTaLe8wTa6GJWmGRQy0B2/OUwYLGaU2zHACRXAjOAlk7zO4uh8zh/rhNxoC8DgLhaeHnENQFks87P6910nf5CxcCXgZ8Xj7mSEq8BoMJrIzrwWx9xnbwHmMwAgOzwpgDQvUiGjnVgYOr1beCjSkWFVQHxPjADQEt35qfF0HmcO9cttrypzh/MmU6pFWo9J7hmdEDvMm3fC6ua6cPdodoHtktcq2tVAHoJZV40dKueGcaqZtQSOeK6Fv+MNW7mVlBJTBlqCRVeIEO2HyW+a/AtjA5TgeQ0FmMIzFDYo6U789Ni6DzOnSt0xoYtur7Cvie5PXDMtRATm4wLIfApxXliF3tJzl+CuO4evWtCVWM6jH7O0wfAmKoOWdgWnIl1jIhYYgHv4pwP1DCtxTQdZDBSqjoF5FS1ew9UbGtCbARnELPG0dJpfloMncf5c4VVdVU1uGQcHzFhy6wDxNXtqVVPfiM57/lcO+0z62SgInDD8BZIND85LTO8/ZYWe6KxCkKtPZxBIeH6X5Tk+r/iOqvtA+UUT2wCwK5WRlYcKkNNu6uRp4IaeR8G3wo91xdDrAwks2aOH9hdDyvBqtWqXTPUtLsaeSqokfdh8KvwcwV4GeA7qPE5YHJYLQHAYsyipt3VyFPhNPJ+DP4VDa69fVvj6jNsaabDNT4LatpdjTwVTiPvxwDfigbX/bQYvTdbja/jiOucVgc17a5GngqnkfdjgG9Fg6utrvVnPJ1mt4uwtHmAmnZXI0+F08j7MfhXNLjqB8jF8GFpaYnPVDATB0BNu6uRp4IaeR8G/wo71yHB1F7oqtqxBVtqCZZYBKhpdzXyVFAj78fgW6HnCpKJ0zJOHHJ39bWqH0OACj3X6EpylVyjJMlVco2SJFfJNUqSXCXXKElyDS1X+fnYv0t+njvEXOX+A6ck98uQXCMmyVVyjZIkV8k1SpJcJdco6d/k+upxPu9OhZFcg+DaruTz7lQYyfVLud6/2HC5+Wb+RlNjy08NSuMVSoX5/tKV5vam/INvGi50HqXCSK5n4/r1xc4rSustpe1O4+AN5c4jSoVpUVoGbyr5y83tP3QepcJIrmfi+kppzT9XWq9+df1683X7OkCpMC1NdhrEm8Yf/0qFkVy/iOth8Et7u/I2TykbLd/aXO2jf6bCSK5nug5cbL55SWm9r9zKdz54rLS/cXHNN3/3fPCBkwojuZ6J66NLzVcb2vLXmpSvOvNXlGY318ELSkObkwojuZ6Ja9v9t62Kfbtqf+Vfue5YKS3GToWR91ln5HqtUWm6Yb+Q/RYpCK6UYiS5yv8PSK6hluQquUZJkqvkGiVJrmHlKp8jks+9uRRyrvI5Tflc8UlJrlGU5Cq5RkmSq+QaJUmukmuUJLlKrlGS5Cq5RkmSayS4ns6HefIQjgwD+L2HJ+cATQiRAXIdPPURgFcsTCGx4BEL47WTK40FZQgN19P5MChuwpE+dpT+ss4N8D3LqmNFe19dWAbgEQtTSHXkPGJhPHdypbGgDGHh6sqH6d3Abhy/6hDjamrnKWfCRmwyE3x/dQfond9ZNvFPsTC9OY9YGM+dXGksKENYuLryYZKrKKnQx8Aylcy4/cLWWB/AtR6mIz4Q0zTvWBji6hEL47GTK40FZQgL1+N8GBfXj1jqIa5L6j4w9AlrzIp3Az1TcHQ6Foa4esTCeOzkSmNBGcLC1ZUPk1zBtsPVxGrS4bqlrtOVmJXT48DDMZBOxcIQV49YGI+dXGksKENYuLryYTJPkT3BNZcCyiIHoDpuYFbFTMeBEZ/1jIUhrh6xMB47udJYUIawcHXlwxQ0kRbHXI1uMTPKhBCT5gjn4h1qv3A+ZHnHwkwLxkUd3rEw23+wdzehiaNxHMefJ5IQqVJLqAe3dMCD0BdKF2tZqQRcGMv01LlZTw50brOX7kn2tOChpYfCgtBTocNCD0N72IM3y6xkWBgvwhamh1mEQnoQV8mI2d9xow1U+wK7mEIy/L+Q1NSQBz4ENfKo97/J1f6fUzu4xnX092EMjNS5e7M3tPP//1mY+9/k6vAOLrouoMiVXD0YuZKrlyJXcvVS5EquXopcXetK84ppHvxwLnelz23Q54xGIldyJVdyJVdyJVdy/dpc5TlytXPUde01udqN7/pS/EaY+FmbXJh4NrmivZB48HBrgk+dket4rs/Z9MuJCc3PVw79S5o4/XruUJjbDX5HruO6/qKtsXP/M03zL/3IDjVtiy19OzVFruO6vrWW3/wLfVdro++6sLRE5+vYrktn06J24/qWzZ0/PxdWzne3yHVc10kmbFmmWn9ZE5i4+/0E4yvkOq6rdqYNdTZY/U6vs8Z0fcE1K7reAl3HkqsLI1dy9VLkSq5eilzJ1UuRq1tdaR4RzXsbyeWuNE+T5hUPR65ejFzJ1UuRK7l6KXIlVy9FruTqpciVXL0UuZKrlyJXcvVS5EquXopc3eraoOh8Hcnd5ytFrsORqxcjV3J1cW0MR64OdZz76QtuI1dn+pLL5T7iNnJ1qL3cq79xG7k6lPlnB0ORqzP99f79RwzljOtpE49lnJh4qKsK+jUb+K8Zlz24tr1cLuf88xYr4rFq7BIPtS6hX5wDdvs1PNplEdhnJbi2d6/c5frHAWAnp/FoeRHQ96/h3vae0LVbXC10UCgBjYwJ7BzBdm29WS2ivAmgnjHN/dVsF7ZrJY/KdiX1pttL+2bTFVysJ8tAtpJVUVaTNQBVNXl6FOPpbCvdtkdopS8yGR3oWUcy4I6e0NWc4REhZCwHgCQros0Ltqse8McEtcyOgMUQor6YHLFd+3/WuRgRlW5UCEZLp4Iyw08g+aTVIp+dYSUUmRzlqsKiy9aR7BFqTFIC3EBEXpychTt6Qtd9VoHONiusioAYRVY0bdeEDBSCUKJoC9slVkeT60Ou7AQH7BpyGlBiwPIiJMVETwdmFhGIAJ+RFwdHskeosSS6fMdkBeAKrujDD7ncr//gNgddkxKA0DyC8TIvciO8CNs17AuFQqyxw/WMaCaZtcHzQ64i0GanA1dBDoX8MiQVaCdmFDEMvg4r29UeocaqQCCFGI9kXPI4sJcbfUHgpOs67wFyHKq8OAspw8o3rnVElJpV15RSgSRUoWpttIZcJaBjufpTgC9u3VeHtAEkpGJ1NgwpMXAVBq72CNatgSvKqjwDV/Th+Pj4nfPn63aj0biqstXWJjuAzngRcR5Evy7PYJMVehcpICVwHdZezXayecSqd1yjStOIyic4yg5c5wNGRQgjJpV6aqvGioalaY9guxqqgYQMt+aEaz8JeZH5VAAR0bT4VAyKc8VaOI8Ben+FvI8x5QJhlgCwIWHDdi35WewqwriQgbQJVGXuC0fQjjAWrGOes1N2aY9Qv3H9pHBBLsCtOXkde4X7tXXA/GQOH6kDK72DOzV6gPH59mAm+hnXg7X+wAiGS5617kfvD5CrxyJXcvVS5EquXopcydVLkSu5eilyJdd/27WD16bBMI7jf+BCC7t4KQoehHlYEaJ78RIJxMMYo8JuxdPwEE+BLTBYwKPmMIuCZRehs3MQN9jrmub9bSe77HWbcxTbROkbf9/Dy/vw3D6UQuA1KbrS1aRKcB2+aFiNNwC2GhmA+3u4Ouv1xrMD6N3Let5+PlS84q5q4fH+4MMKgMb8NoD5z7g6dwc7q7U9vVPD4cLmcHgxVLzirju1IfLeN97d06K/nCtPL3d4uAU9VLzirhv39WVxE3c+3eK6fVfvtKseql1x17c15O3Xvw9eP7nFdeOB3mlXPVS74q5Hc7s4b3nOsqy5g99dl5ahd7mrHmb5udVMuGJx8Rh7z4+tb+e4qzddB6+srz93uevlUOlKcD1Zqtfq6+uPAOCLNZi3arXagT5Hx8IuLncj12tDlSvoqjsG4/fWRXQ1MbrS1aToSleToitdTYqudDWp4q4nR4emdXSCQDTLTgSluprHOoINfImyk35QpuuhiQmJ8pPiv3dt4m/UpCtd6WpQdKWrSdGVriZF13/pGom8BONLJV0nclVZttbJMoXxRQFdJ3DNW+sAbV/EgRAh+q01u50idoU/ututPpKW7QV2U/TpOrlry00QSylkrxlLryttmXaQdFXkw/dlL4kCxd/rNK4xILux+7EngCBUdtgH0OsErhIJ/wemd+0is4NzVw8IQySh20bkRqGjmnQt5JrYKrW1a5YgbabtCKEDL1JSdlp0ndJVtR3H066J67kBesJtOUgc4fRST8R0nfK7IFU37iq9uOeHoiu/t/LoSle60pWudKUrXelKV7oa+I6I79500g/4TnP232ky8L32tehqYnSlq0nRla4mRVe6mhRd6WpSdKWrSdGVriZFV7qaFF3palJ0patJ0ZWuJkVXupoUXelqUnSdLddTsDGdTut6RthxrGd/7somaZzrD8oBAMffjbluAAAAAElFTkSuQmCC"}}]); \ No newline at end of file diff --git a/assets/js/977c4838.ec5d78f6.js b/assets/js/977c4838.ec5d78f6.js new file mode 100644 index 0000000000..44636961b8 --- /dev/null +++ b/assets/js/977c4838.ec5d78f6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[817],{3905:(e,t,n)=>{n.d(t,{Zo:()=>l,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var d=r.createContext({}),c=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},l=function(e){var t=c(e.components);return r.createElement(d.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,d=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),u=c(n),m=o,f=u["".concat(d,".").concat(m)]||u[m]||p[m]||a;return n?r.createElement(f,i(i({ref:t},l),{},{components:n})):r.createElement(f,i({ref:t},l))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var d in t)hasOwnProperty.call(t,d)&&(s[d]=t[d]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var c=2;c{n.d(t,{Z:()=>f});var r=n(7294),o=n(6010),a=n(9960),i=n(3438),s=n(3919),d=n(5999);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function l(e){let{href:t,children:n}=e;return r.createElement(a.Z,{href:t,className:(0,o.Z)("card padding--lg",c.cardContainer)},n)}function u(e){let{href:t,icon:n,title:a,description:i}=e;return r.createElement(l,{href:t},r.createElement("h2",{className:(0,o.Z)("text--truncate",c.cardTitle),title:a},n," ",a),i&&r.createElement("p",{className:(0,o.Z)("text--truncate",c.cardDescription),title:i},i))}function p(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?r.createElement(u,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,d.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function m(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",o=(0,i.xz)(t.docId??void 0);return r.createElement(u,{href:t.href,icon:n,title:t.label,description:t.description??o?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(m,{item:t});case"category":return r.createElement(p,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,n)=>{n.d(t,{Z:()=>d});var r=n(7294),o=n(6010),a=n(3438),i=n(1564);function s(e){let{className:t}=e;const n=(0,a.jA)();return r.createElement(d,{items:n.items,className:t})}function d(e){const{items:t,className:n}=e;if(!t)return r.createElement(s,e);const d=(0,a.MN)(t);return r.createElement("section",{className:(0,o.Z)("row",n)},d.map(((e,t)=>r.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},r.createElement(i.Z,{item:e})))))}},7525:(e,t,n)=>{n.d(t,{n:()=>a});var r=n(4477);function o(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&o(t.items)}}function a(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)o(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},6548:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>d,default:()=>f,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var r=n(7462),o=(n(7294),n(3905)),a=n(9268),i=n(7525);const s={},d="Run Node",c={unversionedId:"node/README",id:"node/README",title:"Run Node",description:"The following documentation is intended to assist any individual or",source:"@site/docs/node/README.mdx",sourceDirName:"node",slug:"/node/",permalink:"/node/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",next:{title:"Mainnet",permalink:"/node/mainnet/"}},l={},u=[{value:"Node Roles",id:"node-roles",level:2},{value:"Quick Navigation",id:"quick-navigation",level:2}],p={toc:u},m="wrapper";function f(e){let{components:t,...n}=e;return(0,o.kt)(m,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"run-node"},"Run Node"),(0,o.kt)("p",null,"The following documentation is intended to assist any individual or\norganization in participating in the Oasis network as a node operator. To join\nthe network we recommend you first try running a node on the Testnet. The\nTestnet is a playground where you can learn and experiment without the risk\nof losing real tokens."),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network")," consists of the consensus layer and ParaTimes. Consensus and\nParaTime nodes can be operated by anyone."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Consensus layer is a decentralised set of 120 validator nodes that are a\nbackbone of the Oasis Network. The current validator set size is determined by\ngovernance - the network started with 80 nodes in the validator set in 2020 and\nhas expanded to 120 nodes over the past few network upgrades. Current node\noperators can be seen on a block explorer such as ",(0,o.kt)("a",{parentName:"p",href:"https://www.oasisscan.com/validators"},"Oasis Scan"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Operating a ParaTime Node on the Mainnet requires the participation of node\noperators who have the validator node in the active validator set. ParaTimes\nhave their own reward system, participation requirements and structure. As a\nnode operator you can participate in any number of ParaTimes.")),(0,o.kt)("p",null,"If you have any questions about running a node you can find us on ",(0,o.kt)("a",{parentName:"p",href:"https://oasis.io/discord"},"Discord"),"."),(0,o.kt)("h2",{id:"node-roles"},"Node Roles"),(0,o.kt)("p",null,"To run a ",(0,o.kt)("strong",{parentName:"p"},"Validator node"),", make sure your system meets the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/hardware-recommendations"},"Hardware")," and the\n",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/system-configuration"},"System")," prerequisites and has ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node")," installed."),(0,o.kt)("p",null,"Then proceed by following the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"Run a Validator Node")," guide to:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Create your entity."),(0,o.kt)("li",{parentName:"ul"},"Initialize and configure your node."),(0,o.kt)("li",{parentName:"ul"},"Put enough stake in your escrow account."),(0,o.kt)("li",{parentName:"ul"},"Register your entity on the network.")),(0,o.kt)("p",null,"To run a ",(0,o.kt)("strong",{parentName:"p"},"ParaTime node")," make sure to first set up a Validator node. Then,\nset up a ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"},"trusted execution environment (TEE)"),", if you want to run confidential\nParaTimes. After that, proceed to the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"Run a ParaTime node"),"."),(0,o.kt)("p",null,"If you are ",(0,o.kt)("strong",{parentName:"p"},"building a service")," on top of the Oasis Network, you will simply\nwant to set up your own ",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("a",{parentName:"strong",href:"/node/run-your-node/non-validator-node"},"Non-validator node"))," and (optionally) a\n",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("a",{parentName:"strong",href:"/node/run-your-node/paratime-node"},"ParaTime client node")),". This way, your service will not depend on third\nparty endpoints which can be behind a traffic limiter, can go down unexpectedly,\nor they can have some more CPU-intensive queries disabled which you would like\nto use."),(0,o.kt)("h2",{id:"quick-navigation"},"Quick Navigation"),(0,o.kt)(a.Z,{items:[(0,i.n)("/node/mainnet/"),(0,i.n)("/node/testnet/"),(0,i.n)("/node/run-your-node/prerequisites"),(0,i.n)("/node/run-your-node/validator-node"),(0,i.n)("/node/run-your-node/non-validator-node"),(0,i.n)("/node/web3")],mdxType:"DocCardList"}))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9795c642.93d7d668.js b/assets/js/9795c642.93d7d668.js new file mode 100644 index 0000000000..ee3029e458 --- /dev/null +++ b/assets/js/9795c642.93d7d668.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4913],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>v});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var d=o.createContext({}),l=function(e){var t=o.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=l(e.components);return o.createElement(d.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,d=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),c=l(n),m=r,v=c["".concat(d,".").concat(m)]||c[m]||p[m]||a;return n?o.createElement(v,i(i({ref:t},u),{},{components:n})):o.createElement(v,i({ref:t},u))}));function v(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var d in t)hasOwnProperty.call(t,d)&&(s[d]=t[d]);s.originalType=e,s[c]="string"==typeof e?e:r,i[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var o=n(7462),r=(n(7294),n(3905));const a={},i="Consensus Validator Node",s={unversionedId:"get-involved/run-node/validator-node",id:"get-involved/run-node/validator-node",title:"Consensus Validator Node",description:"This guide provides an overview of the technical setup and stake requirements to",source:"@site/docs/get-involved/run-node/validator-node.md",sourceDirName:"get-involved/run-node",slug:"/get-involved/run-node/validator-node",permalink:"/get-involved/run-node/validator-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/run-node/validator-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"Run a Node",permalink:"/get-involved/run-node"},next:{title:"ParaTime Node",permalink:"/get-involved/run-node/paratime-node"}},d={},l=[{value:"About Oasis Network",id:"about-oasis-network",level:2},{value:"Technical setup",id:"technical-setup",level:2},{value:"Stake requirements",id:"stake-requirements",level:2}],u={toc:l},c="wrapper";function p(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,o.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"consensus-validator-node"},"Consensus Validator Node"),(0,r.kt)("p",null,"This guide provides an overview of the technical setup and stake requirements to\nbecome a validator on the consensus layer of the Oasis Network."),(0,r.kt)("h2",{id:"about-oasis-network"},"About Oasis Network"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network"),"'s consensus Layer is a decentralised set of validator nodes that maintain a proof-of-stake blockchain."),(0,r.kt)("p",null,"Hence, it needs a set of distributed node operators that run different nodes (including validator nodes)."),(0,r.kt)("h2",{id:"technical-setup"},"Technical setup"),(0,r.kt)("p",null,"Make sure your system meets the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/hardware-recommendations"},"Hardware")," prerequisites and has ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node")," installed."),(0,r.kt)("p",null,"Then proceed by following the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"Run a Validator Node")," guide to:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Create your entity."),(0,r.kt)("li",{parentName:"ul"},"Initialize and configure your node."),(0,r.kt)("li",{parentName:"ul"},"Put enough stake in your escrow account."),(0,r.kt)("li",{parentName:"ul"},"Register your entity on the network.")),(0,r.kt)("h2",{id:"stake-requirements"},"Stake requirements"),(0,r.kt)("p",null,"To become a validator on the Oasis Network, you need to have enough tokens staked in your escrow account."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For more information about obtaining information on your entity's account, see the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"Account Get Info")," doc.")),(0,r.kt)("p",null,"Currently, you should have:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"100 ROSE staked for your entity's registration since that is the ",(0,r.kt)("a",{parentName:"li",href:"/node/genesis-doc#node-and-paratime-token-thresholds"},"current entity's staking threshold"),"."),(0,r.kt)("li",{parentName:"ul"},"100 ROSE staked for your validator node's registration since that is the ",(0,r.kt)("a",{parentName:"li",href:"/node/genesis-doc#node-and-paratime-token-thresholds"},"current validator node's staking threshold"),"."),(0,r.kt)("li",{parentName:"ul"},"Enough ROSE staked to be in the top 120 entities (by stake) so your validator will be elected into the consensus committee.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The size of the consensus committee (i.e. the validator set) is configured by the ",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#consensus"},(0,r.kt)("strong",{parentName:"a"},"max_validators")," consensus parameter"),".")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"To determine if you are eligible to receive a delegation from the Oasis Protocol Foundation, see the ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/delegation-policy"},"Delegation Policy")," document.")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/994ee662.6b21b1e5.js b/assets/js/994ee662.6b21b1e5.js new file mode 100644 index 0000000000..23cac84da5 --- /dev/null +++ b/assets/js/994ee662.6b21b1e5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1932],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>k});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),d=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=d(e.components);return a.createElement(l.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},g=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=d(n),g=o,k=u["".concat(l,".").concat(g)]||u[g]||p[g]||r;return n?a.createElement(k,i(i({ref:t},c),{},{components:n})):a.createElement(k,i({ref:t},c))}));function k(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,i=new Array(r);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var d=2;d{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var a=n(7462),o=(n(7294),n(3905));const r={},i="Staking and Delegating",s={unversionedId:"general/manage-tokens/staking-and-delegating",id:"general/manage-tokens/staking-and-delegating",title:"Staking and Delegating",description:"Staking and Delegation on the Oasis Network is a wonderful way to hold your ROSE",source:"@site/docs/general/manage-tokens/staking-and-delegating.md",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/staking-and-delegating",permalink:"/general/manage-tokens/staking-and-delegating",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/staking-and-delegating.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Terminology",permalink:"/general/manage-tokens/terminology"},next:{title:"Oasis Wallets",permalink:"/general/manage-tokens/oasis-wallets/"}},l={},d=[{value:"Rewards and Tokenomics",id:"rewards-and-tokenomics",level:2},{value:"How to Stake and Delegate",id:"how-to-stake-and-delegate",level:2},{value:"Tools to use for Staking and Delegation",id:"tools-to-use-for-staking-and-delegation",level:3},{value:"Verify your Staking and Delegations",id:"verify-your-staking-and-delegations",level:3},{value:"Run your own Node",id:"run-your-own-node",level:3}],c={toc:d},u="wrapper";function p(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,a.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"staking-and-delegating"},"Staking and Delegating"),(0,o.kt)("p",null,"Staking and Delegation on the Oasis Network is a wonderful way to hold your ROSE\ntokens.\nHere are a few key resources to get started!"),(0,o.kt)("h2",{id:"rewards-and-tokenomics"},"Rewards and Tokenomics"),(0,o.kt)("p",null,"Staking rewards vary over the course of the Network. In the first four years rewards will range between 20-2% over time. More ",(0,o.kt)("a",{parentName:"p",href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives"},"here"),"."),(0,o.kt)("h2",{id:"how-to-stake-and-delegate"},"How to Stake and Delegate"),(0,o.kt)("p",null,"The Oasis Network is supported by an amazing community of validators and infrastructure providers. Many provide services to help you set up your own validator node and/or make delegation easy."),(0,o.kt)("h3",{id:"tools-to-use-for-staking-and-delegation"},"Tools to use for Staking and Delegation"),(0,o.kt)("p",null,"In addition to using the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/"},"Oasis CLI")," for generating the ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.AddEscrow")," transaction, there are a number of wallets and custodians that support staking and delegation on the Oasis Network. Those include:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/web"},"Oasis Wallet - Web")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/browser-extension"},"Oasis Wallet - Browser Extension")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/general/manage-tokens/staking-and-delegating#rewards-and-tokenonomics"},"Copper.co")," (custodian)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://anchorage.com"},"Anchorage")," (custodian)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://finoa.io"},"Finoa")," (custodian)")),(0,o.kt)("p",null,"You can obtain the list of active validators including their fee and contact information at the Oasis block explorers such as the ",(0,o.kt)("a",{parentName:"p",href:"https://www.oasisscan.com/validators"},"Oasis Scan")," or the ",(0,o.kt)("a",{parentName:"p",href:"https://oasismonitor.com/validators"},"Oasis Monitor"),". The wallets will also obtain that list from one of the block explorers so you can easily browse through the validators and select the one that you prefer."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Some validators prefer anonymity and they do not list their name or any contact information. In this case only their entity's Oasis address is shown.")),(0,o.kt)("p",null,"You can stop staking and reclaim your tokens at any time. This can be done with a CLI tool or any of the wallets mentioned above. After sending the corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.ReclaimEscrow")," transaction, your tokens will, to ensure the network security and robustness, enter the ",(0,o.kt)("strong",{parentName:"p"},"debonding period")," defined in the current ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"genesis")," document. Currently, this period is 336 epochs (around 14 days) and no staking rewards are earned for the duration of this period. Afterwards your ROSE will be free to use."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Staking your ROSE is a different transaction than sending them!")," When you stake your tokens (",(0,o.kt)("inlineCode",{parentName:"p"},"staking.Escrow")," transaction), you can reclaim them at any time. Sending your tokens (",(0,o.kt)("inlineCode",{parentName:"p"},"staking.Transfer")," transaction) on the other hand means that the ",(0,o.kt)("strong",{parentName:"p"},"receiver will own the tokens and there is no way of retrieving that tokens back by yourself"),"."),(0,o.kt)("p",{parentName:"admonition"},"If you happen to send your tokens to the validator instead of staking them, try contacting the validator via email or other channels listed on the block explorers and kindly ask them to send the tokens back to you. Know that it is completely up to them to send the tokens back and there is no other mechanism of doing it.")),(0,o.kt)("h3",{id:"verify-your-staking-and-delegations"},"Verify your Staking and Delegations"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Use the ",(0,o.kt)("a",{parentName:"li",href:"https://www.oasisscan.com"},"Oasis Scan block explorer")," and verify your Staking (Escrow) by entering your ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1"),' wallet address. Check the "Amount" column in the "Escrow Active" section to see all your active ROSE delegations.')),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Account details of entered oasis1 address in Oasis Scan",src:n(8672).Z,width:"2460",height:"1426"})),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Alternatively, you can use the ",(0,o.kt)("a",{parentName:"li",href:"https://wallet.oasis.io"},"Oasis Web Wallet"),", to verify the status of your delegations.")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Account details of searched oasis1 address in Official Web Wallet",src:n(9985).Z,width:"3828",height:"1888"})),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You don't need to open your wallet, you can just search your ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis1")," address.")),(0,o.kt)("h3",{id:"run-your-own-node"},"Run your own Node"),(0,o.kt)("p",null,"If you're interested in running your own node and become a validator you can get started ",(0,o.kt)("a",{parentName:"p",href:"/node/"},"here"),". Be sure to ",(0,o.kt)("a",{parentName:"p",href:"/get-involved/"},"join the ",(0,o.kt)("strong",{parentName:"a"},"#node-operators")," channel on Discord and sign up for the node operator mailing list"),"!"))}p.isMDXComponent=!0},8672:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/oasisscan_account_details-3fd09f8a59be210c67bbbaadf716f1c5.png"},9985:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/active_delegations-35fdecb7b195c877bca7fd010b9e3926.png"}}]); \ No newline at end of file diff --git a/assets/js/9ba66431.3bc07ef8.js b/assets/js/9ba66431.3bc07ef8.js new file mode 100644 index 0000000000..fe7e2efc97 --- /dev/null +++ b/assets/js/9ba66431.3bc07ef8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[910],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>k});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,p=r(e,["components","mdxType","originalType","parentName"]),d=c(n),m=o,k=d["".concat(l,".").concat(m)]||d[m]||u[m]||s;return n?a.createElement(k,i(i({ref:t},p),{},{components:n})):a.createElement(k,i({ref:t},p))}));function k(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var s=n.length,i=new Array(s);i[0]=m;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[d]="string"==typeof e?e:o,i[1]=r;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var a=n(7462),o=(n(7294),n(3905));const s={},i="Staking",r={unversionedId:"core/consensus/services/staking",id:"core/consensus/services/staking",title:"Staking",description:"The staking service is responsible for managing the staking ledger in the",source:"@site/docs/core/consensus/services/staking.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/staking",permalink:"/core/consensus/services/staking",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/staking.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Random Beacon",permalink:"/core/consensus/services/beacon"},next:{title:"Registry",permalink:"/core/consensus/services/registry"}},l={},c=[{value:"Tokens and Base Units",id:"tokens-and-base-units",level:2},{value:"Accounts",id:"accounts",level:2},{value:"User Accounts",id:"user-accounts",level:3},{value:"Runtime Accounts",id:"runtime-accounts",level:3},{value:"Reserved Addresses",id:"reserved-addresses",level:3},{value:"General",id:"general",level:3},{value:"Escrow",id:"escrow",level:3},{value:"Delegation",id:"delegation",level:4},{value:"Commission Schedule",id:"commission-schedule",level:4},{value:"Methods",id:"methods",level:2},{value:"Transfer",id:"transfer",level:3},{value:"Burn",id:"burn",level:3},{value:"Add Escrow",id:"add-escrow",level:3},{value:"Reclaim Escrow",id:"reclaim-escrow",level:3},{value:"Amend Commission Schedule",id:"amend-commission-schedule",level:3},{value:"Allow",id:"allow",level:3},{value:"Withdraw",id:"withdraw",level:3},{value:"Events",id:"events",level:2},{value:"Transfer Event",id:"transfer-event",level:3},{value:"Burn Event",id:"burn-event",level:3},{value:"Escrow Event",id:"escrow-event",level:3},{value:"Add Escrow Event",id:"add-escrow-event",level:4},{value:"Take Escrow Event",id:"take-escrow-event",level:4},{value:"Reclaim Escrow Event",id:"reclaim-escrow-event",level:4},{value:"Allowance Change Event",id:"allowance-change-event",level:3},{value:"Consensus Parameters",id:"consensus-parameters",level:2},{value:"Test Vectors",id:"test-vectors",level:2}],p={toc:c},d="wrapper";function u(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"staking"},"Staking"),(0,o.kt)("p",null,"The staking service is responsible for managing the staking ledger in the\nconsensus layer. It enables operations like transferring stake between accounts\nand escrowing stake for specific needs (e.g., operating nodes)."),(0,o.kt)("p",null,"The service interface definition lives in ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/staking/api/api.go"},(0,o.kt)("inlineCode",{parentName:"a"},"go/staking/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc"},"consensus service API documentation"),"."),(0,o.kt)("h2",{id:"tokens-and-base-units"},"Tokens and Base Units"),(0,o.kt)("p",null,"Stake amounts can be denominated in tokens and base units."),(0,o.kt)("p",null,"Tokens are used in user-facing scenarios (e.g. CLI commands) where the token\namount is prefixed with the token's ticker symbol as defined by the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Genesis"},(0,o.kt)("inlineCode",{parentName:"a"},"Genesis"),"'\n",(0,o.kt)("inlineCode",{parentName:"a"},"TokenSymbol")," field"),"."),(0,o.kt)("p",null,"Another ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Genesis"},(0,o.kt)("inlineCode",{parentName:"a"},"Genesis"),"' field, ",(0,o.kt)("inlineCode",{parentName:"a"},"TokenValueExponent")),", defines the\ntoken's value base-10 exponent.\nFor example, if ",(0,o.kt)("inlineCode",{parentName:"p"},"TokenValueExponent")," is 6, then 1 token equals 10^6 (i.e. one\nmillion) base units."),(0,o.kt)("p",null,"Internally, base units are used for all stake calculation and processing."),(0,o.kt)("h2",{id:"accounts"},"Accounts"),(0,o.kt)("p",null,"A staking account is an entry in the staking ledger. It can hold both general\nand escrow accounts."),(0,o.kt)("p",null,"Each staking account has an address which is derived from the corresponding\npublic key as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"[ 1 byte ][ first 20 bytes of SHA512-256( || || ) ]\n")),(0,o.kt)("p",null,"Where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," represent the staking account\naddress' context version and identifier and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," represents the data\nspecific to the address kind."),(0,o.kt)("p",null,"There are two kinds of accounts:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"User accounts linked to a specific public key."),(0,o.kt)("li",{parentName:"ul"},"Runtime accounts linked to a specific ",(0,o.kt)("a",{parentName:"li",href:"/core/runtime/identifiers"},"runtime identifier"),".")),(0,o.kt)("p",null,"Addresses use ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32"},"Bech32 encoding")," for text serialization with ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis")," as its human\nreadable part (HRP) prefix (for both kinds of accounts)."),(0,o.kt)("h3",{id:"user-accounts"},"User Accounts"),(0,o.kt)("p",null,"In case of user accounts, the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," are as\ndefined by the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables"},(0,o.kt)("inlineCode",{parentName:"a"},"AddressV0Context")," variable"),", and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," represents the\naccount signer's public key (e.g. entity id)."),(0,o.kt)("p",null,"For more details, see the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAddress"},(0,o.kt)("inlineCode",{parentName:"a"},"NewAddress")," function"),"."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"When generating an account's private/public key pair, follow ",(0,o.kt)("a",{parentName:"p",href:"/adrs/0008-standard-account-key-generation"},"ADR 0008:\nStandard Account Key Generation"),".")),(0,o.kt)("h3",{id:"runtime-accounts"},"Runtime Accounts"),(0,o.kt)("p",null,"In case of runtime accounts, the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," are as\ndefined by the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables"},(0,o.kt)("inlineCode",{parentName:"a"},"AddressRuntimeV0Context")," variable"),", and ",(0,o.kt)("inlineCode",{parentName:"p"},"")," represents the\n",(0,o.kt)("a",{parentName:"p",href:"/core/runtime/identifiers"},"runtime identifier"),"."),(0,o.kt)("p",null,"For more details, see the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewRuntimeAddress"},(0,o.kt)("inlineCode",{parentName:"a"},"NewRuntimeAddress")," function"),"."),(0,o.kt)("p",null,"The runtime accounts belong to runtimes and can only be manipulated by the\nruntime by ",(0,o.kt)("a",{parentName:"p",href:"/core/runtime/messages"},"emitting messages")," to the consensus layer."),(0,o.kt)("h3",{id:"reserved-addresses"},"Reserved Addresses"),(0,o.kt)("p",null,"Some staking account addresses are reserved to prevent them from being\naccidentally used in the actual ledger."),(0,o.kt)("p",null,"Currently, they are:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qrmufhkkyyf79s5za2r8yga9gnk4t446dcy3a5zm"),": common pool address\n(defined by ",(0,o.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables"},(0,o.kt)("inlineCode",{parentName:"a"},"CommonPoolAddress")," variable"),")."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qqnv3peudzvekhulf8v3ht29z4cthkhy7gkxmph5"),": per-block fee accumulator\naddress (defined by ",(0,o.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables"},(0,o.kt)("inlineCode",{parentName:"a"},"FeeAccumulatorAddress")," variable"),")."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"oasis1qp65laz8zsa9a305wxeslpnkh9x4dv2h2qhjz0ec"),": governance deposits address\n(defined by the ",(0,o.kt)("a",{parentName:"li",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables"},(0,o.kt)("inlineCode",{parentName:"a"},"GovernanceDeposits")," variable"),").")),(0,o.kt)("h3",{id:"general"},"General"),(0,o.kt)("p",null,"General accounts store account's general balance and nonce.\nNonce is the incremental number that must be unique for each account's\ntransaction."),(0,o.kt)("h3",{id:"escrow"},"Escrow"),(0,o.kt)("p",null,"Escrow accounts are used to hold stake delegated for specific consensus-layer\noperations (e.g., registering and running nodes).\nTheir balance is subject to special delegation provisions and a debonding\nperiod."),(0,o.kt)("p",null,"Delegation provisions, also called commissions, are specified by the\n",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionSchedule"},(0,o.kt)("inlineCode",{parentName:"a"},"CommissionSchedule")," field"),"."),(0,o.kt)("p",null,"An escrow account also has a corresponding stake accumulator.\nIt stores stake claims for an escrow account and ensures all claims are\nsatisfied at any given point.\nAdding a new claim is only possible if all of the existing claims plus the new\nclaim can be satisfied."),(0,o.kt)("h4",{id:"delegation"},"Delegation"),(0,o.kt)("p",null,"When a delegator wants to delegate some of amount of stake to a staking account,\nhe needs to escrow stake using ",(0,o.kt)("a",{parentName:"p",href:"#add-escrow"},"Add Escrow method"),"."),(0,o.kt)("p",null,"Similarly, when a delegator wants to reclaim some amount of escrowed stake back\nto his general account, he needs to reclaim stake using ",(0,o.kt)("a",{parentName:"p",href:"#reclaim-escrow"},"Reclaim Escrow method"),"."),(0,o.kt)("p",null,"To simplify accounting, each escrow results in the delegator account being\nissued shares which can be converted back to stake during the reclaim escrow\noperation."),(0,o.kt)("p",null,"When a delegator delegates some amount of stake to an escrow account, the\ndelegator receives the number of shares proportional to the current\n",(0,o.kt)("em",{parentName:"p"},"share price")," (in base units) calculated from the total number of stake\ndelegated to an escrow account so far and the number of shares issued so far:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"shares_per_base_unit = account_issued_shares / account_delegated_base_units\n")),(0,o.kt)("p",null,"For example, if an escrow account has the following state:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"escrow": {\n "active": {\n "balance": "250",\n "total_shares": "1000"\n },\n ...\n}\n')),(0,o.kt)("p",null,"then the current share price (i.e. ",(0,o.kt)("inlineCode",{parentName:"p"},"shares_per_base_unit"),") is 1000 / 250 = 4."),(0,o.kt)("p",null,"Delegating 500 base units to this escrow account would result in 500 * 4 = 2000\nnewly issued shares."),(0,o.kt)("p",null,"Thus, the escrow account would have the following state afterwards:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"escrow": {\n "active": {\n "balance": "750",\n "total_shares": "3000"\n },\n ...\n}\n')),(0,o.kt)("p",null,"When a delegator wants to reclaim a certain number of escrowed stake, the\n",(0,o.kt)("em",{parentName:"p"},"base unit price")," (in shares) must be calculated based on the escrow account's\ncurrent active balance and the number of issued shares:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"base_units_per_share = account_delegated_base_units / account_issued_shares\n")),(0,o.kt)("p",null,"Returning to our example escrow account, the current base unit price (i.e.\n",(0,o.kt)("inlineCode",{parentName:"p"},"base_units_per_share"),") is 750 / 3000 = 0.25."),(0,o.kt)("p",null,"Reclaiming 1200 shares would result in 1200 * 0.25 = 300 base units being\nreclaimed."),(0,o.kt)("p",null,"The escrow account would have the following state afterwards:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'"escrow": {\n "active": {\n "balance": "450",\n "total_shares": "1800"\n },\n ...\n}\n')),(0,o.kt)("p",null,"Reclaiming escrow does not complete immediately, but may be subject to a\ndebonding period during in which the stake still remains escrowed."),(0,o.kt)("h4",{id:"commission-schedule"},"Commission Schedule"),(0,o.kt)("p",null,"A staking account can be configured to take a commission on staking rewards\ngiven to its node(s). They are defined by the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionRateStep"},(0,o.kt)("inlineCode",{parentName:"a"},"CommissionRateStep")," type"),"."),(0,o.kt)("p",null,"The commission rate must be within bounds, which the staking account can also\nspecify using the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionRateBoundStep"},(0,o.kt)("inlineCode",{parentName:"a"},"CommissionRateBoundStep")," type"),"."),(0,o.kt)("p",null,"The commission rates and rate bounds can change over time which is defined\nby the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionSchedule"},(0,o.kt)("inlineCode",{parentName:"a"},"CommissionSchedule")," type"),"."),(0,o.kt)("p",null,"To prevent unexpected changes in commission rates and rate bounds, they must\nbe specified a number of epochs in the future, controlled by the\n",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionScheduleRules"},(0,o.kt)("inlineCode",{parentName:"a"},"CommissionScheduleRules")," consensus parameter"),"."),(0,o.kt)("h2",{id:"methods"},"Methods"),(0,o.kt)("p",null,"The following sections describe the methods supported by the consensus staking\nservice."),(0,o.kt)("h3",{id:"transfer"},"Transfer"),(0,o.kt)("p",null,"Transfer enables stake transfer between different accounts in the staking\nledger. A new transfer transaction can be generated using\n",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewTransferTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewTransferTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.Transfer\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Transfer struct {\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"to")," specifies the destination account's address."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," specifies the amount of base units to transfer.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the source account."),(0,o.kt)("h3",{id:"burn"},"Burn"),(0,o.kt)("p",null,"Burn destroys some stake in the caller's account. A new burn transaction can be\ngenerated using ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewBurnTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewBurnTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.Burn\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Burn struct {\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," specifies the amount of base units to burn.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the caller's account."),(0,o.kt)("h3",{id:"add-escrow"},"Add Escrow"),(0,o.kt)("p",null,"Escrow transfers stake into an escrow account.\nFor more details, see the ",(0,o.kt)("a",{parentName:"p",href:"#delegation"},"Delegation section")," of this document.\nA new add escrow transaction can be generated using ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAddEscrowTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewAddEscrowTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.AddEscrow\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Escrow struct {\n Account Address `json:"account"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"account")," specifies the destination escrow account's address."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," specifies the amount of base units to transfer.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the source account."),(0,o.kt)("h3",{id:"reclaim-escrow"},"Reclaim Escrow"),(0,o.kt)("p",null,"Reclaim escrow starts the escrow reclamation process.\nFor more details, see the ",(0,o.kt)("a",{parentName:"p",href:"#delegation"},"Delegation section")," of this document.\nA new reclaim escrow transaction can be generated using\n",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewReclaimEscrowTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewReclaimEscrowTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.ReclaimEscrow\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ReclaimEscrow struct {\n Account Address `json:"account"`\n Shares quantity.Quantity `json:"shares"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"account")," specifies the source escrow account's address."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"shares")," specifies the number of shares to reclaim.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the destination account."),(0,o.kt)("h3",{id:"amend-commission-schedule"},"Amend Commission Schedule"),(0,o.kt)("p",null,"Amend commission schedule updates the commission schedule specified for the\ngiven escrow account.\nFor more details, see the ",(0,o.kt)("a",{parentName:"p",href:"#commission-schedule"},"Commission Schedule section")," of this document.\nA new amend commission schedule transaction can be\ngenerated using ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAmendCommissionScheduleTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewAmendCommissionScheduleTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.AmendCommissionSchedule\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type AmendCommissionSchedule struct {\n Amendment CommissionSchedule `json:"amendment"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amendment")," defines the amended commission schedule.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the escrow account."),(0,o.kt)("h3",{id:"allow"},"Allow"),(0,o.kt)("p",null,"Allow enables an account holder to set an allowance for a beneficiary. A new\nallow transaction can be generated using ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAllowTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewAllowTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.Allow\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Allow struct {\n Beneficiary Address `json:"beneficiary"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"beneficiary")," specifies the beneficiary account address."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount_change")," specifies the absolute value of the amount of base units to\nchange the allowance for."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"negative")," specifies whether the ",(0,o.kt)("inlineCode",{parentName:"li"},"amount_change")," should be subtracted instead\nof added.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the general account. Upon executing\nthe allow the following actions are performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If either the ",(0,o.kt)("inlineCode",{parentName:"p"},"disable_transfers")," staking consensus parameter is set to ",(0,o.kt)("inlineCode",{parentName:"p"},"true"),"\nor the ",(0,o.kt)("inlineCode",{parentName:"p"},"max_allowances")," staking consensus parameter is set to zero, the method\nfails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"It is checked whether either the transaction signer address or the\n",(0,o.kt)("inlineCode",{parentName:"p"},"beneficiary")," address are reserved. If any are reserved, the method fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Address specified by ",(0,o.kt)("inlineCode",{parentName:"p"},"beneficiary")," is compared with the transaction signer\naddress. If the addresses are the same, the method fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The account indicated by the signer is loaded.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the allow would create a new allowance and the maximum number of allowances\nfor an account has been reached, the method fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrTooManyAllowances"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The set of allowances is updated so that the allowance is updated as specified\nby ",(0,o.kt)("inlineCode",{parentName:"p"},"amount_change"),"/",(0,o.kt)("inlineCode",{parentName:"p"},"negative"),". In case the change would cause the allowance to\nbe equal to zero or negative, the allowance is removed.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The account is saved.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("a",{parentName:"p",href:"#allowance-change-event"},(0,o.kt)("inlineCode",{parentName:"a"},"AllowanceChangeEvent"))," is emitted."))),(0,o.kt)("h3",{id:"withdraw"},"Withdraw"),(0,o.kt)("p",null,"Withdraw enables a beneficiary to withdraw from the given account. A new\nwithdraw transaction can be generated using ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewWithdrawTx"},(0,o.kt)("inlineCode",{parentName:"a"},"NewWithdrawTx")," function"),"."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"staking.Withdraw\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Withdraw struct {\n From Address `json:"from"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"from")," specifies the account address to withdraw from."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," specifies the amount of base units to withdraw.")),(0,o.kt)("p",null,"The transaction signer implicitly specifies the destination general account.\nUpon executing the withdrawal the following actions are performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If either the ",(0,o.kt)("inlineCode",{parentName:"p"},"disable_transfers")," staking consensus parameter is set to ",(0,o.kt)("inlineCode",{parentName:"p"},"true"),"\nor the ",(0,o.kt)("inlineCode",{parentName:"p"},"max_allowances")," staking consensus parameter is set to zero, the method\nfails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"It is checked whether either the transaction signer address or the\n",(0,o.kt)("inlineCode",{parentName:"p"},"from")," address are reserved. If any are reserved, the method fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Address specified by ",(0,o.kt)("inlineCode",{parentName:"p"},"from")," is compared with the transaction signer address.\nIf the addresses are the same, the method fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The source account indicated by ",(0,o.kt)("inlineCode",{parentName:"p"},"from")," is loaded.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The destination account indicated by the transaction signer is loaded.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"amount")," is deducted from the corresponding allowance in the source account.\nIf this would cause the allowance to go negative, the method fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"amount")," is deducted from the source general account balance. If this would\ncause the balance to go negative, the method fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrInsufficientBalance"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"amount")," is added to the destination general account balance.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Both source and destination accounts are saved.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("a",{parentName:"p",href:"#transfer-event"},(0,o.kt)("inlineCode",{parentName:"a"},"TransferEvent"))," is emitted.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("a",{parentName:"p",href:"#allowance-change-event"},(0,o.kt)("inlineCode",{parentName:"a"},"AllowanceChangeEvent"))," is emitted with the updated\nallowance."))),(0,o.kt)("h2",{id:"events"},"Events"),(0,o.kt)("h3",{id:"transfer-event"},"Transfer Event"),(0,o.kt)("p",null,"The transfer event is emitted when tokens are transferred from a source account\nto a destination account."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type TransferEvent struct {\n From Address `json:"from"`\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"from")," contains the address of the source account."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"to")," contains the address of the destination account."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," contains the amount (in base units) transferred.")),(0,o.kt)("h3",{id:"burn-event"},"Burn Event"),(0,o.kt)("p",null,"The burn event is emitted when tokens are burned."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type BurnEvent struct {\n Owner Address `json:"owner"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"owner")," contains the address of the account that burned tokens."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," contains the amount (in base units) burned.")),(0,o.kt)("h3",{id:"escrow-event"},"Escrow Event"),(0,o.kt)("p",null,"Escrow events are emitted when tokens are escrowed, taken from escrow by the\nprotocol or reclaimed from escrow by the account owner."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type EscrowEvent struct {\n Add *AddEscrowEvent `json:"add,omitempty"`\n Take *TakeEscrowEvent `json:"take,omitempty"`\n Reclaim *ReclaimEscrowEvent `json:"reclaim,omitempty"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"add")," is set if the emitted event is an ",(0,o.kt)("em",{parentName:"li"},"Add Escrow")," event."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"take")," is set if the emitted event is a ",(0,o.kt)("em",{parentName:"li"},"Take Escrow")," event."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"reclaim")," is set if the emitted event is a ",(0,o.kt)("em",{parentName:"li"},"Reclaim Escrow")," event.")),(0,o.kt)("h4",{id:"add-escrow-event"},"Add Escrow Event"),(0,o.kt)("p",null,"The add escrow event is emitted when funds are escrowed."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type AddEscrowEvent struct {\n Owner Address `json:"owner"`\n Escrow Address `json:"escrow"`\n Amount quantity.Quantity `json:"amount"`\n NewShares quantity.Quantity `json:"new_shares"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"owner")," contains the address of the source account."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"escrow")," contains the address of the destination account the tokens are being\nescrowed to."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," contains the amount (in base units) escrowed."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"new_shares")," contains the amount of shares created as a result of the added\nescrow event. Can be zero in case of (non-commissioned) rewards, where stake\nis added without new shares to increase share price.")),(0,o.kt)("h4",{id:"take-escrow-event"},"Take Escrow Event"),(0,o.kt)("p",null,"The take escrow event is emitted by the protocol when escrowed funds are\nslashed for whatever reason."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type TakeEscrowEvent struct {\n Owner Address `json:"owner"`\n Amount quantity.Quantity `json:"amount"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"owner")," contains the address of the account escrow has been taken from."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," contains the amount (in base units) taken.")),(0,o.kt)("h4",{id:"reclaim-escrow-event"},"Reclaim Escrow Event"),(0,o.kt)("p",null,"The reclaim escrow event is emitted when a reclaim escrow operation completes\nsuccessfully (after the debonding period has passed)."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ReclaimEscrowEvent struct {\n Owner Address `json:"owner"`\n Escrow Address `json:"escrow"`\n Amount quantity.Quantity `json:"amount"`\n Shares quantity.Quantity `json:"shares"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"owner")," contains the address of the account that reclaimed tokens from escrow."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"escrow")," contains the address of the account escrow has been reclaimed from."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," contains the amount (in base units) reclaimed."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"shares")," contains the amount of shares reclaimed.")),(0,o.kt)("h3",{id:"allowance-change-event"},"Allowance Change Event"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type AllowanceChangeEvent struct {\n Owner Address `json:"owner"`\n Beneficiary Address `json:"beneficiary"`\n Allowance quantity.Quantity `json:"allowance"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"owner")," contains the address of the account owner where allowance has been\nchanged."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"beneficiary")," contains the address of the beneficiary."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"allowance")," contains the new total allowance."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount_change")," contains the absolute amount the allowance has changed for."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"negative")," specifies whether the allowance has been reduced rather than\nincreased.")),(0,o.kt)("p",null,"The event is emitted even if the new allowance is zero."),(0,o.kt)("h2",{id:"consensus-parameters"},"Consensus Parameters"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"max_allowances")," (uint32) specifies the maximum number of ",(0,o.kt)("a",{parentName:"li",href:"#allow"},"allowances")," an\naccount can store. Zero means that allowance functionality is disabled.")),(0,o.kt)("h2",{id:"test-vectors"},"Test Vectors"),(0,o.kt)("p",null,"To generate test vectors for various staking ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/transactions"},"transactions"),", run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"make -C go staking/gen_vectors\n")),(0,o.kt)("p",null,"For more information about the structure of the test vectors see the section\non ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/test-vectors"},"Transaction Test Vectors"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9fc93287.0264c73c.js b/assets/js/9fc93287.0264c73c.js new file mode 100644 index 0000000000..dac04739f7 --- /dev/null +++ b/assets/js/9fc93287.0264c73c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5851],{5488:e=>{e.exports=JSON.parse('{"title":"High-Level Components","slug":"core/high-level-components","permalink":"/core/high-level-components","navigation":{"previous":{"title":"Deploying a Runtime","permalink":"/core/development-setup/deploying-a-runtime"},"next":{"title":"Consensus Layer","permalink":"/core/consensus/"}}}')}}]); \ No newline at end of file diff --git a/assets/js/9fda2e12.2ca45c31.js b/assets/js/9fda2e12.2ca45c31.js new file mode 100644 index 0000000000..94f78bc5f4 --- /dev/null +++ b/assets/js/9fda2e12.2ca45c31.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7907],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},p=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=l(r),u=a,f=d["".concat(c,".").concat(u)]||d[u]||m[u]||i;return r?n.createElement(f,o(o({ref:t},p),{},{components:r})):n.createElement(f,o({ref:t},p))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[d]="string"==typeof e?e:a,o[1]=s;for(var l=2;l{r.d(t,{Z:()=>f});var n=r(7294),a=r(6010),i=r(9960),o=r(3438),s=r(3919),c=r(5999);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function p(e){let{href:t,children:r}=e;return n.createElement(i.Z,{href:t,className:(0,a.Z)("card padding--lg",l.cardContainer)},r)}function d(e){let{href:t,icon:r,title:i,description:o}=e;return n.createElement(p,{href:t},n.createElement("h2",{className:(0,a.Z)("text--truncate",l.cardTitle),title:i},r," ",i),o&&n.createElement("p",{className:(0,a.Z)("text--truncate",l.cardDescription),title:o},o))}function m(e){let{item:t}=e;const r=(0,o.Wl)(t);return r?n.createElement(d,{href:r,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,c.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const r=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,o.xz)(t.docId??void 0);return n.createElement(d,{href:t.href,icon:r,title:t.label,description:t.description??a?.description})}function f(e){let{item:t}=e;switch(t.type){case"link":return n.createElement(u,{item:t});case"category":return n.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,r)=>{r.d(t,{Z:()=>c});var n=r(7294),a=r(6010),i=r(3438),o=r(1564);function s(e){let{className:t}=e;const r=(0,i.jA)();return n.createElement(c,{items:r.items,className:t})}function c(e){const{items:t,className:r}=e;if(!t)return n.createElement(s,e);const c=(0,i.MN)(t);return n.createElement("section",{className:(0,a.Z)("row",r)},c.map(((e,t)=>n.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},n.createElement(o.Z,{item:e})))))}},7525:(e,t,r)=>{r.d(t,{n:()=>i});var n=r(4477);function a(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&a(t.items)}}function i(e){const t=(0,n.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)a(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},1074:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>c,default:()=>f,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var n=r(7462),a=(r(7294),r(3905)),i=r(1564),o=(r(9268),r(7525));const s={description:"Home of the Oasis dApp developer resources"},c="Create dApp",l={unversionedId:"dapp/README",id:"dapp/README",title:"Create dApp",description:"Home of the Oasis dApp developer resources",source:"@site/docs/dapp/README.mdx",sourceDirName:"dapp",slug:"/dapp/",permalink:"/dapp/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Home of the Oasis dApp developer resources"},sidebar:"developers",next:{title:"Sapphire ParaTime",permalink:"/dapp/sapphire/"}},p={},d=[],m={toc:d},u="wrapper";function f(e){let{components:t,...s}=e;return(0,a.kt)(u,(0,n.Z)({},m,s,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"create-dapp"},"Create dApp"),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Oasis architectural design including ParaTime and consensus layers",src:r(4128).Z,width:"1523",height:"718"})),(0,a.kt)("p",null,"The ",(0,a.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis architecture")," is designed to have a simple, robust consensus layer\non top which connects handful of ParaTimes executing smart contracts.\nDApp developers may choose among those ParaTimes depending on whether they\nrequire confidentiality and/or EVM-compatibility."),(0,a.kt)("p",null,"Learn more by exploring the ParaTimes below!"),(0,a.kt)("table",null,(0,a.kt)("thead",{parentName:"table"},(0,a.kt)("tr",{parentName:"thead"},(0,a.kt)("th",{parentName:"tr",align:"right"}),(0,a.kt)("th",{parentName:"tr",align:null},"EVM-compatible"),(0,a.kt)("th",{parentName:"tr",align:null},"Oasis Wasm"))),(0,a.kt)("tbody",{parentName:"table"},(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:"right"},(0,a.kt)("strong",{parentName:"td"},"Confidential")),(0,a.kt)("td",{parentName:"tr",align:null},(0,a.kt)(i.Z,{item:(0,o.n)("/dapp/sapphire/"),mdxType:"DocCard"})),(0,a.kt)("td",{parentName:"tr",align:null},(0,a.kt)(i.Z,{item:(0,o.n)("/dapp/cipher/"),mdxType:"DocCard"}))),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:"right"},(0,a.kt)("strong",{parentName:"td"},"Non-Confidential")),(0,a.kt)("td",{parentName:"tr",align:null},(0,a.kt)(i.Z,{item:(0,o.n)("/dapp/emerald/"),mdxType:"DocCard"})),(0,a.kt)("td",{parentName:"tr",align:null})))),(0,a.kt)("p",null,"In addition to building fully native dApps running on one of the Oasis\nParaTimes, you can also add privacy to your existing dApps running on other,\nnon-confidential chains, and only use Oasis as a ",(0,a.kt)("em",{parentName:"p"},"privacy service"),"."),(0,a.kt)("p",null,"The Oasis team prepared a rich cross-chain toolkit called the\n",(0,a.kt)("a",{parentName:"p",href:"/dapp/opl/"},(0,a.kt)("strong",{parentName:"a"},"Oasis Privacy Layer")),". It consists of solidity precompiles\nintegrating bridges and wrapping the OpenZeppelin ERC2771 contract on top of\nSapphire, demonstrates best practices for writing confidential smart contracts\nand working examples for you to explore and extend."),(0,a.kt)(i.Z,{item:(0,o.n)("/dapp/opl/"),mdxType:"DocCard"}))}f.isMDXComponent=!0},4128:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"}}]); \ No newline at end of file diff --git a/assets/js/a02c83e6.a84ea599.js b/assets/js/a02c83e6.a84ea599.js new file mode 100644 index 0000000000..05fcb35291 --- /dev/null +++ b/assets/js/a02c83e6.a84ea599.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3228],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=a.createContext({}),l=function(e){var n=a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=l(e.components);return a.createElement(c.Provider,{value:n},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,s=e.originalType,c=e.parentName,p=r(e,["components","mdxType","originalType","parentName"]),u=l(t),d=o,h=u["".concat(c,".").concat(d)]||u[d]||m[d]||s;return t?a.createElement(h,i(i({ref:n},p),{},{components:t})):a.createElement(h,i({ref:n},p))}));function h(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var s=t.length,i=new Array(s);i[0]=d;var r={};for(var c in n)hasOwnProperty.call(n,c)&&(r[c]=n[c]);r.originalType=e,r[u]="string"==typeof e?e:o,i[1]=r;for(var l=2;l{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var a=t(7462),o=(t(7294),t(3905));const s={},i="Transactions",r={unversionedId:"core/consensus/transactions",id:"core/consensus/transactions",title:"Transactions",description:"The consensus layer uses a common transaction format for all transactions. As",source:"@site/docs/core/consensus/transactions.md",sourceDirName:"core/consensus",slug:"/core/consensus/transactions",permalink:"/core/consensus/transactions",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/transactions.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Consensus Layer",permalink:"/core/consensus/"},next:{title:"Services",permalink:"/core/consensus/services"}},c={},l=[{value:"Format",id:"format",level:2},{value:"Fees",id:"fees",level:2},{value:"Gas",id:"gas",level:3},{value:"Gas Estimation",id:"gas-estimation",level:2},{value:"Submission",id:"submission",level:2}],p={toc:l},u="wrapper";function m(e){let{components:n,...t}=e;return(0,o.kt)(u,(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"transactions"},"Transactions"),(0,o.kt)("p",null,"The consensus layer uses a common transaction format for all transactions. As\nwith other Oasis Core components, it tries to be independent of any concrete\n",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus backend"),"."),(0,o.kt)("p",null,"The transaction API definitions and helper methods for creating and verifying\ntransactions lives in ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/api/transaction/transaction.go"},(0,o.kt)("inlineCode",{parentName:"a"},"go/consensus/api/transaction")),". For more information\nyou can also check out the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api/transaction?tab=doc"},"consensus backend API documentation"),"."),(0,o.kt)("h2",{id:"format"},"Format"),(0,o.kt)("p",null,"Each (unsigned) transaction is represented by the following ",(0,o.kt)("a",{parentName:"p",href:"/core/encoding"},"encoded")," structure:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Transaction struct {\n Nonce uint64 `json:"nonce"`\n Fee *Fee `json:"fee,omitempty"`\n\n Method string `json:"method"`\n Body interface{} `json:"body,omitempty"`\n}\n')),(0,o.kt)("p",null,"Fields:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"nonce")," is the current caller's nonce to prevent replays."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"fee")," is an optional fee that the caller commits to paying to execute the\ntransaction."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"method")," is the called method name. Method names are composed of two parts,\nthe component name and the method name, joined by a separator (",(0,o.kt)("inlineCode",{parentName:"li"},"."),"). For\nexample, ",(0,o.kt)("inlineCode",{parentName:"li"},"staking.Transfer")," is the method name of the staking service's\n",(0,o.kt)("inlineCode",{parentName:"li"},"Transfer")," method."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"body")," is the method-specific body.")),(0,o.kt)("p",null,"The actual transaction that is submitted to the consensus layer must be signed\nwhich means that it is wrapped into a ",(0,o.kt)("a",{parentName:"p",href:"/core/crypto#signed-envelope"},"signed envelope"),"."),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"/core/crypto#domain-separation"},"Domain separation")," context (+ ",(0,o.kt)("a",{parentName:"p",href:"/core/crypto#chain-domain-separation"},"chain domain separation"),"):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-core/consensus: tx\n")),(0,o.kt)("h2",{id:"fees"},"Fees"),(0,o.kt)("p",null,"As the consensus operations require resources to process, the consensus layer\ncharges fees to perform operations."),(0,o.kt)("h3",{id:"gas"},"Gas"),(0,o.kt)("p",null,"Gas is an unsigned 64-bit integer denominated in ",(0,o.kt)("em",{parentName:"p"},"gas units"),"."),(0,o.kt)("p",null,"Different operations cost different amounts of gas as defined by the consensus\nparameters of the consensus component that implements the operation."),(0,o.kt)("p",null,"Transactions that require fees to process will include a ",(0,o.kt)("inlineCode",{parentName:"p"},"fee")," field to declare\nhow much the caller is willing to pay for fees.\nSpecifying an ",(0,o.kt)("inlineCode",{parentName:"p"},"amount")," (in base units) and ",(0,o.kt)("inlineCode",{parentName:"p"},"gas")," (in gas units) implicitly\ndefines a ",(0,o.kt)("em",{parentName:"p"},"gas price")," (price of one gas unit) as ",(0,o.kt)("inlineCode",{parentName:"p"},"amount / gas"),".\nConsensus validators may refuse to process operations with a gas price that is\ntoo low."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"gas")," field defines the maximum amount of gas that can be used by an\noperation for which the fee has been included. In case an operation uses more\ngas, processing will be aborted and no state changes will take place."),(0,o.kt)("p",null,"Signing a transaction which includes a fee structure implicitly grants\npermission to withdraw the given amount of base units from the signer's account.\nIn case there is not enough balance in the account, the operation will fail."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Fee struct {\n Amount quantity.Quantity `json:"amount"`\n Gas Gas `json:"gas"`\n}\n')),(0,o.kt)("p",null,"Fees are not refunded."),(0,o.kt)("p",null,"Fields:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"amount")," is the total fee amount (in base units) to be paid."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"gas")," is the maximum gas that an operation can use.")),(0,o.kt)("h2",{id:"gas-estimation"},"Gas Estimation"),(0,o.kt)("p",null,"As transactions need to provide the maximum amount of gas that can be consumed\nduring their execution, the caller may need to be able to estimate the amount of\ngas needed. In order to do that the consensus backend API includes a method\ncalled ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend.EstimateGas"},(0,o.kt)("inlineCode",{parentName:"a"},"EstimateGas"))," for estimating gas."),(0,o.kt)("p",null,"The implementation of gas estimation is ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/"},"backend-specific")," but usually involves\nsome kind of simulation of transaction execution to derive the maximum amount\nconsumed by execution."),(0,o.kt)("h2",{id:"submission"},"Submission"),(0,o.kt)("p",null,"Transactions can be submitted to the consensus layer by calling ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend.SubmitTx"},(0,o.kt)("inlineCode",{parentName:"a"},"SubmitTx"))," and\nproviding a signed transaction."),(0,o.kt)("p",null,"The consensus backend API provides a submission manager for cases where the\n",(0,o.kt)("a",{parentName:"p",href:"/core/crypto"},"signer")," is available and automatic gas estimation and nonce lookup is desired.\nIt is available via the ",(0,o.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#SignAndSubmitTx"},(0,o.kt)("inlineCode",{parentName:"a"},"SignAndSubmitTx"))," function."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a11d2c44.a34bab9f.js b/assets/js/a11d2c44.a34bab9f.js new file mode 100644 index 0000000000..98ab372fe0 --- /dev/null +++ b/assets/js/a11d2c44.a34bab9f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1581],{3905:(e,n,a)=>{a.d(n,{Zo:()=>p,kt:()=>m});var t=a(7294);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function o(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function i(e){for(var n=1;n=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var d=t.createContext({}),s=function(e){var n=t.useContext(d),a=n;return e&&(a="function"==typeof e?e(n):i(i({},n),e)),a},p=function(e){var n=s(e.components);return t.createElement(d.Provider,{value:n},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},g=t.forwardRef((function(e,n){var a=e.components,r=e.mdxType,o=e.originalType,d=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(a),g=r,m=u["".concat(d,".").concat(g)]||u[g]||c[g]||o;return a?t.createElement(m,i(i({ref:n},p),{},{components:a})):t.createElement(m,i({ref:n},p))}));function m(e,n){var a=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=a.length,i=new Array(o);i[0]=g;var l={};for(var d in n)hasOwnProperty.call(n,d)&&(l[d]=n[d]);l.originalType=e,l[u]="string"==typeof e?e:r,i[1]=l;for(var s=2;s{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>c,frontMatter:()=>o,metadata:()=>l,toc:()=>s});var t=a(7462),r=(a(7294),a(3905));const o={},i="Upgrading Key Managers",l={unversionedId:"node/run-your-node/keymanager-node/key-manager-upgrade",id:"node/run-your-node/keymanager-node/key-manager-upgrade",title:"Upgrading Key Managers",description:"This guide will describe how to upgrade a key manager node.",source:"@site/docs/node/run-your-node/keymanager-node/key-manager-upgrade.md",sourceDirName:"node/run-your-node/keymanager-node",slug:"/node/run-your-node/keymanager-node/key-manager-upgrade",permalink:"/node/run-your-node/keymanager-node/key-manager-upgrade",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/keymanager-node/key-manager-upgrade.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Signing Key Manager Policy",permalink:"/node/run-your-node/keymanager-node/signing-key-manager-policy"},next:{title:"IAS Proxy",permalink:"/node/run-your-node/ias-proxy"}},d={},s=[{value:"About the Upgrade",id:"about-the-upgrade",level:2},{value:"Safe Upgrade Procedure",id:"safe-upgrade-procedure",level:2},{value:"Upgrade Nodes",id:"upgrade-nodes",level:3},{value:"After the Upgrade",id:"after-the-upgrade",level:3},{value:"Verifying Successful Replication",id:"verifying-successful-replication",level:4},{value:"Troubleshooting",id:"troubleshooting",level:2}],p={toc:s},u="wrapper";function c(e){let{components:n,...a}=e;return(0,r.kt)(u,(0,t.Z)({},p,a,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"upgrading-key-managers"},"Upgrading Key Managers"),(0,r.kt)("p",null,"This guide will describe how to upgrade a key manager node."),(0,r.kt)("h2",{id:"about-the-upgrade"},"About the Upgrade"),(0,r.kt)("p",null,"Every key manager node contains all the keys used by confidential ParaTimes\ninside its TEE-encrypted state. The key material is sealed and can only be\ndecrypted by exactly the same TEE enclave running on the exactly same CPU. This\nmeans that newer key manager ParaTimes can not read the key material and that\nkey material can not be restored on another machine. "),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"During a key manager node upgrade it is therefore essential that the key\nmaterial is not lost, not even due to an operational error or even a\ncatastrophically failed upgrade.")),(0,r.kt)("h2",{id:"safe-upgrade-procedure"},"Safe Upgrade Procedure"),(0,r.kt)("p",null,"A key manager node's upgrade procedure differs from other Oasis nodes upgrades\nbecause the upgraded node cannot unseal/decrypt the old key manager's state."),(0,r.kt)("p",null,"To upgrade a key manager node, we need to delete the local state and let the\nkey manager's state replicate itself from other nodes. Only one key manager\nruntime in the configuration file can be present at once. "),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"In case you are running multiple key manager nodes always follow the safe\nupgrade procedure:")),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Keep approximately one half of nodes running the old version."),(0,r.kt)("li",{parentName:"ol"},"Upgrade the other half."),(0,r.kt)("li",{parentName:"ol"},"Wait for the ParaTime upgrade epoch."),(0,r.kt)("li",{parentName:"ol"},"Verify that secrets have been replicated ",(0,r.kt)("a",{parentName:"li",href:"#verifying-successful-replication"},"as shown below"),"."),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("strong",{parentName:"li"},"Verify again.")),(0,r.kt)("li",{parentName:"ol"},"Upgrade the rest of the nodes.")),(0,r.kt)("h3",{id:"upgrade-nodes"},"Upgrade Nodes"),(0,r.kt)("p",null,"To upgrade a key manager node, follow the next steps:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Stop the node."),(0,r.kt)("li",{parentName:"ol"},"Wipe its local state ",(0,r.kt)("inlineCode",{parentName:"li"},"worker-local-storage.badger.db"),", e.g.:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"rm -rf runtimes/4000000000000000000000000000000000000000000000004a1a53dff2ae482d/worker-local-storage.badger.db/\n")),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"Upgrade the key manager runtime: ",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"get the new ORC file (",(0,r.kt)("a",{parentName:"li",href:"../../mainnet/#key-manager"},"mainnet"),", ",(0,r.kt)("a",{parentName:"li",href:"../../testnet/#key-manager"},"testnet"),"); "),(0,r.kt)("li",{parentName:"ul"},"update the configuration to replace the ORC file; and"),(0,r.kt)("li",{parentName:"ul"},"restart the node."))),(0,r.kt)("li",{parentName:"ol"},"Wait for the key material to get replicated from active nodes before\ncontinuing."),(0,r.kt)("li",{parentName:"ol"},"Verify that secrets have been replicated ",(0,r.kt)("a",{parentName:"li",href:"#verifying-successful-replication"},"as shown below"),".")),(0,r.kt)("h3",{id:"after-the-upgrade"},"After the Upgrade"),(0,r.kt)("h4",{id:"verifying-successful-replication"},"Verifying Successful Replication"),(0,r.kt)("p",null,"After the upgrade epoch and when the key material is successfully replicated,\nthe ",(0,r.kt)("inlineCode",{parentName:"p"},"control status")," output should show ",(0,r.kt)("inlineCode",{parentName:"p"},'keymanager.status="ready"')," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"registration.descriptor.runtimes.0.extra_info")," should contain a hash of the\nkey material state:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'$ oasis_node oasis-node -a unix:/storage/node/internal.sock control status\n...\n "registration": {\n "last_registration": "2023-02-06T08:40:30Z",\n "descriptor": {\n...\n "runtimes": [\n {\n "id": "4000000000000000000000000000000000000000000000004a1a53dff2ae482d",\n "version": {\n "minor": 3,\n "patch": 3\n },\n "capabilities": {\n "tee": {\n "hardware": 1,\n...\n }\n },\n "extra_info": "omlzaWduYXR1cmVYQG7nDuKTOUKAlJAfukdY6Xljox376lCLI0cIP0zPw2B8abJxa31j+NoQAWA0KZuHD41XPyICmjXDTpjDXukEEgVtaW5pdF9yZXNwb25zZaNoY2hlY2tzdW1YIEWZF5YaFQChstrZ9u1UdgyqZCagmNfghvyQna9WkmvyaWlzX3NlY3VyZfVvcG9saWN5X2NoZWNrc3VtWCCsrqRzYjx05t+KoCYz7wFSdKJ720g2LQBAsRKXmClMvw=="\n }\n ],\n "roles": "key-manager",\n }\n }\n...\n "keymanager": {\n "status": "ready",\n "may_generate": false,\n "runtime_id": "4000000000000000000000000000000000000000000000004a1a53dff2ae482d",\n "client_runtimes": [\n "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c",\n "0000000000000000000000000000000000000000000000000000000000000000"\n ],\n "access_list": [\n...\n ],\n "private_peers": [\n...\n ]\n }\n')),(0,r.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,r.kt)("p",null,"If you forgot to wipe the key manager's state when upgrading, the upgraded Key\nManager will be unable to unseal the old state and will abort:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'{"level":"warn","module":"runtime","msg":"thread \'main\' panicked at \'runtime execution failed: Enclave panicked.\', runtime-loader/bin/main.rs:57:10","runtime_id":"4000000000000000000000000000000000000000000000004a1a53dff2ae482d","runtime_name":"keymanager","ts":"2022-11-11T13:38:18.805919693Z"}\n')))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a14fc975.2169ad9a.js b/assets/js/a14fc975.2169ad9a.js new file mode 100644 index 0000000000..dadf3f3009 --- /dev/null +++ b/assets/js/a14fc975.2169ad9a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9560],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>g});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},d=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},c=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),m=p(a),c=o,g=m["".concat(l,".").concat(c)]||m[c]||u[c]||r;return a?n.createElement(g,i(i({ref:t},d),{},{components:a})):n.createElement(g,i({ref:t},d))}));function g(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[m]="string"==typeof e?e:o,i[1]=s;for(var p=2;p{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>p});var n=a(7462),o=(a(7294),a(3905));const r={},i="Upgrade Log",s={unversionedId:"node/mainnet/upgrade-log",id:"node/mainnet/upgrade-log",title:"Upgrade Log",description:"For each upgrade of the Oasis Network, we are tracking important changes for",source:"@site/docs/node/mainnet/upgrade-log.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/upgrade-log",permalink:"/node/mainnet/upgrade-log",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/upgrade-log.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Upgrade to Mainnet",permalink:"/node/mainnet/previous-upgrades/mainnet-upgrade"},next:{title:"Testnet",permalink:"/node/testnet/"}},l={},p=[{value:"2022-04-11 (8:30 UTC) - Damask Upgrade",id:"damask-upgrade",level:2},{value:"Instructions - Voting",id:"instructions---voting",level:3},{value:"Instructions - Before upgrade",id:"instructions---before-upgrade",level:3},{value:"Instructions - Upgrade day",id:"instructions---upgrade-day",level:3},{value:"Configuration Changes",id:"damask-conf-changes",level:3},{value:"Additional notes",id:"additional-notes",level:3},{value:"2021-08-31 (16:00 UTC) - Parameter Update",id:"2021-08-31-upgrade",level:2},{value:"Proposed Parameter Changes",id:"proposed-parameter-changes",level:3},{value:"Instructions - Voting",id:"instructions---voting-1",level:3},{value:"Instructions - Before Upgrade System Preparation",id:"instructions---before-upgrade-system-preparation",level:3},{value:"BadgerDB v2 to v3 Migration",id:"badgerdb-v2-to-v3-migration",level:3},{value:"Extra storage requirements",id:"extra-storage-requirements",level:4},{value:"Extra memory requirements",id:"extra-memory-requirements",level:4},{value:"Installing Oasis App 2.3.1 to Your Ledger",id:"installing-oasis-app-231-to-your-ledger",level:3},{value:"Update Firmware to Version 2.0.0",id:"update-firmware-to-version-200",level:4},{value:"Install Prerequisites for Manual Installation",id:"install-prerequisites-for-manual-installation",level:4},{value:"Download Oasis App 2.3.1",id:"download-oasis-app-231",level:4},{value:"Install Oasis App 2.3.1",id:"install-oasis-app-231",level:4},{value:"Verify Installation",id:"verify-installation",level:4},{value:"2021-04-28 (16:00 UTC) - Cobalt Upgrade",id:"cobalt-upgrade",level:2},{value:"Instructions - Before upgrade",id:"instructions---before-upgrade-1",level:3},{value:"Runtime operators",id:"runtime-operators",level:4},{value:"Instructions - Upgrade day",id:"instructions---upgrade-day-1",level:3},{value:"Additional notes",id:"additional-notes-1",level:3},{value:"2020-11-18 (16:00 UTC) - Mainnet",id:"mainnet-upgrade",level:2},{value:"Instructions",id:"instructions",level:3},{value:"Configuration changes",id:"configuration-changes",level:3},{value:"2020-10-01 - Mainnet Beta",id:"mainnet-beta-upgrade",level:2},{value:"Instructions",id:"instructions-1",level:3},{value:"2020-09-22 - Mainnet Dry Run",id:"mainnet-dry-run",level:2},{value:"Instructions",id:"instructions-2",level:3}],d={toc:p},m="wrapper";function u(e){let{components:t,...a}=e;return(0,o.kt)(m,(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"upgrade-log"},"Upgrade Log"),(0,o.kt)("p",null,"For each upgrade of the Oasis Network, we are tracking important changes for\nnode operators' deployments."),(0,o.kt)("p",null,"They are enumerated and explained in this document."),(0,o.kt)("h2",{id:"damask-upgrade"},"2022-04-11 (8:30 UTC) - Damask Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"13402"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Mainnet network to reach this epoch at around 2022-04-11 8:30\nUTC.")),(0,o.kt)("h3",{id:"instructions---voting"},"Instructions - Voting"),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Voting for the upgrade proposal will end at epoch 13152. We expect the Mainnet\nnetwork to reach this epoch at around 2022-03-31 21:00 UTC"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"At this time only entities which have active validator nodes scheduled in the\nvalidator set are eligible to vote for governance proposals.")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"At least ",(0,o.kt)("strong",{parentName:"p"},"75%")," of the total ",(0,o.kt)("strong",{parentName:"p"},"voting power")," of the validator set needs to\ncast a vote on the upgrade proposal for the result to be valid."),(0,o.kt)("p",{parentName:"admonition"},"At least ",(0,o.kt)("strong",{parentName:"p"},"90%")," of the vote needs to be ",(0,o.kt)("strong",{parentName:"p"},"yes")," votes for a proposal to be\naccepted.")),(0,o.kt)("p",null,"The Oasis Protocol Foundation has submitted an ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/governance#submit-proposal"},"upgrade governance proposal"),"\nwith the following contents:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'{\n "v": 1,\n "handler": "mainnet-upgrade-2022-04-11",\n "target": {\n "consensus_protocol": {\n "major": 5\n },\n "runtime_host_protocol": {\n "major": 5\n },\n "runtime_committee_protocol": {\n "major": 4\n }\n },\n "epoch": 13402\n}\n')),(0,o.kt)("p",null,"To view the proposal yourself, you can run the following command on your online\nOasis Node:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node governance list_proposals -a $ADDR\n")),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"$ADDR")," represents the path to the internal Oasis Node UNIX socket\nprefixed with ",(0,o.kt)("inlineCode",{parentName:"p"},"unix:")," (e.g.",(0,o.kt)("inlineCode",{parentName:"p"},"unix:/serverdir/node/internal.sock"),")."),(0,o.kt)("p",null,"The output should look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'[\n {\n "id": 2,\n "submitter": "oasis1qpydpeyjrneq20kh2jz2809lew6d9p64yymutlee",\n "state": "active",\n "deposit": "10000000000000",\n "content": {\n "upgrade": {\n "v": 1,\n "handler": "mainnet-upgrade-2022-04-11",\n "target": {\n "consensus_protocol": {\n "major": 5\n },\n "runtime_host_protocol": {\n "major": 5\n },\n "runtime_committee_protocol": {\n "major": 4\n }\n },\n "epoch": 13402\n }\n },\n "created_at": 12984,\n "closes_at": 13152\n }\n]\n')),(0,o.kt)("p",null,"Obtain ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"your entity's nonce")," and store it in the ",(0,o.kt)("inlineCode",{parentName:"p"},"NONCE")," variable. You can do\nthat by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"ENTITY_DIR=\nADDRESS=$(oasis-node stake pubkey2address --public_key \\\n $(cat $ENTITY_DIR/entity.json | jq .id -r))\nNONCE=$(oasis-node stake account nonce --stake.account.address $ADDRESS -a $ADDR)\n")),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is the path to your entity's descriptor, e.g.\n",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node/entity/"),"."),(0,o.kt)("p",null,"To vote for the proposal, use the following command to generate a suitable\ntransaction:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'oasis-node governance gen_cast_vote \\\n "${TX_FLAGS[@]}" \\\n --vote.proposal.id 2 \\\n --vote yes \\\n --transaction.file tx_cast_vote.json \\\n --transaction.nonce $NONCE \\\n --transaction.fee.gas 2000 \\\n --transaction.fee.amount 2000\n')),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"TX_FLAGS")," refer to previously set base and signer flags as described in\nthe ",(0,o.kt)("a",{parentName:"p",href:"/core/oasis-node/cli#storing-base-and-signer-flags-in-an-environment-variable"},"Oasis CLI Tools Setup")," doc."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"If you use a Ledger-signer backed entity, you will need to install version 2.3.2\nof the Oasis App as described in ",(0,o.kt)("a",{parentName:"p",href:"../../oasis-core-ledger/usage/setup#installing-oasis-app-on-your-ledger-wallet"},"Installing Oasis App on Your Ledger Wallet"),"."),(0,o.kt)("p",{parentName:"admonition"},"Note that the previous version of the Oasis App available through Ledger Live,\nversion 1.8.2, doesn't support signing the ",(0,o.kt)("inlineCode",{parentName:"p"},"governance.CastVote")," transaction\ntype.")),(0,o.kt)("p",null,"To submit the generated transaction, copy ",(0,o.kt)("inlineCode",{parentName:"p"},"tx_cast_vote.json")," to the online\nOasis node and submit it from there:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node consensus submit_tx \\\n -a $ADDR \\\n --transaction.file tx_cast_vote.json\n")),(0,o.kt)("h3",{id:"instructions---before-upgrade"},"Instructions - Before upgrade"),(0,o.kt)("p",null,"This upgrade will upgrade ",(0,o.kt)("strong",{parentName:"p"},"Oasis Core")," to the ",(0,o.kt)("strong",{parentName:"p"},"22.1.x release series")," which\n",(0,o.kt)("strong",{parentName:"p"},"no longer allow running Oasis Node")," (i.e. the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary)\n",(0,o.kt)("strong",{parentName:"p"},"as root")," (effective user ID of 0)."),(0,o.kt)("p",null,'Running network accessible services as the root user is extremely bad for\nsystem security as a general rule. While it would be "ok" if we could drop\nprivileges, ',(0,o.kt)("inlineCode",{parentName:"p"},"syscall.AllThreadsSyscall")," does not work if the binary uses ",(0,o.kt)("inlineCode",{parentName:"p"},"cgo"),"\nat all."),(0,o.kt)("p",null,"Nothing in Oasis Node will ever require elevated privileges.\nAttempting to run the ",(0,o.kt)("inlineCode",{parentName:"p"},"oasis-node")," process as the root user will now terminate\nimmediately on startup."),(0,o.kt)("p",null,"While there may be specific circumstances where it is safe to run network\nservices with the effective user ID set to 0, the overwhelming majority of cases\nwhere this is done is a misconfiguration."),(0,o.kt)("p",null,"Please, follow our ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/system-configuration#change-to-non-root"},"Changing Your Setup to Run Oasis Services with Non-root\nSystem User")," guide for steps-by-step instructions on how\nto update your system."),(0,o.kt)("p",null,"If the previous behavior is required, the binary must be run in unsafe/debug\nmode (via the intentionally undocumented flag), and ",(0,o.kt)("inlineCode",{parentName:"p"},"debug.allow_root")," must also\nbe set."),(0,o.kt)("h3",{id:"instructions---upgrade-day"},"Instructions - Upgrade day"),(0,o.kt)("p",null,"Following steps should be performed on ",(0,o.kt)("strong",{parentName:"p"},"2022-04-11")," only after the network has\nreached the upgrade epoch and has halted:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"Download the genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2022-04-11"},"Damask upgrade release"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Mainnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"13402")," will be exported and migrated to a 22.1.x\ncompatible genesis file."),(0,o.kt)("p",{parentName:"admonition"},"Upgrade genesis file will be published on the above link soon after reaching the\nupgrade epoch.")),(0,o.kt)("ol",{start:2},(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Verify the provided Damask upgrade genesis file by comparing it to network\nstate dump."),(0,o.kt)("p",{parentName:"li"},"The state changes are described in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/damask-upgrade#state-changes"},"Damask Upgrade")," document."),(0,o.kt)("p",{parentName:"li"},"See instructions in the ",(0,o.kt)("a",{parentName:"p",href:"../run-your-node/maintenance/handling-network-upgrades#verify-genesis"},"Handling Network Upgrades")," guide.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Replace the old genesis file with the new Damask upgrade genesis file.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Ensure your node will remain stopped by disabling auto-starting via your\nprocess manager (e.g., ",(0,o.kt)("a",{parentName:"p",href:"https://systemd.io/"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org/"},"Supervisor"),")")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1.3"},"22.1.3"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("a",{parentName:"p",href:"../run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."))),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"State of ParaTimes/runtimes is not affected by this upgrade and should NOT be\nwiped.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"We recommend ",(0,o.kt)("strong",{parentName:"p"},"backing up the pre-Damask consensus state")," so all the\ntransactions and history are not permanently lost."),(0,o.kt)("p",{parentName:"admonition"},"Also, if you ever need to access that state in the future, you will be able to\nspin up an Oasis Node in archive mode and query the pre-Damask state.")),(0,o.kt)("ol",{start:7},(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Perform any needed ",(0,o.kt)("a",{parentName:"p",href:"#damask-conf-changes"},"configuration changes")," described\nbelow.")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"(only for ParaTime operators) Replace old versions of your ParaTime binaries\nwith the new ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/issues/4469"},"Oasis Runtime Containers (",(0,o.kt)("inlineCode",{parentName:"a"},".orc"),")")," introduced in the\nDamask upgrade."),(0,o.kt)("p",{parentName:"li"},"For the official Oasis ParaTimes, use the following versions:"),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Emerald ParaTime: ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v8.2.0"},"8.2.0")),(0,o.kt)("li",{parentName:"ul"},"Cipher ParaTime: ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v1.1.0"},"1.1.0")))),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"(only Emerald Web3 Gateway operators) Replace old version of Emerald Web3\nGateway with version ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/emerald-web3-gateway/releases/tag/v2.1.0"},"2.1.0"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"(only Rosetta Gateway operators) Replace old version of Oasis Rosetta\nGateway with version ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.2.0"},"2.2.0"),".")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("p",{parentName:"li"},"Start your node and re-enable auto-starting via your process manager."))),(0,o.kt)("h3",{id:"damask-conf-changes"},"Configuration Changes"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"To see the full extent of the changes examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md"},"Change Log"),":\nof the ",(0,o.kt)("strong",{parentName:"p"},"Oasis Core 22.1.3"),", in particular the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#221-2022-04-01"},"22.1")," and\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#220-2022-03-01"},"22.0")," sections.")),(0,o.kt)("p",null,"If your node is currently configured to run a ParaTime, you need to perform some\nadditional steps."),(0,o.kt)("p",null,"The way ParaTime binaries are distributed has changed so that all required\nartifacts are contained in a single archive called the Oasis Runtime Container\nand have the ",(0,o.kt)("inlineCode",{parentName:"p"},".orc")," extension."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Links to updated ParaTime binaries will be published on the\n",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/#paratimes"},"Network Parameters")," page for their respective\nParaTimes.")),(0,o.kt)("p",null,"The configuration is simplified as the ",(0,o.kt)("inlineCode",{parentName:"p"},"runtime.paths")," now only needs to list\nall of the supported ",(0,o.kt)("inlineCode",{parentName:"p"},".orc")," files (see below for an example)."),(0,o.kt)("p",null,"Instead of separately configuring various roles for a node, there is now a\nsingle configuration flag called ",(0,o.kt)("inlineCode",{parentName:"p"},"runtime.mode")," which enables the correct roles\nas needed. It should be set to one of the following values:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"none")," (runtime support is disabled, only consensus layer is enabled)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"compute")," (node is participating as a runtime compute node for all the\nconfigured runtimes)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"keymanager")," (node is participating as a keymanager node)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"client")," (node is a stateful runtime client)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"client-stateless")," (node is a stateless runtime client and connects to\nremote nodes for any state queries)")),(0,o.kt)("p",null,"Nodes that have so far been participating as compute nodes should set the mode\nto ",(0,o.kt)("inlineCode",{parentName:"p"},"compute")," and nodes that have been participating as clients for querying\nand transaction submission should set it to ",(0,o.kt)("inlineCode",{parentName:"p"},"client"),"."),(0,o.kt)("p",null,"The following configuration flags have been removed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"runtime.supported")," (existing ",(0,o.kt)("inlineCode",{parentName:"li"},"runtime.paths")," is used instead)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.p2p.enabled")," (now automatically set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.compute.enabled")," (now set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.keymanager.enabled")," (now set based on runtime mode)"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"worker.storage.enabled")," (no longer needed)")),(0,o.kt)("p",null,"Also the ",(0,o.kt)("inlineCode",{parentName:"p"},"worker.client")," option is no longer needed unless you are providing\nconsensus layer RPC services."),(0,o.kt)("p",null,"For example, if your ",(0,o.kt)("em",{parentName:"p"},"previous")," configuration looked like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'runtime:\n supported:\n - "000000000000000000000000000000000000000000000000000000000000beef"\n\n paths:\n "000000000000000000000000000000000000000000000000000000000000beef": /path/to/runtime\n\nworker:\n # ... other settings omitted ...\n\n storage:\n enabled: true\n\n compute:\n enabled: true\n\n client:\n port: 12345\n addresses:\n - "xx.yy.zz.vv:12345"\n\n p2p:\n enabled: true\n port: 12346\n addresses:\n - "xx.yy.zz.vv:12346"\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("em",{parentName:"p"},"new")," configuration should look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'runtime:\n mode: compute\n paths:\n - /path/to/runtime.orc\n\nworker:\n # ... other settings omitted ...\n\n p2p:\n port: 12346\n addresses:\n - "xx.yy.zz.vv:12346"\n')),(0,o.kt)("h3",{id:"additional-notes"},"Additional notes"),(0,o.kt)("p",null,"Examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md"},"Change Log")," of the 22.1.3 release, in particular\nthe ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#221-2022-04-01"},"22.1")," and ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#220-2022-03-01"},"22.0")," sections."),(0,o.kt)("h2",{id:"2021-08-31-upgrade"},"2021-08-31 (16:00 UTC) - Parameter Update"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"8049."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Mainnet network to reach this epoch at around 2021-08-31 16:00 UTC.")),(0,o.kt)("h3",{id:"proposed-parameter-changes"},"Proposed Parameter Changes"),(0,o.kt)("p",null,"The ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"Oasis Core 21.2.8")," release contains the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.2.8/go/upgrade/migrations/consensus_parameters.go"},(0,o.kt)("inlineCode",{parentName:"a"},"consensus-params-update-2021-08")," upgrade handler")," which will update the following parameters in the consensus layer:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.max_allowances")," ")," specifies the maximum number of allowances on account can store. It will be set to ",(0,o.kt)("inlineCode",{parentName:"li"},"16")," (default value is ",(0,o.kt)("inlineCode",{parentName:"li"},"0"),") to enable support for beneficiary allowances which are required to transfer tokens into a ParaTime."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"staking.params.gas_costs")," ")," , ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"governance.params.gas_costs"))," and ",(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"roothash.params.gas_costs"))," specify gas costs for various types of staking, governance and roothash transactions. Gas costs for transactions that were missing gas costs will be added."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators"))," is the maximum size of the consensus committee (i.e. the validator set). It will be increased to",(0,o.kt)("inlineCode",{parentName:"li"},"110")," (it was set to ",(0,o.kt)("inlineCode",{parentName:"li"},"100")," previously).")),(0,o.kt)("h3",{id:"instructions---voting-1"},"Instructions - Voting"),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Voting for the upgrade proposal will end at epoch 7876. We expect the Mainnet network to reach this epoch at around 2021-08-24 12:00 UTC"),(0,o.kt)("em",{parentName:"p"},(0,o.kt)("strong",{parentName:"em"},".")))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"At this time only entities which have active validator nodes scheduled in the validator set are eligible to vote for governance proposals.")),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"At least ",(0,o.kt)("strong",{parentName:"p"},"75%")," of the ",(0,o.kt)("strong",{parentName:"p"},"voting power")," needs to cast vote on the upgrade proposal for the result to be valid."),(0,o.kt)("p",{parentName:"admonition"},"At least ",(0,o.kt)("strong",{parentName:"p"},"90%")," of the votes need to be ",(0,o.kt)("strong",{parentName:"p"},"yes")," votes for a proposal to be accepted.")),(0,o.kt)("p",null,"This upgrade will be the first upgrade that will use the new on-chain governance service introduced in the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade"},"Cobalt Upgrade"),"."),(0,o.kt)("p",null,"The Oasis Protocol Foundation has submitted an ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/governance#submit-proposal"},"upgrade governance proposal")," with the following contents:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'{\n "v": 1,\n "handler": "consensus-params-update-2021-08",\n "target": {\n "consensus_protocol": {\n "major": 4\n },\n "runtime_host_protocol": {\n "major": 3\n },\n "runtime_committee_protocol": {\n "major": 2\n }\n },\n "epoch": 8049\n}\n')),(0,o.kt)("p",null,"To view the proposal yourself, you can run the following command on your online Oasis Node:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node governance list_proposals -a $ADDR | jq\n")),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"$ADDR")," represents the path to the internal Oasis Node UNIX socket prefixed with ",(0,o.kt)("inlineCode",{parentName:"p"},"unix:")," (e.g.",(0,o.kt)("inlineCode",{parentName:"p"},"unix:/serverdir/node/internal.sock"),")."),(0,o.kt)("p",null,"The output should look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},'[\n {\n "id": 1,\n "submitter": "oasis1qpydpeyjrneq20kh2jz2809lew6d9p64yymutlee",\n "state": "active",\n "deposit": "10000000000000",\n "content": {\n "upgrade": {\n "v": 1,\n "handler": "consensus-params-update-2021-08",\n "target": {\n "consensus_protocol": {\n "major": 4\n },\n "runtime_host_protocol": {\n "major": 3\n },\n "runtime_committee_protocol": {\n "major": 2\n }\n },\n "epoch": 8049\n }\n },\n "created_at": 7708,\n "closes_at": 7876\n }\n]\n')),(0,o.kt)("p",null,"Obtain ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"your entity's nonce")," and store it in the ",(0,o.kt)("inlineCode",{parentName:"p"},"NONCE")," variable. You can do that by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"ENTITY_DIR=\nADDRESS=$(oasis-node stake pubkey2address --public_key \\\n $(cat $ENTITY_DIR/entity.json | jq .id -r))\nNONCE=$(oasis-node stake account nonce --stake.account.address $ADDRESS -a $ADDR)\n")),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"")," is the path to your entity's descriptor, e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node/entity/"),"."),(0,o.kt)("p",null,"To vote for the proposal, use the following command to generate a suitable transaction:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'oasis-node governance gen_cast_vote \\\n "${TX_FLAGS[@]}" \\\n --vote.proposal.id 1 \\\n --vote yes \\\n --transaction.file tx_cast_vote.json \\\n --transaction.nonce $NONCE \\\n --transaction.fee.gas 2000 \\\n --transaction.fee.amount 2000\n')),(0,o.kt)("p",null,"where ",(0,o.kt)("inlineCode",{parentName:"p"},"TX_FLAGS")," refer to previously set base and signer flags as described in the ",(0,o.kt)("a",{parentName:"p",href:"/core/oasis-node/cli#storing-base-and-signer-flags-in-an-environment-variable"},"Oasis CLI Tools Setup")," doc."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"If you use a Ledger-signer backed entity, you will need to install version 2.3.1 of the Oasis App as described in ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/upgrade-log#installing-oasis-app-2-3-1-to-your-ledger"},"Installing Oasis App 2.3.1 to Your Ledger"),". This is needed because the current version of the Oasis App available through Ledger Live, version 1.8.2, doesn't support signing the ",(0,o.kt)("inlineCode",{parentName:"p"},"governance.CastVote")," transaction type.")),(0,o.kt)("p",null,"To submit the generated transaction, copy ",(0,o.kt)("inlineCode",{parentName:"p"},"tx_cast_vote.json")," to the online Oasis node and submit it from there:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node consensus submit_tx \\\n -a $ADDR \\\n --transaction.file tx_cast_vote.json\n")),(0,o.kt)("h3",{id:"instructions---before-upgrade-system-preparation"},"Instructions - Before Upgrade System Preparation"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"This upgrade will upgrade ",(0,o.kt)("strong",{parentName:"li"},"Oasis Core")," to version ",(0,o.kt)("strong",{parentName:"li"},"21.2.8")," which:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Upgrades the BadgerDB database backend from v2 to v3. See ",(0,o.kt)("a",{parentName:"li",href:"/node/mainnet/upgrade-log#badgerdb-v2-to-v3-migration"},(0,o.kt)("strong",{parentName:"a"},"BadgerDB v2 to v3 Migration"))," section for required steps to be done before upgrade."),(0,o.kt)("li",{parentName:"ul"},"Has a check that makes sure the ",(0,o.kt)("strong",{parentName:"li"},"file descriptor limit")," is set to an appropriately high value (at least 50000). While previous versions only warned in case the limit was set too low, this version will refuse to start. Follow the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/system-configuration#file-descriptor-limit"},"File Descriptor Limit")," documentation page for details on how to increase the limit on your system."))),(0,o.kt)("li",{parentName:"ul"},"Stop your node, replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"21.2.8")," and restart your node.")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Since Oasis Core 21.2.8 is otherwise compatible with the current consensus layer protocol, you may upgrade your Mainnet node to this version at any time.")),(0,o.kt)("admonition",{title:"This is not dump & restore upgrade",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"For this upgrade, ",(0,o.kt)("strong",{parentName:"p"},"do NOT wipe state"),".")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8"},"21.2.8"),".",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If you upgraded your node to Oasis Core 21.2.8 before the upgrade epoch was reached, you only need to restart your node for the upgrade to proceed."),(0,o.kt)("li",{parentName:"ul"},"Otherwise, you need to upgrade your node to Oasis Core 21.2.8 first and then restart it.")))),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you use a process manager like ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/systemd/systemd"},"systemd")," or ",(0,o.kt)("a",{parentName:"p",href:"http://supervisord.org"},"Supervisor"),", you can configure it to restart the Oasis Node automatically.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Mainnet's genesis file and the genesis document's hash will remain the same.")),(0,o.kt)("h3",{id:"badgerdb-v2-to-v3-migration"},"BadgerDB v2 to v3 Migration"),(0,o.kt)("p",null,"This upgrade will upgrade Oasis Core to version ",(0,o.kt)("strong",{parentName:"p"},"21.2.x")," which includes the new ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/dgraph-io/badger"},(0,o.kt)("strong",{parentName:"a"},"BadgerDB"))," ",(0,o.kt)("strong",{parentName:"p"},"v3"),"."),(0,o.kt)("p",null,"Since BadgerDB's on-disk format changed in v3, it requires on-disk state migration. The migration process is done automatically and makes the following steps:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Upon startup, Oasis Node will start migrating all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")," files (Badger v2 files) and start writing Badger v3 DB to files with the ",(0,o.kt)("inlineCode",{parentName:"p"},".migrate")," suffix.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the migration fails in the middle, Oasis Node will delete all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.migrate")," files the next time it starts and start the migration (of the remaining ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")),(0,o.kt)("p",{parentName:"li"},"files) again.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the migration succeeds, Oasis Node will append the ",(0,o.kt)("inlineCode",{parentName:"p"},".backup")," suffix to all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db")," files (Badger v2 files) and remove the ",(0,o.kt)("inlineCode",{parentName:"p"},".migrate")," suffix from all ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.migrate")," files (Badger v3 files)."))),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The BadgerDB v2 to v3 migration is ",(0,o.kt)("strong",{parentName:"p"},"very I/O intensive")," (both IOPS and throughput) and ",(0,o.kt)("strong",{parentName:"p"},"may take a couple of hours")," to complete."),(0,o.kt)("p",{parentName:"admonition"},"To follow its progress, run:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"shopt -s globstar\ndu -h /**/*.badger.db* | sort -h -r\n")),(0,o.kt)("p",{parentName:"admonition"},"and observe the sizes of various ",(0,o.kt)("inlineCode",{parentName:"p"},"*.badger.db*")," directories."),(0,o.kt)("p",{parentName:"admonition"},"For example, if it outputted the following:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre"},"55G data/tendermint/data/blockstore.badger.db\n37G data/tendermint/abci-state/mkvs_storage.badger.db.backup\n32G data/tendermint/abci-state/mkvs_storage.badger.db\n16G data/tendermint/data/blockstore.badger.db.migration\n2.9G data/tendermint/data/state.badger.db\n62M data/persistent-store.badger.db.backup\n2.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601/ca51b06a054b69f2c18b9781ea42f0b00900de199c1937398514331b0d136ec3/chunks\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601/ca51b06a054b69f2c18b9781ea42f0b00900de199c1937398514331b0d136ec3\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601/2ec3a28b1f4a2fcce503f2e80eb5d77b6c0a4d1075e8a14d880ac390338a855e/chunks\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601/2ec3a28b1f4a2fcce503f2e80eb5d77b6c0a4d1075e8a14d880ac390338a855e\n1.1M data/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601\n36K data/persistent-store.badger.db\n20K data/tendermint/data/evidence.badger.db\n")),(0,o.kt)("p",{parentName:"admonition"},"then the ",(0,o.kt)("inlineCode",{parentName:"p"},"mkvs_storage.badger.db")," was already migrated:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},"old BadgerDB v2 directory: ",(0,o.kt)("inlineCode",{parentName:"li"},"37G data/tendermint/abci-state/mkvs_storage.badger.db.backup")),(0,o.kt)("li",{parentName:"ul"},"new BadgerDB v3 directory: ",(0,o.kt)("inlineCode",{parentName:"li"},"32G data/tendermint/abci-state/mkvs_storage.badger.db"))),(0,o.kt)("p",{parentName:"admonition"},"and now the ",(0,o.kt)("inlineCode",{parentName:"p"},"blockstore.badger.db")," is being migrated:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"current BadgerDB v2 directory:"),(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"55G data/tendermint/data/blockstore.badger.db"))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"new BadgerDB v3 directory: ",(0,o.kt)("inlineCode",{parentName:"p"},"16G data/tendermint/data/blockstore.badger.db.migration")))),(0,o.kt)("p",{parentName:"admonition"},"Note that usually, the new BadgerDB v3 directory is smaller due to less fragmentation.")),(0,o.kt)("h4",{id:"extra-storage-requirements"},"Extra storage requirements"),(0,o.kt)("p",null,"Your node will thus need to have extra storage space to store both the old and the new BadgerDB files."),(0,o.kt)("p",null,"To see estimate how much extra space the migration will need, use the ",(0,o.kt)("inlineCode",{parentName:"p"},"du")," tool:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"shopt -s globstar\ndu -h /**/*.badger.db | sort -h -r\n")),(0,o.kt)("p",null,"This is an example output from a Mainnet node that uses ",(0,o.kt)("inlineCode",{parentName:"p"},"/srv/oasis/node")," as the ",(0,o.kt)("inlineCode",{parentName:"p"},""),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"43G /srv/oasis/node/tendermint/data/blockstore.badger.db\n28G /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db\n311M /srv/oasis/node/tendermint/data/state.badger.db\n2.0M /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints\n996K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601\n996K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601\n992K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601/ba6218d7be2df31ba6e7201a8585c6435154728e55bbb7df1ffebe683bf60217\n992K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601/1e0bf592bb0d99832b13ad91bc32aed018dfc2639e07b93a254a05f6791a19ac\n984K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601/ba6218d7be2df31ba6e7201a8585c6435154728e55bbb7df1ffebe683bf60217/chunks\n984K /srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601/1e0bf592bb0d99832b13ad91bc32aed018dfc2639e07b93a254a05f6791a19ac/chunks\n148K /srv/oasis/node/persistent-store.badger.db\n36K /srv/oasis/node/tendermint/data/evidence.badger.db\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"After you've confirmed your node is up and running, you can safely delete all the ",(0,o.kt)("inlineCode",{parentName:"p"},"/**/*.badger.db.backup")," files.")),(0,o.kt)("h4",{id:"extra-memory-requirements"},"Extra memory requirements"),(0,o.kt)("p",null,"BadgerDB v2 to v3 migration can use a number of Go routines to migrate different database files in parallel."),(0,o.kt)("p",null,"However, this comes with a memory cost. For larger database files, it might need up to 4 GB of RAM per database, so we recommend lowering the number of Go routines BadgerDB uses during migration (",(0,o.kt)("inlineCode",{parentName:"p"},"badger.migrate.num_go_routines"),") if your node has less than 8 GB of RAM."),(0,o.kt)("p",null,"If your node has less than 8 GB of RAM, set the number of Go routines BadgerDB uses during migration to 2 (default is 8) by adding the following to your node's ",(0,o.kt)("inlineCode",{parentName:"p"},"config.yml"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"# BadgerDB configuration.\nbadger:\n migrate:\n # Set the number of Go routines BadgerDB uses during migration to 2 to lower\n # the memory pressure during migration (at the expense of a longer migration\n # time).\n num_go_routines: 2\n")),(0,o.kt)("h3",{id:"installing-oasis-app-231-to-your-ledger"},"Installing Oasis App 2.3.1 to Your Ledger"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This manual installation procedure is needed until the latest version of the Oasis App, version 2.3.1, becomes available through ",(0,o.kt)("a",{parentName:"p",href:"https://www.ledger.com/ledger-live/"},"Ledger Live"),"'s Manager.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Unlike Nano S devices, ",(0,o.kt)("strong",{parentName:"p"},"Nano X")," devices are locked meaning one cannot manual install the latest version of the Oasis App on them. If you use a Nano X device, you will need to temporarily switch to a Nano S device or wait for the new version of the Oasis App to be available through Ledger Live's Manager.")),(0,o.kt)("h4",{id:"update-firmware-to-version-200"},"Update Firmware to Version 2.0.0"),(0,o.kt)("p",null,"First, make sure the firmware on your Nano S is up-to-date. At least ",(0,o.kt)("a",{parentName:"p",href:"https://support.ledger.com/hc/en-us/articles/360010446000-Ledger-Nano-S-firmware-release-notes"},"version 2.0.0")," released on May 4, 2021, is required. Follow ",(0,o.kt)("a",{parentName:"p",href:"https://support.ledger.com/hc/en-us/articles/360002731113-Update-Ledger-Nano-S-firmware"},"Ledger's instructions for updating the firmware on your Nano S"),"."),(0,o.kt)("h4",{id:"install-prerequisites-for-manual-installation"},"Install Prerequisites for Manual Installation"),(0,o.kt)("p",null,"The manual installation process relies on some tooling that needs to be available on the system:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://www.python.org"},"Python")," 3."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/LedgerHQ/blue-loader-python"},"Python tools for Ledger Blue, Nano S and Nano X"),".")),(0,o.kt)("p",null,"Most systems should already have ",(0,o.kt)("a",{parentName:"p",href:"https://www.python.org"},"Python")," pre-installed."),(0,o.kt)("p",null,"To install ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/blue-loader-python"},"Python tools for Ledger Blue, Nano S and Nano X"),", use ",(0,o.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/"},"pip"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"pip3 install --upgrade ledgerblue\n")),(0,o.kt)("p",null,"You might want to install the packages to a ",(0,o.kt)("a",{parentName:"p",href:"https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments"},"Python virtual environment")," or via so-called ",(0,o.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/user_guide/#user-installs"},"User install")," (i.e. isolated to the current user)."),(0,o.kt)("h4",{id:"download-oasis-app-231"},"Download Oasis App 2.3.1"),(0,o.kt)("p",null,"Download the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/Zondax/ledger-oasis/releases/download/v2.3.1/installer_s.sh"},"Oasis App 2.3.1 installer for Nano S")," from ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/Zondax/ledger-oasis"},"Zondax's Oasis App GitHub repo"),"."),(0,o.kt)("h4",{id:"install-oasis-app-231"},"Install Oasis App 2.3.1"),(0,o.kt)("p",null,"Make the downloaded installer executable by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"chmod +x installer_s.sh\n")),(0,o.kt)("p",null,"Connect you Nano S and unlock it. Then execute the installer:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"./installer_s.sh load\n")),(0,o.kt)("p",null,"Your Nano S will give you the option to either:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("em",{parentName:"li"},"Deny unsafe manager"),", or"),(0,o.kt)("li",{parentName:"ul"},"review the ",(0,o.kt)("em",{parentName:"li"},"Public Key")," and ",(0,o.kt)("em",{parentName:"li"},"Allow unsafe manager"),".")),(0,o.kt)("p",null,"First review the public key and ensure it matches the ",(0,o.kt)("inlineCode",{parentName:"p"},"Generated random root public key")," displayed in the terminal."),(0,o.kt)("p",null,"Then double press the ",(0,o.kt)("em",{parentName:"p"},"Allow unsafe manager")," option."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"If there is an existing version of the ",(0,o.kt)("em",{parentName:"p"},"Oasis App")," installed on your Nano S, you will be prompted with the ",(0,o.kt)("em",{parentName:"p"},"Uninstall Oasis")," screen, followed by reviewing the ",(0,o.kt)("em",{parentName:"p"},"Identifier")," (it will depend on the version of the Oasis App you have currently installed) and finally confirming deletion on the ",(0,o.kt)("em",{parentName:"p"},"Confirm action")," screen.")),(0,o.kt)("p",null,"After the new version of the Oasis App has finished loading, you will be prompted with the ",(0,o.kt)("em",{parentName:"p"},"Install app Oasis")," screen, followed by reviewing the ",(0,o.kt)("em",{parentName:"p"},"Version"),", ",(0,o.kt)("em",{parentName:"p"},"Identifier")," and ",(0,o.kt)("em",{parentName:"p"},"Code Identifier")," screens",(0,o.kt)("em",{parentName:"p"},".")," Ensure the values are as follows:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Version: 2.3.1"),(0,o.kt)("li",{parentName:"ul"},"Identifier (",(0,o.kt)("em",{parentName:"li"},"Application full hash")," on the terminal): ",(0,o.kt)("inlineCode",{parentName:"li"},"E0CB424D3B1C2A0F694BCB6E99C3B37C7685399D59DD12D7CF80AF4A487882B1")),(0,o.kt)("li",{parentName:"ul"},"Code Identifier: ",(0,o.kt)("inlineCode",{parentName:"li"},"C17EBE7CD356D01411A02A81C64CDA3E81F193BDA09BEBBD0AEAF75AD7EC35E3"))),(0,o.kt)("p",null,"Finally, confirm installation of the new app by double pressing on the ",(0,o.kt)("em",{parentName:"p"},"Perform installation")," screen. Your Ledger device will ask for your PIN again."),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"Installing Oasis App 2.3.1 on a Nano S with the firmware version < 2.0.0 (e.g. 1.6.1) will NOT fail. It will show a different ",(0,o.kt)("em",{parentName:"p"},"Identifier")," when installing the app which will NOT match the ",(0,o.kt)("em",{parentName:"p"},"Application full hash"),' shown on the terminal. However, opening the app will not work and it will "freeze" your Nano S device.')),(0,o.kt)("h4",{id:"verify-installation"},"Verify Installation"),(0,o.kt)("p",null,"Open the Oasis App on your Nano S and ensure the ",(0,o.kt)("em",{parentName:"p"},"Version")," screen shows version 2.3.1."),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Starting the manually installed version of the Oasis App will always show the ",(0,o.kt)("em",{parentName:"p"},"This app is not genuine")," screen, followed by ",(0,o.kt)("em",{parentName:"p"},"Identifier")," (which should match the Identifier value above) screen. Finally, open the application by double pressing on the ",(0,o.kt)("em",{parentName:"p"},"Open application")," screen.")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"After you've signed your ",(0,o.kt)("inlineCode",{parentName:"p"},"governance.CastVote")," transaction, you can safely downgrade Oasis App to the latest official version available via ",(0,o.kt)("a",{parentName:"p",href:"https://www.ledger.com/ledger-live/"},"Ledger Live"),", version 1.8.2."),(0,o.kt)("p",{parentName:"admonition"},"To do that, just open Ledger Live's Manager and it will prompt you to install version 1.8.2.")),(0,o.kt)("h2",{id:"cobalt-upgrade"},"2021-04-28 (16:00 UTC) - Cobalt Upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade height:")," upgrade is scheduled to happen at epoch ",(0,o.kt)("strong",{parentName:"li"},"5046."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Mainnet network to reach this epoch at around 2021-04-28 12:00 UTC.")),(0,o.kt)("h3",{id:"instructions---before-upgrade-1"},"Instructions - Before upgrade"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Make sure you are running the latest Mainnet-compatible Oasis Node version: ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.7"},"20.12.7"),".",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"If you are running a different ",(0,o.kt)("strong",{parentName:"li"},"20.12.x")," Oasis Node version, update to version ",(0,o.kt)("strong",{parentName:"li"},"20.12.7")," before the upgrade.")))),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Version ",(0,o.kt)("strong",{parentName:"p"},"20.12.7")," is backwards compatible with other ",(0,o.kt)("strong",{parentName:"p"},"20.12.x")," releases, so upgrade can be performed at any time by stopping the node and replacing the binary.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"To ensure your node will stop at epoch ",(0,o.kt)("strong",{parentName:"p"},"5046")," ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades#stop-the-node-at-specific-epoch"},"submit the following upgrade descriptor")," at any time before the upgrade:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},'{\n "name": "mainnet-upgrade-2021-04-28",\n "method": "internal",\n "identifier": "mainnet-upgrade-2021-04-28",\n "epoch": 5046\n}\n')))),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The upgrade descriptor contains a non-existing upgrade handler and will be used to coordinate the network shutdown, the rest of the upgrade is manual.")),(0,o.kt)("h4",{id:"runtime-operators"},(0,o.kt)("strong",{parentName:"h4"},"Runtime operators")),(0,o.kt)("p",null,"Following section is relevant only for ",(0,o.kt)("strong",{parentName:"p"},"runtime operators")," that are running ",(0,o.kt)("strong",{parentName:"p"},"storage")," nodes for active runtimes on the Mainnet."),(0,o.kt)("p",null,"This upgrade requires a runtime storage node migration to be performed ",(0,o.kt)("strong",{parentName:"p"},"before the upgrade genesis is published"),". This can be done before the upgrade epoch is reached by stopping all runtime nodes and running the migration."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Backup your node's data directory")),(0,o.kt)("p",null,"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."),(0,o.kt)("p",null,"For example, to backup the ",(0,o.kt)("inlineCode",{parentName:"p"},"/serverdir/node")," directory using the ",(0,o.kt)("a",{parentName:"p",href:"https://rsync.samba.org"},"rsync")," tool, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n")),(0,o.kt)("p",null,"The storage database on all storage nodes needs to be migrated with the following command (using the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1.1"},"21.1.1")," binary):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n")),(0,o.kt)("p",null,"After the migration to v5 completes, you will see an output similar to:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"...\n- migrating from v4 to v5...\n- migrating version 24468...\n- migrated root state-root:195cf7a9a103e7300b2bb4e537cb9935cbebd83e448e67aa55433861a6ad7426 -> state-root:cea105a5d701deab935b94af9e8e0c5af5dcdb61c242bf434da9f11aa8d110ba\n- migrated root io-root:0850c5a33ee7f45aa92724b7d5f28c9ac9ae8799b88cc5be9773e8aba9526ca7 -> io-root:19713a2b44e1bf868ebee43c36872baa3058870bb890a5e25d1c4cea2622be77\n- migrated root io-root:477391131f60ac2c22bce9167c7e3783a13d4fb81fddd2d388b4ead6a586fe52 -> io-root:f29f86d491303c5fd7b3572e97cbd65b7487b6b4ac519623afd161cc2e4678b7\n")),(0,o.kt)("p",null,"Take note of the displayed ",(0,o.kt)("inlineCode",{parentName:"p"},"state-root")," and report it to the Foundation, as it needs to be included in the upgrade's new genesis file. Keep the runtime nodes stopped until the upgrade epoch is reached. At upgrade epoch, upgrade the nodes by following the remaining steps above."),(0,o.kt)("h3",{id:"instructions---upgrade-day-1"},"Instructions - Upgrade day"),(0,o.kt)("p",null,"Following steps should be performed on ",(0,o.kt)("strong",{parentName:"p"},"2021-04-28")," only after the network has reached the upgrade epoch and has halted:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Download the genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2021-04-28"},"Cobalt Upgrade release"),".")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Mainnet state at epoch ",(0,o.kt)("strong",{parentName:"p"},"5046")," will be exported and migrated to a 21.1.x compatible genesis file. Upgrade genesis file will be published on the above link soon after reaching the upgrade epoch.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Verify the provided Cobalt upgrade genesis file by comparing it to network state dump. See instructions in the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/handling-network-upgrades#download-and-verify-the-provided-genesis-file"},"Handling Network Upgrades")," guide."),(0,o.kt)("li",{parentName:"ul"},"Replace the old genesis file with the new Cobalt upgrade genesis file."),(0,o.kt)("li",{parentName:"ul"},"Stop your node (if you haven't stopped it already by submitting the upgrade descriptor)."),(0,o.kt)("li",{parentName:"ul"},"Replace the old version of Oasis Node with version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1.1"},"21.1.1"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For more detailed instructions, see the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"Handling Network Upgrades")," guide.")),(0,o.kt)("h3",{id:"additional-notes-1"},"Additional notes"),(0,o.kt)("p",null,"Examine the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.1.1/CHANGELOG.md"},"Change Log")," of the 21.1.1 (and 21.0) releases."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Runtime operators")),(0,o.kt)("p",null,"Note the following configuration change in the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v21.1.1/CHANGELOG.md#configuration-changes"},"21.0")," release."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"p"},"Storage access policy changes")),(0,o.kt)("p",{parentName:"admonition"},"Due to the changes in the default access policy on storage nodes, at least one of the storage nodes should be configured with the ",(0,o.kt)("inlineCode",{parentName:"p"},"worker.storage.public_rpc.enabled")," flag set to ",(0,o.kt)("inlineCode",{parentName:"p"},"true"),"."),(0,o.kt)("p",{parentName:"admonition"},"Otherwise, external runtime clients wont be able to connect to any storage nodes.")),(0,o.kt)("h2",{id:"mainnet-upgrade"},"2020-11-18 (16:00 UTC) - Mainnet"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Block height")," when Mainnet Beta network stops: ",(0,o.kt)("strong",{parentName:"li"},"702000."))),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"We expect the Mainnet Beta network to reach this block height at around 2020-11-18 13:30 UTC.")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Upgrade window:"),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Start: ",(0,o.kt)("strong",{parentName:"li"},"2020-11-18T16:00:00Z.")),(0,o.kt)("li",{parentName:"ul"},"End: After nodes representing ",(0,o.kt)("strong",{parentName:"li"},"2/3+ stake")," do the upgrade.")))),(0,o.kt)("h3",{id:"instructions"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Download ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node")," version ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.2"},"20.12.2"),", while continuing to run version 20.10.x."),(0,o.kt)("li",{parentName:"ul"},"(optional) Use Oasis Node version 20.12.2 to dump network state at the specified block height. It will connect to the running version 20.10.x node."),(0,o.kt)("li",{parentName:"ul"},"Download the Mainnet genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18"},"2020-11-18 release"),"."),(0,o.kt)("li",{parentName:"ul"},"(optional) Verify the provided Mainnet genesis file by comparing it to network state dump. See instructions in the ",(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/handling-network-upgrades#download-and-verify-the-provided-genesis-file"},"Handling Network Upgrades")," guide."),(0,o.kt)("li",{parentName:"ul"},"Replace the old Mainnet Beta genesis file with the Mainnet genesis file."),(0,o.kt)("li",{parentName:"ul"},"Stop your node."),(0,o.kt)("li",{parentName:"ul"},"Remove the old 20.10.x version of Oasis Node."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Update your node's configuration per instructions in ",(0,o.kt)("a",{parentName:"li",href:"/node/mainnet/upgrade-log#configuration-changes"},"Configuration changes")," below."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This time, we recommend dumping the network state with the upgraded Oasis Node binary so that the genesis file will be in the ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/genesis#canonical-form"},"canonical form"),"."),(0,o.kt)("p",{parentName:"admonition"},"The canonical form will make it easier to compare the obtained genesis file with the one provided by us.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For more detailed instructions, see the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"Handling Network Upgrades")," guide.")),(0,o.kt)("h3",{id:"configuration-changes"},"Configuration changes"),(0,o.kt)("p",null,"Since we are upgrading to the Mainnet, we recommend you change your node's configuration and disable pruning of the consensus' state by removing the ",(0,o.kt)("inlineCode",{parentName:"p"},"consensus.tendermint.abci.prune")," key."),(0,o.kt)("p",null,"For example, this configuration:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"...\n\n# Consensus backend.\nconsensus:\n # Setting this to true will mean that the node you're deploying will attempt\n # to register as a validator.\n validator: true\n\n # Tendermint backend configuration.\n tendermint:\n abci:\n prune:\n strategy: keep_n\n # Keep ~7 days of data since block production is ~1 block every 6 seconds.\n # (7*24*3600/6 = 100800)\n num_kept: 100800\n core:\n listen_address: tcp://0.0.0.0:26656\n\n ...\n")),(0,o.kt)("p",null,"Becomes:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"...\n\n# Consensus backend.\nconsensus:\n # Setting this to true will mean that the node you're deploying will attempt\n # to register as a validator.\n validator: true\n\n # Tendermint backend configuration.\n tendermint:\n core:\n listen_address: tcp://0.0.0.0:26656\n\n ...\n")),(0,o.kt)("h2",{id:"mainnet-beta-upgrade"},"2020-10-01 - Mainnet Beta"),(0,o.kt)("h3",{id:"instructions-1"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Stop your node."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wipe state"),"."),(0,o.kt)("li",{parentName:"ul"},"Replace the old genesis file with the Mainnet Beta genesis file published in the ",(0,o.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-10-01"},"2020-10-01 release"),"."),(0,o.kt)("li",{parentName:"ul"},"Start your node.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You should keep using Oasis Core version 20.10.")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"For more detailed instructions, see the ",(0,o.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades"},"Handling Network Upgrades")," guide.")),(0,o.kt)("h2",{id:"mainnet-dry-run"},"2020-09-22 - Mainnet Dry Run"),(0,o.kt)("h3",{id:"instructions-2"},"Instructions"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"This is the initial deployment.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a271df25.a8986361.js b/assets/js/a271df25.a8986361.js new file mode 100644 index 0000000000..af213f0af2 --- /dev/null +++ b/assets/js/a271df25.a8986361.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2916],{3905:(e,t,r)=>{r.d(t,{Zo:()=>d,kt:()=>g});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},d=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),u=p(r),m=a,g=u["".concat(l,".").concat(m)]||u[m]||c[m]||o;return r?n.createElement(g,i(i({ref:t},d),{},{components:r})):n.createElement(g,i({ref:t},d))}));function g(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:a,i[1]=s;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var n=r(7462),a=(r(7294),r(3905));const o={},i="Setup",s={unversionedId:"oasis-core-ledger/usage/setup",id:"oasis-core-ledger/usage/setup",title:"Setup",description:"Oasis Core Ledger is currently only supported on x86_64 Linux and macOS systems.",source:"@site/docs/oasis-core-ledger/usage/setup.md",sourceDirName:"oasis-core-ledger/usage",slug:"/oasis-core-ledger/usage/setup",permalink:"/oasis-core-ledger/usage/setup",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/usage/setup.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Oasis Core Ledger Documentation",permalink:"/oasis-core-ledger/"},next:{title:"Obtaining Account Address",permalink:"/oasis-core-ledger/usage/address"}},l={},p=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Oasis Core Ledger CLI",id:"oasis-core-ledger-cli",level:3},{value:"Ledger Signer Plugin",id:"ledger-signer-plugin",level:3},{value:"Downloading a Binary Release",id:"downloading-a-binary-release",level:2},{value:"Building From Source",id:"building-from-source",level:2},{value:"Adding oasis-core-ledger Binary to PATH",id:"adding-oasis-core-ledger-binary-to-path",level:2},{value:"Remembering Path to ledger-signer Plugin",id:"remembering-path-to-ledger-signer-plugin",level:2},{value:"Installing Oasis App on Your Ledger Wallet",id:"installing-oasis-app-on-your-ledger-wallet",level:2}],d={toc:p},u="wrapper";function c(e){let{components:t,...o}=e;return(0,a.kt)(u,(0,n.Z)({},d,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"setup"},"Setup"),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Oasis Core Ledger is currently only supported on x86_64 Linux and macOS systems.")),(0,a.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,a.kt)("h3",{id:"oasis-core-ledger-cli"},"Oasis Core Ledger CLI"),(0,a.kt)("p",null,"There are no special requirements for running the Oasis Core Ledger CLI."),(0,a.kt)("h3",{id:"ledger-signer-plugin"},"Ledger Signer Plugin"),(0,a.kt)("p",null,"You will need an appropriate version Oasis Node CLI installed your system."),(0,a.kt)("p",null,"For more details, see the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node")," documentation in the general\n",(0,a.kt)("a",{parentName:"p",href:"/general/"},"Oasis Docs"),"."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Currently, there are no binary releases of the Oasis Node CLI for macOS systems."),(0,a.kt)("p",{parentName:"admonition"},"To be able to use the Ledger signer plugin on a macOS system, you will need to\n",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node#building-from-source"},"build the Oasis Node CLI from source"),".")),(0,a.kt)("h2",{id:"downloading-a-binary-release"},"Downloading a Binary Release"),(0,a.kt)("p",null,"Go to ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/releases"},"Oasis Core Ledger's GitHub Releases page")," and download the latest\nversion."),(0,a.kt)("h2",{id:"building-from-source"},"Building From Source"),(0,a.kt)("p",null,(0,a.kt)("em",{parentName:"p"},"TODO: Link to Development docs once they exist.")),(0,a.kt)("h2",{id:"adding-oasis-core-ledger-binary-to-path"},"Adding ",(0,a.kt)("inlineCode",{parentName:"h2"},"oasis-core-ledger")," Binary to ",(0,a.kt)("inlineCode",{parentName:"h2"},"PATH")),(0,a.kt)("p",null,"To install the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-core-ledger")," binary for the current user, copy/symlink it\nto ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.local/bin"),"."),(0,a.kt)("p",null,"To install the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-core-ledger")," binary for all users of the system, copy it\nto ",(0,a.kt)("inlineCode",{parentName:"p"},"/usr/local/bin"),"."),(0,a.kt)("h2",{id:"remembering-path-to-ledger-signer-plugin"},"Remembering Path to ",(0,a.kt)("inlineCode",{parentName:"h2"},"ledger-signer")," Plugin"),(0,a.kt)("p",null,"For convenience, set the ",(0,a.kt)("inlineCode",{parentName:"p"},"LEDGER_SIGNER_PATH")," to the location of the\n",(0,a.kt)("inlineCode",{parentName:"p"},"ledger-signer")," binary, e.g.:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'LEDGER_SIGNER_PATH="$HOME/oasis_core_ledger_1.0.0_linux_amd64/ledger-signer"\n')),(0,a.kt)("h2",{id:"installing-oasis-app-on-your-ledger-wallet"},"Installing Oasis App on Your Ledger Wallet"),(0,a.kt)("p",null,"The recommended way to install the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/Zondax/ledger-oasis"},"Oasis app")," on your Ledger wallet is to\ninstall it via ",(0,a.kt)("a",{parentName:"p",href:"https://www.ledger.com/ledger-live/"},"Ledger Live"),"'s Manager."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"Currently, you will have enable ",(0,a.kt)("em",{parentName:"p"},"Developer mode")," by going to\n",(0,a.kt)("em",{parentName:"p"},"Settings -> Experimental features"),", to be able to find the Oasis app in\nLedger Live's Manager.")),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"To be able to install the current version (",(0,a.kt)("a",{parentName:"p",href:"https://github.com/LedgerHQ/app-oasis/releases/tag/v2.3.2"},"version 2.3.2"),") of the Oasis app,\nthe firmware on your Ledger wallet needs to be up-to-date:"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"At least ",(0,a.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360010446000-Ledger-Nano-S-firmware-release-notes"},"version 2.1.0")," released on Nov 30, 2021 on a\nNano S device."),(0,a.kt)("li",{parentName:"ul"},"At least ",(0,a.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360014980580-Ledger-Nano-X-firmware-release-notes"},"version 2.0.0")," released on Oct 21, 2021 on a\nNano X device.")),(0,a.kt)("p",{parentName:"admonition"},"Follow Ledger's instructions for updating the firmware on your Ledger wallet:"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360002731113-Update-Ledger-Nano-S-firmware"},"Nano S")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360013349800"},"Nano X")))),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"To find the Oasis app in the Ledger Live app store, go to the App catalog\nsearch bar and type in ",(0,a.kt)("em",{parentName:"p"},"Oasis"),"."),(0,a.kt)("p",{parentName:"admonition"},"You may see both the ",(0,a.kt)("em",{parentName:"p"},"Oasis")," app and the ",(0,a.kt)("em",{parentName:"p"},"OasisVal")," app come up in the search\nresults. You need to use the standard ",(0,a.kt)("em",{parentName:"p"},"Oasis")," app."),(0,a.kt)("p",{parentName:"admonition"},(0,a.kt)("img",{alt:"Oasis app in Ledger Live",src:r(4627).Z,width:"2090",height:"1448"}))),(0,a.kt)("p",null,"Once installed, the Oasis app will use the generated mnemonic stored on the\nLedger wallet to generate the private & public key pairs for your accounts."))}c.isMDXComponent=!0},4627:(e,t,r)=>{r.d(t,{Z:()=>n});const n=r.p+"assets/images/ledger-live-manager-oasis-c2e03e9ceb8fe81107faa3b8a175f837.png"}}]); \ No newline at end of file diff --git a/assets/js/a71e7da1.75f2c8bf.js b/assets/js/a71e7da1.75f2c8bf.js new file mode 100644 index 0000000000..171ee149fb --- /dev/null +++ b/assets/js/a71e7da1.75f2c8bf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8323],{3905:(e,t,n)=>{n.d(t,{Zo:()=>l,kt:()=>m});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var d=o.createContext({}),u=function(e){var t=o.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},l=function(e){var t=u(e.components);return o.createElement(d.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,d=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),c=u(n),h=r,m=c["".concat(d,".").concat(h)]||c[h]||p[h]||a;return n?o.createElement(m,i(i({ref:t},l),{},{components:n})):o.createElement(m,i({ref:t},l))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=h;var s={};for(var d in t)hasOwnProperty.call(t,d)&&(s[d]=t[d]);s.originalType=e,s[c]="string"==typeof e?e:r,i[1]=s;for(var u=2;u{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var o=n(7462),r=(n(7294),n(3905));const a={},i="Shutting Down a Node",s={unversionedId:"node/run-your-node/maintenance/shutting-down-a-node",id:"node/run-your-node/maintenance/shutting-down-a-node",title:"Shutting Down a Node",description:"When a node registers for an epoch, it is committing to being available",source:"@site/docs/node/run-your-node/maintenance/shutting-down-a-node.md",sourceDirName:"node/run-your-node/maintenance",slug:"/node/run-your-node/maintenance/shutting-down-a-node",permalink:"/node/run-your-node/maintenance/shutting-down-a-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/shutting-down-a-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Refreshing Node Certificates",permalink:"/node/run-your-node/maintenance/refreshing-certificates"},next:{title:"Advanced",permalink:"/node/run-your-node/advanced"}},d={},u=[{value:"Restarting a Shutdown Node",id:"restarting-a-shutdown-node",level:2}],l={toc:u},c="wrapper";function p(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,o.Z)({},l,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"shutting-down-a-node"},"Shutting Down a Node"),(0,r.kt)("p",null,"When a node registers for an epoch, it is committing to being available\nto service requests for the entire epoch. Due to this availability\ncommitment, validator and non-client paratime nodes must be shutdown\ngracefully to avoid network disruption."),(0,r.kt)("p",null,"The graceful shutdown process involves the following steps:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Halt the automatic re-registration."),(0,r.kt)("li",{parentName:"ol"},"Wait for the node's existing registration to expire."),(0,r.kt)("li",{parentName:"ol"},"Terminate the node binary.")),(0,r.kt)("p",null,"To have the node gracefully shutdown, run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# Issue a graceful shutdown request.\noasis-node control shutdown\n\n# Issue a graceful shutdown request, and block until the node terminates.\n# Note: This can take up to a full epoch to complete.\noasis-node control shutdown \\\n --wait\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Failure to gracefully shutdown the node may result in the node being\nfrozen (and potentially stake being slashed) due to the node being\nunavailable to service requests in an epoch that it is registered.")),(0,r.kt)("h2",{id:"restarting-a-shutdown-node"},"Restarting a Shutdown Node"),(0,r.kt)("p",null,"To prevent restart loops causes by service managers, and to ensure\nthat the node will shutdown when requested, the node will persist\na flag indicating that a shutdown is in progress."),(0,r.kt)("p",null,"Oasis nodes prior to 22.0.3 will require that once a node is gracefully\nshutdown, the next time it is launched, the\n",(0,r.kt)("inlineCode",{parentName:"p"},"--worker.registration.force_register")," command line argument or equivalent\nconfig option be passed to the node the next time the node is started,\nor the node will shutdown immediately."),(0,r.kt)("p",null,"This behavior has been changed in newer revisions of the software such\nthat the flag should no longer be required."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a7d941e7.5d9f511b.js b/assets/js/a7d941e7.5d9f511b.js new file mode 100644 index 0000000000..4086a40b19 --- /dev/null +++ b/assets/js/a7d941e7.5d9f511b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6966],{3905:(e,a,n)=>{n.d(a,{Zo:()=>l,kt:()=>u});var t=n(7294);function r(e,a,n){return a in e?Object.defineProperty(e,a,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[a]=n,e}function i(e,a){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);a&&(t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.push.apply(n,t)}return n}function s(e){for(var a=1;a=0||(r[n]=e[n]);return r}(e,a);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=t.createContext({}),d=function(e){var a=t.useContext(c),n=a;return e&&(n="function"==typeof e?e(a):s(s({},a),e)),n},l=function(e){var a=d(e.components);return t.createElement(c.Provider,{value:a},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var a=e.children;return t.createElement(t.Fragment,{},a)}},f=t.forwardRef((function(e,a){var n=e.components,r=e.mdxType,i=e.originalType,c=e.parentName,l=o(e,["components","mdxType","originalType","parentName"]),p=d(n),f=r,u=p["".concat(c,".").concat(f)]||p[f]||m[f]||i;return n?t.createElement(u,s(s({ref:a},l),{},{components:n})):t.createElement(u,s({ref:a},l))}));function u(e,a){var n=arguments,r=a&&a.mdxType;if("string"==typeof e||r){var i=n.length,s=new Array(i);s[0]=f;var o={};for(var c in a)hasOwnProperty.call(a,c)&&(o[c]=a[c]);o.originalType=e,o[p]="string"==typeof e?e:r,s[1]=o;for(var d=2;d{n.r(a),n.d(a,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>i,metadata:()=>o,toc:()=>d});var t=n(7462),r=(n(7294),n(3905));const i={title:"ParaTime",description:"Managing ParaTimes"},s="Managing Your ParaTimes",o={unversionedId:"general/manage-tokens/cli/paratime",id:"general/manage-tokens/cli/paratime",title:"ParaTime",description:"Managing ParaTimes",source:"@site/docs/general/manage-tokens/cli/paratime.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/paratime",permalink:"/general/manage-tokens/cli/paratime",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/paratime.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"ParaTime",description:"Managing ParaTimes"},sidebar:"general",previous:{title:"Network",permalink:"/general/manage-tokens/cli/network"},next:{title:"Wallet",permalink:"/general/manage-tokens/cli/wallet"}},c={},d=[{value:"Add a ParaTime",id:"add",level:2},{value:"List ParaTimes",id:"list",level:2},{value:"Remove a ParaTime",id:"remove",level:2},{value:"Set Default ParaTime",id:"set-default",level:2},{value:"Show",id:"show",level:2},{value:"Advanced",id:"advanced",level:2},{value:"Register a New ParaTime",id:"register",level:3},{value:"Statistics",id:"statistics",level:3}],l={toc:d},p="wrapper";function m(e){let{components:a,...n}=e;return(0,r.kt)(p,(0,t.Z)({},l,n,{components:a,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"managing-your-paratimes"},"Managing Your ParaTimes"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime")," command lets you manage your ParaTime configurations bound to a\nspecific ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network"},"network"),". If you are a ParaTime developer, the command allows you to\nregister a new ParaTime into the public network's registry. The command\nalso supports examining specific block and a transaction inside the ParaTime\nand printing different validator-related statistics."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"When running the Oasis CLI for the first time, it will automatically configure\nofficial Oasis ParaTimes running on the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Mainnet")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet")," networks.")),(0,r.kt)("h2",{id:"add"},"Add a ParaTime"),(0,r.kt)("p",null,"Invoke ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime add ")," to add a new ParaTime to your Oasis\nCLI configuration. Beside the name of the corresponding network and the unique\nParaTime name inside that network, you will also need to provide the\n",(0,r.kt)("a",{parentName:"p",href:"/core/runtime/identifiers"},"ParaTime ID"),". This is a unique identifier of the ParaTime on the network, and\nit remains the same even when the network and ParaTime upgrades occur. You can\nalways check the IDs of the official Oasis ParaTimes on the respective\n",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Mainnet")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet")," pages."),(0,r.kt)("p",null,"Each ParaTime also has a native token denomination symbol defined with specific\nnumber of decimal places which you will need to specify."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime add testnet sapphire2 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6d\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"? Description: \n? Denomination symbol: TEST\n? Denomination decimal places: 18\n")),(0,r.kt)("admonition",{title:"Decimal places of the native and ParaTime token may differ!",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Emerald and Sapphire use ",(0,r.kt)("strong",{parentName:"p"},"18 decimals")," for compatibility with\nEthereum tooling. The Oasis Mainnet and Testnet consensus layer tokens and the\ntoken native to Cipher have ",(0,r.kt)("strong",{parentName:"p"},"9 decimals"),"."),(0,r.kt)("p",{parentName:"admonition"},"Configuring the wrong number of decimal places will lead to incorrect amount\nof tokens to be deposited, withdrawn or transferred from or into the ParaTime!")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you configured your network with the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#add-local"},(0,r.kt)("inlineCode",{parentName:"a"},"network add-local"))," command, then all\nregistered ParaTimes of that network will be detected and added to your Oasis\nCLI config automatically.")),(0,r.kt)("h2",{id:"list"},"List ParaTimes"),(0,r.kt)("p",null,"Invoke ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime list")," to list all configured ParaTimes across the networks."),(0,r.kt)("p",null,"For example, at time of writing this section the following ParaTimes were\npreconfigured by the Oasis CLI:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NETWORK PARATIME ID \nmainnet cipher 000000000000000000000000000000000000000000000000e199119c992377cb \nmainnet emerald 000000000000000000000000000000000000000000000000e2eaa99fc008f87f \nmainnet sapphire (*) 000000000000000000000000000000000000000000000000f80306c9858e7279 \ntestnet cipher 0000000000000000000000000000000000000000000000000000000000000000 \ntestnet emerald 00000000000000000000000000000000000000000000000072c8215e60d5bca7 \ntestnet sapphire (*) 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c \n")),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"#set-default"},"default ParaTime")," for each network is marked with the ",(0,r.kt)("inlineCode",{parentName:"p"},"(*)"),"\nsign."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"ParaTimes on this list are configured inside your Oasis CLI instance. They\nmay not actually exist on the network.")),(0,r.kt)("h2",{id:"remove"},"Remove a ParaTime"),(0,r.kt)("p",null,"To remove a configuration of a ParaTime for a specific network, use\n",(0,r.kt)("inlineCode",{parentName:"p"},"paratime remove "),". For example, let's remove the\n",(0,r.kt)("a",{parentName:"p",href:"#add"},"previously added")," ParaTime:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NETWORK PARATIME ID \nmainnet cipher 000000000000000000000000000000000000000000000000e199119c992377cb \nmainnet emerald (*) 000000000000000000000000000000000000000000000000e2eaa99fc008f87f \nmainnet sapphire 000000000000000000000000000000000000000000000000f80306c9858e7279 \ntestnet cipher 0000000000000000000000000000000000000000000000000000000000000000 \ntestnet emerald (*) 00000000000000000000000000000000000000000000000072c8215e60d5bca7 \ntestnet sapphire 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c \ntestnet sapphire2 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6d \n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime remove testnet sapphire2\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NETWORK PARATIME ID \nmainnet cipher 000000000000000000000000000000000000000000000000e199119c992377cb \nmainnet emerald (*) 000000000000000000000000000000000000000000000000e2eaa99fc008f87f \nmainnet sapphire 000000000000000000000000000000000000000000000000f80306c9858e7279 \ntestnet cipher 0000000000000000000000000000000000000000000000000000000000000000 \ntestnet emerald (*) 00000000000000000000000000000000000000000000000072c8215e60d5bca7 \ntestnet sapphire 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c \n")),(0,r.kt)("h2",{id:"set-default"},"Set Default ParaTime"),(0,r.kt)("p",null,"To change the default ParaTime for Oasis CLI transactions on the specific\nnetwork, use ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime set-default "),"."),(0,r.kt)("p",null,"For example, to set the Cipher ParaTime default on the Testnet, run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime set-default testnet cipher\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NETWORK PARATIME ID \nmainnet cipher 000000000000000000000000000000000000000000000000e199119c992377cb \nmainnet emerald 000000000000000000000000000000000000000000000000e2eaa99fc008f87f \nmainnet sapphire (*) 000000000000000000000000000000000000000000000000f80306c9858e7279 \ntestnet cipher (*) 0000000000000000000000000000000000000000000000000000000000000000 \ntestnet emerald 00000000000000000000000000000000000000000000000072c8215e60d5bca7 \ntestnet sapphire 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c \n")),(0,r.kt)("h2",{id:"show"},"Show"),(0,r.kt)("p",null,"Use ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime show ")," providing the block round to print its header and\nother information."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime show 5850612\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Network: mainnet\nParaTime: emerald\nRound: 5850612\nVersion: 0\nNamespace: 000000000000000000000000000000000000000000000000e2eaa99fc008f87f\nTimestamp: 2023-05-29T11:21:20Z\nType: 1\nPrevious: 3e91bd4fc60d8a2cc03dc50c87ff532bef5703fedc35bba8aed4d8980526bb51\nI/O root: d16db82426c93e2671b8fbe74db56d17fbc88800e93490dd0a6feae11d35a9a8\nState root: 2c1bc5c89c59bee77511e7a58e7494bb815ab73bb63333da1c15d171e48b79b8\nMessages (out): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nMessages (in): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nTransactions: 1\n")),(0,r.kt)("p",null,"To show the details of the transaction stored inside the block including the\ntransaction status and any emitted events, pass the transaction index in the\nblock or its hash:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime show 5850612 0\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'Network: mainnet\nParaTime: emerald\nRound: 5850612\nVersion: 0\nNamespace: 000000000000000000000000000000000000000000000000e2eaa99fc008f87f\nTimestamp: 2023-05-29T11:21:20Z\nType: 1\nPrevious: 3e91bd4fc60d8a2cc03dc50c87ff532bef5703fedc35bba8aed4d8980526bb51\nI/O root: d16db82426c93e2671b8fbe74db56d17fbc88800e93490dd0a6feae11d35a9a8\nState root: 2c1bc5c89c59bee77511e7a58e7494bb815ab73bb63333da1c15d171e48b79b8\nMessages (out): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nMessages (in): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nTransactions: 1\n\n=== Transaction 0 ===\nKind: evm.ethereum.v0\nHash: 4fc2907da5f73599519ed120916b7a9073a433b23b7ae65747e24fe75ebba832\nEth hash: 0x9cc12c960004b724356000d1d9af0ca3a092951d759590748a98431eb49c8d10\nChain ID: 42262\nNonce: 1976\nType: 0\nTo: 0x47DAcE3BDcc877f77fB92925ea55e25c792Bf265\nValue: 0\nGas limit: 900000\nGas price: 100000000000\nData:\n 2ee6f87400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000008d03941494a56164ea04d79f9867dddb0dd754a625cc21085e9307a7ec5206ca17db95be9eba7c71362e238396d4d01ba5621e66894a0228f6b3651f15660000008606060000000000066a7c4e95a979400021c718c22d52d0f3a789b752d4c2fd5908a8a733f02b3e437304892105992512539f769423a515cba1e73c01e0cf7930f5e91cb291031739fe5ad6c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n\n=== Result of transaction 0 ===\nStatus: ok\nData:\n "0000000000000000000000000000000000000000000000000000000000000000"\n\n=== Events emitted by transaction 0 ===\nEvents: 1\n\n --- Event 0 ---\n Module: core\n Code: 1\n Data:\n [\n {\n "amount": 48219\n }\n ]\n\n')),(0,r.kt)("p",null,"Encrypted transactions can also be examined, although the data chunk will be\nencrypted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime show 1078544 0 --network testnet --paratime sapphire\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'Network: testnet\nParaTime: sapphire\nRound: 1078544\nVersion: 0\nNamespace: 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\nTimestamp: 2023-05-03T15:06:19Z\nType: 1\nPrevious: 1e239120b149d02e04778affbfc126cebfe5c758c953b015ab8cef876bd5f702\nI/O root: 498269b1f1607ac35f8860437d2e9648994263f865905a4551174cf6e0fce52f\nState root: 9c2abe9051842cfa8d4b0981cfc9a08e55d13e516811ec20147e8a58c0b85c08\nMessages (out): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nMessages (in): c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a\nTransactions: 1\n\n=== Transaction 0 ===\nKind: evm.ethereum.v0\nHash: 41cc58c02147b7728c9dfcf528cfa71c6f4c04fc98fe33c5b2b9811e0379fa82\nEth hash: 0x970a642de01cffdcdd9e75d288d912b96c48bd29e14f2ad2b572770647ac97d4\nChain ID: 23295\nNonce: 1185\nType: 0\nTo: 0x8c064bCf7C0DA3B3b090BAbFE8f3323534D84d68\nValue: 0\nGas limit: 1000000\nGas price: 100000000000\nData:\n a264626f6479a362706b5820051201801dd7c98d4b5b195344146ce425cc01f12912e37cbd2fd92d5654354c646461746159015d6c56384c75f48ba3e3ca53607969ae6d9d44e2b6921e7fd34ee5aee8da5a1b519709bf4778a725048552e6b3520281285969cae0169adfd6d5792847bc37439d89c4b9dbbf2cf3c22e305c9a3a3d5b61026831c8f672b49e565cdc6eda81a55492262a0ede45742020efdca28f9d53ec928c1ac5171345d956bdda31971eafc90892f8fdaf75587358db0c2cd20f182b34b9d11e98958fb2320f0b62a4061bca65ca529dcd51ced9b8f1d8ca45d4c3be642000324b176077fec82bbc7770ca670f5fa73a397871e4940fef662654c70aebeac53424f42a5a6b90792db90807912f8a491a2d5ea141dddf03cb8061c8cbedef1d847779792d6ccc679a64adf7961e793c0a9314c74e151e938d111186d0c47a265f390e482edc37ce53a49f7e319bcaa395c882cf5778c7c8245828db199000ae494c66f9f6dd7159116417d2671dd99c4e00683e42e53700014b3e71f9b752579fdb499eddbf83a71333656e6f6e63654f914e6a1dcbf430c9de867ed8534ec266666f726d617401\n\n=== Result of transaction 0 ===\nStatus: ok\nData:\n "a1626f6ba264646174615561a6f942703204748459335a5d50058ebe8bf6cc5c656e6f6e63654f000000000010750f00000000000000"\n\n=== Events emitted by transaction 0 ===\nEvents: 1\n\n --- Event 0 ---\n Module: core\n Code: 1\n Data:\n [\n {\n "amount": 31451\n }\n ]\n\n')),(0,r.kt)("h2",{id:"advanced"},"Advanced"),(0,r.kt)("h3",{id:"register"},"Register a New ParaTime"),(0,r.kt)("p",null,"ParaTime developers may add a new ParaTime to the network's registry by\ninvoking the ",(0,r.kt)("inlineCode",{parentName:"p"},"paratime register ")," command and providing a JSON file\nwith the ParaTime descriptor. You can use the\n",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#show-id"},(0,r.kt)("inlineCode",{parentName:"a"},"network show"))," command passing the ParaTime ID to\nsee how descriptors of the currently registered ParaTimes look like."),(0,r.kt)("p",null,"To learn more about registering your own ParaTime, check the\n",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#register-runtime"},"Oasis Core Registry service"),"."),(0,r.kt)("h3",{id:"statistics"},"Statistics"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"paratime statistics [ []]")," will examine the voting\ndetails for a range of blocks. First, it will print you aggregated statistics\nshowing you the number of successful rounds in that range, epoch transitions\nand also anomalies such as the proposer timeouts, failed rounds and\ndiscrepancies. Then, it will print out detailed validator per-entity\nstatistics for that range of blocks."),(0,r.kt)("p",null,"The passed block number should be enumerated based on the round\ninside the ParaTime. The start round can be one of the following:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"If no round given, the validation of the last block will be examined."),(0,r.kt)("li",{parentName:"ul"},"If a negative round number ",(0,r.kt)("inlineCode",{parentName:"li"},"N")," is passed, the last ",(0,r.kt)("inlineCode",{parentName:"li"},"N")," blocks will be\nexamined."),(0,r.kt)("li",{parentName:"ul"},"If ",(0,r.kt)("inlineCode",{parentName:"li"},"0")," is given, the oldest block available to the Oasis endpoint will be\nconsidered as a starting block."),(0,r.kt)("li",{parentName:"ul"},"A positive number will be considered as a start round.")),(0,r.kt)("p",null,"At time of writing, the following statistics was available:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime statistics\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"=== PARATIME STATISTICS ===\nNetwork: mainnet\nParaTime ID: 000000000000000000000000000000000000000000000000e2eaa99fc008f87f\nStart height: 14097886\nEnd height: 14097887\nParaTime rounds: 1\nSuccessful rounds: 1\nEpoch transition rounds: 0\nProposer timed out rounds: 0\nFailed rounds: 0\nDiscrepancies: 0\nDiscrepancies (timeout): 0\nSuspended: 0\n\n=== ENTITY STATISTICS ===\n| ENTITY ADDR | ENTITY NAME | ELECTED | PRIMARY | BACKUP | PROPOSER | PRIMARY INVOKED | PRIMARY GOOD COMMIT | PRIM BAD COMMMIT | BCKP INVOKED | BCKP GOOD COMMIT | BCKP BAD COMMIT | PRIMARY MISSED | BCKP MISSED | PROPOSER MISSED | PROPOSED TIMEOUT |\n|------------------------------------------------|--------------------------------|---------|---------|--------|----------|-----------------|---------------------|------------------|--------------|------------------|-----------------|----------------|-------------|-----------------|------------------|\n| oasis1qpxpnxxk4qcgl7n55tx0yuqmrcw5cy2u5vzjq5u4 | Perfect Stake | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpavd66xsezz8s4wjw2fyycxw8jm2nlpnuejlg2g | Spherical One | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz72lvk2jchk0fjrz7u2swpazj3t5p0edsdv7sf8 | Ocean Stake | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz0ea28d8p4xk8xztems60wq22f9pm2yyyd82tmt | Simply Staking | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzl99wft8jtt7ppprk7ce7s079z3r3t77s6pf3dd | DCC Capital | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qps9drw07z0gmh5z2pn7zwl3z53ate2yvqf3uzq5 | cherkes | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpjuke27se2wnmvx6e8uc4l5h44yjp9h7g2clqfq | RockX | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz8vfnkcc48grazt83gstfm6yjwyptalny8cywtp | Kumaji | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzt4fvcc6cw9af69tek9p3mfjwn3a5e5vcyrw7ac | StakeService | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz0pvg26eudajp60835wl3jxhdxqz03q5qt9us34 | AnkaStake | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrs8zlh0mj37ug0jzlcykz808ylw93xwkvknm7yc | Bitoven | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qr0jwz65c29l044a204e3cllvumdg8cmsgt2k3ql | Staking Fund | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpntrlgxp5tt36pkdezdjt5d27fzkvp22y46qura | Chloris Network | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzf03q57jdgdwp2w7y6a8yww6mak9khuag9qt0kd | Spectrum Staking | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qq7vyz4ewrdh00yujw0mgkf459et306xmvh2h3zg | P2P.ORG - P2P Validator | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzugextrcdueshq63w7l9x4xglnusznsgqa95w7e | Alexander (aka Bambarello) | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| | Validator | | | | | | | | | | | | | | |\n| oasis1qrugz89g5esmhs0ezer0plsfvmcgctge35n32vmr | Validatrium | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrdx0n7lgheek24t24vejdks9uqmfldtmgdv7jzz | Bit Cat\ud83d\udc31 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp9xlxurlcx3k5h3pkays56mp48zfv9nmcf982kn | ELYSIUM | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp4f47plgld98n5g2ltalalnndnzz96euv9n89lz | Julia-Ju | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqf6wmc0ax3mykd028ltgtqr49h3qffcm50gwag3 | ou812 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qq0xmq7r0z9sdv02t5j9zs7en3n6574gtg8v9fyt | Mars Staking | Long term fee | 1 | 1 | 1 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| | 1% | | | | | | | | | | | | | | |\n| oasis1qqewwznmvwfvee0dyq9g48acy0wcw890g549pukz | Wanderer Staking | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqx820g2geqzeyeyfnm5hgz72eaj9emajgqmscy0 | max999 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp60saapdcrhe5zp3c3zk52r4dcfkr2uyuc5qjxp | Tessellated Geometry | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpaygvzwd5ffh2f5p4qdqylymgqcvl7sp5gxyrl3 | Appload | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrgxl0ylc7lvkj0akv6s32rj4k98nr0f7smf6m4k | itokenpool | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qram2p9w3yxm4px5nth8n7ugggk5rr6ay5d284at | Realizable | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz22xm9vyg0uqxncc667m4j4p5mrsj455c743lfn | S5 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qppctxzn8djkqfvrxugak9v7dp25vddq7sxqhkry | Tuzem | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqrv4g5wu543wa7fcae76eucqfn2uc77zgqw8fxk | Lusia | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrtq873ddwnnjqyv66ezdc9ql2a07l37d5vae9k0 | Forbole | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp53ud2pcmm73mlf4qywnrr245222mvlz5a2e5ty | SerGo | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrmexg6kh67xvnp7k42sx482nja5760stcrcdkhm | ushakov | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n")),(0,r.kt)("p",null,"To extend statistics to, say 5 last blocks, you can run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime statistics -- -5\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"=== PARATIME STATISTICS ===\nNetwork: mainnet\nParaTime ID: 000000000000000000000000000000000000000000000000e2eaa99fc008f87f\nStart height: 14097903\nEnd height: 14097908\nParaTime rounds: 4\nSuccessful rounds: 4\nEpoch transition rounds: 0\nProposer timed out rounds: 0\nFailed rounds: 0\nDiscrepancies: 0\nDiscrepancies (timeout): 0\nSuspended: 0\n\n=== ENTITY STATISTICS ===\n| ENTITY ADDR | ENTITY NAME | ELECTED | PRIMARY | BACKUP | PROPOSER | PRIMARY INVOKED | PRIMARY GOOD COMMIT | PRIM BAD COMMMIT | BCKP INVOKED | BCKP GOOD COMMIT | BCKP BAD COMMIT | PRIMARY MISSED | BCKP MISSED | PROPOSER MISSED | PROPOSED TIMEOUT |\n|------------------------------------------------|--------------------------------|---------|---------|--------|----------|-----------------|---------------------|------------------|--------------|------------------|-----------------|----------------|-------------|-----------------|------------------|\n| oasis1qrmexg6kh67xvnp7k42sx482nja5760stcrcdkhm | ushakov | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzt4fvcc6cw9af69tek9p3mfjwn3a5e5vcyrw7ac | StakeService | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qq7vyz4ewrdh00yujw0mgkf459et306xmvh2h3zg | P2P.ORG - P2P Validator | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqx820g2geqzeyeyfnm5hgz72eaj9emajgqmscy0 | max999 | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz22xm9vyg0uqxncc667m4j4p5mrsj455c743lfn | S5 | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqewwznmvwfvee0dyq9g48acy0wcw890g549pukz | Wanderer Staking | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp60saapdcrhe5zp3c3zk52r4dcfkr2uyuc5qjxp | Tessellated Geometry | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrs8zlh0mj37ug0jzlcykz808ylw93xwkvknm7yc | Bitoven | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzf03q57jdgdwp2w7y6a8yww6mak9khuag9qt0kd | Spectrum Staking | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpjuke27se2wnmvx6e8uc4l5h44yjp9h7g2clqfq | RockX | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpxpnxxk4qcgl7n55tx0yuqmrcw5cy2u5vzjq5u4 | Perfect Stake | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqrv4g5wu543wa7fcae76eucqfn2uc77zgqw8fxk | Lusia | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qqf6wmc0ax3mykd028ltgtqr49h3qffcm50gwag3 | ou812 | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qps9drw07z0gmh5z2pn7zwl3z53ate2yvqf3uzq5 | cherkes | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qr0jwz65c29l044a204e3cllvumdg8cmsgt2k3ql | Staking Fund | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qq0xmq7r0z9sdv02t5j9zs7en3n6574gtg8v9fyt | Mars Staking | Long term fee | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| | 1% | | | | | | | | | | | | | | |\n| oasis1qrdx0n7lgheek24t24vejdks9uqmfldtmgdv7jzz | Bit Cat\ud83d\udc31 | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpntrlgxp5tt36pkdezdjt5d27fzkvp22y46qura | Chloris Network | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrtq873ddwnnjqyv66ezdc9ql2a07l37d5vae9k0 | Forbole | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp9xlxurlcx3k5h3pkays56mp48zfv9nmcf982kn | ELYSIUM | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpavd66xsezz8s4wjw2fyycxw8jm2nlpnuejlg2g | Spherical One | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz8vfnkcc48grazt83gstfm6yjwyptalny8cywtp | Kumaji | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qppctxzn8djkqfvrxugak9v7dp25vddq7sxqhkry | Tuzem | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp4f47plgld98n5g2ltalalnndnzz96euv9n89lz | Julia-Ju | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzl99wft8jtt7ppprk7ce7s079z3r3t77s6pf3dd | DCC Capital | 4 | 4 | 0 | 1 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz0pvg26eudajp60835wl3jxhdxqz03q5qt9us34 | AnkaStake | 4 | 4 | 0 | 1 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrgxl0ylc7lvkj0akv6s32rj4k98nr0f7smf6m4k | itokenpool | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qrugz89g5esmhs0ezer0plsfvmcgctge35n32vmr | Validatrium | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qram2p9w3yxm4px5nth8n7ugggk5rr6ay5d284at | Realizable | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz72lvk2jchk0fjrz7u2swpazj3t5p0edsdv7sf8 | Ocean Stake | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qp53ud2pcmm73mlf4qywnrr245222mvlz5a2e5ty | SerGo | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qz0ea28d8p4xk8xztems60wq22f9pm2yyyd82tmt | Simply Staking | 4 | 4 | 0 | 1 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qpaygvzwd5ffh2f5p4qdqylymgqcvl7sp5gxyrl3 | Appload | 4 | 4 | 0 | 1 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| oasis1qzugextrcdueshq63w7l9x4xglnusznsgqa95w7e | Alexander (aka Bambarello) | 4 | 4 | 4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n| | Validator | | | | | | | | | | | | | | |\n")),(0,r.kt)("p",null,"For further analysis, you can easily export entity statistics to a CSV file by\npassing the ",(0,r.kt)("inlineCode",{parentName:"p"},"--output-file")," parameter and the file name:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis paratime statistics -o stats.csv\n")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The analysis of the range of blocks may require some time or even occasionally\nfail due to denial-of-service protection. If you encounter such issues,\nconsider setting up your own gRPC endpoint!")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a89bcaa3.d80d1c8c.js b/assets/js/a89bcaa3.d80d1c8c.js new file mode 100644 index 0000000000..2e327ea080 --- /dev/null +++ b/assets/js/a89bcaa3.d80d1c8c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2625],{3905:(e,a,n)=>{n.d(a,{Zo:()=>d,kt:()=>m});var t=n(7294);function s(e,a,n){return a in e?Object.defineProperty(e,a,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[a]=n,e}function o(e,a){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);a&&(t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),n.push.apply(n,t)}return n}function r(e){for(var a=1;a=0||(s[n]=e[n]);return s}(e,a);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var i=t.createContext({}),p=function(e){var a=t.useContext(i),n=a;return e&&(n="function"==typeof e?e(a):r(r({},a),e)),n},d=function(e){var a=p(e.components);return t.createElement(i.Provider,{value:a},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var a=e.children;return t.createElement(t.Fragment,{},a)}},h=t.forwardRef((function(e,a){var n=e.components,s=e.mdxType,o=e.originalType,i=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),c=p(n),h=s,m=c["".concat(i,".").concat(h)]||c[h]||u[h]||o;return n?t.createElement(m,r(r({ref:a},d),{},{components:n})):t.createElement(m,r({ref:a},d))}));function m(e,a){var n=arguments,s=a&&a.mdxType;if("string"==typeof e||s){var o=n.length,r=new Array(o);r[0]=h;var l={};for(var i in a)hasOwnProperty.call(a,i)&&(l[i]=a[i]);l.originalType=e,l[c]="string"==typeof e?e:s,r[1]=l;for(var p=2;p{n.r(a),n.d(a,{assets:()=>i,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var t=n(7462),s=(n(7294),n(3905));const o={},r="ADR 0016: Consensus Parameters Change Proposal",l={unversionedId:"adrs/0016-consensus-parameters-change-proposal",id:"adrs/0016-consensus-parameters-change-proposal",title:"ADR 0016: Consensus Parameters Change Proposal",description:"Component",source:"@site/docs/adrs/0016-consensus-parameters-change-proposal.md",sourceDirName:"adrs",slug:"/adrs/0016-consensus-parameters-change-proposal",permalink:"/adrs/0016-consensus-parameters-change-proposal",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0016-consensus-parameters-change-proposal.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0015: Randomized Paratime Proposer Selection",permalink:"/adrs/0015-vrf-per-block-entropy"},next:{title:"ADR 0017: ParaTime Application Standard Proposal Process",permalink:"/adrs/0017-app-standards"}},i={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Implementation",id:"implementation",level:2},{value:"New proposal",id:"new-proposal",level:3},{value:"Parameter changes",id:"parameter-changes",level:3},{value:"Submission",id:"submission",level:3},{value:"Execution",id:"execution",level:3},{value:"How to enable the new proposal",id:"how-to-enable-the-new-proposal",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],d={toc:p},c="wrapper";function u(e){let{components:a,...n}=e;return(0,s.kt)(c,(0,t.Z)({},d,n,{components:a,mdxType:"MDXLayout"}),(0,s.kt)("h1",{id:"adr-0016-consensus-parameters-change-proposal"},"ADR 0016: Consensus Parameters Change Proposal"),(0,s.kt)("h2",{id:"component"},"Component"),(0,s.kt)("p",null,"Oasis Core"),(0,s.kt)("h2",{id:"changelog"},"Changelog"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"2022-09-15: Initial version")),(0,s.kt)("h2",{id:"status"},"Status"),(0,s.kt)("p",null,"Proposed"),(0,s.kt)("h2",{id:"context"},"Context"),(0,s.kt)("p",null,"Currently consensus parameters can only be changed with an upgrade governance\nproposal which is effective but not very efficient. Upgrades require downtime\nduring which binaries need to be updated, nodes restarted and synced, consensus\nnetwork version has to be increased etc. We would like to avoid this cumbersome\nprocedure and change the parameters of a consensus module as fast and as simple\nas possible without affecting the performance of the consensus layer."),(0,s.kt)("h2",{id:"decision"},"Decision"),(0,s.kt)("p",null,"Implement governance proposal which changes consensus parameters only."),(0,s.kt)("h2",{id:"implementation"},"Implementation"),(0,s.kt)("h3",{id:"new-proposal"},"New proposal"),(0,s.kt)("p",null,"A new type of governance proposal named ",(0,s.kt)("inlineCode",{parentName:"p"},"ChangeParametersProposal")," should be\nadded to the consensus layer. The proposal should contain two non-empty fields:"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"the name of the consensus ",(0,s.kt)("inlineCode",{parentName:"p"},"Module")," the changes should be applied to, and,")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"a CBOR-encoded document ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes")," describing parameter changes."))),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},'// ChangeParametersProposal is a consensus parameters change proposal.\ntype ChangeParametersProposal struct {\n // Module identifies the consensus backend module to which changes should be\n // applied.\n Module string `json:"module"`\n // Changes are consensus parameter changes that should be applied to\n // the module.\n Changes cbor.RawMessage `json:"changes"`\n}\n')),(0,s.kt)("p",null,"Both fields should be validated before proposal submission to avoid having\ninvalid proposals with empty fields. A more in-depth validation should be done\nby consensus modules during submission to ensure that the encoded ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes")," are\ncomplete and well-formed and that there is exactly one module to which changes\nwill be applied."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"// ValidateBasic performs a basic validation on the change parameters proposal.\nfunc (p *ChangeParametersProposal) ValidateBasic() error {\n // Validate that both fields are set.\n}\n")),(0,s.kt)("p",null,"The new proposal should be added to the ",(0,s.kt)("inlineCode",{parentName:"p"},"ProposalContent"),". The extension should\nstill allow only one proposal at a time, so we must not forget to update\nthe code responsible for validation."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalContent struct {\n ...\n ChangeParameters *ChangeParametersProposal `json:"change_parameters,omitempty"`\n}\n')),(0,s.kt)("h3",{id:"parameter-changes"},"Parameter changes"),(0,s.kt)("p",null,"Each consensus module should carefully scope which parameters are allowed to\nbe changed. For example, a governance module could allow changing only the gas\ncosts and the voting period, while the staking module would allow changing\nall parameters."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},'// ConsensusParameterChanges define allowed governance consensus parameter\n// changes.\ntype ConsensusParameterChanges struct {\n // GasCosts are the new gas costs.\n GasCosts *transaction.Costs `json:"gas_costs,omitempty"`\n // VotingPeriod is the new voting period.\n VotingPeriod *beacon.EpochTime `json:"voting_period,omitempty"`\n}\n')),(0,s.kt)("p",null,"To prevent invalid proposals being submitted, ",(0,s.kt)("inlineCode",{parentName:"p"},"ConsensusParameterChanges"),"\nshould expose validation method which can be used to check if changes are\nvalid (e.g. changes are not empty, parameters have the right ranges)."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"// SanityCheck performs a sanity check on the consensus parameters changes.\nfunc (c *ConsensusParameterChanges) SanityCheck() error {\n // Validate changes.\n}\n")),(0,s.kt)("p",null,"How changes are executed is up to the module implementation."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"// Apply applies changes to the given consensus parameters.\nfunc (c *ConsensusParameterChanges) Apply(params *ConsensusParameters) error {\n // Apply changes.\n}\n")),(0,s.kt)("h3",{id:"submission"},"Submission"),(0,s.kt)("p",null,"When a new ",(0,s.kt)("inlineCode",{parentName:"p"},"ChangeParametersProposal")," is submitted a basic validation is\nperformed first which checks whether the ",(0,s.kt)("inlineCode",{parentName:"p"},"Module")," name and ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes")," are set\ncorrectly. Afterwards, a validation message is broadcasted to all modules\nrequesting them to validate the proposal. Only the module for which ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes"),"\nare intended should act and reply to the message, other modules should silently\nignore it. In case no module replies, the proposal is immediately rejected\nas not being supported."),(0,s.kt)("p",null,"The module should carefully examine the proposal, check whether the proposal\nis well-formed, ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes")," are not empty and deserialize correctly to the\nexpected format, deserialized parameter changes are valid etc. If all checks\nsucceed, the module should respond with a confirmation message. Otherwise,\nan error describing why proposal is invalid should be returned as a response."),(0,s.kt)("p",null,"Note: Validation at this stage cannot always be complete as valid parameter\nvalues are not necessary independent of each other. If multiple proposals are\nbeing executed at the same time, the resulting parameters can be invalid even\nthough validation of each proposal passed. Therefore, another validation\nis required when the proposal is about to be executed."),(0,s.kt)("h3",{id:"execution"},"Execution"),(0,s.kt)("p",null,"If ",(0,s.kt)("inlineCode",{parentName:"p"},"ChangeParametersProposal")," closes as accepted (vote passed), the governance\nmodule will execute the proposal by broadcasting a message containing\nthe proposal to all modules. Notification can be done using the same message\ndispatch mechanism as in the submission phase. Once messages are delivered,\nonly one module will act and try to apply ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes"),"."),(0,s.kt)("p",null,"That module should first fetch current consensus parameters, then apply\nproposed ",(0,s.kt)("inlineCode",{parentName:"p"},"Changes")," and finally validate the result. Validation of parameters\nis necessary as mentioned in the submission phase. If validation succeeds,\nthe consensus parameters are updated and proposal is marked as passed.\nOtherwise, the proposal is marked as failed and the proposed parameter\nchanges are discarded."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},"// SanityCheck performs a sanity check on the consensus parameters.\nfunc (p *ConsensusParameters) SanityCheck() error {\n // Validate parameters.\n}\n")),(0,s.kt)("h3",{id:"how-to-enable-the-new-proposal"},"How to enable the new proposal"),(0,s.kt)("p",null,"Adding a new proposal type is a consensus breaking change. To make it\nnon-breaking we introduce a new governance consensus parameter which disables\nthe new type by default and can be enabled via governance. When disabled,\nthe governance module will treat the new proposal type as invalid, thus not\nviolating the consensus."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},'type ConsensusParameters struct {\n ...\n // EnableChangeParametersProposal is true iff change parameters proposals are\n // allowed.\n EnableChangeParametersProposal bool `json:"enable_change_parameters_proposal,omitempty"`\n}\n')),(0,s.kt)("h2",{id:"consequences"},"Consequences"),(0,s.kt)("h3",{id:"positive"},"Positive"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Agile and zero-downtime consensus parameter changes.")),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("p",{parentName:"li"},"Separation of consensus parameter changes and consensus upgrades."))),(0,s.kt)("h3",{id:"negative"},"Negative"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"Introduction of a new governance consensus parameter which enables new\nproposals in the upgrade handler. New parameters can always be considered\nas a minor disadvantage as they usually increase the complexity of the code.")),(0,s.kt)("h3",{id:"neutral"},"Neutral"),(0,s.kt)("h2",{id:"references"},"References"),(0,s.kt)("p",null,"No references."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a9e87a2c.e9130a69.js b/assets/js/a9e87a2c.e9130a69.js new file mode 100644 index 0000000000..d09a61c496 --- /dev/null +++ b/assets/js/a9e87a2c.e9130a69.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7771],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>h});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var l=r.createContext({}),c=function(e){var t=r.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(a),m=n,h=p["".concat(l,".").concat(m)]||p[m]||u[m]||i;return a?r.createElement(h,o(o({ref:t},d),{},{components:a})):r.createElement(h,o({ref:t},d))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:n,o[1]=s;for(var c=2;c{a.d(t,{Z:()=>h});var r=a(7294),n=a(6010),i=a(9960),o=a(3438),s=a(3919),l=a(5999);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:a}=e;return r.createElement(i.Z,{href:t,className:(0,n.Z)("card padding--lg",c.cardContainer)},a)}function p(e){let{href:t,icon:a,title:i,description:o}=e;return r.createElement(d,{href:t},r.createElement("h2",{className:(0,n.Z)("text--truncate",c.cardTitle),title:i},a," ",i),o&&r.createElement("p",{className:(0,n.Z)("text--truncate",c.cardDescription),title:o},o))}function u(e){let{item:t}=e;const a=(0,o.Wl)(t);return a?r.createElement(p,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function m(e){let{item:t}=e;const a=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,o.xz)(t.docId??void 0);return r.createElement(p,{href:t.href,icon:a,title:t.label,description:t.description??n?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(m,{item:t});case"category":return r.createElement(u,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},7525:(e,t,a)=>{a.d(t,{n:()=>i});var r=a(4477);function n(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&n(t.items)}}function i(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)n(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},7632:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>p});var r=a(7462),n=(a(7294),a(3905)),i=a(1564),o=a(7525);const s={},l="Oasis Network",c={unversionedId:"general/oasis-network/README",id:"general/oasis-network/README",title:"Oasis Network",description:"The Oasis Network is a Layer 1 decentralized blockchain network designed to be uniquely scalable, privacy-first and versatile.",source:"@site/docs/general/oasis-network/README.mdx",sourceDirName:"general/oasis-network",slug:"/general/oasis-network/",permalink:"/general/oasis-network/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Use Oasis",permalink:"/general/"},next:{title:"Why Oasis?",permalink:"/general/oasis-network/why-oasis"}},d={},p=[{value:"Technology Highlights",id:"technology-highlights",level:2},{value:"Benefits of the Oasis Network Technology Stack",id:"benefits-of-the-oasis-network-technology-stack",level:2},{value:"Scalability",id:"scalability",level:3},{value:"Privacy-First",id:"privacy-first",level:3},{value:"Versatility",id:"versatility",level:3},{value:"Learn more",id:"learn-more",level:3}],u={toc:p},m="wrapper";function h(e){let{components:t,...s}=e;return(0,n.kt)(m,(0,r.Z)({},u,s,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"oasis-network"},"Oasis Network"),(0,n.kt)("p",null,"The Oasis Network is a Layer 1 decentralized blockchain network designed to be uniquely scalable, privacy-first and versatile."),(0,n.kt)("p",null,"The Network has two main architectural components, the consensus layer and the ParaTime layer."),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"consensus layer")," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."),(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"ParaTime layer")," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state.")),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Oasis architectural design including ParaTime and consensus layers",src:a(4128).Z,width:"1523",height:"718"})),(0,n.kt)("h2",{id:"technology-highlights"},"Technology Highlights"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("strong",{parentName:"p"},"Separates consensus and execution into two layers")," \u2014 the consensus layer and the ParaTime layer \u2014 for better scalability and increased versatility.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Separation of consensus and execution allows ",(0,n.kt)("strong",{parentName:"p"},"multiple ParaTimes to process transactions in parallel"),", meaning complex workloads processed on one ParaTime won\u2019t slow down faster, simpler transactions on another.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The ParaTime layer is entirely decentralized, allowing ",(0,n.kt)("strong",{parentName:"p"},"anyone to develop and build their own ParaTime"),". Each ParaTime can be developed in isolation to meet the needs of a specific application, such as confidential compute, open or closed committees, and more.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The network\u2019s sophisticated discrepancy detection makes Oasis ",(0,n.kt)("strong",{parentName:"p"},"more efficient than sharding and parachains")," \u2014 requiring a smaller replication factor for the same level of security.")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},(0,n.kt)("strong",{parentName:"p"},"The network has broad support for confidential computing technology"),". The Oasis Eth/WASI Runtime is an open source example of a confidential ParaTime that uses secure enclaves to keep data private while being processed."))),(0,n.kt)("h2",{id:"benefits-of-the-oasis-network-technology-stack"},"Benefits of the Oasis Network Technology Stack"),(0,n.kt)("h3",{id:"scalability"},"Scalability"),(0,n.kt)("p",null,"The Oasis Network\u2019s impressive scalability is achieved through a cutting-edge set of features that provide faster transaction speeds and higher throughput than other networks. The top-tier performance of the network is largely due to its separation of compute and consensus operations into the consensus layer and ParaTime layer. This separation allows multiple ParaTimes to process transactions in parallel, meaning complex workloads processed on one ParaTime won\u2019t slow down faster, simpler transactions on another. Plus, the network\u2019s sophisticated discrepancy detection makes Oasis more efficient than sharding and parachains \u2014 requiring a smaller replication factor for the same level of security."),(0,n.kt)("h3",{id:"privacy-first"},"Privacy-First"),(0,n.kt)("p",null,"The Oasis Network designed the first ever confidential ParaTime with support for confidential smart contracts. In a confidential ParaTime, nodes are required to use a type of secure computing technology called a TEE (trusted execution environment.) TEEs act as a hypothetical black box for smart contract execution in a confidential ParaTime. Encrypted data goes into the black box along with the smart contract, data is decrypted, processed by the smart contract, and then encrypted before it is sent out of the TEE. This process ensures that data remains confidential, and is never leaked to the node operator or application developer."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Client, Key Manager, Compute Node diagram",src:a(8332).Z,width:"765",height:"486"})),(0,n.kt)("p",null,"The Oasis Eth/WASI Runtime is an open source example of a confidential ParaTime that uses Intel SGX. Other secure compute technology, such as ZKP, HE, or other secure enclaves, can also be used. In the future we hope to support additional computation techniques such as secure multi-party compute, federated learning and more."),(0,n.kt)("p",null,"Confidentiality unlocks a range of new use cases on blockchain by allowing personal or sensitive data, such as their social security number, bank statements, health information to be used by apps on the Oasis Network \u2014 something incredibly risky on other Layer 1 networks."),(0,n.kt)("h3",{id:"versatility"},"Versatility"),(0,n.kt)("p",null,"Designed to support the next generation of blockchain applications, the Oasis Network is incredibly versatile, agile, and customizable. Namely, each ParaTime can be developed in isolation to meet the needs of a specific application. ParaTimes committees can be made large or small, open or closed, allowing for faster or more secure execution depending on the requirements of a particular use case. Nodes can be required to have specific hardware, such as Secure Enclaves in a confidential ParaTime. Each ParaTime can similarly run different Runtime VMs (ParaTime Engines) such as EVM backwards compatible engine, Rust based smart contract language, or a Data tokenization engine. Finally to support enterprise and developer use cases, ParaTimes can be made Permissioned or Permissionless \u2014 allowing consortiums to have their own closed ParaTime, or communities to have full decentralized open ParaTimes."),(0,n.kt)("p",null,"The versatility of the ParaTime layer allows the Oasis Network to expand and grow to address a broad set of new and exciting use cases, while still maintaining the same core ledger and consensus layer."),(0,n.kt)("h3",{id:"learn-more"},"Learn more"),(0,n.kt)(i.Z,{item:(0,o.n)("/general/oasis-network/why-oasis"),mdxType:"DocCard"}))}h.isMDXComponent=!0},8332:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/client-km-compute-8776815a499e44e00cfdd8953fdc9fb3.svg"},4128:(e,t,a)=>{a.d(t,{Z:()=>r});const r=a.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"}}]); \ No newline at end of file diff --git a/assets/js/ab39d68c.4cd6a85d.js b/assets/js/ab39d68c.4cd6a85d.js new file mode 100644 index 0000000000..32fee91daa --- /dev/null +++ b/assets/js/ab39d68c.4cd6a85d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8679],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),u=l(r),f=a,m=u["".concat(s,".").concat(f)]||u[f]||d[f]||o;return r?n.createElement(m,i(i({ref:t},p),{},{components:r})):n.createElement(m,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c[u]="string"==typeof e?e:a,i[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var n=r(7462),a=(r(7294),r(3905));const o={},i="Merklized Key-Value Store (MKVS)",c={unversionedId:"core/mkvs",id:"core/mkvs",title:"Merklized Key-Value Store (MKVS)",description:"For all places that require an [authenticated data structure (ADS)] we provide",source:"@site/docs/core/mkvs.md",sourceDirName:"core",slug:"/core/mkvs",permalink:"/core/mkvs",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/mkvs.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Authenticated gRPC",permalink:"/core/authenticated-grpc"},next:{title:"Processes",permalink:"/core/processes"}},s={},l=[{value:"Interfaces",id:"interfaces",level:2},{value:"Updates",id:"updates",level:3},{value:"Read Syncer",id:"read-syncer",level:3}],p={toc:l},u="wrapper";function d(e){let{components:t,...r}=e;return(0,a.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"merklized-key-value-store-mkvs"},"Merklized Key-Value Store (MKVS)"),(0,a.kt)("p",null,"For all places that require an ",(0,a.kt)("a",{parentName:"p",href:"https://www.cs.umd.edu/~mwh/papers/gpads.pdf"},"authenticated data structure (ADS)")," we provide\nan implementation of a Merklized Key-Value Store, internally implemented as a\nMerklized ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Radix_tree#PATRICIA"},"Patricia trie"),"."),(0,a.kt)("h2",{id:"interfaces"},"Interfaces"),(0,a.kt)("h3",{id:"updates"},"Updates"),(0,a.kt)("h3",{id:"read-syncer"},"Read Syncer"))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ab8e36ce.bd990d56.js b/assets/js/ab8e36ce.bd990d56.js new file mode 100644 index 0000000000..ab36ebe95c --- /dev/null +++ b/assets/js/ab8e36ce.bd990d56.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5585],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},m=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},p=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),d=c(n),p=a,g=d["".concat(l,".").concat(p)]||d[p]||u[p]||o;return n?r.createElement(g,i(i({ref:t},m),{},{components:n})):r.createElement(g,i({ref:t},m))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=p;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:a,i[1]=s;for(var c=2;c{n.d(t,{Z:()=>g});var r=n(7294),a=n(6010),o=n(9960),i=n(3438),s=n(3919),l=n(5999);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function m(e){let{href:t,children:n}=e;return r.createElement(o.Z,{href:t,className:(0,a.Z)("card padding--lg",c.cardContainer)},n)}function d(e){let{href:t,icon:n,title:o,description:i}=e;return r.createElement(m,{href:t},r.createElement("h2",{className:(0,a.Z)("text--truncate",c.cardTitle),title:o},n," ",o),i&&r.createElement("p",{className:(0,a.Z)("text--truncate",c.cardDescription),title:i},i))}function u(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?r.createElement(d,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function p(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,i.xz)(t.docId??void 0);return r.createElement(d,{href:t.href,icon:n,title:t.label,description:t.description??a?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(p,{item:t});case"category":return r.createElement(u,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,n)=>{n.d(t,{Z:()=>l});var r=n(7294),a=n(6010),o=n(3438),i=n(1564);function s(e){let{className:t}=e;const n=(0,o.jA)();return r.createElement(l,{items:n.items,className:t})}function l(e){const{items:t,className:n}=e;if(!t)return r.createElement(s,e);const l=(0,o.MN)(t);return r.createElement("section",{className:(0,a.Z)("row",n)},l.map(((e,t)=>r.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},r.createElement(i.Z,{item:e})))))}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var r=n(4477);function a(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&a(t.items)}}function o(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)a(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},2375:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>m,contentTitle:()=>l,default:()=>g,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var r=n(7462),a=(n(7294),n(3905)),o=n(9268),i=n(7525);const s={},l="Overview",c={unversionedId:"general/manage-tokens/README",id:"general/manage-tokens/README",title:"Overview",description:"This documentation will guide you on how to use your ROSE tokens, where to keep them, how to transfer them, how to stake/delegate them, and more.",source:"@site/docs/general/manage-tokens/README.mdx",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/",permalink:"/general/manage-tokens/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Frequently Asked Questions",permalink:"/general/oasis-network/faq"},next:{title:"Terminology",permalink:"/general/manage-tokens/terminology"}},m={},d=[{value:"Summary",id:"summary",level:2},{value:"Quick Navigation",id:"quick-navigation",level:2}],u={toc:d},p="wrapper";function g(e){let{components:t,...n}=e;return(0,a.kt)(p,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"overview"},"Overview"),(0,a.kt)("p",null,"This documentation will guide you on how to use your ROSE tokens, where to keep them, how to transfer them, how to stake/delegate them, and more."),(0,a.kt)("h2",{id:"summary"},"Summary"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"For ",(0,a.kt)("strong",{parentName:"li"},"self-custody"),", we recommend using one of our ",(0,a.kt)("strong",{parentName:"li"},"official")," ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/"},(0,a.kt)("strong",{parentName:"a"},"Oasis Wallets")),", ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/web"},"Web")," or ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/browser-extension"},"Browser Extension"),"."),(0,a.kt)("li",{parentName:"ul"},"ROSE is supported via three ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/holding-rose-tokens/custody-providers"},(0,a.kt)("strong",{parentName:"a"},"custody providers")),": ",(0,a.kt)("a",{parentName:"li",href:"https://copper.co"},"Copper.co"),", ",(0,a.kt)("a",{parentName:"li",href:"https://anchorage.com"},"Anchorage")," and ",(0,a.kt)("a",{parentName:"li",href:"https://finoa.io"},"Finoa"),"."),(0,a.kt)("li",{parentName:"ul"},"For extra security with self-custody, we recommend using the ",(0,a.kt)("a",{parentName:"li",href:"https://www.ledger.com"},"Ledger")," wallet with one of our official ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/"},"Oasis Wallets"),"."),(0,a.kt)("li",{parentName:"ul"},"For experienced developers/power users, we offer ",(0,a.kt)("a",{parentName:"li",href:"/general/manage-tokens/cli/"},"Oasis CLI Tools"),".")),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"For your own security and peace of mind, please only use wallets that are listed in our official documentation. Any other wallets are likely unofficial and may be subject to critical security vulnerabilities and other technical issues. Using wallets that not listed in our official documentation could result in the permanent loss of your ROSE tokens.")),(0,a.kt)("h2",{id:"quick-navigation"},"Quick Navigation"),(0,a.kt)(o.Z,{items:[(0,i.n)("/general/manage-tokens/terminology"),(0,i.n)("/general/manage-tokens/staking-and-delegating"),(0,i.n)("/general/manage-tokens/oasis-wallets/"),(0,i.n)("/general/manage-tokens/cli/"),(0,i.n)("/general/manage-tokens/holding-rose-tokens/custody-providers"),(0,i.n)("/general/manage-tokens/holding-rose-tokens/ledger-wallet")],mdxType:"DocCardList"}))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/acdeae29.1f361571.js b/assets/js/acdeae29.1f361571.js new file mode 100644 index 0000000000..aa90dc6309 --- /dev/null +++ b/assets/js/acdeae29.1f361571.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9532],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>u});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),d=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=d(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),p=d(n),h=r,u=p["".concat(l,".").concat(h)]||p[h]||m[h]||o;return n?a.createElement(u,i(i({ref:t},c),{},{components:n})):a.createElement(u,i({ref:t},c))}));function u(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:r,i[1]=s;for(var d=2;d{n.d(t,{Z:()=>u});var a=n(7294),r=n(6010),o=n(9960),i=n(3438),s=n(3919),l=n(5999);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function c(e){let{href:t,children:n}=e;return a.createElement(o.Z,{href:t,className:(0,r.Z)("card padding--lg",d.cardContainer)},n)}function p(e){let{href:t,icon:n,title:o,description:i}=e;return a.createElement(c,{href:t},a.createElement("h2",{className:(0,r.Z)("text--truncate",d.cardTitle),title:o},n," ",o),i&&a.createElement("p",{className:(0,r.Z)("text--truncate",d.cardDescription),title:i},i))}function m(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?a.createElement(p,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function h(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return a.createElement(p,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function u(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(h,{item:t});case"category":return a.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var a=n(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function o(e){const t=(0,a.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},8966:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>s,metadata:()=>d,toc:()=>p});var a=n(7462),r=(n(7294),n(3905)),o=n(1564),i=n(7525);const s={},l="Writing dApps on Emerald",d={unversionedId:"dapp/emerald/writing-dapps-on-emerald",id:"dapp/emerald/writing-dapps-on-emerald",title:"Writing dApps on Emerald",description:"This tutorial will show you how to set up dApp development environment for",source:"@site/docs/dapp/emerald/writing-dapps-on-emerald.mdx",sourceDirName:"dapp/emerald",slug:"/dapp/emerald/writing-dapps-on-emerald",permalink:"/dapp/emerald/writing-dapps-on-emerald",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/emerald/writing-dapps-on-emerald.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Emerald ParaTime",permalink:"/dapp/emerald/"},next:{title:"Integrating BAND oracle smart contract",permalink:"/dapp/emerald/integrating-band-oracle-smart-contract"}},c={},p=[{value:"Oasis Consensus Layer and Emerald ParaTime",id:"oasis-consensus-layer-and-emerald-paratime",level:2},{value:"Testnet and Mainnet",id:"testnet-and-mainnet",level:2},{value:"Running a Private Oasis Network Locally",id:"running-a-private-oasis-network-locally",level:2},{value:"Create dApp on Emerald with Hardhat",id:"create-dapp-on-emerald-with-hardhat",level:2},{value:"Create dApp on Emerald with Truffle",id:"create-dapp-on-emerald-with-truffle",level:2},{value:"Create dApp on Emerald with Remix - Ethereum IDE",id:"create-dapp-on-emerald-with-remix---ethereum-ide",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Deployment of my contract timed out on Testnet or Mainnet",id:"deployment-of-my-contract-timed-out-on-testnet-or-mainnet",level:3},{value:"Execution of my contract failed. How do I debug what went wrong?",id:"execution-of-my-contract-failed-how-do-i-debug-what-went-wrong",level:3},{value:"See also",id:"see-also",level:2}],m={toc:p},h="wrapper";function u(e){let{components:t,...s}=e;return(0,r.kt)(h,(0,a.Z)({},m,s,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"writing-dapps-on-emerald"},"Writing dApps on Emerald"),(0,r.kt)("p",null,"This tutorial will show you how to set up dApp development environment for\nEmerald to be able to write and deploy dApps on Oasis Emerald."),(0,r.kt)("p",null,"We will walk you through the Hardhat and Truffle configuration and -\nfor those who prefer a simpler web-only interface - the Remix IDE.\nOasis Emerald exposes an EVM-compatible interface so writing dApps isn't much\ndifferent compared to the original Ethereum Network!"),(0,r.kt)("h2",{id:"oasis-consensus-layer-and-emerald-paratime"},"Oasis Consensus Layer and Emerald ParaTime"),(0,r.kt)("p",null,"Oasis Network consists of the consensus layer and a number of Layer 2 chains\ncalled the ParaTimes (to learn more, check the ",(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network Overview")," chapter). Emerald is a ParaTime which implements the Ethereum\nVirtual Machine (EVM)."),(0,r.kt)("p",null,"The minimum and also expected block time in Emerald is ",(0,r.kt)("strong",{parentName:"p"},"6 seconds"),". Any\nEmerald transaction will require at least this amount of time to be executed."),(0,r.kt)("p",null,"The native Oasis addresses are Bech32-encoded (e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis1qpupfu7e2n6pkezeaw0yhj8mcem8anj64ytrayne"),")\nwhile Emerald supports both the Bech32-encoded and the Ethereum-compatible\nhex-encoded addresses (e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"0x90adE3B7065fa715c7a150313877dF1d33e777D5"),"). The\nunderlying algorithm for signing the transactions is ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/EdDSA#Ed25519"},"Ed25519")," on the Consensus\nlayer and both ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/EdDSA#Ed25519"},"Ed25519")," and ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"},"ECDSA")," in Emerald. The Ed25519 scheme is used\nmostly by the Emerald compute nodes for managing their computation rewards. For\nsigning your dApp-related transactions on Emerald you will probably want to use\nECDSA since this is the de facto scheme supported by Ethereum wallets and\nlibraries."),(0,r.kt)("p",null,"Finally, the ParaTimes are not allowed to directly access your tokens stored in\nConsensus layer addresses. You will need to ",(0,r.kt)("strong",{parentName:"p"},"deposit")," tokens from your consensus\naccount to Emerald. Consult the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime"},"How to transfer ROSE into Emerald ParaTime")," chapter to learn more."),(0,r.kt)("h2",{id:"testnet-and-mainnet"},"Testnet and Mainnet"),(0,r.kt)("p",null,"The Oasis Network currently has, similar to some other blockchains, two major\npublic deployments: the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Mainnet")," and the ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet"),". The\nnative tokens are called ROSE and TEST respectively. Each deployment has its own\nstate, a different set of validators and ParaTimes. The state of the Mainnet is\nconsidered immutable for indefinite time, while the data on the Testnet can be\nsubject to wipe in the future."),(0,r.kt)("p",null,"The Emerald ParaTime is deployed similarly: the ",(0,r.kt)("a",{parentName:"p",href:"/dapp/emerald/#mainnet"},"Emerald Mainnet")," is deployed on the Oasis Mainnet\nNetwork while the ",(0,r.kt)("a",{parentName:"p",href:"/dapp/emerald/#testnet"},"Emerald Testnet")," on the Oasis Testnet Network. The Emerald state on the Mainnet\nis stable. Testnet, apart from running the unstable version of the code and being prone to bugs, can\nhave the state deliberately wiped either on the Emerald ParaTime layer or on the Oasis Testnet\nNetwork level."),(0,r.kt)("admonition",{title:"Never deploy production service on Testnet",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Because Testnet state can be wiped in the future, you should ",(0,r.kt)("strong",{parentName:"p"},"never deploy a\nproduction service on the Testnet"),"!")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For testing purposes, visit our ",(0,r.kt)("a",{parentName:"p",href:"https://faucet.testnet.oasis.dev/"},"Testnet faucet")," to obtain some TEST which you\ncan then use on the Emerald Testnet to pay for gas fees. The faucet supports\nsending TEST both to your Consensus layer address or to your address inside the\nParaTime.")),(0,r.kt)("h2",{id:"running-a-private-oasis-network-locally"},"Running a Private Oasis Network Locally"),(0,r.kt)("p",null,"For convenient development and testing of your dApps the Oasis team prepared\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"ghcr.io/oasisprotocol/emerald-dev")," Docker image which brings you a complete Oasis\nstack to your desktop. This network is isolated from the Mainnet or Testnet and\nconsists of:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"single Oasis validator node with 1-second block time and 30-second epoch,"),(0,r.kt)("li",{parentName:"ul"},"single Oasis client node,"),(0,r.kt)("li",{parentName:"ul"},"three compute nodes running Oasis Emerald,"),(0,r.kt)("li",{parentName:"ul"},"PostgreSQL instance,"),(0,r.kt)("li",{parentName:"ul"},"Oasis Web3 gateway with transaction indexer,"),(0,r.kt)("li",{parentName:"ul"},"helper script which populates initial test accounts for you.")),(0,r.kt)("p",null,"To run the image, execute:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-dev\n")),(0,r.kt)("p",null,"After a while, the tool will show you something like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"emerald-dev 2023-02-28-git84730b2 (oasis-core: 22.2.6, emerald-paratime: 10.0.0, oasis-web3-gateway: 3.2.0-git84730b2)\n\nStarting oasis-net-runner with emerald...\nStarting postgresql...\nStarting oasis-web3-gateway...\nBootstrapping network and populating account(s) (this might take a minute)...\n\nAvailable Accounts\n==================\n(0) 0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2 (100 ROSE)\n(1) 0x903a7dce5a26a3f4DE2d157606c2191740Bc4BC9 (100 ROSE)\n(2) 0xF149ad5CBFfD92ba84F5784106f6Cb071A32a1b8 (100 ROSE)\n(3) 0x2315F40C1122400Df55483743B051D2997ef0a62 (100 ROSE)\n(4) 0xf6FdcacbA93A428A07d27dacEf1fBF25E2C65B0F (100 ROSE)\n\nPrivate Keys\n==================\n(0) 0x160f52faa5c0aecfa26c793424a04d53cbf23dcad5901ce15b50c2e85b9d6ca7\n(1) 0x0ba685723b47d8e744b1b70a9bea9d4d968f60205385ae9de99865174c1af110\n(2) 0xfa990cf0c22af455d2734c879a2a844ff99bd779b400bb0e2919758d1be284b5\n(3) 0x3bf225ef73b1b56b03ceec8bb4dfb4830b662b073b312beb7e7fec3159b1bb4f\n(4) 0xad0dd7ceb896fd5f5ddc76d56e54ee6d5c2a3ffeac7714d3ef544d3d6262512c\n\nHD Wallet\n==================\nMnemonic: bench remain brave curve frozen verify dream margin alarm world repair innocent\nBase HD Path: m/44'/60'/0'/0/%d\n\nWARNING: The chain is running in ephemeral mode. State will be lost after restart!\n\nListening on http://localhost:8545 and ws://localhost:8546\n")),(0,r.kt)("p",null,"Those familiar with local dApp environments will find the output above similar\nto ",(0,r.kt)("inlineCode",{parentName:"p"},"geth --dev")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"ganache-cli")," commands or the ",(0,r.kt)("inlineCode",{parentName:"p"},"geth-dev-assistant")," npm\npackage. ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev")," will spin up a private Oasis Network locally, generate\nand populate test accounts and make the following Web3 endpoints available for\nyou to use:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"http://localhost:8545")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"ws://localhost:8546"))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you prefer using the same mnemonics each time (e.g. for testing purposes)\nor to populate just a single wallet, use ",(0,r.kt)("inlineCode",{parentName:"p"},"-to")," flag and pass the mnemonics or\nthe wallet addresses. For example"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-dev -to "bench remain brave curve frozen verify dream margin alarm world repair innocent"\ndocker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-dev -to "0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2,0xbDA5747bFD65F08deb54cb465eB87D40e51B197E"\n'))),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev")," runs in ephemeral mode. Any smart contract and wallet balance\nwill be lost after you quit the Docker container!")),(0,r.kt)("h2",{id:"create-dapp-on-emerald-with-hardhat"},"Create dApp on Emerald with Hardhat"),(0,r.kt)("p",null,"Let's begin writing our dApp with Hardhat. We will lay out a base for a modern\ndApp including TypeScript bindings for tests and later for the frontend\napplication."),(0,r.kt)("p",null,"First, make sure you installed ",(0,r.kt)("a",{parentName:"p",href:"https://nodejs.org"},"Node.js")," and that you have ",(0,r.kt)("inlineCode",{parentName:"p"},"npm")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"npx"),"\nreadily available. Then run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"npx hardhat init\n")),(0,r.kt)("p",null,"Select the ",(0,r.kt)("inlineCode",{parentName:"p"},"Create an advanced sample project that uses TypeScript")," option and\nenter the root directory for your project. You can leave other options as\ndefault. After a while Hardhat will finish downloading the dependencies and\ncreate a simple greeter dApp."),(0,r.kt)("p",null,"To compile, deploy and test the smart contract of your sample project locally,\nmove to your project directory and type:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ npx hardhat compile\nCompiling 2 files with 0.8.4\nGenerating typings for: 2 artifacts in dir: typechain for target: ethers-v5\nSuccessfully generated 5 typings!\nCompilation finished successfully\n\n$ npx hardhat test\nNo need to generate any newer typings.\n\n\n Greeter\nDeploying an Emerald Greeter with greeting: Hello, world!\nChanging greeting from 'Hello, world!' to 'Hola, mundo!'\n \u2713 Should return the new greeting once it's changed (613ms)\n\n\n 1 passing (614ms)\n")),(0,r.kt)("p",null,"Hardhat already comes with a built-in EVM which is spun up from scratch each\ntime we call ",(0,r.kt)("inlineCode",{parentName:"p"},"hardhat test")," without parameters. It populates 20 accounts with\nETH and registers them to the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.ethers.io/v5/"},"ethers.js")," instance used in the tests."),(0,r.kt)("p",null,"Next, let's look at how to configure Hardhat for Emerald. For convenience, we\nassign the ",(0,r.kt)("inlineCode",{parentName:"p"},"PRIVATE_KEY")," environment variable a hex-encoded private key of your\nEmerald wallet containing tokens to pay for gas fees. If you are running\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev"),", use any of the five generated private keys."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'export PRIVATE_KEY="YOUR_0x_EMERALD_PRIVATE_KEY"\n')),(0,r.kt)("p",null,"Next, we configure three networks: ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_local"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_testnet"),", and\n",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_mainnet"),". Open ",(0,r.kt)("inlineCode",{parentName:"p"},"hardhat.config.ts")," and replace the ",(0,r.kt)("inlineCode",{parentName:"p"},"networks")," field to\nmatch the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'networks: {\n emerald_local: {\n url: "http://localhost:8545",\n accounts:\n process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],\n },\n emerald_testnet: {\n url: "https://testnet.emerald.oasis.dev",\n accounts:\n process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],\n },\n emerald_mainnet: {\n url: "https://emerald.oasis.dev",\n accounts:\n process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],\n },\n },\n')),(0,r.kt)("p",null,"Next, we increase the default timeout for mocha tests from 20 seconds to 60\nseconds. This step is not needed, if you will test your contracts solely on\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev"),", but is required for Testnet to avoid timeouts. Append the\nfollowing block to the ",(0,r.kt)("inlineCode",{parentName:"p"},"config")," object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"mocha: {\n timeout: 60000\n}\n")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("inlineCode",{parentName:"p"},"geth --dev")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"ganache-cli"),' tools use a so-called "instant mining" mode.\nIn this mode, a new block is mined immediately when a new transaction occurs in\nthe mempool. Neither Oasis Mainnet and Testnet Networks nor ',(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev"),"\nsupport such mode and the new block will always be mined at least after the 1\nsecond block time elapsed.")),(0,r.kt)("p",null,"Now deploy the contract to the local ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev")," Docker container by\nselecting the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_local")," network we configured above and run the tests:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ npx hardhat run scripts/deploy.ts --network emerald_local\nNo need to generate any newer typings.\nGreeter deployed to: 0x4e1de2f6cf4e57a8f55b4a5dd1fce770db734962\n\n$ npx hardhat test --network emerald_local\nNo need to generate any newer typings.\n\n\n Greeter\n \u2713 Should return the new greeting once it's changed (6017ms)\n\n\n 1 passing (6s)\n")),(0,r.kt)("p",null,"Next, you can try deploying the contract to the Testnet. Temporarily replace\nyour ",(0,r.kt)("inlineCode",{parentName:"p"},"PRIVATE_KEY")," environment variable with your Testnet one and deploy the\ncontract by using the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_testnet")," network. Similarly, you can also\nrun the tests."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'$ PRIVATE_KEY="0xYOUR_TESTNET_PRIVATE_KEY" npx hardhat run scripts/deploy.ts --network emerald_testnet\nNo need to generate any newer typings.\nGreeter deployed to: 0x735df9F166a2715bCA3D3A66B119CBef95a0D129\n\n$ PRIVATE_KEY="0xYOUR_TESTNET_PRIVATE_KEY" npx hardhat test --network emerald_testnet\nNo need to generate any newer typings.\n\n\n Greeter\n \u2713 Should return the new greeting once it\'s changed (21016ms)\n\n\n 1 passing (6s)\n')),(0,r.kt)("p",null,"Congratulations, you have just deployed your first smart contract to the public\nEmerald Testnet Network! If you are unsure, whether your contract was\nsuccessfully deployed, you can monitor the transactions on the Emerald block\nexplorer (",(0,r.kt)("a",{parentName:"p",href:"https://explorer.emerald.oasis.dev"},"Mainnet"),", ",(0,r.kt)("a",{parentName:"p",href:"https://testnet.explorer.emerald.oasis.dev"},"Testnet"),"). This tool\nindexes all Emerald accounts, blocks, transactions and even offers a neat user\ninterface for browsing ETH-specifics like the ERC20 tokens and the ERC721 NFTs."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Emerald Block Explorer showing the latest transactions",src:n(9162).Z,width:"2205",height:"1335"})),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Emerald Block Explorer showing our account 0x90adE3B7065fa715c7a150313877dF1d33e777D5 used for deploying the smart contract",src:n(1566).Z,width:"2208",height:"1339"})),(0,r.kt)("p",null,"Finally, by selecting the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_mainnet")," network and the corresponding\nprivate key, we can deploy the contract on the Mainnet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'$ PRIVATE_KEY="0xYOUR_MAINNET_PRIVATE_KEY" npx hardhat run scripts/deploy.ts --network emerald_mainnet\nNo need to generate any newer typings.\nGreeter deployed to: 0x6e8e9e0DBCa4EF4a65eBCBe4032e7C2a6fb7C623\n')),(0,r.kt)("h2",{id:"create-dapp-on-emerald-with-truffle"},"Create dApp on Emerald with Truffle"),(0,r.kt)("p",null,"Truffle and its accompanying ",(0,r.kt)("a",{parentName:"p",href:"https://web3js.readthedocs.io/en/v1.5.2/"},"web3.js")," library is another popular smart\ncontract deployment tool. Let's follow ",(0,r.kt)("a",{parentName:"p",href:"https://trufflesuite.com/docs/truffle/quickstart.html"},"the official Truffle's quickstart\nguide")," and unbox the MetaCoin example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ mkdir MetaCoin\n$ cd MetaCoin\n$ npx truffle unbox metacoin\n\nStarting unbox...\n=================\n\n\u2714 Preparing to download box\n\u2714 Downloading\n\u2714 Cleaning up temporary files\n\u2714 Setting up box\n\nUnbox successful, sweet!\n\nCommands:\n\n Compile contracts: truffle compile\n Migrate contracts: truffle migrate\n Test contracts: truffle test\n")),(0,r.kt)("p",null,"To compile and test the contract type:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ npx truffle test\nUsing network 'test'.\n\n\nCompiling your contracts...\n===========================\n> Compiling ./test/TestMetaCoin.sol\n> Artifacts written to /tmp/test--1052348-l4q3zOSy9nRA\n> Compiled successfully using:\n - solc: 0.5.16+commit.9c3226ce.Emscripten.clang\n\n\n\n TestMetaCoin\n \u2713 testInitialBalanceUsingDeployedContract (112ms)\n \u2713 testInitialBalanceWithNewMetaCoin (106ms)\n\n Contract: MetaCoin\n \u2713 should put 10000 MetaCoin in the first account (59ms)\n \u2713 should call a function that depends on a linked library (78ms)\n \u2713 should send coin correctly (185ms)\n\n\n 5 passing (6s)\n")),(0,r.kt)("p",null,"This spawns an instance of Truffle Develop blockchain in the background with a\nnumber of prepopulated ETH accounts and runs the tests."),(0,r.kt)("p",null,"Now, let's add support to Truffle for reading the private key stored in the\nenvironment variable. Add the ",(0,r.kt)("inlineCode",{parentName:"p"},"@truffle/hdwallet-provider")," package:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ npm i @truffle/hdwallet-provider --save-dev\n")),(0,r.kt)("p",null,"Import the library by adding the following line at the beginning of your\n",(0,r.kt)("inlineCode",{parentName:"p"},"truffle-config.js"),":"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},'const HDWalletProvider = require("@truffle/hdwallet-provider");')),(0,r.kt)("p",null,"Open ",(0,r.kt)("inlineCode",{parentName:"p"},"truffle-config.js")," and configure the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_local"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_testnet"),"\nand ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_mainnet")," networks:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'emerald_local: {\n url: "http://localhost:8545",\n provider: function() {\n return new HDWalletProvider(process.env.PRIVATE_KEYS.split(","), "http://localhost:8545");\n },\n network_id: "*"\n},\nemerald_testnet: {\n url: "https://testnet.emerald.oasis.dev:8545",\n provider: function() {\n return new HDWalletProvider(process.env.PRIVATE_KEY, "https://testnet.emerald.oasis.dev");\n },\n network_id: "*"\n},\nemerald_mainnet: {\n url: "https://emerald.oasis.dev:8545",\n provider: function() {\n return new HDWalletProvider(process.env.PRIVATE_KEY, "https://emerald.oasis.dev");\n },\n network_id: "*"\n}\n')),(0,r.kt)("p",null,"The MetaCoin example is somewhat specific in that it expects at least two\nprivate keys for running the token transfer test. That's why we use the\n",(0,r.kt)("inlineCode",{parentName:"p"},'.split(",")')," in the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_local")," network configuration above and we assign\ntwo private keys to the environment variable. If you are running ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev"),",\ncopy and paste any two of the generated private keys."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'export PRIVATE_KEYS="0xYOUR_FIRST_EMERALD_PRIVATE_KEY,0xYOUR_SECOND_EMERALD_PRIVATE_KEY"\n')),(0,r.kt)("p",null,"When we run the tests Truffle will deploy the contract with its dependencies\nand call the contract numerous times so it may take a few moments to complete."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ truffle test --network emerald_local\nUsing network 'emerald_local'.\n\n\nCompiling your contracts...\n===========================\n> Compiling ./test/TestMetaCoin.sol\n> Artifacts written to /tmp/test--1083354-x87wt3FdmfDE\n> Compiled successfully using:\n - solc: 0.5.16+commit.9c3226ce.Emscripten.clang\n\n\n\n TestMetaCoin\n \u2713 testInitialBalanceUsingDeployedContract (1091ms)\n \u2713 testInitialBalanceWithNewMetaCoin (913ms)\n\n Contract: MetaCoin\n \u2713 should put 10000 MetaCoin in the first account (349ms)\n \u2713 should call a function that depends on a linked library (677ms)\naccount one: 0x90adE3B7065fa715c7a150313877dF1d33e777D5\naccount two: 0x33a8Ba274FEdFeed6A08d09eC524a1E1A6Da8262\n \u2713 should send coin correctly (2795ms)\n\n\n 5 passing (26s)\n")),(0,r.kt)("p",null,"In order to deploy the contracts to the Testnet and finally the Mainnet run the\n",(0,r.kt)("inlineCode",{parentName:"p"},"migrate")," Truffle command and use the ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_testnet")," or ",(0,r.kt)("inlineCode",{parentName:"p"},"emerald_mainnet"),"\nnetwork accordingly. For the Mainnet, you would run something like this and in\na few rounds - depending on the network congestion - the contracts will be\ndeployed:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"$ PRIVATE_KEY=0xYOUR_MAINNET_PRIVATE_KEY truffle migrate --network emerald_mainnet\n\nCompiling your contracts...\n===========================\n> Everything is up to date, there is nothing to compile.\n\n\n\nStarting migrations...\n======================\n> Network name: 'emerald_mainnet'\n> Network id: 42262\n> Block gas limit: 21000000 (0x1406f40)\n\n\n1_initial_migration.js\n======================\n\n Deploying 'Migrations'\n ----------------------\n > transaction hash: 0x1630945ac8abfe6395a2e2627bd0acfffcf4bda9e107943cb3e4d6ef1d0905d4\n > Blocks: 1 Seconds: 44\n > contract address: 0xFaeA7eda8Be7AC83f811019094D0065D28F52c7c\n > block number: 93914\n > block timestamp: 1642176860\n > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5\n > balance: 0\n > gas used: 209087 (0x330bf)\n > gas price: 0 gwei\n > value sent: 0 ETH\n > total cost: 0 ETH\n\n\n > Saving migration to chain.\n > Saving artifacts\n -------------------------------------\n > Total cost: 0 ETH\n\n\n2_deploy_contracts.js\n=====================\n\n Deploying 'ConvertLib'\n ----------------------\n > transaction hash: 0xf2c53938773c316051f4ce98395e5df21cfcf0c686f634c1079725e04b9c556c\n > Blocks: 2 Seconds: 80\n > contract address: 0xA0FB05d6Ce497beb162C4EbA4F203544B18A3f31\n > block number: 93918\n > block timestamp: 1642177009\n > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5\n > balance: 0\n > gas used: 121235 (0x1d993)\n > gas price: 0 gwei\n > value sent: 0 ETH\n > total cost: 0 ETH\n\n\n Linking\n -------\n * Contract: MetaCoin <--\x3e Library: ConvertLib (at address: 0xA0FB05d6Ce497beb162C4EbA4F203544B18A3f31)\n\n Deploying 'MetaCoin'\n --------------------\n > transaction hash: 0x2c5e8177df03d643e56a37b64cbe660420b114ffec097dc5d793bfc666af8e16\n > Blocks: 2 Seconds: 60\n > contract address: 0x5a1C04012bc233c898aebb8BB4353F80D96f3dD2\n > block number: 93920\n > block timestamp: 1642177073\n > account: 0x90adE3B7065fa715c7a150313877dF1d33e777D5\n > balance: 0\n > gas used: 361168 (0x582d0)\n > gas price: 0 gwei\n > value sent: 0 ETH\n > total cost: 0 ETH\n\n\n > Saving migration to chain.\n > Saving artifacts\n -------------------------------------\n > Total cost: 0 ETH\n\n\nSummary\n=======\n> Total deployments: 3\n> Final cost: 0 ETH\n")),(0,r.kt)("p",null,"In the output above, the MetaCoin contract has been successfully deployed to\n",(0,r.kt)("inlineCode",{parentName:"p"},"0x5a1C04012bc233c898aebb8BB4353F80D96f3dD2")," address on the Mainnet."),(0,r.kt)("h2",{id:"create-dapp-on-emerald-with-remix---ethereum-ide"},"Create dApp on Emerald with Remix - Ethereum IDE"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://remix.ethereum.org"},"Remix")," is a popular web IDE for swift development, deployment and testing\nsmart contracts on the Ethereum Network. We will use it in combination with\nMetaMask to access the network settings and your wallet to sign and submit the\ntransactions."),(0,r.kt)("p",null,"If you haven't done it yet, first ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/how-to-transfer-rose-into-paratime#verifying-rose-balance-on-paratime"},"install the MetaMask extension for your\nbrowser"),". Import your wallet and configure Emerald Testnet and\nMainnet Networks. If you wish to connect to ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-dev"},"emerald-dev")," container, configure\nthe local network as well."),(0,r.kt)("p",null,'When you open Remix for the first time, it automatically creates an example\nproject. Let\'s open one of the contracts and compile it in the "Solidity\ncompiler" tab.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"The initial example project in Remix - Ethereum IDE",src:n(3723).Z,width:"2219",height:"1332"})),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Solidity compiler tab",src:n(9039).Z,width:"2217",height:"1338"})),(0,r.kt)("p",null,'Next, in the "Deploy and Run Transactions" tab, select the "Injected Web3"\nenvironment. A MetaMask popup will appear and you will have to connect one or\nmore accounts with Remix. Once the connection succeeds, click on the "Deploy"\nbutton. The MetaMask popup appears again and you will have to review the\ntransaction, the gas options and finally confirm the transaction.'),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Metamask transaction confirmation",src:n(6932).Z,width:"2219",height:"1332"})),(0,r.kt)("p",null,"If everything goes well, your transaction will be deployed using the selected\naccount in the MetaMask and the corresponding Emerald Network."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Successful contract deployment on Emerald Testnet with Remix",src:n(9603).Z,width:"2219",height:"1332"})),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Sometimes the gas limit estimation function might compute a slightly lower\nvalue from the required one. In this case, try increasing the gas limit\nmanually by 10% or 20%.")),(0,r.kt)("p",null,"Congratulations! Now you can start developing your own smart contracts on the\nOasis Emerald blockchain! Should you have any questions, do not hesitate to\nshare them with us on the ",(0,r.kt)("a",{parentName:"p",href:"https://oasis.io/discord"},"#emerald-paratime Discord channel"),"."),(0,r.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,r.kt)("h3",{id:"deployment-of-my-contract-timed-out-on-testnet-or-mainnet"},"Deployment of my contract timed out on Testnet or Mainnet"),(0,r.kt)("p",null,"Emerald validators, similar to Ethereum ones, order the execution of\ntransactions by gas price. When deploying a contract and the deployment times\nout, first wait another few rounds to make sure that the contract will not be\ndeployed eventually."),(0,r.kt)("p",null,"Next, check that your ",(0,r.kt)("inlineCode",{parentName:"p"},"gasPrice")," ",(0,r.kt)("strong",{parentName:"p"},"is at least 10 nROSE")," which is a minimum\nrequired gas price on Emerald. This value should already be propagated\nautomatically by the web3 endpoint, but your deployment configuration might\nhave ignored it."),(0,r.kt)("p",null,"Finally, consider increasing the ",(0,r.kt)("inlineCode",{parentName:"p"},"gasPrice")," parameter in Hardhat/Truffle config\nfiles by a fraction (e.g. 10% or 20%). This will require more ROSE from your\nwallet to deploy the contract, but you will also increase the chance of your\ntransaction being included in the block."),(0,r.kt)("h3",{id:"execution-of-my-contract-failed-how-do-i-debug-what-went-wrong"},"Execution of my contract failed. How do I debug what went wrong?"),(0,r.kt)("p",null,"If you are using Testnet or Mainnet, try to debug your transaction by finding\nit on the Emerald block explorer (",(0,r.kt)("a",{parentName:"p",href:"https://explorer.emerald.oasis.dev"},"Mainnet"),", ",(0,r.kt)("a",{parentName:"p",href:"https://testnet.explorer.emerald.oasis.dev"},"Testnet"),"):"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Emerald block explorer showing a failed transaction",src:n(5239).Z,width:"2219",height:"1332"})),(0,r.kt)("p",null,"In some cases, the transaction result on Emerald block explorer might be stuck\nat ",(0,r.kt)("inlineCode",{parentName:"p"},"Error: (Awaiting internal transactions for reason)"),". In this case or in\ncase of other Consensus layer \u2194 ParaTime issues, try to find your Emerald\ntransaction on the Oasis Scan (",(0,r.kt)("a",{parentName:"p",href:"https://oasisscan.com"},"Mainnet"),", ",(0,r.kt)("a",{parentName:"p",href:"https://testnet.oasisscan.com"},"Testnet"),") which is primarily a Consensus layer explorer, but offers\nsome introspection into ParaTime transactions as well. Once you find your\nfailed Emerald transaction, the ",(0,r.kt)("inlineCode",{parentName:"p"},"Status")," field should contain a more verbose\nerror description, for example:"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Scan showing the Out of gas error for a transaction on Emerald",src:n(1263).Z,width:"2219",height:"1332"})),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(o.Z,{item:(0,i.n)("/node/run-your-node/paratime-client-node"),mdxType:"DocCard"}),(0,r.kt)(o.Z,{item:(0,i.n)("/node/web3"),mdxType:"DocCard"}))}u.isMDXComponent=!0},9162:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/block_explorer1-300ad8505c206bca6ecb6416836e6770.png"},1566:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/block_explorer2-c07d43edbfeb9e90e1b38710179e9062.png"},5239:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/oasisscan1-024c1033c1ceeff4ca4f4294f544ce9c.png"},1263:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/oasisscan2-00e68913dfa621eb7c5f170e3b2f6378.png"},3723:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/remix1-400bc72123a178beea4c86d2ba9857cd.png"},9039:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/remix2-66fd8dbfe9f2a299501f5f9c75bdd08d.png"},6932:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/remix3-e2db0ab19df6a1aff70c68018b93e897.png"},9603:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/remix4-41183efd0966503c866863efba485d1c.png"}}]); \ No newline at end of file diff --git a/assets/js/b230e4e5.e9147289.js b/assets/js/b230e4e5.e9147289.js new file mode 100644 index 0000000000..53a1f4cb80 --- /dev/null +++ b/assets/js/b230e4e5.e9147289.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5751],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>h});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function a(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=i.createContext({}),m=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=m(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=m(n),c=r,h=d["".concat(l,".").concat(c)]||d[c]||p[c]||o;return n?i.createElement(h,a(a({ref:t},u),{},{components:n})):i.createElement(h,a({ref:t},u))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,a=new Array(o);a[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,a[1]=s;for(var m=2;m{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>s,toc:()=>m});var i=n(7462),r=(n(7294),n(3905));const o={},a="ADR 0004: Runtime Governance",s={unversionedId:"adrs/0004-runtime-governance",id:"adrs/0004-runtime-governance",title:"ADR 0004: Runtime Governance",description:"Component",source:"@site/docs/adrs/0004-runtime-governance.md",sourceDirName:"adrs",slug:"/adrs/0004-runtime-governance",permalink:"/adrs/0004-runtime-governance",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0004-runtime-governance.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0003: Consensus/Runtime Token Transfer",permalink:"/adrs/0003-consensus-runtime-token-transfer"},next:{title:"ADR 0005: Runtime Compute Node Slashing",permalink:"/adrs/0005-runtime-compute-slashing"}},l={},m=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Runtime Descriptor",id:"runtime-descriptor",level:3},{value:"Governance Model",id:"governance-model",level:4},{value:"Entity Whitelist Admission Policy",id:"entity-whitelist-admission-policy",level:4},{value:"Minimum Required Committee Election Pool Size",id:"minimum-required-committee-election-pool-size",level:4},{value:"State",id:"state",level:3},{value:"Stored Runtime Descriptors",id:"stored-runtime-descriptors",level:4},{value:"Genesis Document",id:"genesis-document",level:3},{value:"Transaction Methods",id:"transaction-methods",level:3},{value:"Register Runtime",id:"register-runtime",level:4},{value:"Messages",id:"messages",level:3},{value:"Update Runtime Descriptor",id:"update-runtime-descriptor",level:4},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Registry",id:"registry",level:4},{value:"Rust Runtime Support Library",id:"rust-runtime-support-library",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],u={toc:m},d="wrapper";function p(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,i.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"adr-0004-runtime-governance"},"ADR 0004: Runtime Governance"),(0,r.kt)("h2",{id:"component"},"Component"),(0,r.kt)("p",null,"Oasis Core"),(0,r.kt)("h2",{id:"changelog"},"Changelog"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2020-10-07: Add per-role max node limits, minimum required election pool size"),(0,r.kt)("li",{parentName:"ul"},"2020-09-30: Add entity whitelist admission policy max nodes limit"),(0,r.kt)("li",{parentName:"ul"},"2020-09-17: Initial draft")),(0,r.kt)("h2",{id:"status"},"Status"),(0,r.kt)("p",null,"Accepted"),(0,r.kt)("h2",{id:"context"},"Context"),(0,r.kt)("p",null,"Currently all runtimes can only be governed by a single entity -- the runtime\nowner. In this regard governance means being able to update certain fields in\nthe runtime descriptor stored by the consensus layer registry service. On one\nhand the runtime descriptor contains security-critical parameters and on the\nother there needs to be a mechanism through which the runtimes can be upgraded\n(especially so for TEE-based runtimes where a specific runtime binary is\nenforced via remote attestation mechanisms)."),(0,r.kt)("p",null,"This proposal extends runtime governance options and enables a path towards\nruntimes that can define their own governance mechanisms. This proposal assumes\nthat ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0003-consensus-runtime-token-transfer"},"ADR 0003")," has been adopted and runtimes can have their own accounts in the\nstaking module."),(0,r.kt)("h2",{id:"decision"},"Decision"),(0,r.kt)("p",null,"This proposal takes a simplistic but powerful approach which allows each runtime\nto choose its governance model upon its first registration. It does so through\na newly introduced field in the runtime descriptor which indicates how the\nruntime descriptor can be updated in the future."),(0,r.kt)("h3",{id:"runtime-descriptor"},"Runtime Descriptor"),(0,r.kt)("p",null,"The runtime descriptor version is bumped to ",(0,r.kt)("inlineCode",{parentName:"p"},"2"),". Version ",(0,r.kt)("inlineCode",{parentName:"p"},"1")," descriptors are\naccepted at genesis and are converted to the new format by assuming the entity\ngovernance model as that is the only option in v1. All new runtime registrations\nmust use the v2 descriptor."),(0,r.kt)("h4",{id:"governance-model"},"Governance Model"),(0,r.kt)("p",null,"This proposal updates the runtime descriptor by adding fields as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type Runtime struct {\n // GovernanceModel specifies the runtime governance model.\n GovernanceModel RuntimeGovernanceModel `json:"governance_model"`\n\n // ... existing fields omitted ...\n}\n\n// RuntimeGovernanceModel specifies the runtime governance model.\ntype RuntimeGovernanceModel uint8\n\nconst (\n GovernanceEntity RuntimeGovernanceModel = 1\n GovernanceRuntime RuntimeGovernanceModel = 2\n GovernanceConsensus RuntimeGovernanceModel = 3\n)\n\n// ... some text serialization methods omitted ...\n')),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"governance_model")," field can specifiy one of the following governance\nmodels:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Entity governance (",(0,r.kt)("inlineCode",{parentName:"strong"},"GovernanceEntity"),").")," This causes the runtime to behave\nexactly as before, the runtime owner (indicated by ",(0,r.kt)("inlineCode",{parentName:"p"},"entity_id")," in the runtime\ndescriptor) is the only one who can update the runtime descriptor via\n",(0,r.kt)("inlineCode",{parentName:"p"},"registry.RegisterRuntime")," method calls."),(0,r.kt)("p",{parentName:"li"},"The runtime owner is also the one that needs to provide the required stake\nin escrow in order to avoid the runtime from being suspended. As before note\nthat anyone can delegate the required stake to the runtime owner in order to\nenable runtime operation (but the owner can always prevent the runtime from\noperating by performing actions which would cause the stake claims to no\nlonger be satisfied).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Runtime-defined governance (",(0,r.kt)("inlineCode",{parentName:"strong"},"GovernanceRuntime"),").")," In this case the runtime\nitself is the only one who can update the runtime descriptor by emitting a\nruntime message. The runtime owner (indicated by ",(0,r.kt)("inlineCode",{parentName:"p"},"entity_id"),") is not able to\nperform any updates after the initial registration and such attempts must\nreturn ",(0,r.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),"."),(0,r.kt)("p",{parentName:"li"},"The runtime itself is the one that needs to provide the required stake in\nescrow in order to avoid the runtime from being suspended. This assumes that\nruntimes can have accounts in the staking module as specified by ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0003-consensus-runtime-token-transfer"},"ADR 0003"),".\nNote that anyone can delegate the required stake to a runtime in order to\nenable its operation.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Consensus layer governance (",(0,r.kt)("inlineCode",{parentName:"strong"},"GovernanceConsensus"),").")," In this case only the\nconsensus layer itself can update the runtime descriptor either through a\nnetwork upgrade or via a consensus layer governance mechanism not specified by\nthis proposal."),(0,r.kt)("p",{parentName:"li"},"Runtimes using this governance model are never suspended and do not need to\nprovide stake in escrow."),(0,r.kt)("p",{parentName:"li"},"Runtimes using this governance model cannot be registered/updated via regular\nregistry method calls or runtime messages (doing so must return\n",(0,r.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),"). Instead such a runtime can only be registered at genesis,\nthrough a network upgrade or via a consensus layer governance mechanism not\nspecified by this proposal."))),(0,r.kt)("h4",{id:"entity-whitelist-admission-policy"},"Entity Whitelist Admission Policy"),(0,r.kt)("p",null,"The entity whitelist admission policy configuration structure is changed to\nallow specifying the maximum number of nodes that each entity can register under\nthe given runtime for each role."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type EntityWhitelistConfig struct {\n // MaxNodes is the maximum number of nodes that an entity can register under\n // the given runtime for a specific role. If the map is empty or absent, the\n // number of nodes is unlimited. If the map is present and non-empty, the\n // the number of nodes is restricted to the specified maximum (where zero\n // means no nodes allowed), any missing roles imply zero nodes.\n MaxNodes map[node.RolesMask]uint16 `json:"max_nodes,omitempty"`\n}\n\ntype EntityWhitelistRuntimeAdmissionPolicy struct {\n Entities map[signature.PublicKey]EntityWhitelistConfig `json:"entities"`\n}\n')),(0,r.kt)("p",null,"The new ",(0,r.kt)("inlineCode",{parentName:"p"},"max_nodes")," field specifies the maximum number of nodes an entity can\nregister for the given runtime for each role. If the map is empty or absent, the\nnumber of nodes is unlimited. If the map is present and non-empty, the number of\nnodes is restricted to the specified number (where zero means no nodes are\nallowed). Any missing roles imply zero nodes."),(0,r.kt)("p",null,"Each key (roles mask) in the ",(0,r.kt)("inlineCode",{parentName:"p"},"max_nodes")," map must specify a single role,\notherwise the runtime descriptor is rejected with ",(0,r.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),"."),(0,r.kt)("p",null,"When transforming runtime descriptors from version 1, an entry in the ",(0,r.kt)("inlineCode",{parentName:"p"},"entities"),"\nfield maps to an ",(0,r.kt)("inlineCode",{parentName:"p"},"EntityWhitelistConfig")," structure with ",(0,r.kt)("inlineCode",{parentName:"p"},"max_nodes")," absent,\ndenoting that an unlimited number of nodes is allowed (as before)."),(0,r.kt)("h4",{id:"minimum-required-committee-election-pool-size"},"Minimum Required Committee Election Pool Size"),(0,r.kt)("p",null,"The executor and storage runtime parameters are updated to add a new field\ndefining the minimum required committee election pool size. The committee\nscheduler is updated to refuse election for a given runtime committee in case\nthe number of candidate nodes is less than the configured minimum pool size."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},'type ExecutorParameters struct {\n // MinPoolSize is the minimum required candidate compute node pool size.\n MinPoolSize uint64 `json:"min_pool_size"`\n\n // ... existing fields omitted ...\n}\n\ntype StorageParameters struct {\n // MinPoolSize is the minimum required candidate storage node pool size.\n MinPoolSize uint64 `json:"min_pool_size"`\n\n // ... existing fields omitted ...\n}\n')),(0,r.kt)("p",null,"The value of ",(0,r.kt)("inlineCode",{parentName:"p"},"min_pool_size")," must be non-zero and must be equal to or greater\nthan the corresponding sum of ",(0,r.kt)("inlineCode",{parentName:"p"},"group_size")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"group_backup_size"),". Otherwise\nthe runtime descriptor is rejected with ",(0,r.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),"."),(0,r.kt)("p",null,"When transforming runtime descriptors from version 1, ",(0,r.kt)("inlineCode",{parentName:"p"},"min_pool_size")," for the\nexecutor committee is computed as ",(0,r.kt)("inlineCode",{parentName:"p"},"group_size + group_backup_size")," while the\n",(0,r.kt)("inlineCode",{parentName:"p"},"min_pool_size")," for the storage committee is equal to ",(0,r.kt)("inlineCode",{parentName:"p"},"group_size"),"."),(0,r.kt)("h3",{id:"state"},"State"),(0,r.kt)("p",null,"This proposal introduces/updates the following consensus state in the registry\nmodule:"),(0,r.kt)("h4",{id:"stored-runtime-descriptors"},"Stored Runtime Descriptors"),(0,r.kt)("p",null,"Since the runtime descriptors can now be updated by actors other than the\ninitial registering entity, it does not make sense to store signed runtime\ndescriptors. The value of storage key prefixed with ",(0,r.kt)("inlineCode",{parentName:"p"},"0x13")," which previously\ncontained signed runtime descriptors is modified to store plain runtime\ndescriptors."),(0,r.kt)("h3",{id:"genesis-document"},"Genesis Document"),(0,r.kt)("p",null,"This proposal updates the registry part of the genesis document as follows:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The type of the ",(0,r.kt)("inlineCode",{parentName:"p"},"runtimes")," field is changed to a list of runtime descriptors\n(was a list of ",(0,r.kt)("em",{parentName:"p"},"signed")," runtime descriptors before).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The type of the ",(0,r.kt)("inlineCode",{parentName:"p"},"suspended_runtimes")," field is changed to a list of runtime\ndescriptors (was a list of ",(0,r.kt)("em",{parentName:"p"},"signed")," runtime descriptors before)."))),(0,r.kt)("p",null,"Runtime descriptors must be transformed to support the new fields."),(0,r.kt)("h3",{id:"transaction-methods"},"Transaction Methods"),(0,r.kt)("p",null,"This proposal updates the following transaction methods in the registry module:"),(0,r.kt)("h4",{id:"register-runtime"},"Register Runtime"),(0,r.kt)("p",null,"Runtime registration enables a new runtime to be created or an existing runtime\nto be updated (in case the governance model allows it)."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Method name:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"registry.RegisterRuntime\n")),(0,r.kt)("p",null,"The body of a register runtime transaction must be a ",(0,r.kt)("inlineCode",{parentName:"p"},"Runtime")," descriptor.\nThe signer of the transaction must be the owning entity key."),(0,r.kt)("p",null,"Registering a runtime may require sufficient stake in either the owning entity's\n(when entity governance is used) or the runtime's (when runtime governance is\nused) escrow account."),(0,r.kt)("p",null,"Changing the governance model from ",(0,r.kt)("inlineCode",{parentName:"p"},"GovernanceEntity")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"GovernanceRuntime")," is\nallowed. Any other governance model changes are not allowed and must fail with\n",(0,r.kt)("inlineCode",{parentName:"p"},"ErrForbidden"),". Support for other changes is deferred to a consensus layer\ngovernance mechanism not specified by this proposal."),(0,r.kt)("p",null,"Using the ",(0,r.kt)("inlineCode",{parentName:"p"},"GovernanceRuntime")," governance model for a runtime of any kind other\nthan ",(0,r.kt)("inlineCode",{parentName:"p"},"KindCompute")," must return ",(0,r.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),"."),(0,r.kt)("h3",{id:"messages"},"Messages"),(0,r.kt)("p",null,"This proposal introduces the following runtime messages:"),(0,r.kt)("h4",{id:"update-runtime-descriptor"},"Update Runtime Descriptor"),(0,r.kt)("p",null,"The update runtime descriptor message enables a runtime to update its own\ndescriptor when the current governance model allows it."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Field name:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"update_runtime\n")),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Body:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-golang"},"type UpdateRuntimeMessage struct {\n registry.Runtime\n}\n")),(0,r.kt)("p",null,"The body of the update runtime descriptor message is a new runtime descriptor\nthat must be for the runtime emitting this message. Otherwise the message is\nconsidered malformed."),(0,r.kt)("p",null,"The actions performed when processing the message are the same as those\nperformed when processing the ",(0,r.kt)("inlineCode",{parentName:"p"},"registry.RegisterRuntime")," method call, just made\non the runtime's (instead of an entity's) behalf."),(0,r.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,r.kt)("h4",{id:"registry"},"Registry"),(0,r.kt)("p",null,"This proposal introduces the following new consensus parameters in the registry\nmodule:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"enable_runtime_governance_models")," (set of ",(0,r.kt)("inlineCode",{parentName:"li"},"RuntimeGovernanceModel"),") specifies\nthe set of runtime governance models that are allowed to be used when\ncreating/updating registrations (either via method calls or via runtime\nmessages). In case a runtime is using a governance model not specified in this\nlist, an update to such a runtime must fail with ",(0,r.kt)("inlineCode",{parentName:"li"},"ErrForbidden"),".")),(0,r.kt)("h3",{id:"rust-runtime-support-library"},"Rust Runtime Support Library"),(0,r.kt)("p",null,"The Rust runtime support library (",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-core-runtime"),") must be updated to\nsupport the updated and newly needed message structures (the runtime descriptor\nand the update runtime message)."),(0,r.kt)("h2",{id:"consequences"},"Consequences"),(0,r.kt)("h3",{id:"positive"},"Positive"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Runtimes can define their governance model, enabling them to become more\ndecentralized while still allowing upgrades.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Runtimes using the entity whitelist admission policy can limit the number of\nnodes that each entity can register.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Runtimes can specify the minimum size of the compute/storage node pool from\nwhich committees are elected."))),(0,r.kt)("h3",{id:"negative"},"Negative"),(0,r.kt)("h3",{id:"neutral"},"Neutral"),(0,r.kt)("h2",{id:"references"},"References"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"/adrs/0003-consensus-runtime-token-transfer"},"ADR 0003")," - Consensus/Runtime Token Transfer")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b4883e93.30ff7a45.js b/assets/js/b4883e93.30ff7a45.js new file mode 100644 index 0000000000..d078fa7fb0 --- /dev/null +++ b/assets/js/b4883e93.30ff7a45.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7729],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>u});var i=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,i)}return a}function s(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var l=i.createContext({}),c=function(e){var t=i.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},p=function(e){var t=c(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},m=i.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,l=e.parentName,p=r(e,["components","mdxType","originalType","parentName"]),d=c(a),m=n,u=d["".concat(l,".").concat(m)]||d[m]||h[m]||o;return a?i.createElement(u,s(s({ref:t},p),{},{components:a})):i.createElement(u,s({ref:t},p))}));function u(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,s=new Array(o);s[0]=m;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[d]="string"==typeof e?e:n,s[1]=r;for(var c=2;c{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>c});var i=a(7462),n=(a(7294),a(3905));const o={},s="Why Oasis?",r={unversionedId:"general/oasis-network/why-oasis",id:"general/oasis-network/why-oasis",title:"Why Oasis?",description:"Network Overview",source:"@site/docs/general/oasis-network/why-oasis.md",sourceDirName:"general/oasis-network",slug:"/general/oasis-network/why-oasis",permalink:"/general/oasis-network/why-oasis",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/why-oasis.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Oasis Network",permalink:"/general/oasis-network/"},next:{title:"Token Metrics and Distribution",permalink:"/general/oasis-network/token-metrics-and-distribution"}},l={},c=[{value:"Network Overview",id:"network-overview",level:2},{value:"Why the Oasis Network?",id:"why-the-oasis-network",level:3},{value:"Technology Highlights",id:"technology-highlights",level:3},{value:"New Application Domains",id:"new-application-domains",level:2},{value:"Scalable, Private DeFi",id:"scalable-private-defi",level:3},{value:"Data Tokenization & A Responsible Data Economy",id:"data-tokenization--a-responsible-data-economy",level:3},{value:"Technology Overview",id:"technology-overview",level:2},{value:"Scalability",id:"scalability",level:3},{value:"Privacy-First",id:"privacy-first",level:3},{value:"Versatility",id:"versatility",level:3},{value:"Traction and Adoption",id:"traction-and-adoption",level:2},{value:"The Oasis Ecosystem",id:"the-oasis-ecosystem",level:3},{value:"The DeFi Ecosystem",id:"the-defi-ecosystem",level:3},{value:"The $200m Ecosystem Fund",id:"the-200m-ecosystem-fund",level:3},{value:"Grants & DevAccelerator",id:"grants--devaccelerator",level:3},{value:"Community Efforts",id:"community-efforts",level:3},{value:"Contributing Team",id:"contributing-team",level:3},{value:"Oasis Foundation",id:"oasis-foundation",level:4},{value:"Oasis Labs",id:"oasis-labs",level:4},{value:"Press",id:"press",level:3}],p={toc:c},d="wrapper";function h(e){let{components:t,...o}=e;return(0,n.kt)(d,(0,i.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"why-oasis"},"Why Oasis?"),(0,n.kt)("h2",{id:"network-overview"},"Network Overview"),(0,n.kt)("p",null,"Designed for the next generation of blockchain, the Oasis Network is the first privacy-enabled blockchain platform built to scale for open finance, a responsible data economy, and web 3. Combined with its high throughput and secure architecture, the Oasis Network will power private, scalable DeFi, revolutionizing Open Finance and expanding it beyond traders and early adopters to a mass market. Its unique privacy features will not only redefine DeFi and Web 3 but also create a new type of digital asset called Tokenized Data. This will enable users to take control of the data they generate and earn rewards for staking it with applications, creating the first-ever responsible data economy."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Oasis Timeline",src:a(9577).Z,width:"5744",height:"1070"})),(0,n.kt)("h3",{id:"why-the-oasis-network"},"Why the Oasis Network?"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Privacy-Enabled Blockchain:")," The Oasis Network is the world\u2019s leading scalable, privacy-enabled blockchain. ParaTimes on the Oasis Network can leverage privacy-preserving technology enabling users to share their data to earn income while keeping it totally confidential, unlocking new Web 3 use cases like digital identity and private metaverse applications for blockchain."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Scalable, Private DeFi:")," The DeFi market is still in its infancy, with trillions of dollars in existing financial markets ready to enter the space. The expansion of DeFi is limited by a lack of privacy, security as well as high fees. The result is an overloaded and expensive system that\u2019s impossible to scale. Oasis Network is a Layer 1 blockchain that can expand DeFi beyond early adopters into mass-market adoption."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Enables Data Tokenization:")," The Oasis Network can Tokenize Data. This will unlock game-changing use cases for blockchain, and an entirely new ecosystem of apps and projects on the network, powering the next generation of privacy-first applications that reward users for the value they create."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Rapidly Growing Community:")," The Oasis Network has a thriving community of node operators, developers, enterprise partners, ambassadors, and community members engaged in global social channels."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Top-Tier Team:")," The Oasis Team is made up of top talent, from around the world, with backgrounds from Apple, Google, Amazon, Goldman Sachs, UC Berkeley, Carnegie Mellon, Stanford, Harvard, and more. All the core engineering team are PHD level educated and all committed to growing and expanding the impact of the Oasis Network."),(0,n.kt)("h3",{id:"technology-highlights"},"Technology Highlights"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Separates consensus and execution into two layers"),", the consensus layer and The ParaTime layer, for better scalability and increased versatility."),(0,n.kt)("li",{parentName:"ul"},"Separation of consensus and execution allows ",(0,n.kt)("strong",{parentName:"li"},"multiple ParaTimes to process transactions in parallel"),", meaning complex workloads processed on one ParaTime won\u2019t slow down faster, simpler transactions on another."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"The ParaTime layer is entirely decentralized, allowing anyone to develop and build their own ParaTime.")," Each ParaTime can be developed in isolation to meet the needs of a specific application, such as confidential compute, open or closed committees, and more."),(0,n.kt)("li",{parentName:"ul"},"The network\u2019s sophisticated discrepancy detection makes ",(0,n.kt)("strong",{parentName:"li"},"Oasis more efficient than sharding and parachains"),", requiring a smaller replication factor for the same level of security."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"There are 3 ParaTimes built by the Oasis core team already on the network."),(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Emerald ParaTime, the EVM-Compatible ParaTime"),", was built to solve the problems faced by Solidity developers. High fees and low throughput. Emerald solves both of these problems by increasing the throughput of transactions to 1,000 per second and reducing fees by 99%+ compared to Ethereum. This means more users will be able to use and build on the network."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Cipher ParaTime, the confidential smart contract ParaTime"),", holds the features that Oasis is known for \u2014 privacy-preserving smart contracts. As with Emerald, it boasts high throughput, instant finality, and low fees with added privacy-preserving features. Cipher enables DEX\u2019s to stop front-running transactions, NFT users to protect their assets privately, and can potentially unlock trillions in credit and lending markets from traditional finance. Cipher executes smart contracts compiled in Oasis Wasm. Currently, we offer tooling for the ",(0,n.kt)("a",{parentName:"li",href:"https://www.rust-lang.org/"},"Rust programming language")," which is very rigorous about memory management and thus suitable for security-first apps."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Sapphire ParaTime, the EVM-Compatible confidential smart contract ParaTime")," is the latest addition to the Oasis ecosystem. It enables confidential computation of the smart contracts written in Solidity or other EVM-compatible language. In contrast to Cipher, dApp developers can integrate Sapphire for privacy-preserving data storage, governance, and computation into their applications with little or no additional work to existing smart contracts code.")))),(0,n.kt)("h2",{id:"new-application-domains"},"New Application Domains"),(0,n.kt)("h3",{id:"scalable-private-defi"},"Scalable, Private DeFi"),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Scalable, Private DeFi",src:a(6021).Z,width:"1251",height:"668"})),(0,n.kt)("p",null,"The DeFi market is still in its infancy, with trillions of dollars in existing financial markets ready to enter the space. The expansion of DeFi is limited by a lack of privacy, security, and high fees. The result is an overloaded and expensive system that\u2019s impossible to scale."),(0,n.kt)("p",null,"The Oasis Network is ideal for DeFi applications due to its scalability, instant finality, 99% lower gas fees versus Ethereum, and high throughput."),(0,n.kt)("p",null,"The Oasis Network is designed to support confidential smart contracts that keep data private while being processed. By providing end-to-end data confidentiality on Blockchain, the Oasis Network unlocks new and exciting use cases in DeFi. From under-collateralized lending to preventing front/back running, the Oasis Network can help expand DeFi beyond traders and early adopters to a mainstream market."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Oasis Network in lending market",src:a(3833).Z,width:"3892",height:"2036"})),(0,n.kt)("p",null,"The network\u2019s cutting-edge scalability features can help unblock DeFi as it works today, fixing the high-transaction fees and slow throughput currently plaguing other Layer 1 networks. Combined, Oasis\u2019 unique ability to provide scalable, private DeFi is expected to make it the leading platform for unlocking the next generation of DeFi markets and use cases."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Comparison of networks",src:a(7783).Z,width:"1274",height:"611"})),(0,n.kt)("h3",{id:"data-tokenization--a-responsible-data-economy"},"Data Tokenization & A Responsible Data Economy"),(0,n.kt)("p",null,"The Oasis Network\u2019s combination of confidential computing and blockchain enables a new paradigm called Tokenized Data. Blockchain allows for logging and enforcement of usage policies with high integrity and \u2018auditability\u2019. Confidential computing ensures that data remains private during computation and cannot be reused without permission. This capsule of data + policies creates a new kind of digital asset that can be consumed, along with specific guidelines for a fee or exchange of value."),(0,n.kt)("p",null,"With Tokenized Data, the Oasis Network can power the next generation of privacy-first applications and unlock a new responsible data society. Data providers on the Oasis Network can put their Tokenized Data to use. They can earn rewards by staking their data with apps that want to analyze it or control how their most sensitive information is consumed by the services they use."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Data tokenization on the Oasis",src:a(6975).Z,width:"7118",height:"2794"})),(0,n.kt)("p",null,"Many projects have already begun building apps that leverage data tokenization on the Oasis. Here are just a few examples:"),(0,n.kt)("admonition",{title:"Case Study: Binance CryptoSafe Alliance",type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Crypto theft and attacks are on the rise, and exchanges need a platform to identify and ban bad actors. The CryptoSafe Platform was developed by Oasis Labs and Binance to allow exchanges to share threat intelligence data. Because of the Oasis Network\u2019s support for confidential compute, exchange data is kept confidential even while it's being compared.")),(0,n.kt)("admonition",{title:"Case Study: Fortune 500 Healthcare Provider",type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"A Fortune 500 healthcare provider wanted to share data with external parties while retaining control of the data and protecting the confidentiality of patient data. Using an Oasis Labs-built API this leading healthcare company is able to track, trace, and control data usage even when shared with 3rd parties.")),(0,n.kt)("admonition",{title:"Case Study: Nebula Genomics",type:"tip"},(0,n.kt)("p",{parentName:"admonition"},"Nebula Genomics wants to differentiate their product from other competitors by giving their users control of their genetic data. Using Oasis\u2019 framework, customers can retain ownership of their genomic data and Nebula Genomics can run analysis on the data without seeing the customer\u2019s raw information.")),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Projects and Partners",src:a(2412).Z,width:"1298",height:"613"})),(0,n.kt)("h2",{id:"technology-overview"},"Technology Overview"),(0,n.kt)("p",null,"The Oasis Network is a Layer 1, proof-of-stake, decentralized network. It has two main components, the consensus layer and the ParaTime layer."),(0,n.kt)("ol",null,(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"consensus layer")," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."),(0,n.kt)("li",{parentName:"ol"},"The ",(0,n.kt)("strong",{parentName:"li"},"ParaTime layer")," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state.")),(0,n.kt)("h3",{id:"scalability"},"Scalability"),(0,n.kt)("p",null,"The Oasis Network\u2019s impressive scalability is achieved through a cutting-edge set of features that provide faster transaction speeds and higher throughput than other networks. The top-tier performance of the network is largely due to its separation of compute and consensus operations into the consensus layer and ParaTime layer. This separation allows multiple ParaTimes to process transactions in parallel, meaning complex workloads processed on one ParaTime won\u2019t slow down faster, simpler transactions on another. Plus, the network\u2019s sophisticated discrepancy detection makes Oasis more efficient than sharding and parachains, requiring a smaller replication factor for the same level of security."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Scalability",src:a(4128).Z,width:"1523",height:"718"})),(0,n.kt)("h3",{id:"privacy-first"},"Privacy-First"),(0,n.kt)("p",null,"The Oasis Network designed Cipher, the first-ever confidential ParaTime with support for confidential smart contracts. In a confidential ParaTime, nodes are required to use a type of secure computing technology called a TEE (trusted execution environment.) TEEs act as a hypothetical black box for smart contract execution in a confidential ParaTime. Encrypted data goes into the black box along with the smart contract, where the data is decrypted, processed by the smart contract, and then encrypted before it is sent out of the TEE. This process ensures that data remains confidential and is never leaked to the node operator or application developer The Oasis Eth/WASI Runtime is an open-source example of a confidential ParaTime that uses Intel SGX. Other secure compute technology can also be used, such as ZKP, HE, or other secure enclaves. In the future, we hope to support additional computation techniques such as secure multi-party compute, federated learning, and more."),(0,n.kt)("p",null,"Confidentiality unlocks a range of new use cases on blockchain. Personal or sensitive data, such as identity documents, social security numbers, bank statements, financial and credit records, health information, internet usage data, IoT data like fitness records and location data could all be used by apps on the Oasis Network, all the while protecting the user\u2019s privacy. Connecting all these data sources is something even today you wouldn\u2019t even dream of doing, especially not on an existing public Layer 1 blockchain. With Oasis, confidentiality and data tokenization together will give people the ability to securely, privately share their data, turning the data they create every day into income-generating assets."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Secure enclave",src:a(2573).Z,width:"648",height:"283"})),(0,n.kt)("h3",{id:"versatility"},"Versatility"),(0,n.kt)("p",null,"Designed to support the next generation of blockchain applications, the Oasis Network is incredibly versatile, agile, and customizable. Namely, each ParaTime can be developed in isolation to meet the needs of a specific application. ParaTime committees can be made large or small, open or closed, allowing for faster or more secure execution depending on the requirements of a particular use case. Nodes can be required to have specific hardware, such as Secure Enclaves on a confidential ParaTime. Each ParaTime can similarly run different Runtime VMs (ParaTime Engines), such as EVM backwards compatible engine, Rust-based smart contract language, or a Data tokenization engine. Finally, to support enterprise and developer use cases, ParaTimes can be made Permissioned or Permissionless, allowing consortiums to have their own closed ParaTime, or communities to have full decentralized open ParaTimes."),(0,n.kt)("p",null,"The versatility of the ParaTime layer allows the Oasis Network to expand and grow to address a broad set of new and exciting use cases while still maintaining the same core ledger and consensus layer."),(0,n.kt)("h2",{id:"traction-and-adoption"},"Traction and Adoption"),(0,n.kt)("h3",{id:"the-oasis-ecosystem"},"The Oasis Ecosystem"),(0,n.kt)("p",null,"The Oasis Network has a thriving and rapidly growing ecosystem consisting of industry-leading app developers, blockchain infrastructure teams, node operators, universities, and more. We are proud to highlight some of our key partners and community members in the chart below:"),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"The Oasis Ecosystem",src:a(9927).Z,width:"11564",height:"6597"})),(0,n.kt)("h3",{id:"the-defi-ecosystem"},"The DeFi Ecosystem"),(0,n.kt)("p",null,"Emerald, The EVM Compatible Paratime is now live on mainnet, and developers are releasing new projects all the time. Here we highlight some of the recent DeFi projects building on the network:"),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"The DeFi Ecosystem",src:a(7813).Z,width:"1200",height:"675"})),(0,n.kt)("h3",{id:"the-200m-ecosystem-fund"},"The $200m Ecosystem Fund"),(0,n.kt)("p",null,"The Oasis Foundation brought together some of the industry's biggest backers including Binance Labs, Pantera, Dragonfly Capital, Jump Capital, Electric Capital, and more. They all share our vision that privacy is an essential component of successful Web 3 and have pooled together $200m in funding for developers and projects looking to build the next generation of Web 3, DeFi, Metaverse, DAO, and NFT projects on the Oasis Network."),(0,n.kt)("p",null,"If you want to build on Oasis, you can read more about the Ecosystem Fund ",(0,n.kt)("a",{parentName:"p",href:"https://medium.com/oasis-protocol-project/binance-labs-backs-the-oasis-ecosystem-fund-to-support-the-projects-building-on-oasis-network-f6bcb3be6ee4"},"here")," or apply to the Ecosystem Fund through this form ",(0,n.kt)("a",{parentName:"p",href:"https://airtable.com/shrSyNBumurHhf7cd"},"here"),"."),(0,n.kt)("h3",{id:"grants--devaccelerator"},"Grants & DevAccelerator"),(0,n.kt)("p",null,"The Oasis Foundation has been working with many talented dev teams via our ",(0,n.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/ecosystem#grantsprogram"},"Grants program")," to build new applications and integrations on top of the Oasis Network. These include:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://anthem.chorus.one"},"Anthem (by Chorus One)")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-alethea-ai-aac8f854e436"},"Alethea.ai"),": A marketplace for AI-generated media"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-bankex-9bb127f9e449"},"Bankex"),": Send digital assets across your social networks"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-castalise-347f155ab66f"},"Castalise"),": Enabling privacy-preserving predictive analytics on pharmaceutical data"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/Chainflow/oasis-mission-control-grant"},"Chainflow Mission Control")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-dead-mans-switch-32d07cdfc057"},"Dead Man\u2019s Switch"),": A decentralized, censorship-resistant tool for whistleblowers"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://luther.ai"},"Luther.ai:")," Building artificial intelligence to Retain, Reinforce, Recall and ultimately augment your human memory."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://oasis.fish/leaderboard/"},"Oasis.Fish (by Stakefish)")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.figment.io/"},"Oasis Hubble (by Figment Networks)")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://oasismonitor.com"},"Oasis Monitor (by Everstake)")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://oasisscan.com"},"Oasisscan (by bitcat)")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://oasis.smartstake.io"},"Oasis Smartstake (by Smartstake)"),": Providing validation services for the Oasis Network"),(0,n.kt)("li",{parentName:"ul"},"Oasis Mobile Wallet by RockX"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-ruyi-health-7c068cfeecea"},"Ruyi Health"),": A Secure, Intuitive, and Intelligent Health Management Solution for Stroke Patients and their providers and insurers."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-saferate-2dbb99c3a43a"},"SafeRate"),": Automatically reduce mortgage payments when neighborhoods home values fall"),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/SimplyVC/panic_oasis"},"SimplyVC Panic Monitoring"))),(0,n.kt)("h3",{id:"community-efforts"},"Community Efforts"),(0,n.kt)("p",null,"The Oasis Network has a thriving community with members from around the world. This is driven in part by the Oasis Ambassador program, where volunteers passionate about the Oasis Network run meetups, write and translate content, answer developer questions, manage online communities, stress test the Oasis Network and more."),(0,n.kt)("p",null,"Ambassadors are also growing strong communities worldwide, including Bangladesh, Vietnam, India, Brazil, Korea, Nigeria, Philippines, Russia, China, South Korea, Turkey, and more."),(0,n.kt)("p",null,"The Oasis Network also has the ",(0,n.kt)("strong",{parentName:"p"},"largest University Program of any Layer-1 blockchain")," with over 25 top university departments, blockchain clubs, and others across 5 continents. Members of the program run nodes, build apps and more. Participating universities and university student organizations include Blockchain at Berkeley, Tsinghua University\u2019s Student Association of Digital Finance, Cambridge University\u2019s Blockchain Society, and many more."),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Oasis University Program",src:a(2475).Z,width:"4001",height:"2801"})),(0,n.kt)("h3",{id:"contributing-team"},"Contributing Team"),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Some of the many places contributing team members come from",src:a(3186).Z,width:"3791",height:"1036"})),(0,n.kt)("p",null,"The Oasis Team is made up of world-leading researchers, security experts, and privacy advocates \u2014 all working together to build a platform for a responsible data economy."),(0,n.kt)("h4",{id:"oasis-foundation"},(0,n.kt)("a",{parentName:"h4",href:"https://www.linkedin.com/company/oasisprotocol/"},"Oasis Foundation")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://oasisprotocol.org"},"See team page on our website"))),(0,n.kt)("h4",{id:"oasis-labs"},(0,n.kt)("a",{parentName:"h4",href:"https://www.linkedin.com/company/oasis-labs"},"Oasis Labs")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.linkedin.com/in/dawn-song-51586033/"},"Dawn Song, Founder")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.linkedin.com/in/peter-gilbert-2b70b1167/"},"Peter Gilbert, Director of Engineering"))),(0,n.kt)("h3",{id:"press"},"Press"),(0,n.kt)("p",null,"Over 200 articles have been written since the company came out of stealth mode. Top articles and interviews include:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.nytimes.com/2019/11/19/technology/artificial-intelligence-dawn-song.html"},"The New York Times: Building a World Where Data Privacy Exists Online")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.wired.com/story/dawn-song-oasis-labs-data-privacy-wired25/"},"WIRED: Oasis Labs' Dawn Song on a Safer Way to Protect Your Data")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.technologyreview.com/2019/05/14/239125/how-ai-could-save-lives-without-spilling-secrets/"},"MIT Technology Review: How AI could save lives without spilling medical secrets")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.yahoo.com/now/web3-users-control-data-says-132837055.html"},"Yahoo! Finance: Web3 Users will Control Their Data, Says Oasis Ecosystem Head")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://cointelegraph.com/news/first-dex-on-oasis-network-hits-100m-tvl-in-24-hours"},"Cointelegraph: First DEX on Oasis Network hits $100M TVL in 24 hours ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://cointelegraph.com/news/binance-labs-backs-200m-oasis-ecosystem-fund"},"Cointelegraph: Binance Labs backs $200M Oasis Ecosystem Fund ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.coinspeaker.com/oasis-protocol-partnership-meta/"},"CoinSpeaker: Oasis Protocol Inks Partnership with Meta to Facilitate AI Computing Applications")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://cointelegraph.com/news/akon-to-sell-historic-dna-data-art-as-nft-on-oasis-network"},"Cointelegraph: AkoinNFT to Sell Historic DNA Data Art as NFT In Collaboration With Oasis Network ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.nature.com/articles/d41586-021-01642-3"},"Nature: How scientists are embracing NFTs ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://cointelegraph.com/news/concerns-around-data-privacy-are-rising-and-blockchain-is-the-solution"},"Cointelegraph: Concerns around data privacy are rising, and blockchain is the solution")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.coindesk.com/business/2021/10/05/the-educator-entrepreneurs-of-crypto/"},"Coin Desk: The Educator-Entrepreneurs of Crypto"))),(0,n.kt)("p",null,"Articles about the Oasis Network have focused on a variety of topics and span across both mainstream and crypto press:"),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Press",src:a(68).Z,width:"3632",height:"538"})))}h.isMDXComponent=!0},4128:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"},7783:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/compare_networks-9630fe031fad10dc47c0c56aa1f00d33.png"},6975:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/data_tokenization-3931e375a8cea5a5756f82573ea95223.png"},7813:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/ecosystem-defi-52ce0ac1743d0d251120d3ac98519906.jpg"},9927:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/ecosystem-9c15f2d71858df610097d36faa5e0f71.jpg"},6021:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/features-69565025aa30dbd10c01eed76e58b212.png"},3833:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/lending_market-89baec95cc4d9c2a312f884a6c1c9a78.png"},2412:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/partners-98bce621edbe8c16b650cf27984f15e1.png"},68:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/press_logos-c37908c3371f7230bc2f71ef5729788f.png"},2573:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/secure_enclave-685f409cf66aabca221edfab5292e1dc.png"},3186:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/team_logos-343a69f4e7c6b3d857f51f910752efb6.png"},9577:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/timeline-fcb8cf7365a3b7742c563223e08cd070.png"},2475:(e,t,a)=>{a.d(t,{Z:()=>i});const i=a.p+"assets/images/uni_map-342c7d3df7a918f68531615dfb33b3ee.png"}}]); \ No newline at end of file diff --git a/assets/js/b4c66254.9a31f948.js b/assets/js/b4c66254.9a31f948.js new file mode 100644 index 0000000000..5d0010332b --- /dev/null +++ b/assets/js/b4c66254.9a31f948.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5275],{6752:e=>{e.exports=JSON.parse('{"title":"Run a Node","slug":"get-involved/run-node","permalink":"/get-involved/run-node","navigation":{"previous":{"title":"Join our Community","permalink":"/get-involved/"},"next":{"title":"Consensus Validator Node","permalink":"/get-involved/run-node/validator-node"}}}')}}]); \ No newline at end of file diff --git a/assets/js/b5f911d2.c1579686.js b/assets/js/b5f911d2.c1579686.js new file mode 100644 index 0000000000..d1489e7c2c --- /dev/null +++ b/assets/js/b5f911d2.c1579686.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5414],{5426:e=>{e.exports=JSON.parse('{"title":"Running Tests and Development Networks","slug":"core/development-setup/running-tests-and-development-networks","permalink":"/core/development-setup/running-tests-and-development-networks","navigation":{"previous":{"title":"Building","permalink":"/core/development-setup/building"},"next":{"title":"Running Tests","permalink":"/core/development-setup/running-tests"}}}')}}]); \ No newline at end of file diff --git a/assets/js/b622a7ea.1e0f7d11.js b/assets/js/b622a7ea.1e0f7d11.js new file mode 100644 index 0000000000..dbad4051a3 --- /dev/null +++ b/assets/js/b622a7ea.1e0f7d11.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9627],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var i=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=i.createContext({}),u=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},m=function(e){var t=u(e.components);return i.createElement(l.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),p=u(n),c=r,h=p["".concat(l,".").concat(c)]||p[c]||d[c]||a;return n?i.createElement(h,o(o({ref:t},m),{},{components:n})):i.createElement(h,o({ref:t},m))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,o=new Array(a);o[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:r,o[1]=s;for(var u=2;u{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var i=n(7462),r=(n(7294),n(3905));const a={},o="Modules",s={unversionedId:"paratime/modules",id:"paratime/modules",title:"Modules",description:"As we saw in the [minimal runtime example], creating an Oasis runtime is very",source:"@site/docs/paratime/modules.md",sourceDirName:"paratime",slug:"/paratime/modules",permalink:"/paratime/modules",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/modules.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"paratime",previous:{title:"Minimal Runtime",permalink:"/paratime/minimal-runtime"},next:{title:"Reproducibility",permalink:"/paratime/reproducibility"}},l={},u=[{value:"Runtime Trait",id:"runtime-trait",level:2},{value:"Version",id:"version",level:3},{value:"List of Modules",id:"list-of-modules",level:3},{value:"Genesis State",id:"genesis-state",level:3},{value:"Module Lifecycle Traits",id:"module-lifecycle-traits",level:2},{value:"Context",id:"context",level:2},{value:"Putting It All Together",id:"putting-it-all-together",level:2}],m={toc:u},p="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(p,(0,i.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"modules"},"Modules"),(0,r.kt)("p",null,"As we saw in the ",(0,r.kt)("a",{parentName:"p",href:"/paratime/minimal-runtime"},"minimal runtime example"),", creating an Oasis runtime is very\neasy to do thanks to the boilerplate provided by the Oasis SDK. The example\nhinted that almost all of the implementation of the state transition function\nis actually hidden inside the ",(0,r.kt)("em",{parentName:"p"},"modules")," that are composed together to form a\nruntime."),(0,r.kt)("p",null,"This section explores how modules are built."),(0,r.kt)("h2",{id:"runtime-trait"},"Runtime Trait"),(0,r.kt)("p",null,"Let's briefly revisit the ",(0,r.kt)("inlineCode",{parentName:"p"},"Runtime")," trait which is what brings everything\ntogether. As we saw when ",(0,r.kt)("a",{parentName:"p",href:"/paratime/minimal-runtime#runtime-definition"},"defining the minimal runtime"),", the trait requires\nimplementing some basic things:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-rust"},"impl sdk::Runtime for Runtime {\n // Use the crate version from Cargo.toml as the runtime version.\n const VERSION: Version = sdk::version_from_cargo!();\n\n // Define the modules that the runtime will be composed of.\n type Modules = (modules::core::Module, modules::accounts::Module);\n\n // Define the genesis (initial) state for all of the specified modules. This\n // state is used when the runtime is first initialized.\n //\n // The return value is a tuple of states in the same order as the modules\n // are defined above.\n fn genesis_state() -> ::Genesis {\n (\n // Core module.\n modules::core::Genesis {\n // ... snip ...\n },\n // Accounts module.\n modules::accounts::Genesis {\n // ... snip ...\n },\n )\n }\n}\n")),(0,r.kt)("h3",{id:"version"},"Version"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"VERSION")," constant is pretty self-explanatory as it makes it possible to\nversion runtimes and check compatibility with other nodes. The versioning scheme\nfollows ",(0,r.kt)("a",{parentName:"p",href:"https://semver.org/"},"semantic versioning")," with the following semantics:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The ",(0,r.kt)("strong",{parentName:"p"},"major")," version is used when determining state transition function\ncompatibility. If any introduced change could lead to a discrepancy when\nrunning alongside a previous version, the major version ",(0,r.kt)("em",{parentName:"p"},"must")," be bumped."),(0,r.kt)("p",{parentName:"li"},"The ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/scheduler"},"Oasis Core scheduler service")," will make sure to only schedule nodes which\nare running a compatible version in order to make upgrades easier.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The ",(0,r.kt)("strong",{parentName:"p"},"minor")," and ",(0,r.kt)("strong",{parentName:"p"},"patch")," versions are ignored when determining\ncompatibility and can be used for non-breaking features or fixes."))),(0,r.kt)("h3",{id:"list-of-modules"},"List of Modules"),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"Modules")," associated type contains all of the module types that compose the\nruntime. Due to the way modules are defined, you can specify multiple modules\nby using a tuple."),(0,r.kt)("h3",{id:"genesis-state"},"Genesis State"),(0,r.kt)("p",null,"The genesis state is the initial state of the runtime. It is used when the\nruntime is first deployed to populate the initial persistent state of all of the\nmodules."),(0,r.kt)("p",null,"Each module can define its own genesis state format together with the methods\nfor transforming that genesis state into internal persistent state."),(0,r.kt)("h2",{id:"module-lifecycle-traits"},"Module Lifecycle Traits"),(0,r.kt)("h2",{id:"context"},"Context"),(0,r.kt)("h2",{id:"putting-it-all-together"},"Putting It All Together"))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b66dccd5.f60b1674.js b/assets/js/b66dccd5.f60b1674.js new file mode 100644 index 0000000000..46d47a4a6a --- /dev/null +++ b/assets/js/b66dccd5.f60b1674.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2126],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>g});var i=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);n&&(i=i.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,i)}return t}function r(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var l=i.createContext({}),c=function(e){var n=i.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},u=function(e){var n=c(e.components);return i.createElement(l.Provider,{value:n},e.children)},m="mdxType",d={inlineCode:"code",wrapper:function(e){var n=e.children;return i.createElement(i.Fragment,{},n)}},p=i.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),m=c(t),p=a,g=m["".concat(l,".").concat(p)]||m[p]||d[p]||o;return t?i.createElement(g,r(r({ref:n},u),{},{components:t})):i.createElement(g,r({ref:n},u))}));function g(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,r=new Array(o);r[0]=p;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[m]="string"==typeof e?e:a,r[1]=s;for(var c=2;c{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var i=t(7462),a=(t(7294),t(3905));const o={},r="Minimal Runtime",s={unversionedId:"paratime/minimal-runtime",id:"paratime/minimal-runtime",title:"Minimal Runtime",description:"This section will show you how to quickly create, build and test a minimal",source:"@site/docs/paratime/minimal-runtime.md",sourceDirName:"paratime",slug:"/paratime/minimal-runtime",permalink:"/paratime/minimal-runtime",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/minimal-runtime.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"paratime",previous:{title:"Prerequisites",permalink:"/paratime/prerequisites"},next:{title:"Modules",permalink:"/paratime/modules"}},l={},c=[{value:"Repository Structure and Dependencies",id:"repository-structure-and-dependencies",level:2},{value:"Runtime Definition",id:"runtime-definition",level:2},{value:"Building and Running",id:"building-and-running",level:2},{value:"Deploying Locally",id:"deploying-locally",level:2},{value:"Testing From Oasis CLI",id:"testing-from-oasis-cli",level:2},{value:"Testing From a Client",id:"testing-from-a-client",level:2}],u={toc:c},m="wrapper";function d(e){let{components:n,...t}=e;return(0,a.kt)(m,(0,i.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"minimal-runtime"},"Minimal Runtime"),(0,a.kt)("p",null,"This section will show you how to quickly create, build and test a minimal\nruntime that allows transfers between accounts by using the ",(0,a.kt)("inlineCode",{parentName:"p"},"accounts")," module\nprovided by the Runtime SDK."),(0,a.kt)("h2",{id:"repository-structure-and-dependencies"},"Repository Structure and Dependencies"),(0,a.kt)("p",null,"First we create the basic directory structure for the minimal runtime using\nRust's ",(0,a.kt)("a",{parentName:"p",href:"https://doc.rust-lang.org/cargo"},(0,a.kt)("inlineCode",{parentName:"a"},"cargo")),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"cargo init minimal-runtime\n")),(0,a.kt)("p",null,"This will create the ",(0,a.kt)("inlineCode",{parentName:"p"},"minimal-runtime")," directory and populate it with some\nboilerplate needed to describe a Rust application. It will also set up the\ndirectory for version control using Git. The rest of the guide assumes that you\nare executing commands from within this directory."),(0,a.kt)("p",null,"Since the Runtime SDK requires a nightly version of the Rust toolchain, you need\nto specify a version to use by creating a special file called ",(0,a.kt)("inlineCode",{parentName:"p"},"rust-toolchain"),"\ncontaining the following information:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"nightly-2023-01-16\n")),(0,a.kt)("p",null,"Additionally, due to the requirements of some upstream dependencies, you need to\nconfigure Cargo to always build with specific target CPU platform features\n(namely AES-NI and SSE3) by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},".cargo/config")," file with the following\ncontent:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-toml"},'[build]\nrustflags = ["-C", "target-feature=+aes,+ssse3"]\nrustdocflags = ["-C", "target-feature=+aes,+ssse3"]\n\n[test]\nrustflags = ["-C", "target-feature=+aes,+ssse3"]\nrustdocflags = ["-C", "target-feature=+aes,+ssse3"]\n')),(0,a.kt)("p",null,"After you complete this guide, the minimal runtime directory structure will look\nas follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"minimal-runtime\n\u251c\u2500\u2500 .cargo\n\u2502 \u2514\u2500\u2500 config # Cargo configuration.\n\u251c\u2500\u2500 Cargo.lock # Rust dependency tree checksums.\n\u251c\u2500\u2500 Cargo.toml # Rust crate defintion.\n\u251c\u2500\u2500 rust-toolchain # Rust toolchain version configuration.\n\u251c\u2500\u2500 src\n\u2502 \u251c\u2500\u2500 lib.rs # The runtime definition.\n\u2502 \u2514\u2500\u2500 main.rs # Some boilerplate for building the runtime.\n\u2514\u2500\u2500 test\n \u251c\u2500\u2500 go.mod # Go module definition\n \u251c\u2500\u2500 go.sum # Go dependency tree checksums.\n \u2514\u2500\u2500 test.go # Test client implementation.\n")),(0,a.kt)("h2",{id:"runtime-definition"},"Runtime Definition"),(0,a.kt)("p",null,"First you need to declare the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-runtime-sdk")," as a dependency in order to be\nable to use its features. To do this, edit the ",(0,a.kt)("inlineCode",{parentName:"p"},"[dependencies]")," section in your\n",(0,a.kt)("inlineCode",{parentName:"p"},"Cargo.toml")," to look like the following:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-toml",metastring:'title="Cargo.toml"',title:'"Cargo.toml"'},'[package]\nname = "minimal-runtime"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\noasis-runtime-sdk = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "runtime-sdk/v0.3.0" }\n')),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"We are using the Git repository directly instead of releasing Rust packages on\ncrates.io.")),(0,a.kt)("p",null,"After you have declared the dependency on the Runtime SDK the next thing is to\ndefine the minimal runtime. To do this, create ",(0,a.kt)("inlineCode",{parentName:"p"},"src/lib.rs")," with the following\ncontent:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-rust",metastring:'title="src/lib.rs"',title:'"src/lib.rs"'},"//! Minimal runtime.\nuse std::collections::BTreeMap;\n\nuse oasis_runtime_sdk::{self as sdk, modules, types::token::Denomination, Version};\n\n/// Configuration of the various modules.\npub struct Config;\n\n// The base runtime type.\n//\n// Note that everything is statically defined, so the runtime has no state.\npub struct Runtime;\n\nimpl modules::core::Config for Config {}\n\nimpl sdk::Runtime for Runtime {\n // Use the crate version from Cargo.toml as the runtime version.\n const VERSION: Version = sdk::version_from_cargo!();\n\n // Define the module that provides the core API.\n type Core = modules::core::Module;\n\n // Define the modules that the runtime will be composed of. Here we just use\n // the core and accounts modules from the SDK. Later on we will go into\n // detail on how to create your own modules.\n type Modules = (modules::core::Module, modules::accounts::Module);\n\n // Define the genesis (initial) state for all of the specified modules. This\n // state is used when the runtime is first initialized.\n //\n // The return value is a tuple of states in the same order as the modules\n // are defined above.\n fn genesis_state() -> ::Genesis {\n (\n // Core module.\n modules::core::Genesis {\n parameters: modules::core::Parameters {\n max_batch_gas: 10_000,\n max_tx_signers: 8,\n max_tx_size: 10_000,\n max_multisig_signers: 8,\n min_gas_price: BTreeMap::from([(Denomination::NATIVE, 0)]),\n ..Default::default()\n },\n },\n // Accounts module.\n modules::accounts::Genesis {\n parameters: modules::accounts::Parameters {\n gas_costs: modules::accounts::GasCosts { tx_transfer: 100 },\n ..Default::default()\n },\n balances: BTreeMap::from([\n (\n sdk::testing::keys::alice::address(),\n BTreeMap::from([(Denomination::NATIVE, 1_000_000_000)]),\n ),\n (\n sdk::testing::keys::bob::address(),\n BTreeMap::from([(Denomination::NATIVE, 2_000_000_000)]),\n ),\n ]),\n total_supplies: BTreeMap::from([(Denomination::NATIVE, 3_000_000_000)]),\n ..Default::default()\n },\n )\n }\n}\n")),(0,a.kt)("p",null,"This defines the behavior (state transition function) and the initial state of\nthe runtime. We are populating the state with some initial accounts so that we\nwill be able to test things later. The accounts use test keys provided by the\nSDK."),(0,a.kt)("admonition",{type:"danger"},(0,a.kt)("p",{parentName:"admonition"},"While the test keys are nice for testing they ",(0,a.kt)("strong",{parentName:"p"},"should never be used in\nproduction")," versions of the runtimes as the private keys are generated from\npublicly known seeds!")),(0,a.kt)("p",null,"In order to be able to build a runtime binary that can be loaded by an Oasis\nNode, we need to add some boilerplate into ",(0,a.kt)("inlineCode",{parentName:"p"},"src/main.rs")," as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-rust",metastring:'title="src/main.rs"',title:'"src/main.rs"'},"use oasis_runtime_sdk::Runtime;\n\nfn main() {\n minimal_runtime::Runtime::start();\n}\n")),(0,a.kt)("h2",{id:"building-and-running"},"Building and Running"),(0,a.kt)("p",null,"In order to build the runtime you can use the regular Cargo build process by\nrunning:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"cargo build\n")),(0,a.kt)("p",null,"This will generate a binary under ",(0,a.kt)("inlineCode",{parentName:"p"},"target/debug/minimal-runtime")," which will\ncontain the runtime."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"For simplicity, we are building a non-confidential runtime which results in a\nregular ELF binary. In order to build a runtime that requires the use of a TEE\nlike Intel SGX you need to perform some additional steps which are described in\nlater sections of the guide.")),(0,a.kt)("p",null,"You can also try to run your runtime using:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"cargo run\n")),(0,a.kt)("p",null,"However, this will result in the startup process failing similar to the\nfollowing:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},' Finished dev [unoptimized + debuginfo] target(s) in 0.08s\n Running `target/debug/minimal-runtime`\n{"msg":"Runtime is starting","level":"INFO","ts":"2021-06-09T10:35:10.913154095+02:00","module":"runtime"}\n{"msg":"Establishing connection with the worker host","level":"INFO","ts":"2021-06-09T10:35:10.913654559+02:00","module":"runtime"}\n{"msg":"Failed to connect with the worker host","level":"ERRO","ts":"2021-06-09T10:35:10.913723541+02:00","module":"runtime","err":"Invalid argument (os error 22)"}\n')),(0,a.kt)("p",null,"The reason is that the built runtime binary is designed to be run by Oasis Node\ninside a specific sandbox environment. We will see how to deploy the runtime in\na local test environment in the next section."),(0,a.kt)("h2",{id:"deploying-locally"},"Deploying Locally"),(0,a.kt)("p",null,"In order to deploy the newly developed runtime in a local development network,\nyou can use the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-net-runner")," provided in Oasis Core. This will set up a\nsmall network of local nodes that will run the runtime."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"rm -rf /tmp/minimal-runtime-test; mkdir -p /tmp/minimal-runtime-test\n${OASIS_CORE_PATH}/oasis-net-runner \\\n --fixture.default.node.binary ${OASIS_CORE_PATH}/oasis-node \\\n --fixture.default.runtime.binary target/debug/minimal-runtime \\\n --fixture.default.runtime.loader ${OASIS_CORE_PATH}/oasis-core-runtime-loader \\\n --fixture.default.runtime.provisioner unconfined \\\n --fixture.default.keymanager.binary '' \\\n --basedir /tmp/minimal-runtime-test \\\n --basedir.no_temp_dir\n")),(0,a.kt)("p",null,"After successful startup this should result in the following message being\ndisplayed:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'level=info module=net-runner caller=root.go:152 ts=2021-06-14T08:42:47.219513806Z msg="client node socket available" path=/tmp/minimal-runtime-test/net-runner/network/client-0/internal.sock\n')),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The local network runner will take control of the current terminal until you\nterminate it via Ctrl+C. For the rest of the guide keep the local network\nrunning and use a separate terminal to run the client.")),(0,a.kt)("h2",{id:"testing-from-oasis-cli"},"Testing From Oasis CLI"),(0,a.kt)("p",null,"After you have the runtime running in your local network, the next step is to\ntest that it actually works. First, let's add a new ",(0,a.kt)("inlineCode",{parentName:"p"},"localhost")," network to the\nOasis CLI and provide the path to the local socket file reported above:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis network add-local localhost unix:/tmp/minimal-runtime-test/net-runner/network/client-0/internal.sock\n? Description: localhost\n? Denomination symbol: TEST\n? Denomination decimal places: 9\n")),(0,a.kt)("p",null,"Now, let's see, if the local network was correctly initialized and the runtime\nis ready:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis inspect node-status --network localhost\n")),(0,a.kt)("p",null,"If everything is working correctly, you should see the ",(0,a.kt)("inlineCode",{parentName:"p"},'"status": "ready"'),"\nunder the runtime's ",(0,a.kt)("inlineCode",{parentName:"p"},'"committee"')," field after a while and an increasing\n",(0,a.kt)("inlineCode",{parentName:"p"},'"latest_round"')," value:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},' "committee": {\n "status": "ready",\n "active_version": {\n "minor": 1\n },\n "latest_round": 19,\n "latest_height": 302,\n "executor_roles": null,\n')),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"When you restart ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-net-runner"),", a new ",(0,a.kt)("a",{parentName:"p",href:"/core/crypto#chain-domain-separation"},"chain context")," will be generated\nand you will have to remove the ",(0,a.kt)("inlineCode",{parentName:"p"},"localhost")," network and add it again to Oasis\nCLI.")),(0,a.kt)("p",null,"Now, let's add ",(0,a.kt)("inlineCode",{parentName:"p"},"minimal")," runtime to the wallet. By default, ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-net-runner"),"\nassigns ID ",(0,a.kt)("inlineCode",{parentName:"p"},"8000000000000000000000000000000000000000000000000000000000000000"),"\nto the first provided runtime."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis paratime add localhost minimal 8000000000000000000000000000000000000000000000000000000000000000\n? Description: minimal\n? Denomination symbol: TEST\n? Denomination decimal places: 9\n")),(0,a.kt)("p",null,"If the Oasis CLI was configured correctly, you should see the balance of Alice's\naccount in the runtime. Oasis CLI comes with hidden accounts for Alice, Bob and\nother test users (check the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/blob/main/client-sdk/go/testing/testing.go"},"oasis-sdk testing source")," for a complete list).\nYou can access the accounts by prepending ",(0,a.kt)("inlineCode",{parentName:"p"},"test:")," literal in front of the test\nuser's name, for example ",(0,a.kt)("inlineCode",{parentName:"p"},"test:alice"),"."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis accounts show test:alice --network localhost\nAddress: oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve\nNonce: 0\n\n=== CONSENSUS LAYER (localhost) ===\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n\n\n=== minimal PARATIME ===\nBalances for all denominations:\n 1.0 TEST\n")),(0,a.kt)("p",null,"Sending some TEST in your runtime should also work. Let's send 0.1 TEST to\nBob's address."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'oasis accounts transfer 0.1 test:bob --network localhost --account test:alice \nUnlock your account.\n? Passphrase: \nYou are about to sign the following transaction:\n{\n "v": 1,\n "call": {\n "method": "accounts.Transfer",\n "body": "omJ0b1UAyND0Wds45cwxynfmbSxEVty+tQJmYW1vdW50gkQF9eEAQA=="\n },\n "ai": {\n "si": [\n {\n "address_spec": {\n "signature": {\n "ed25519": "NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE="\n }\n },\n "nonce": 0\n }\n ],\n "fee": {\n "amount": {\n "Amount": "0",\n "Denomination": ""\n },\n "gas": 100\n }\n }\n}\n\nAccount: test:alice\nNetwork: localhost (localhost)\nParatime: minimal (minimal)\n? Sign this transaction? Yes\n(In case you are using a hardware-based signer you may need to confirm on device.)\nBroadcasting transaction...\nTransaction included in block successfully.\nRound: 14\nTransaction hash: 03a73bd08fb23472673ea45938b0871edd9ecd2cd02b3061d49c0906a772348a\nExecution successful.\n')),(0,a.kt)("h2",{id:"testing-from-a-client"},"Testing From a Client"),(0,a.kt)("p",null,"While the Oasis CLI is useful to quickly get your hands dirty, a more convenient\nway for writing end-to-end tests for your runtime once it grows is to create a\nGo client. Let's see how to use Go bindings for Oasis Runtime SDK in practice\nto submit some transactions and perform queries."),(0,a.kt)("p",null,"First, create a ",(0,a.kt)("inlineCode",{parentName:"p"},"tests")," directory and move into it, creating a Go module:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"go mod init example.com/oasisprotocol/minimal-runtime-client\ngo mod tidy\n")),(0,a.kt)("p",null,"Then create a ",(0,a.kt)("inlineCode",{parentName:"p"},"test.go")," file with the following content:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="test.go"',title:'"test.go"'},'package main\n\nimport (\n "context"\n "fmt"\n "os"\n "time"\n\n "google.golang.org/grpc"\n "google.golang.org/grpc/credentials/insecure"\n\n "github.com/oasisprotocol/oasis-core/go/common"\n cmnGrpc "github.com/oasisprotocol/oasis-core/go/common/grpc"\n "github.com/oasisprotocol/oasis-core/go/common/logging"\n "github.com/oasisprotocol/oasis-core/go/common/quantity"\n\n "github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"\n "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/accounts"\n "github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"\n "github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"\n)\n\n// In reality these would come from command-line arguments, the environment\n// or a configuration file.\nconst (\n // This is the default runtime ID as used in oasis-net-runner. It can\n // be changed by using its --fixture.default.runtime.id argument.\n runtimeIDHex = "8000000000000000000000000000000000000000000000000000000000000000"\n // This is the default client node address as set in oasis-net-runner.\n nodeAddress = "unix:/tmp/minimal-runtime-test/net-runner/network/client-0/internal.sock"\n)\n\n// The global logger.\nvar logger = logging.GetLogger("minimal-runtime-client")\n\n// Client contains the client helpers for communicating with the runtime. This is a simple wrapper\n// used for convenience.\ntype Client struct {\n client.RuntimeClient\n\n // Accounts are the accounts module helpers.\n Accounts accounts.V1\n}\n\n// showBalances is a simple helper for displaying account balances.\nfunc showBalances(ctx context.Context, rc *Client, address types.Address) error {\n // Query the runtime, specifically the accounts module, for the given address\' balances.\n rsp, err := rc.Accounts.Balances(ctx, client.RoundLatest, address)\n if err != nil {\n return fmt.Errorf("failed to fetch account balances: %w", err)\n }\n\n fmt.Printf("=== Balances for %s ===\\n", address)\n for denom, balance := range rsp.Balances {\n fmt.Printf("%s: %s\\n", denom, balance)\n }\n fmt.Printf("\\n")\n\n return nil\n}\n\nfunc tokenTransfer() error {\n // Initialize logging.\n if err := logging.Initialize(os.Stdout, logging.FmtLogfmt, logging.LevelDebug, nil); err != nil {\n return fmt.Errorf("unable to initialize logging: %w", err)\n }\n\n // Decode hex runtime ID into something we can use.\n var runtimeID common.Namespace\n if err := runtimeID.UnmarshalHex(runtimeIDHex); err != nil {\n return fmt.Errorf("malformed runtime ID: %w", err)\n }\n\n // Establish a gRPC connection with the client node.\n logger.Info("connecting to local node")\n conn, err := cmnGrpc.Dial(nodeAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))\n if err != nil {\n return fmt.Errorf("failed to establish connection to %s: %w", nodeAddress, err)\n }\n defer conn.Close()\n\n // Create the runtime client with account module query helpers.\n c := client.New(conn, runtimeID)\n rc := &Client{\n RuntimeClient: c,\n Accounts: accounts.NewV1(c),\n }\n\n ctx, cancelFn := context.WithTimeout(context.Background(), 30*time.Second)\n defer cancelFn()\n\n // Show initial balances for Alice\'s and Bob\'s accounts.\n logger.Info("dumping initial balances")\n if err = showBalances(ctx, rc, testing.Alice.Address); err != nil {\n return err\n }\n if err = showBalances(ctx, rc, testing.Bob.Address); err != nil {\n return err\n }\n\n // Get current nonce for Alice\'s account.\n nonce, err := rc.Accounts.Nonce(ctx, client.RoundLatest, testing.Alice.Address)\n if err != nil {\n return fmt.Errorf("failed to fetch account nonce: %w", err)\n }\n\n // Perform a transfer from Alice to Bob.\n logger.Info("performing transfer", "nonce", nonce)\n // Create a transfer transaction with Bob\'s address as the destination and 10 native base units\n // as the amount.\n tb := rc.Accounts.Transfer(\n testing.Bob.Address,\n types.NewBaseUnits(*quantity.NewFromUint64(10), types.NativeDenomination),\n ).\n // Configure gas as set in genesis parameters. We could also estimate it instead.\n SetFeeGas(100).\n // Append transaction authentication information using a single signature variant.\n AppendAuthSignature(testing.Alice.SigSpec, nonce)\n // Sign the transaction using the signer. Before a transaction can be submitted it must be\n // signed by all configured signers. This will automatically fetch the corresponding chain\n // domain separation context for the runtime.\n if err = tb.AppendSign(ctx, testing.Alice.Signer); err != nil {\n return fmt.Errorf("failed to sign transfer transaction: %w", err)\n }\n // Submit the transaction and wait for it to be included and a runtime block.\n if err = tb.SubmitTx(ctx, nil); err != nil {\n return fmt.Errorf("failed to submit transfer transaction: %w", err)\n }\n\n // Show final balances for Alice\'s and Bob\'s accounts.\n logger.Info("dumping final balances")\n if err = showBalances(ctx, rc, testing.Alice.Address); err != nil {\n return err\n }\n return showBalances(ctx, rc, testing.Bob.Address)\n}\n\nfunc main() {\n if err := tokenTransfer(); err != nil {\n panic(err)\n }\n}\n')),(0,a.kt)("p",null,"Fetch the dependencies:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"go get\n")),(0,a.kt)("p",null,"And build it:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"go build\n")),(0,a.kt)("p",null,"The example client will connect to one of the nodes in the network (the ",(0,a.kt)("em",{parentName:"p"},"client"),"\nnode), query the runtime for initial balances of two accounts (Alice and Bob as\nspecified above in the genesis state), then proceed to issue a transfer\ntransaction that will transfer 10 native base units from Alice to Bob. At the\nend it will again query and display the final balances of both accounts."),(0,a.kt)("p",null,"To run the built client do:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"./minimal-runtime-client\n")),(0,a.kt)("p",null,"The output should be something like the following:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'level=info ts=2022-06-28T14:08:02.834961397Z caller=test.go:81 module=minimal-runtime-client msg="connecting to local node"\nlevel=info ts=2022-06-28T14:08:02.836059713Z caller=test.go:103 module=minimal-runtime-client msg="dumping initial balances"\n=== Balances for oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve ===\n: 1000000000\n\n=== Balances for oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx ===\n: 2000000000\n\nlevel=info ts=2022-06-28T14:08:02.864348758Z caller=test.go:117 module=minimal-runtime-client msg="performing transfer" nonce=0\nlevel=info ts=2022-06-28T14:08:18.515842571Z caller=test.go:146 module=minimal-runtime-client msg="dumping final balances"\n=== Balances for oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve ===\n: 999999990\n\n=== Balances for oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx ===\n: 2000000010\n\n')),(0,a.kt)("p",null,"You can try running the client multiple times and it should transfer the given\namount each time. As long as the local network is running the state will be\npreserved."),(0,a.kt)("p",null,"Congratulations, you have successfully built and deployed your first runtime!"),(0,a.kt)("admonition",{title:"Example",type:"info"},(0,a.kt)("p",{parentName:"admonition"},"You can view and download complete ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/runtime-sdk/minimal-runtime"},"runtime example")," and ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/client-sdk/go/minimal-runtime-client"},"client code in Go"),"\nfrom the Oasis SDK repository.")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b821a83b.51ee0a15.js b/assets/js/b821a83b.51ee0a15.js new file mode 100644 index 0000000000..e8318d63a1 --- /dev/null +++ b/assets/js/b821a83b.51ee0a15.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1078],{3905:(e,n,t)=>{t.d(n,{Zo:()=>A,kt:()=>m});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var d=o.createContext({}),l=function(e){var n=o.useContext(d),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},A=function(e){var n=l(e.components);return o.createElement(d.Provider,{value:n},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},c=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,d=e.parentName,A=s(e,["components","mdxType","originalType","parentName"]),u=l(t),c=r,m=u["".concat(d,".").concat(c)]||u[c]||p[c]||i;return t?o.createElement(m,a(a({ref:n},A),{},{components:t})):o.createElement(m,a({ref:n},A))}));function m(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,a=new Array(i);a[0]=c;var s={};for(var d in n)hasOwnProperty.call(n,d)&&(s[d]=n[d]);s.originalType=e,s[u]="string"==typeof e?e:r,a[1]=s;for(var l=2;l{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var o=t(7462),r=(t(7294),t(3905));const i={},a="Adding or Removing Nodes",s={unversionedId:"node/run-your-node/maintenance/adding-or-removing-nodes",id:"node/run-your-node/maintenance/adding-or-removing-nodes",title:"Adding or Removing Nodes",description:"At some point you may wish to add or remove nodes from your entity. In order to",source:"@site/docs/node/run-your-node/maintenance/adding-or-removing-nodes.md",sourceDirName:"node/run-your-node/maintenance",slug:"/node/run-your-node/maintenance/adding-or-removing-nodes",permalink:"/node/run-your-node/maintenance/adding-or-removing-nodes",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/adding-or-removing-nodes.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Handling Network Upgrades",permalink:"/node/run-your-node/maintenance/handling-network-upgrades"},next:{title:"Refreshing Node Certificates",permalink:"/node/run-your-node/maintenance/refreshing-certificates"}},d={},l=[{value:"Overview",id:"overview",level:2},{value:"Retrieving Your Latest Entity Descriptor",id:"retrieving-your-latest-entity-descriptor",level:2},{value:"Updating Your Entity Descriptor",id:"updating-your-entity-descriptor",level:2},{value:"To Add a Node",id:"to-add-a-node",level:3},{value:"To Remove a Node",id:"to-remove-a-node",level:2},{value:"Updating Your Entity Registration on the Network",id:"updating-your-entity-registration-on-the-network",level:2},{value:"Generating a register Transaction",id:"generating-a-register-transaction",level:3},{value:"Submitting the Transaction",id:"submitting-the-transaction",level:3}],A={toc:l},u="wrapper";function p(e){let{components:n,...t}=e;return(0,r.kt)(u,(0,o.Z)({},A,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"adding-or-removing-nodes"},"Adding or Removing Nodes"),(0,r.kt)("p",null,"At some point you may wish to add or remove nodes from your entity. In order to\ndo so, you will need to have at least the following:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Access to a synced node"),(0,r.kt)("li",{parentName:"ul"},"Access to your entity's private key")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you just need to temporarily disable your node (e.g. to perform system\nupdates), use ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/shutting-down-a-node"},"graceful shutdown")," instead. This will assure you that your\nentity will not get penalized during node's downtime.")),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"The process for adding/removing nodes is similar and has the following steps:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Retrieve your up to date entity descriptor (",(0,r.kt)("inlineCode",{parentName:"li"},"entity.json"),")"),(0,r.kt)("li",{parentName:"ol"},"Update your entity descriptor by adding/removing a node"),(0,r.kt)("li",{parentName:"ol"},"Generate a ",(0,r.kt)("inlineCode",{parentName:"li"},"register")," transaction to update your entity registration on the\nnetwork.")),(0,r.kt)("h2",{id:"retrieving-your-latest-entity-descriptor"},"Retrieving Your Latest Entity Descriptor"),(0,r.kt)("p",null,"To ensure that we do not update your entity descriptor (",(0,r.kt)("inlineCode",{parentName:"p"},"entity.json"),")\nincorrectly we should get the latest entity descriptor state. For this\noperation, you will need to know the base64 encoding of your entity's\npublic key."),(0,r.kt)("p",null,"On your server run this command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'ENTITY_PUBLIC_KEY="some-base64-public-key"\noasis-node registry entity list \\\n -a unix:/serverdir/node/internal.sock -v | grep $ENTITY_PUBLIC_KEY\n')),(0,r.kt)("h2",{id:"updating-your-entity-descriptor"},"Updating Your Entity Descriptor"),(0,r.kt)("h3",{id:"to-add-a-node"},"To Add a Node"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Due to how the node election process works, only a single node from your entity\ncan be selected as a validator for any given epoch. Additional nodes will ",(0,r.kt)("em",{parentName:"p"},"not"),"\ngive you more voting power nor will it, inherently, provide high availability\nto have multiple nodes.")),(0,r.kt)("p",null,"Adding a node is a simple operation that is directly supported by the\n",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary. For this operation you'll need to have initialized a new\nnode, and you'll need to have the ",(0,r.kt)("inlineCode",{parentName:"p"},"node_genesis.json")," file in order to add it\nto the entity descriptor."),(0,r.kt)("p",null,"Assuming that the ",(0,r.kt)("inlineCode",{parentName:"p"},"node_genesis.json")," is at ",(0,r.kt)("inlineCode",{parentName:"p"},"/localhostdir/new_node/node_genesis.json"),"\nthe command is the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"NEW_NODE_GENESIS_PATH=/localhostdir/new_node/node_genesis.json\noasis-node registry entity update \\\n --signer.dir /localhostdir/entity \\\n --entity.node.descriptor /localhostdir/new_node/node_genesis.json\n")),(0,r.kt)("h2",{id:"to-remove-a-node"},"To Remove a Node"),(0,r.kt)("p",null,"Removing a node requires updating the entity descriptor manually. The entity\ndescriptor file is a simple JSON document that looks something like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-javascript"},'{\n "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "nodes": [\n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="\n ],\n "allow_entity_signed_nodes": false\n}\n')),(0,r.kt)("p",null,"In the above entity descriptor 2 nodes are attached to the entity:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"A node with an identity ",(0,r.kt)("inlineCode",{parentName:"li"},"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")),(0,r.kt)("li",{parentName:"ol"},"A node with an identity ",(0,r.kt)("inlineCode",{parentName:"li"},"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="))),(0,r.kt)("p",null,"To remove the Node ",(0,r.kt)("inlineCode",{parentName:"p"},"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")," you would\nremove it from the array in the ",(0,r.kt)("inlineCode",{parentName:"p"},"nodes")," field, like so:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-javascript"},'{\n "id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "nodes": [\n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n ],\n "allow_entity_signed_nodes": false\n}\n')),(0,r.kt)("h2",{id:"updating-your-entity-registration-on-the-network"},"Updating Your Entity Registration on the Network"),(0,r.kt)("p",null,"Finally, to commit the changes on the network you'll need to generate a\n",(0,r.kt)("inlineCode",{parentName:"p"},"register")," transaction and submit that transaction to the network."),(0,r.kt)("h3",{id:"generating-a-register-transaction"},"Generating a ",(0,r.kt)("inlineCode",{parentName:"h3"},"register")," Transaction"),(0,r.kt)("p",null,"Run this command on your localhost (as you need your entity's private key):"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'GENESIS_FILE_PATH="path/to/the/current/genesis"\nOUTPUT_REGISTER_TX_FILE_PATH="/localhostdir/update_entity_registration.tx"\noasis-node registry entity gen_register \\\n --genesis.file $GENESIS_FILE_PATH \\\n --signer.backend file \\\n --signer.dir $ENTITY_DIR_PATH \\\n --transaction.file $OUTPUT_REGISTER_TX_FILE_PATH \\\n --transaction.fee.gas 1000 \\\n --transaction.fee.amount 1 \\\n --transaction.nonce 1\n')),(0,r.kt)("p",null,"Once this has exited with a ",(0,r.kt)("inlineCode",{parentName:"p"},"0")," status, you should have a file at\n",(0,r.kt)("inlineCode",{parentName:"p"},"$OUTPUT_REGISTER_TX_FILE_PATH"),". Upload that file to your server."),(0,r.kt)("h3",{id:"submitting-the-transaction"},"Submitting the Transaction"),(0,r.kt)("p",null,"Run this command on your server:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node consensus submit_tx \\\n --transaction.file /serverdir/update_entity_registration.tx \\\n -a unix:/serverdir/node/internal.sock\n")),(0,r.kt)("p",null,"If there are no errors, your entity registration should be updated. You can run\nthis command to see the changes reflected:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'ENTITY_PUBLIC_KEY="some-base64-public-key"\noasis-node registry entity list \\\n -a unix:/serverdir/node/internal.sock -v | grep $ENTITY_PUBLIC_KEY\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/bb3e1595.5e8fee2d.js b/assets/js/bb3e1595.5e8fee2d.js new file mode 100644 index 0000000000..f473e4c909 --- /dev/null +++ b/assets/js/bb3e1595.5e8fee2d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4829],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>v});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=l(r),f=o,v=u["".concat(c,".").concat(f)]||u[f]||d[f]||i;return r?n.createElement(v,a(a({ref:t},p),{},{components:r})):n.createElement(v,a({ref:t},p))}));function v(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=f;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[u]="string"==typeof e?e:o,a[1]=s;for(var l=2;l{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={},a="Develop Oasis Core",s={unversionedId:"get-involved/oasis-core",id:"get-involved/oasis-core",title:"Develop Oasis Core",description:"This document outlines our guidelines for contributing to the Oasis Network's",source:"@site/docs/get-involved/oasis-core.md",sourceDirName:"get-involved",slug:"/get-involved/oasis-core",permalink:"/get-involved/oasis-core",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/oasis-core.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"getInvolved",previous:{title:"ParaTime Node",permalink:"/get-involved/run-node/paratime-node"},next:{title:"Network Governance",permalink:"/get-involved/network-governance"}},c={},l=[],p={toc:l},u="wrapper";function d(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"develop-oasis-core"},"Develop Oasis Core"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This document outlines our guidelines for contributing to the Oasis Network's\ncodebase and documentation. If you are interested in learning more about the\nOasis Network's governance model, including the processes for submitting\nfeature requests and bug fixes,\n",(0,o.kt)("a",{parentName:"p",href:"/get-involved/network-governance"},"please see our governance overview here"),".")),(0,o.kt)("p",null,"If you wish to contribute either code, documentation or larger enhancement\nproposals, feel free to read our\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/master/CONTRIBUTING.md"},"Oasis Core Contributing Guidelines"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/bcbc0322.0c4ed21b.js b/assets/js/bcbc0322.0c4ed21b.js new file mode 100644 index 0000000000..9c1b365e34 --- /dev/null +++ b/assets/js/bcbc0322.0c4ed21b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1088],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),u=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=u(e.components);return a.createElement(s.Provider,{value:t},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),c=u(n),m=r,h=c["".concat(s,".").concat(m)]||c[m]||p[m]||o;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[c]="string"==typeof e?e:r,i[1]=l;for(var u=2;u{n.d(t,{Z:()=>h});var a=n(7294),r=n(6010),o=n(9960),i=n(3438),l=n(3919),s=n(5999);const u={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:n}=e;return a.createElement(o.Z,{href:t,className:(0,r.Z)("card padding--lg",u.cardContainer)},n)}function c(e){let{href:t,icon:n,title:o,description:i}=e;return a.createElement(d,{href:t},a.createElement("h2",{className:(0,r.Z)("text--truncate",u.cardTitle),title:o},n," ",o),i&&a.createElement("p",{className:(0,r.Z)("text--truncate",u.cardDescription),title:i},i))}function p(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?a.createElement(c,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,s.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function m(e){let{item:t}=e;const n=(0,l.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return a.createElement(c,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(m,{item:t});case"category":return a.createElement(p,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},5162:(e,t,n)=>{n.d(t,{Z:()=>i});var a=n(7294),r=n(6010);const o={tabItem:"tabItem_Ymn6"};function i(e){let{children:t,hidden:n,className:i}=e;return a.createElement("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:n},t)}},4866:(e,t,n)=>{n.d(t,{Z:()=>N});var a=n(7462),r=n(7294),o=n(6010),i=n(2466),l=n(6550),s=n(1980),u=n(7392),d=n(12);function c(e){return function(e){return r.Children.map(e,(e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:t,label:n,attributes:a,default:r}}=e;return{value:t,label:n,attributes:a,default:r}}))}function p(e){const{values:t,children:n}=e;return(0,r.useMemo)((()=>{const e=t??c(n);return function(e){const t=(0,u.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function m(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function h(e){let{queryString:t=!1,groupId:n}=e;const a=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,s._X)(o),(0,r.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(a.location.search);t.set(o,e),a.replace({...a.location,search:t.toString()})}),[o,a])]}function f(e){const{defaultValue:t,queryString:n=!1,groupId:a}=e,o=p(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!m({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const a=n.find((e=>e.default))??n[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:t,tabValues:o}))),[s,u]=h({queryString:n,groupId:a}),[c,f]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[a,o]=(0,d.Nk)(n);return[a,(0,r.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:a}),b=(()=>{const e=s??c;return m({value:e,tabValues:o})?e:null})();(0,r.useLayoutEffect)((()=>{b&&l(b)}),[b]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),u(e),f(e)}),[u,f,o]),tabValues:o}}var b=n(2389);const y={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function k(e){let{className:t,block:n,selectedValue:l,selectValue:s,tabValues:u}=e;const d=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.o5)(),p=e=>{const t=e.currentTarget,n=d.indexOf(t),a=u[n].value;a!==l&&(c(t),s(a))},m=e=>{let t=null;switch(e.key){case"Enter":p(e);break;case"ArrowRight":{const n=d.indexOf(e.currentTarget)+1;t=d[n]??d[0];break}case"ArrowLeft":{const n=d.indexOf(e.currentTarget)-1;t=d[n]??d[d.length-1];break}}t?.focus()};return r.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},u.map((e=>{let{value:t,label:n,attributes:i}=e;return r.createElement("li",(0,a.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>d.push(e),onKeyDown:m,onClick:p},i,{className:(0,o.Z)("tabs__item",y.tabItem,i?.className,{"tabs__item--active":l===t})}),n??t)})))}function g(e){let{lazy:t,children:n,selectedValue:a}=e;const o=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=o.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return r.createElement("div",{className:"margin-top--md"},o.map(((e,t)=>(0,r.cloneElement)(e,{key:t,hidden:e.props.value!==a}))))}function v(e){const t=f(e);return r.createElement("div",{className:(0,o.Z)("tabs-container",y.tabList)},r.createElement(k,(0,a.Z)({},e,t)),r.createElement(g,(0,a.Z)({},e,t)))}function N(e){const t=(0,b.Z)();return r.createElement(v,(0,a.Z)({key:String(t)},e))}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var a=n(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function o(e){const t=(0,a.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},5646:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>d,default:()=>b,frontMatter:()=>u,metadata:()=>c,toc:()=>m});var a=n(7462),r=(n(7294),n(3905)),o=n(1564),i=n(7525),l=n(4866),s=n(5162);const u={},d="ParaTime Client Node",c={unversionedId:"node/run-your-node/paratime-client-node",id:"node/run-your-node/paratime-client-node",title:"ParaTime Client Node",description:"These instructions are for setting up a ParaTime client node which only observes ParaTime activity and can submit transactions. If you want to run a ParaTime node instead, see the instructions for running a ParaTime node. Similarly, if you want to run a validator or a non-validator node instead, see the instructions for running a validator node or instructions for running a non-validator node.",source:"@site/docs/node/run-your-node/paratime-client-node.mdx",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/paratime-client-node",permalink:"/node/run-your-node/paratime-client-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/paratime-client-node.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"ParaTime Node",permalink:"/node/run-your-node/paratime-node"},next:{title:"Key Manager Node",permalink:"/node/run-your-node/keymanager-node/"}},p={},m=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"The ParaTime Bundle",id:"the-paratime-bundle",level:3},{value:"Install ParaTime Bundle",id:"install-paratime-bundle",level:3},{value:"Install Bubblewrap Sandbox (at least version 0.3.3)",id:"install-bubblewrap-sandbox-at-least-version-033",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Checking Node Status",id:"checking-node-status",level:2},{value:"See also",id:"see-also",level:2}],h={toc:m},f="wrapper";function b(e){let{components:t,...n}=e;return(0,r.kt)(f,(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"paratime-client-node"},"ParaTime Client Node"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"These instructions are for setting up a ",(0,r.kt)("em",{parentName:"p"},"ParaTime client")," node which only observes ParaTime activity and can submit transactions. If you want to run a ",(0,r.kt)("em",{parentName:"p"},"ParaTime")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"instructions for running a ParaTime node"),". Similarly, if you want to run a ",(0,r.kt)("em",{parentName:"p"},"validator")," or a ",(0,r.kt)("em",{parentName:"p"},"non-validator")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"instructions for running a validator node")," or ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"instructions for running a non-validator node"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you are looking for some concrete ParaTimes that you can run, see ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/run-node/paratime-node"},"the list of ParaTimes and their parameters"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Oasis Core refers to ParaTimes as runtimes internally, so all configuration options will have runtime in their name.")),(0,r.kt)("p",null,"This guide will cover setting up your ParaTime client node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools."),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,r.kt)("a",{parentName:"p",href:"prerequisites"},"Prerequisites")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"Run a Non-validator Node")," sections and have:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Oasis Node binary installed and configured on your system."),(0,r.kt)("li",{parentName:"ul"},"The chosen top-level ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/")," working directory prepared. In addition to ",(0,r.kt)("inlineCode",{parentName:"li"},"etc")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"data")," directories, also prepare the following directories:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"bin"),": This will store binaries needed by Oasis Node for running the ParaTimes."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"runtimes"),": This will store the ParaTime bundles.")))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Feel free to name your working directory as you wish, e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"/srv/oasis/"),"."),(0,r.kt)("p",{parentName:"admonition"},"Just make sure to use the correct working directory path in the instructions below.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Genesis file copied to ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/etc/genesis.json"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Reading the rest of the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"ParaTime node setup instructions")," may also be useful.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"To speed up bootstraping your new node, we recommend ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other"},"copying node's state from your existing node")," or ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/sync-node-using-state-sync"},"syncing it using state sync"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Running a ParaTime client node doesn't require registering an entity or its nodes."),(0,r.kt)("p",{parentName:"admonition"},"It also doesn't require having any stake.")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Running a client node for a ParaTime that runs in a trusted execution environment (TEE) doesn't require having the same TEE available on the ParaTime client node."),(0,r.kt)("p",{parentName:"admonition"},"For example, running a ParaTime client node for an SGX-enabled ParaTime like Cipher doesn't require having SGX on the ParaTime client node.")),(0,r.kt)("h3",{id:"the-paratime-bundle"},"The ParaTime Bundle"),(0,r.kt)("p",null,"In order to run a ParaTime node you need to obtain the ParaTime bundle that\nneeds to come from a trusted source. The bundle (usually with an ",(0,r.kt)("inlineCode",{parentName:"p"},".orc"),"\nextension that stands for Oasis Runtime Container) contains all the needed\nParaTime binaries together with the identifier and version metadata to ease\ndeployment."),(0,r.kt)("p",null,"When the ParaTime is running in a trusted execution environment (TEE) the bundle\nwill also contain all the required artifacts (e.g. SGXS version of the binary\nand any enclave signatures)."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Like the genesis document, make sure you obtain these from a trusted source.")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("h4",{parentName:"admonition",id:"compiling-the-paratime-binary-from-source-code"},(0,r.kt)("strong",{parentName:"h4"},"Compiling the ParaTime Binary from Source Code")),(0,r.kt)("p",{parentName:"admonition"},"In case you decide to build the ParaTime binary from source yourself, make sure\nthat you follow our ",(0,r.kt)("a",{parentName:"p",href:"../../paratime/reproducibility"},"guidelines for deterministic compilation"),"\nto ensure that you receive the exact same binary.")),(0,r.kt)("h3",{id:"install-paratime-bundle"},"Install ParaTime Bundle"),(0,r.kt)("p",null,"For each ParaTime, you need to obtain its bundle and install it to the\n",(0,r.kt)("inlineCode",{parentName:"p"},"runtimes")," subdirectory of your node's working directory."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For example, for the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/#cipher-paratime"},"Cipher ParaTime"),",\nyou would have to obtain the ",(0,r.kt)("inlineCode",{parentName:"p"},"cipher-paratime.orc")," bundle and install it to\n",(0,r.kt)("inlineCode",{parentName:"p"},"/node/runtimes/cipher-paratime.orc"),".")),(0,r.kt)("h3",{id:"install-bubblewrap-sandbox-at-least-version-033"},"Install Bubblewrap Sandbox (at least version 0.3.3)"),(0,r.kt)("p",null,"ParaTime client nodes execute ParaTime binaries inside a sandboxed environment provided by ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/containers/bubblewrap"},"Bubblewrap"),". In order to install it, please follow these instructions, depending on your distribution:"),(0,r.kt)(l.Z,{mdxType:"Tabs"},(0,r.kt)(s.Z,{value:"Ubuntu 18.10+",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install bubblewrap\n"))),(0,r.kt)(s.Z,{value:"Fedora",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo dnf install bubblewrap\n"))),(0,r.kt)(s.Z,{value:"other",label:"Other Distributions",mdxType:"TabItem"},"On other systems, you can download the latest [source release provided by the Bubblewrap project](https://github.com/containers/bubblewrap/releases) and build it yourself.",(0,r.kt)("p",null,"Make sure you have the necessary development tools installed on your system and the ",(0,r.kt)("inlineCode",{parentName:"p"},"libcap")," development headers. On Ubuntu, you can install them with:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install build-essential libcap-dev\n")),(0,r.kt)("p",null,"After obtaining the Bubblewrap source tarball, e.g. ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/containers/bubblewrap/releases/download/v0.4.1/bubblewrap-0.4.1.tar.xz"},"bubblewrap-0.4.1.tar.xz"),", run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"tar -xf bubblewrap-0.4.1.tar.xz\ncd bubblewrap-0.4.1\n./configure --prefix=/usr\nmake\nsudo make install\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Note that Oasis Node expects Bubblewrap to be installed under ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/bin/bwrap")," by default.")))),(0,r.kt)("p",null,"Ensure you have a new enough version by running:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"bwrap --version\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Ubuntu 18.04 LTS (and earlier) provide overly-old ",(0,r.kt)("inlineCode",{parentName:"p"},"bubblewrap"),". Follow ",(0,r.kt)("em",{parentName:"p"},"Other Distributions")," section on those systems.")),(0,r.kt)("h2",{id:"configuration"},"Configuration"),(0,r.kt)("p",null,"In order to configure the ParaTime client node, create the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc/config.yml")," file with the following content:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'datadir: /node/data\n\nlog:\n level:\n default: info\n tendermint: info\n tendermint/context: error\n format: JSON\n\ngenesis:\n file: /node/etc/genesis.json\n\nconsensus:\n tendermint:\n p2p:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n seed:\n - "{{ seed_node_address }}"\n\nruntime:\n mode: client\n paths:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n - "{{ runtime_orc_path }}"\n')),(0,r.kt)("p",null,"Before using this configuration you should collect the following information to replace the variables present in the configuration file:."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ seed_node_address }}"),": The seed node address in the form ",(0,r.kt)("inlineCode",{parentName:"li"},"ID@IP:port"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"You can find the current Oasis Seed Node address in the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/"},"Network Parameters"),"."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ runtime_orc_path }}"),": Path to the ",(0,r.kt)("a",{parentName:"li",href:"/node/run-your-node/paratime-client-node#the-paratime-bundle"},"ParaTime bundle")," of the form ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/runtimes/foo-paratime.orc"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"You can find the current Oasis-supported ParaTimes in the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/#paratimes"},"Network Paramers"),".")))),(0,r.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,r.kt)("p",null,"You can start the node by running the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,r.kt)("h2",{id:"checking-node-status"},"Checking Node Status"),(0,r.kt)("p",null,"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/node/data/internal.sock\n")),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(o.Z,{item:(0,i.n)("/node/web3"),mdxType:"DocCard"}))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/bede16e2.fe1dfc4f.js b/assets/js/bede16e2.fe1dfc4f.js new file mode 100644 index 0000000000..52893a3482 --- /dev/null +++ b/assets/js/bede16e2.fe1dfc4f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7767],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),u=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},d=function(e){var t=u(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=u(n),c=r,h=p["".concat(l,".").concat(c)]||p[c]||m[c]||o;return n?a.createElement(h,i(i({ref:t},d),{},{components:n})):a.createElement(h,i({ref:t},d))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:r,i[1]=s;for(var u=2;u{n.d(t,{Z:()=>h});var a=n(7294),r=n(6010),o=n(9960),i=n(3438),s=n(3919),l=n(5999);const u={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function d(e){let{href:t,children:n}=e;return a.createElement(o.Z,{href:t,className:(0,r.Z)("card padding--lg",u.cardContainer)},n)}function p(e){let{href:t,icon:n,title:o,description:i}=e;return a.createElement(d,{href:t},a.createElement("h2",{className:(0,r.Z)("text--truncate",u.cardTitle),title:o},n," ",o),i&&a.createElement("p",{className:(0,r.Z)("text--truncate",u.cardDescription),title:i},i))}function m(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?a.createElement(p,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,l.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function c(e){let{item:t}=e;const n=(0,s.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return a.createElement(p,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(c,{item:t});case"category":return a.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},5162:(e,t,n)=>{n.d(t,{Z:()=>i});var a=n(7294),r=n(6010);const o={tabItem:"tabItem_Ymn6"};function i(e){let{children:t,hidden:n,className:i}=e;return a.createElement("div",{role:"tabpanel",className:(0,r.Z)(o.tabItem,i),hidden:n},t)}},4866:(e,t,n)=>{n.d(t,{Z:()=>v});var a=n(7462),r=n(7294),o=n(6010),i=n(2466),s=n(6550),l=n(1980),u=n(7392),d=n(12);function p(e){return function(e){return r.Children.map(e,(e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:t,label:n,attributes:a,default:r}}=e;return{value:t,label:n,attributes:a,default:r}}))}function m(e){const{values:t,children:n}=e;return(0,r.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,u.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function c(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function h(e){let{queryString:t=!1,groupId:n}=e;const a=(0,s.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,l._X)(o),(0,r.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(a.location.search);t.set(o,e),a.replace({...a.location,search:t.toString()})}),[o,a])]}function f(e){const{defaultValue:t,queryString:n=!1,groupId:a}=e,o=m(e),[i,s]=(0,r.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!c({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const a=n.find((e=>e.default))??n[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:t,tabValues:o}))),[l,u]=h({queryString:n,groupId:a}),[p,f]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[a,o]=(0,d.Nk)(n);return[a,(0,r.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:a}),k=(()=>{const e=l??p;return c({value:e,tabValues:o})?e:null})();(0,r.useLayoutEffect)((()=>{k&&s(k)}),[k]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!c({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);s(e),u(e),f(e)}),[u,f,o]),tabValues:o}}var k=n(2389);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function y(e){let{className:t,block:n,selectedValue:s,selectValue:l,tabValues:u}=e;const d=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,n=d.indexOf(t),a=u[n].value;a!==s&&(p(t),l(a))},c=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const n=d.indexOf(e.currentTarget)+1;t=d[n]??d[0];break}case"ArrowLeft":{const n=d.indexOf(e.currentTarget)-1;t=d[n]??d[d.length-1];break}}t?.focus()};return r.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},u.map((e=>{let{value:t,label:n,attributes:i}=e;return r.createElement("li",(0,a.Z)({role:"tab",tabIndex:s===t?0:-1,"aria-selected":s===t,key:t,ref:e=>d.push(e),onKeyDown:c,onClick:m},i,{className:(0,o.Z)("tabs__item",b.tabItem,i?.className,{"tabs__item--active":s===t})}),n??t)})))}function g(e){let{lazy:t,children:n,selectedValue:a}=e;const o=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=o.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return r.createElement("div",{className:"margin-top--md"},o.map(((e,t)=>(0,r.cloneElement)(e,{key:t,hidden:e.props.value!==a}))))}function N(e){const t=f(e);return r.createElement("div",{className:(0,o.Z)("tabs-container",b.tabList)},r.createElement(y,(0,a.Z)({},e,t)),r.createElement(g,(0,a.Z)({},e,t)))}function v(e){const t=(0,k.Z)();return r.createElement(N,(0,a.Z)({key:String(t)},e))}},7525:(e,t,n)=>{n.d(t,{n:()=>o});var a=n(4477);function r(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&r(t.items)}}function o(e){const t=(0,a.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)r(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},2129:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>m,contentTitle:()=>d,default:()=>k,frontMatter:()=>u,metadata:()=>p,toc:()=>c});var a=n(7462),r=(n(7294),n(3905)),o=n(1564),i=n(7525),s=n(4866),l=n(5162);const u={},d="ParaTime Node",p={unversionedId:"node/run-your-node/paratime-node",id:"node/run-your-node/paratime-node",title:"ParaTime Node",description:"These instructions are for setting up a ParaTime node which participates in one or more ParaTime compute committees. If you want to run a ParaTime client node instead, see the instructions for running a ParaTime client node. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a non-validator node instead, see the instructions for running a non-validator node.",source:"@site/docs/node/run-your-node/paratime-node.mdx",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/paratime-node",permalink:"/node/run-your-node/paratime-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/paratime-node.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Archive Node",permalink:"/node/run-your-node/archive-node"},next:{title:"ParaTime Client Node",permalink:"/node/run-your-node/paratime-client-node"}},m={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Stake Requirements",id:"stake-requirements",level:3},{value:"Register a New Entity or Update Your Entity Registration",id:"register-a-new-entity-or-update-your-entity-registration",level:3},{value:"The ParaTime Bundle",id:"the-paratime-bundle",level:3},{value:"Install Oasis Core Runtime Loader",id:"install-oasis-core-runtime-loader",level:3},{value:"Install ParaTime Bundle",id:"install-paratime-bundle",level:3},{value:"Install Bubblewrap Sandbox (at least version 0.3.3)",id:"install-bubblewrap-sandbox-at-least-version-033",level:3},{value:"Setting up Trusted Execution Environment (TEE)",id:"setting-up-trusted-execution-environment-tee",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Checking Node Status",id:"checking-node-status",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Too Old Bubblewrap Version",id:"too-old-bubblewrap-version",level:3},{value:"Bubblewrap Sandbox Fails to Start",id:"bubblewrap-sandbox-fails-to-start",level:3},{value:"Stake Requirement",id:"stake-requirement",level:3},{value:"See also",id:"see-also",level:2}],h={toc:c},f="wrapper";function k(e){let{components:t,...n}=e;return(0,r.kt)(f,(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"paratime-node"},"ParaTime Node"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"These instructions are for setting up a ",(0,r.kt)("em",{parentName:"p"},"ParaTime")," node which participates in one or more ParaTime compute committees. If you want to run a ",(0,r.kt)("em",{parentName:"p"},"ParaTime client")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-client-node"},"instructions for running a ParaTime client node"),". If you want to run a ",(0,r.kt)("em",{parentName:"p"},"validator")," node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"instructions for running a validator node"),". Similarly, if you want to run a non-validator node instead, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"instructions for running a non-validator node"),".")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"For a production setup, we recommend running the ParaTime compute/storage node separately from the validator node (if you run one)."),(0,r.kt)("p",{parentName:"admonition"},"Running ParaTime and validator nodes as separate Oasis nodes will prevent configuration mistakes and/or (security) issues affecting one node type from affecting the other one.")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you are looking for some concrete ParaTimes that you can run, see ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/run-node/paratime-node"},"the list of ParaTimes and their parameters"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Oasis Core refers to ParaTimes as runtimes internally, so all configuration options will have runtime in their name.")),(0,r.kt)("p",null,"This guide will cover setting up your ParaTime compute node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools."),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,r.kt)("a",{parentName:"p",href:"prerequisites"},"Prerequisites")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"Run a Non-validator Node")," sections and have:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Oasis Node binary installed and configured on your system."),(0,r.kt)("li",{parentName:"ul"},"The chosen top-level ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/")," working directory prepared. In addition to ",(0,r.kt)("inlineCode",{parentName:"li"},"etc")," and ",(0,r.kt)("inlineCode",{parentName:"li"},"data")," directories, also prepare the following directories:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"bin"),": This will store binaries needed by Oasis Node for running the ParaTimes."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"runtimes"),": This will store the ParaTime bundles.")))),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Feel free to name your working directory as you wish, e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"/srv/oasis/"),"."),(0,r.kt)("p",{parentName:"admonition"},"Just make sure to use the correct working directory path in the instructions below.")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Genesis file copied to ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/etc/genesis.json"),".")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Reading the rest of the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"validator node setup instructions")," may also be useful.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"To speed up bootstraping your new node, we recommend ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other"},"copying node's state from your existing node")," or ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/sync-node-using-state-sync"},"syncing it using state sync"),".")),(0,r.kt)("h3",{id:"stake-requirements"},"Stake Requirements"),(0,r.kt)("p",null,"To be able to register as a ParaTime node on the Oasis Network, you need to\nhave enough tokens staked in your entity's escrow account."),(0,r.kt)("p",null,"Current minimum staking requirements for a specific ParaTime are listed on the\nContribute to the Network section - ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/run-node/paratime-node"},"Run a ParaTime Node")," page. Should you want\nto check the staking requirements for other node roles and registered ParaTimes\nmanually, use the Oasis CLI tools as described in ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#show-native-token"},"Common Staking Info"),"."),(0,r.kt)("p",null,"Finally, to stake the tokens, use our ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#delegate"},"Oasis CLI tools"),". If everything was set\nup correctly, you should see something like below when running ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account#show"},"Oasis Node\nStake Account Info")," command for your entity's account (this is an example for\nthe Testnet):"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"Balance:\n Total: 0.0 TEST\n Available: 0.0 TEST\n\nActive Delegations to this Account:\n Total: 20000.0 TEST (20000000000000 shares)\n Delegations:\n - From: oasis1qrwdwxutpyr9d2m84zh55rzcf99aw0hkts7myvv9\n Amount: 20000.0 TEST (20000000000000 shares)\n\nStake Accumulator:\n Claims:\n - Name: registry.RegisterEntity\n Staking Thresholds:\n - Global: entity\n - Name: registry.RegisterNode.HG5TB3dbY8gtYBBw/R/cHfPaOpe0vT7W1wu/2rtpk/A=\n Staking Thresholds:\n - Global: node-compute\n Staking Thresholds:\n - Global: node-storage\n\nNonce: 1\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The stake requirements may differ from ParaTime to ParaTime and are subject to\nchange in the future.")),(0,r.kt)("h3",{id:"register-a-new-entity-or-update-your-entity-registration"},"Register a New Entity or Update Your Entity Registration"),(0,r.kt)("p",null,"If you don't have an entity yet, create a new one by following the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#creating-your-entity"},"Creating Your Entity")," instructions."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Everything in this section should be done on the ",(0,r.kt)("inlineCode",{parentName:"p"},"localhost")," as there are sensitive items that will be created.")),(0,r.kt)("p",null,"If you will be running the ParaTime on a new Oasis Node, initialize a new node by following the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#initializing-a-node"},"Initializing a Node")," instructions."),(0,r.kt)("p",null,"Then update your entity descriptor by enumerating paths to all your node's descriptors (existing and new ones) in the ",(0,r.kt)("inlineCode",{parentName:"p"},"--entity.node.descriptor")," flag. For example:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry entity update \\\n ... various signer flags ... \\\n --entity.node.descriptor /localhost/node1/node_genesis.json,/localhost/node2/node_genesis.json\n")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"To confirm all nodes are added to your entity descriptor, run:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cat \n")),(0,r.kt)("p",{parentName:"admonition"},"and ensure you see all your nodes' IDs under the ",(0,r.kt)("inlineCode",{parentName:"p"},'"nodes"')," list."),(0,r.kt)("p",{parentName:"admonition"},"For example:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'{\n "v": 2,\n "id": "QTg+ZjubD/36egwByAIGC6lMVBKgqo7xnZPgHVoIKzc=",\n "nodes": [\n "yT1h8/eN0VInQxn3YKcHxvSgGcsjsTSYmdTLZZMBTWI=",\n "HG5TB3dbY8gtYBBw/R/cHfPaOpe0vT7W1wu/2rtpk/A="\n ]\n}\n'))),(0,r.kt)("p",null,"Then generate and submit the new/updated entity descriptor via the entity registration transaction by following the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#generating-entity-registration-transaction"},"Generating Entity Registration Transaction")," instructions."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Make sure your entity descriptor (i.e. ",(0,r.kt)("inlineCode",{parentName:"p"},"entity.json"),") is copied to your online server and saved as ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/entity/entity.json")," to ensure the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#configuration"},"node's configuration")," will find it.")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"You will ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#configuration"},"configure the node")," to automatically register for the roles it has enabled (i.e. storage and compute roles) via the ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.registration.entity")," configuration flag."),(0,r.kt)("p",{parentName:"admonition"},"No manual node registration is necessary.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"ParaTime rewards for running the compute node will be sent to your entity address ",(0,r.kt)("strong",{parentName:"p"},"inside the ParaTime"),". To access the rewards on the consensus layer, you will need to withdraw them first. Read the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/account"},"Deposit/Withdraw Tokens to/from ParaTime")," chapter to learn more.")),(0,r.kt)("h3",{id:"the-paratime-bundle"},"The ParaTime Bundle"),(0,r.kt)("p",null,"In order to run a ParaTime node you need to obtain the ParaTime bundle that\nneeds to come from a trusted source. The bundle (usually with an ",(0,r.kt)("inlineCode",{parentName:"p"},".orc"),"\nextension that stands for Oasis Runtime Container) contains all the needed\nParaTime binaries together with the identifier and version metadata to ease\ndeployment."),(0,r.kt)("p",null,"When the ParaTime is running in a trusted execution environment (TEE) the bundle\nwill also contain all the required artifacts (e.g. SGXS version of the binary\nand any enclave signatures)."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"Like the genesis document, make sure you obtain these from a trusted source.")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("h4",{parentName:"admonition",id:"compiling-the-paratime-binary-from-source-code"},(0,r.kt)("strong",{parentName:"h4"},"Compiling the ParaTime Binary from Source Code")),(0,r.kt)("p",{parentName:"admonition"},"In case you decide to build the ParaTime binary from source yourself, make sure\nthat you follow our ",(0,r.kt)("a",{parentName:"p",href:"/paratime/reproducibility"},"guidelines for deterministic compilation"),"\nto ensure that you receive the exact same binary."),(0,r.kt)("p",{parentName:"admonition"},"When the ParaTime is running in a TEE, a different binary to what is registered\nin the consensus layer will not work and will be rejected by the network.")),(0,r.kt)("h3",{id:"install-oasis-core-runtime-loader"},"Install Oasis Core Runtime Loader"),(0,r.kt)("p",null,"For ParaTimes running inside ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#setting-up-trusted-execution-environment-tee"},"Intel SGX trusted execution environment"),", you will need to install the Oasis Core Runtime Loader."),(0,r.kt)("p",null,"The Oasis Core Runtime Loader binary (",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-core-runtime-loader"),") is part of Oasis Core binary releases, so make sure you download the appropriate version specified the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," page."),(0,r.kt)("p",null,"Install it to ",(0,r.kt)("inlineCode",{parentName:"p"},"bin")," subdirectory of your node's working directory, e.g. ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/bin/oasis-core-runtime-loader"),"."),(0,r.kt)("h3",{id:"install-paratime-bundle"},"Install ParaTime Bundle"),(0,r.kt)("p",null,"For each ParaTime, you need to obtain its bundle and install it to the\n",(0,r.kt)("inlineCode",{parentName:"p"},"runtimes")," subdirectory of your node's working directory."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For example, for the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/#cipher-paratime"},"Cipher ParaTime"),",\nyou would have to obtain the ",(0,r.kt)("inlineCode",{parentName:"p"},"cipher-paratime.orc")," bundle and install it to\n",(0,r.kt)("inlineCode",{parentName:"p"},"/node/runtimes/cipher-paratime.orc"),".")),(0,r.kt)("h3",{id:"install-bubblewrap-sandbox-at-least-version-033"},"Install Bubblewrap Sandbox (at least version 0.3.3)"),(0,r.kt)("p",null,"ParaTime compute nodes execute ParaTime binaries inside a sandboxed environment provided by ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/containers/bubblewrap"},"Bubblewrap"),". In order to install it, please follow these instructions, depending on your distribution:"),(0,r.kt)(s.Z,{mdxType:"Tabs"},(0,r.kt)(l.Z,{value:"Ubuntu 18.10+",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install bubblewrap\n"))),(0,r.kt)(l.Z,{value:"Fedora",mdxType:"TabItem"},(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo dnf install bubblewrap\n"))),(0,r.kt)(l.Z,{value:"Other Distributions",mdxType:"TabItem"},"On other systems, you can download the latest [source release provided by the Bubblewrap project](https://github.com/containers/bubblewrap/releases) and build it yourself.",(0,r.kt)("p",null,"Make sure you have the necessary development tools installed on your system and the ",(0,r.kt)("inlineCode",{parentName:"p"},"libcap")," development headers. On Ubuntu, you can install them with:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install build-essential libcap-dev\n")),(0,r.kt)("p",null,"After obtaining the Bubblewrap source tarball, e.g. ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/containers/bubblewrap/releases/download/v0.4.1/bubblewrap-0.4.1.tar.xz"},"bubblewrap-0.4.1.tar.xz"),", run:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"tar -xf bubblewrap-0.4.1.tar.xz\ncd bubblewrap-0.4.1\n./configure --prefix=/usr\nmake\nsudo make install\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Note that Oasis Node expects Bubblewrap to be installed under ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/bin/bwrap")," by default.")))),(0,r.kt)("p",null,"Ensure you have a new enough version by running:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"bwrap --version\n")),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Ubuntu 18.04 LTS (and earlier) provide overly-old ",(0,r.kt)("inlineCode",{parentName:"p"},"bubblewrap"),". Follow ",(0,r.kt)("em",{parentName:"p"},"Other Distributions")," section on those systems.")),(0,r.kt)("h3",{id:"setting-up-trusted-execution-environment-tee"},"Setting up Trusted Execution Environment (TEE)"),(0,r.kt)("p",null,"If a ParaTime requires the use of a TEE, then make sure you set up TEE as instructed in the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"},"Set up trusted execution environment (TEE)")," doc."),(0,r.kt)("h2",{id:"configuration"},"Configuration"),(0,r.kt)("p",null,"In order to configure the node create the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc/config.yml")," file with the following content:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'datadir: /node/data\n\nlog:\n level:\n default: info\n tendermint: info\n tendermint/context: error\n format: JSON\n\ngenesis:\n file: /node/etc/genesis.json\n\nconsensus:\n tendermint:\n core:\n listen_address: tcp://0.0.0.0:26656\n\n # The external IP that is used when registering this node to the network.\n # NOTE: If you are using the Sentry node setup, this option should be\n # omitted.\n external_address: tcp://{{ external_address }}:26656\n\n p2p:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n seed:\n - "{{ seed_node_address }}"\n\nruntime:\n mode: compute\n paths:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n - "{{ runtime_orc_path }}"\n\n # The following section is required for ParaTimes which are running inside the\n # Intel SGX Trusted Execution Environment.\n sgx:\n loader: /node/bin/oasis-core-runtime-loader\n\nworker:\n registration:\n # In order for the node to register itself, the entity.json of the entity\n # used to provision the node must be available on the node.\n entity: /node/entity/entity.json\n\n p2p:\n # External P2P configuration.\n port: 30002\n addresses:\n # The external IP that is used when registering this node to the network.\n - "{{ external_address }}:30002"\n\n# The following section is required for ParaTimes which are running inside the\n# Intel SGX Trusted Execution Environment.\nias:\n proxy:\n address:\n # List of IAS proxies to connect to.\n # NOTE: You can add additional IAS proxies to this list if you want.\n - "{{ ias_proxy_address }}"\n')),(0,r.kt)("p",null,"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ external_address }}"),": The external IP you used when registering this node."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ seed_node_address }}"),": The seed node address in the form ",(0,r.kt)("inlineCode",{parentName:"li"},"ID@IP:port"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"You can find the current Oasis Seed Node address in the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/"},"Network Parameters"),"."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ runtime_orc_path }}"),": Path to the ",(0,r.kt)("a",{parentName:"li",href:"/node/run-your-node/paratime-node#the-paratime-bundle"},"ParaTime bundle")," of the form ",(0,r.kt)("inlineCode",{parentName:"li"},"/node/runtimes/foo-paratime.orc"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"You can find the current Oasis-supported ParaTimes in the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/#paratimes"},"Network Paramers"),"."))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"{{ ias_proxy_address }}"),": The IAS proxy address in the form ",(0,r.kt)("inlineCode",{parentName:"li"},"ID@HOST:port"),".",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"You can find the current Oasis IAS proxy address in the ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/#cipher-paratime"},"Network Parameters"),"."),(0,r.kt)("li",{parentName:"ul"},"If you want, you can also ",(0,r.kt)("a",{parentName:"li",href:"/node/run-your-node/ias-proxy"},"run your own IAS proxy"),".")))),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Make sure the ",(0,r.kt)("inlineCode",{parentName:"p"},"worker.p2p.port")," (default: ",(0,r.kt)("inlineCode",{parentName:"p"},"9200"),") port is exposed and publicly\naccessible on the internet (for ",(0,r.kt)("inlineCode",{parentName:"p"},"TCP")," traffic).")),(0,r.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,r.kt)("p",null,"You can start the node by running the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,r.kt)("h2",{id:"checking-node-status"},"Checking Node Status"),(0,r.kt)("p",null,"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/node/data/internal.sock\n")),(0,r.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,r.kt)("p",null,"See the general ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/troubleshooting"},"Node troubleshooting")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#troubleshooting"},"Set up TEE troubleshooting")," sections before proceeding with ParaTime node-specific troubleshooting."),(0,r.kt)("h3",{id:"too-old-bubblewrap-version"},"Too Old Bubblewrap Version"),(0,r.kt)("p",null,"Double check your installed ",(0,r.kt)("inlineCode",{parentName:"p"},"bubblewrap")," version, and ensure is at least of version ",(0,r.kt)("strong",{parentName:"p"},"0.3.3"),". For details see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#install-bubblewrap-sandbox-at-least-version-0-3-3"},"Install Bubblewrap Sandbox")," section."),(0,r.kt)("h3",{id:"bubblewrap-sandbox-fails-to-start"},"Bubblewrap Sandbox Fails to Start"),(0,r.kt)("p",null,"If the environment in which you are running the ParaTime node applies too restricted Seccomp or AppArmor profiles, the Bubblewrap sandbox that isolates each runtime may fail to start. In the logs you will see how the runtime attempts to restart, but fails with an ",(0,r.kt)("inlineCode",{parentName:"p"},"bwrap")," error, like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{"level":"warn","module":"runtime","msg":"bwrap: Failed to mount tmpfs: Permission denied","runtime_id":"000000000000000000000000000000000000000000000000f80306c9858e7279","runtime_name":"sapphire-paratime","ts":"2023-03-06T10:08:51.983330021Z"}\n')),(0,r.kt)("p",null,"In case of ",(0,r.kt)("inlineCode",{parentName:"p"},"bwrap")," issues you need to adjust your Seccomp or AppArmor profiles to support Bubblewrap sandboxes. In Docker you can set or disable Seccomp and AppArmor profiles with parameters:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"}," --security-opt apparmor=unconfined \\\n --security-opt seccomp=unconfined \\\n")),(0,r.kt)("h3",{id:"stake-requirement"},"Stake Requirement"),(0,r.kt)("p",null,"Double check your node entity satisfies the staking requirements for a ParaTime node. For details see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node#stake-requirements"},"Stake Requirements")," section."),(0,r.kt)("h2",{id:"see-also"},"See also"),(0,r.kt)(o.Z,{item:(0,i.n)("/node/web3"),mdxType:"DocCard"}))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/c41a84e2.a4749928.js b/assets/js/c41a84e2.a4749928.js new file mode 100644 index 0000000000..a0ce9f6ddc --- /dev/null +++ b/assets/js/c41a84e2.a4749928.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7990],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=i.createContext({}),c=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},m=function(e){var t=c(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},u=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,s=e.originalType,l=e.parentName,m=r(e,["components","mdxType","originalType","parentName"]),d=c(n),u=a,h=d["".concat(l,".").concat(u)]||d[u]||p[u]||s;return n?i.createElement(h,o(o({ref:t},m),{},{components:n})):i.createElement(h,o({ref:t},m))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var s=n.length,o=new Array(s);o[0]=u;var r={};for(var l in t)hasOwnProperty.call(t,l)&&(r[l]=t[l]);r.originalType=e,r[d]="string"==typeof e?e:a,o[1]=r;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var i=n(7462),a=(n(7294),n(3905));const s={},o="Runtime Layer",r={unversionedId:"core/runtime/README",id:"core/runtime/README",title:"Runtime Layer",description:"Runtime Layer",source:"@site/docs/core/runtime/README.md",sourceDirName:"core/runtime",slug:"/core/runtime/",permalink:"/core/runtime/",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/README.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Transaction Test Vectors",permalink:"/core/consensus/test-vectors"},next:{title:"Runtime Host Protocol",permalink:"/core/runtime/runtime-host-protocol"}},l={},c=[{value:"Runtimes",id:"runtimes",level:2},{value:"Operation Model",id:"operation-model",level:2},{value:"Discrepancy Detection and Resolution",id:"discrepancy-detection-and-resolution",level:3},{value:"Compute Committee Roles and Commitments",id:"compute-committee-roles-and-commitments",level:3},{value:"Storage Receipts",id:"storage-receipts",level:3},{value:"Suspending Runtimes",id:"suspending-runtimes",level:3},{value:"Emitting Messages",id:"emitting-messages",level:3}],m={toc:c},d="wrapper";function p(e){let{components:t,...s}=e;return(0,a.kt)(d,(0,i.Z)({},m,s,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"runtime-layer"},"Runtime Layer"),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Runtime Layer",src:n(1475).Z,width:"578",height:"342"})),(0,a.kt)("p",null,"The Oasis Core runtime layer enables independent ",(0,a.kt)("em",{parentName:"p"},"runtimes")," to schedule and\nexecute stateful computations and commit result summaries to the\n",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer"),". In addition to ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"verifying and storing")," the canonical runtime\nstate summaries the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer")," also serves as the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/registry"},"registry")," for node and\nruntime metadata, a ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/scheduler"},"scheduler")," that elects runtime compute committees and a\ncoordinator for ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/keymanager"},"key manager replication"),"."),(0,a.kt)("h2",{id:"runtimes"},"Runtimes"),(0,a.kt)("p",null,"A ",(0,a.kt)("em",{parentName:"p"},"runtime")," is effectively a replicated application with shared state. The\napplication can receive transactions from clients and based on those it can\nperform arbitrary state mutations. This replicated state and application logic\nexists completely separate from the consensus layer state and logic, but it\nleverages the same consensus layer for finality with the consensus layer\nproviding the source of canonical state. Multiple runtimes can share the same\nconsensus layer."),(0,a.kt)("p",null,"In Oasis Core a runtime can be any executable that speaks the\n",(0,a.kt)("a",{parentName:"p",href:"/core/runtime/runtime-host-protocol"},"Runtime Host Protocol")," which is used to communicate between a runtime and an\nOasis Core Node. The executable usually runs in a sandboxed environment with\nthe only external interface being the Runtime Host Protocol. The execution\nenvironment currently includes a sandbox based on Linux namespaces and SECCOMP\noptionally combined with Intel SGX enclaves for confidential computation."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Runtime Execution",src:n(5819).Z,width:"381",height:"161"})),(0,a.kt)("p",null,"In the future this may be expanded with supporting running each runtime in its\nown virtual machine and with other confidential computing technologies."),(0,a.kt)("h2",{id:"operation-model"},"Operation Model"),(0,a.kt)("p",null,"The relationship between ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer services"),' and runtime services is best\ndescribed by a simple example of a "Runtime A" that is created and receives\ntransactions from clients (also see the figure above for an overview).'),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"The runtime first needs to be created. In addition to developing code that\nwill run in the runtime itself, we also need to specify some metadata related\nto runtime operation, including a unique ",(0,a.kt)("a",{parentName:"p",href:"/core/runtime/identifiers"},"runtime identifier"),", and then\n",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#register-runtime"},"register the runtime"),".")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"We also need some nodes that will actually run the runtime executable and\nprocess any transactions from clients (compute nodes). These nodes currently\nneed to have the executable available locally and must be configured as\ncompute nodes.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"In addition to compute nodes a runtime also needs storage nodes to store its\nstate.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Both kinds of ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/registry#register-node"},"nodes will register")," on the consensus layer announcing their\nwillingness to participate in the operation of Runtime A.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"After an ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/epochtime"},"epoch transition")," the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/scheduler"},"committee scheduler")," service will elect\nregistered compute and storage nodes into different committees based on role.\nElections are randomized based on entropy provided by the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/beacon"},"random beacon"),".")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"A client may submit transactions by querying the consensus layer to get the\ncurrent executor committee for a given runtime, connect to it, publish\ntransactions and wait for finalization by the consensus layer. In order to\nmake it easier to write clients, the Oasis Node exposes a runtime\n",(0,a.kt)("a",{parentName:"p",href:"/core/oasis-node/rpc"},"client RPC API")," that encapsulates all this functionality in a ",(0,a.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/client/api?tab=doc#RuntimeClient.SubmitTx"},(0,a.kt)("inlineCode",{parentName:"a"},"SubmitTx")),"\ncall.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"The transactions are batched and proceed through the transaction processing\npipeline. At the end, results are persisted to storage and the\n",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"roothash service")," in the consensus layer finalizes state after verifying\nthat computation was performed correctly and state was correctly persisted.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"The compute nodes are ready to accept the next batch and the process can\nrepeat from step 6."))),(0,a.kt)("p",null,"Note that the above example describes the ",(0,a.kt)("em",{parentName:"p"},"happy path"),", a scenario where there\nare no failures. Described steps mention things like verifying that computation\nwas performed ",(0,a.kt)("em",{parentName:"p"},"correctly")," and that state was ",(0,a.kt)("em",{parentName:"p"},"correctly stored"),". How does the\nconsensus layer actually know that?"),(0,a.kt)("h3",{id:"discrepancy-detection-and-resolution"},"Discrepancy Detection and Resolution"),(0,a.kt)("p",null,"The key idea behind ensuring integrity of runtime computations is replicated\ncomputation with discrepancy detection. This basically means that any\ncomputation (e.g., execution of a transaction) is replicated among multiple\ncompute nodes. They all execute the exact same functions and produce results,\nwhich must all match. If they don't (e.g., if even a single node produces\ndifferent results), this is treated as a discrepancy."),(0,a.kt)("p",null,"In case of a discrepancy, the computation must be repeated using a separate\nlarger compute committee which decides what the correct results were. Since all\ncommitments are attributable to compute nodes, any node(s) that produced\nincorrect results may be subject to having their stake slashed and may be\nremoved from future committees."),(0,a.kt)("p",null,"Given the above, an additional constraint with replicated runtimes is that they\nmust be fully deterministic, meaning that a computation operating on the same\ninitial state executing the same inputs (transactions) must always produce the\nsame outputs and new state. In case a runtime's execution exhibits\nnon-determinism this will manifest itself as discrepancies since nodes will\nderive different results when replicating computation."),(0,a.kt)("h3",{id:"compute-committee-roles-and-commitments"},"Compute Committee Roles and Commitments"),(0,a.kt)("p",null,"A compute node can be elected into an executor committee and may have one of the\nfollowing roles:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Primary executor node. At any given round a single node is selected among all\nthe primary executor nodes to be a ",(0,a.kt)("em",{parentName:"li"},"transaction scheduler node")," (roughly equal\nto the role of a ",(0,a.kt)("em",{parentName:"li"},"block proposer"),")."),(0,a.kt)("li",{parentName:"ul"},"Backup executor node. Backup nodes can be activated by the consensus layer in\ncase it determines that there is a discrepancy.")),(0,a.kt)("p",null,"The size of the primary and backup executor committees, together with other\nrelated parameters, can be configured on a per-runtime basis. The ",(0,a.kt)("em",{parentName:"p"},"primary"),"\nnodes are the ones that will batch incoming transactions into blocks and execute\nthe state transitions to derive the new state root. They perform this in a\nreplicated fashion where all the primary executor nodes execute the same inputs\n(transactions) on the same initial state."),(0,a.kt)("p",null,"After execution they will sign ",(0,a.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api/commitment?tab=doc"},"cryptographic commitments")," specifying the\ninputs, the initial state, the outputs and the resulting state. In case\ncomputation happens inside a trusted execution environment (TEE) like Intel SGX,\nthe commitment will also include a platform attestation proving that the\ncomputation took place in a given TEE."),(0,a.kt)("p",null,"The ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"roothash service")," in the consensus layer will collect commitments and\nverify that all nodes have indeed computed the same result. As mentioned in case\nof discrepancies it will instruct nodes elected as ",(0,a.kt)("em",{parentName:"p"},"backups")," to repeat the\ncomputation."),(0,a.kt)("h3",{id:"storage-receipts"},"Storage Receipts"),(0,a.kt)("p",null,"All runtime persistent state is stored by storage nodes. These provide a\n",(0,a.kt)("a",{parentName:"p",href:"/core/mkvs"},"Merklized Key-Value Store (MKVS)")," to compute nodes. The MKVS stores immutable\nstate cryptographically summarized by a single root hash. When a storage node\nstores a given state update, it signs a receipt stating that it is storing a\nspecific root. These receipts are verified by the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash"},"roothash service")," before\naccepting a commitment from a compute node."),(0,a.kt)("h3",{id:"suspending-runtimes"},"Suspending Runtimes"),(0,a.kt)("p",null,"Since periodic maintenance work must be performed on each epoch transition\n(e.g., electing runtime committees), fees for that maintenance are paid by any\nnodes that register to perform work for a specific runtime. Fees are pre-paid\nfor the number of epochs a node registers for. If there are no committees for a\nruntime on epoch transition, the runtime is suspended for the epoch.\nThe runtime is also suspended in case the registering entity no longer has\nenough stake to cover the entity and runtime deposits. The runtime will be\nresumed on the epoch transition if runtime nodes will register and the\nregistering entity will have enough stake."),(0,a.kt)("h3",{id:"emitting-messages"},"Emitting Messages"),(0,a.kt)("p",null,"Runtimes may ",(0,a.kt)("a",{parentName:"p",href:"/core/runtime/messages"},"emit messages")," to instruct the consensus layer what to do on their\nbehalf. This makes it possible for runtimes to ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#runtime-accounts"},"own staking accounts"),"."))}p.isMDXComponent=!0},1475:(e,t,n)=>{n.d(t,{Z:()=>i});const i=n.p+"assets/images/oasis-core-runtime-details-4fefa00801807028812dc6d3900d2a38.svg"},5819:(e,t,n)=>{n.d(t,{Z:()=>i});const i="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIzODFweCIgaGVpZ2h0PSIxNjFweCIgdmlld0JveD0iLTAuNSAtMC41IDM4MSAxNjEiIGNvbnRlbnQ9IiZsdDtteGZpbGUgaG9zdD0mcXVvdDthcHAuZGlhZ3JhbXMubmV0JnF1b3Q7IG1vZGlmaWVkPSZxdW90OzIwMjAtMDctMjBUMjI6MDM6NTIuNjAzWiZxdW90OyBhZ2VudD0mcXVvdDs1LjAgKE1hY2ludG9zaDsgSW50ZWwgTWFjIE9TIFggMTBfMTRfNikgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzg0LjAuNDE0Ny44OSBTYWZhcmkvNTM3LjM2JnF1b3Q7IGV0YWc9JnF1b3Q7anZjbC1DYkd2THY0c3JRQmhkRjcmcXVvdDsgdmVyc2lvbj0mcXVvdDsxMy40LjkmcXVvdDsgdHlwZT0mcXVvdDtkZXZpY2UmcXVvdDsmZ3Q7Jmx0O2RpYWdyYW0gaWQ9JnF1b3Q7REpYWk9tNWJmMmRqOFNFSVE4Sl8mcXVvdDsgbmFtZT0mcXVvdDtQYWdlLTEmcXVvdDsmZ3Q7N1pmTGNwc3dGSWFmeGpQdEloMHU1dEpsZkVuU1R0cVoxcDFwMHAyTURxQkVTSzRRQWZmcEs5bkNnQ0ZPTWdsZGRXTnpmdDIvLzNCc1RkeDVWbDBLdEVtL2NBeDA0bGk0bXJpTGllUFlkdWlyTDYxczkwb1F1SHNoRVFTYlRvMndJbi9BaUpaUkM0SWg3M1NVbkZOSk5sMHg0b3hCSkRzYUVvS1gzVzR4cDkxVk55aUJuckNLRU8yclB3bVc2VjROUGF2UnI0QWthYjJ5YlptV0ROV2RqWkNuQ1BPeUpibkxpVHNYbk12OVUxYk5nV3A0TlpmOXVJdEhXZzhiRThEa2N3YUVpK25zbnBibDR0ZnRqODkwL3UyT2lPVE16UEtBYUdFTy9GVlpPSEY4cXVhY3JZWGV0OXdhR1A3dlFtOTJGbk1tei9LZFZlZXFnKzFzcXFaUlBTWDYrOTMzZ2ttU3FibXNLNTdMOXdiQ1lUSkg4SUpoMEp1elZmY3lKUkpXR3hUcDFsTGxrdEpTbVZIVHJKYzB5V0U3T2lhVXpqbmxZamVYRzhleEUwVkt6NlhnOTlCcXdmN2E5L3pkdm81eDFXY0hJYUZxU1FiZkpmQU1wTmlxTHFiVk5VNmFWTFlkYngrWFRXTFl0ZHRwS3lsOG95R1RpOGxoNXNZdTlXQWNlNEY3VHMrOUU1U3QxMU1PSXhpbXZBNjlxYWNYd0NoUEQ1NitBWExINmpLdlViYVFIMHBGRzdrOUhZdTUyMk8rUWd5dmVkVkRyNDRvdTN5NzNCaG5jQVRaU0lpU2hLa3dVdUJBNlRNTmpLaWlkRzRhTW9LeFhtYlEwSzdsSFVkNkJ1dlk3SGlnb0x6YXJ1a3o3WExHY212YWM2c3BTOWNjWVVWMzFEZm1uOVNsQTlMNk43WlAzZjQ0UU4wZGk3bzNjbDNxNW5RWE9kallnMkFJK1VjL2NORkl5QTkxL3lubXdWak0vUjd6VDZwNDZHR3J5eHYxdVdRUlJRL3d2MG9ObUdjOTA3elJ5bFJ3b2t6TkNFTm1pYkhLRkVZUXhvTmx5bzlDV01kdjlNNDRSOWpkQWV6QkFIWnZMT3hoanlwZzllL2ZoRnpJbENlY0licHMxS084YmZwY2M3NHh0TzlBeXEzQmpRckp1MTVBUmVSTjYvbFdUL1hCTTlHaU1qUHZnbTBkTUhYY20zYlFHcVhEWnRndXFzY2QrNTVMSk9TNXZoYnA5NWFpUENkUkxWOFFXbS94VWJOelhvZ0lUaEN0cjJoSUpDQ2ZUbmlOKzJUcUNLQklrb2Z1WmV3RmVhREM1b2ExYTJ2ZFU5M2xYdz09Jmx0Oy9kaWFncmFtJmd0OyZsdDsvbXhmaWxlJmd0OyI+PGRlZnMvPjxnPjxyZWN0IHg9IjAiIHk9Ijg1IiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjYwIiByeD0iOSIgcnk9IjkiIGZpbGw9IiNmZmYyY2MiIHN0cm9rZT0iI2Q2YjY1NiIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMThweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMTVweDsgbWFyZ2luLWxlZnQ6IDFweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogY2VudGVyOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+Tm9kZTxiciBzdHlsZT0iZm9udC1zaXplOiAxMnB4IiAvPihSdW50aW1lIEhvc3QpPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYwIiB5PSIxMTkiIGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+Tm9kZS4uLjwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTcwIiB5PSIyMCIgd2lkdGg9IjIxMCIgaGVpZ2h0PSIxNDAiIGZpbGw9IiNmOGNlY2MiIHN0cm9rZT0iI2I4NTQ1MCIgc3Ryb2tlLWRhc2hhcnJheT0iMyAzIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PHJlY3QgeD0iMTcwIiB5PSIwIiB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMjA4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTBweDsgbWFyZ2luLWxlZnQ6IDE3MXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyBmb250LXdlaWdodDogYm9sZDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+U2FuZGJveDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9IjE0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSJib2xkIj5TYW5kYm94PC90ZXh0Pjwvc3dpdGNoPjwvZz48cmVjdCB4PSIxODAiIHk9IjMwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjMwIiBmaWxsPSIjZmZmMmNjIiBzdHJva2U9IiNkNmI2NTYiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMTg4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNDVweDsgbWFyZ2luLWxlZnQ6IDE4MXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5SdW50aW1lIExvYWRlcjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9IjQ5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlJ1bnRpbWUgTG9hZGVyPC90ZXh0Pjwvc3dpdGNoPjwvZz48cmVjdCB4PSIxODAiIHk9IjgwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjcwIiBmaWxsPSIjZTFkNWU3IiBzdHJva2U9IiM5NjczYTYiIHN0cm9rZS1kYXNoYXJyYXk9IjMgMyIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxyZWN0IHg9IjE4MCIgeT0iNjAiIHdpZHRoPSIxOTAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxODhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA3MHB4OyBtYXJnaW4tbGVmdDogMTgxcHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGNlbnRlcjsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IGZvbnQtd2VpZ2h0OiBib2xkOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5JbnRlbCBTR1ggRW5jbGF2ZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIyNzUiIHk9Ijc0IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtd2VpZ2h0PSJib2xkIj5JbnRlbCBTR1ggRW5jbGF2ZTwvdGV4dD48L3N3aXRjaD48L2c+PHJlY3QgeD0iMTkwIiB5PSI5MCIgd2lkdGg9IjE3MCIgaGVpZ2h0PSI1MCIgZmlsbD0iI2RhZThmYyIgc3Ryb2tlPSIjNmM4ZWJmIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDE2OHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDExNXB4OyBtYXJnaW4tbGVmdDogMTkxcHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGNlbnRlcjsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPlJ1bnRpbWUgQmluYXJ5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjI3NSIgeT0iMTE5IiBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0iSGVsdmV0aWNhIiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlJ1bnRpbWUgQmluYXJ5PC90ZXh0Pjwvc3dpdGNoPjwvZz48cGF0aCBkPSJNIDEyNi4zNyAxMTUgTCAxODMuNjMgMTE1IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxwYXRoIGQ9Ik0gMTIxLjEyIDExNSBMIDEyOC4xMiAxMTEuNSBMIDEyNi4zNyAxMTUgTCAxMjguMTIgMTE4LjUgWiIgZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48cGF0aCBkPSJNIDE4OC44OCAxMTUgTCAxODEuODggMTE4LjUgTCAxODMuNjMgMTE1IEwgMTgxLjg4IDExMS41IFoiIGZpbGw9IiMwMDAwMDAiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxzd2l0Y2g+PGcgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ii8+PGEgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtNSkiIHhsaW5rOmhyZWY9Imh0dHBzOi8vZGVzay5kcmF3LmlvL3N1cHBvcnQvc29sdXRpb25zL2FydGljbGVzLzE2MDAwMDQyNDg3IiB0YXJnZXQ9Il9ibGFuayI+PHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1zaXplPSIxMHB4IiB4PSI1MCUiIHk9IjEwMCUiPlZpZXdlciBkb2VzIG5vdCBzdXBwb3J0IGZ1bGwgU1ZHIDEuMTwvdGV4dD48L2E+PC9zd2l0Y2g+PC9zdmc+"}}]); \ No newline at end of file diff --git a/assets/js/c74bdc2d.6e85b943.js b/assets/js/c74bdc2d.6e85b943.js new file mode 100644 index 0000000000..fd18f4441e --- /dev/null +++ b/assets/js/c74bdc2d.6e85b943.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6684],{3905:(e,t,n)=>{n.d(t,{Zo:()=>l,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var d=r.createContext({}),c=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},l=function(e){var t=c(e.components);return r.createElement(d.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,d=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),p=c(n),m=a,g=p["".concat(d,".").concat(m)]||p[m]||u[m]||o;return n?r.createElement(g,i(i({ref:t},l),{},{components:n})):r.createElement(g,i({ref:t},l))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var d in t)hasOwnProperty.call(t,d)&&(s[d]=t[d]);s.originalType=e,s[p]="string"==typeof e?e:a,i[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const o={},i="Obtaining Account Address",s={unversionedId:"oasis-core-ledger/usage/address",id:"oasis-core-ledger/usage/address",title:"Obtaining Account Address",description:"Before following the instructions below, make sure your Ledger wallet is",source:"@site/docs/oasis-core-ledger/usage/address.md",sourceDirName:"oasis-core-ledger/usage",slug:"/oasis-core-ledger/usage/address",permalink:"/oasis-core-ledger/usage/address",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/usage/address.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Setup",permalink:"/oasis-core-ledger/usage/setup"},next:{title:"Exporting Public Key to Entity",permalink:"/oasis-core-ledger/usage/entity"}},d={},c=[],l={toc:c},p="wrapper";function u(e){let{components:t,...n}=e;return(0,a.kt)(p,(0,r.Z)({},l,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"obtaining-account-address"},"Obtaining Account Address"),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"Before following the instructions below, make sure your Ledger wallet is\nunlocked and the Oasis App is open.")),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"While the Oasis App is available in ",(0,a.kt)("em",{parentName:"p"},"Developer mode"),', opening the App brings\nup the "Pending Ledger review" screen.\nYou need to press both buttons at once to close that screen and transition to\nthe ',(0,a.kt)("em",{parentName:"p"},"ordinary"),' "Oasis Ready" screen where the Oasis App is ready to be used.')),(0,a.kt)("p",null,"Each account on your Ledger wallet has a corresponding\n",(0,a.kt)("a",{parentName:"p",href:"/general/manage-tokens/terminology#address"},"staking account address"),"."),(0,a.kt)("p",null,"To obtain a staking account address that corresponds to the account with index\n0 on your Ledger wallet, use:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-core-ledger show_address\n")),(0,a.kt)("p",null,"This will display your wallet's address and show it on your Ledger's screen for\nconfirmation."),(0,a.kt)("p",null,"To skip showing your wallet's address on your Ledger's screen, pass the\n",(0,a.kt)("inlineCode",{parentName:"p"},"--skip-device")," flag in the command above."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"In case you will have more than one Ledger wallet connected, you'll need to\nspecify which wallet to use by passing the ",(0,a.kt)("inlineCode",{parentName:"p"},"--wallet_id ")," flag\nto the command above, replacing ",(0,a.kt)("inlineCode",{parentName:"p"},"")," with the ID of your Ledger\nwallet.\nSee ",(0,a.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/wallets"},"Identifying Wallets")," for more details.")),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"You can obtain as many staking account addresses as needed for the same Ledger\nwallet by passing the ",(0,a.kt)("inlineCode",{parentName:"p"},"--index")," flag and specifying a different account index in\nthe command above."),(0,a.kt)("p",{parentName:"admonition"},"Account index specifies the ",(0,a.kt)("inlineCode",{parentName:"p"},"address_index")," part of the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki"},"BIP32")," path conforming\nto the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki"},"BIP44")," specification.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/c800e6d8.bc9214f5.js b/assets/js/c800e6d8.bc9214f5.js new file mode 100644 index 0000000000..ec10243135 --- /dev/null +++ b/assets/js/c800e6d8.bc9214f5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7383],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>d});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var s=n.createContext({}),p=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},c=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},m="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),m=p(a),u=r,d=m["".concat(s,".").concat(u)]||m[u]||h[u]||i;return a?n.createElement(d,l(l({ref:t},c),{},{components:a})):n.createElement(d,l({ref:t},c))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,l=new Array(i);l[0]=u;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[m]="string"==typeof e?e:r,l[1]=o;for(var p=2;p{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>p});var n=a(7462),r=(a(7294),a(3905));const i={},l="ADR 0022: Forward-Secret Master Secrets",o={unversionedId:"adrs/0022-keymanager-master-secrets",id:"adrs/0022-keymanager-master-secrets",title:"ADR 0022: Forward-Secret Master Secrets",description:"Component",source:"@site/docs/adrs/0022-keymanager-master-secrets.md",sourceDirName:"adrs",slug:"/adrs/0022-keymanager-master-secrets",permalink:"/adrs/0022-keymanager-master-secrets",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0022-keymanager-master-secrets.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0021: Forward-Secret Ephemeral Secrets",permalink:"/adrs/0021-keymanager-ephemeral-secrets"}},s={},p=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Key manager status",id:"key-manager-status",level:3},{value:"Enclave init response",id:"enclave-init-response",level:3},{value:"Master secrets",id:"master-secrets",level:3},{value:"Checksums",id:"checksums",level:3},{value:"Master secret transaction",id:"master-secret-transaction",level:3},{value:"Setup",id:"setup",level:3},{value:"Generation",id:"generation",level:3},{value:"Replication",id:"replication",level:3},{value:"Rotation",id:"rotation",level:3},{value:"Confirmation",id:"confirmation",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3}],c={toc:p},m="wrapper";function h(e){let{components:t,...a}=e;return(0,r.kt)(m,(0,n.Z)({},c,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"adr-0022-forward-secret-master-secrets"},"ADR 0022: Forward-Secret Master Secrets"),(0,r.kt)("h2",{id:"component"},"Component"),(0,r.kt)("p",null,"Oasis Core"),(0,r.kt)("h2",{id:"changelog"},"Changelog"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"2023-04-17: Initial proposal")),(0,r.kt)("h2",{id:"status"},"Status"),(0,r.kt)("p",null,"Proposed"),(0,r.kt)("h2",{id:"context"},"Context"),(0,r.kt)("p",null,"The network needs forward-secret master secrets that are generated periodically\nand distributed amongst enclave executors."),(0,r.kt)("h2",{id:"decision"},"Decision"),(0,r.kt)("h3",{id:"key-manager-status"},"Key manager status"),(0,r.kt)("p",null,"Key manager status will be extended with the following fields:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'type Status struct {\n ...\n\n // Generation is the generation of the latest master secret.\n Generation uint64 `json:"generation,omitempty"`\n\n // RotationEpoch is the epoch of the last master secret rotation.\n RotationEpoch beacon.EpochTime `json:"rotation_epoch,omitempty"`\n}\n')),(0,r.kt)("h3",{id:"enclave-init-response"},"Enclave init response"),(0,r.kt)("p",null,"Key manager enclave init response will be extended with the following fields:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'type InitResponse struct {\n ...\n \n NextChecksum []byte `json:"next_checksum,omitempty"`\n NextRSK *signature.PublicKey `json:"next_rsk,omitempty"`\n}\n')),(0,r.kt)("h3",{id:"master-secrets"},"Master secrets"),(0,r.kt)("p",null,"The key manager enclave will gain the following additional local RPC methods:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'const (\n GenerateMasterSecret = "generate_master_secret"\n LoadMasterSecret = "load_master_secret"\n)\n\ntype GenerateMasterSecretRequest struct {\n Generation uint64 `json:"generation"`\n Epoch beacon.EpochTime `json:"epoch"`\n}\n\ntype GenerateMasterSecretResponse struct {\n SignedSecret SignedEncryptedMasterSecret `json:"signed_secret"`\n}\n\ntype LoadMasterSecretRequest struct {\n SignedSecret SignedEncryptedMasterSecret `json:"signed_secret"`\n}\n\n')),(0,r.kt)("p",null,"Remote RPC method for replicating master secret will be extended to support\nreplication of generations and to return a Merkle proof for secret verification."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"pub struct ReplicateMasterSecretRequest {\n ...\n\n /// Generation.\n #[cbor(optional)]\n pub generation: u64,\n}\n\npub struct ReplicateMasterSecretResponse {\n ... \n\n /// Checksum of the preceding master secret.\n #[cbor(optional)]\n pub checksum: Vec,\n}\n")),(0,r.kt)("p",null,"Master secret generation will return a signed and encrypted master secret\nfor the requested generation and epoch."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'type EncryptedMasterSecret struct {\n // ID is the runtime ID of the key manager.\n ID common.Namespace `json:"runtime_id"`\n\n // Generation is the generation of the secret.\n Generation uint64 `json:"generation"`\n\n // Epoch is the epoch in which the secret was created.\n Epoch beacon.EpochTime `json:"epoch"`\n\n // Secret is the encrypted secret.\n Secret EncryptedSecret `json:"secret"`\n}\n\ntype SignedEncryptedMasterSecret struct {\n // Secret is the encrypted master secret.\n Secret EncryptedMasterSecret `json:"secret"`\n\n // Signature is a signature of the master secret.\n Signature signature.RawSignature `json:"signature"`\n}\n')),(0,r.kt)("h3",{id:"checksums"},"Checksums"),(0,r.kt)("p",null,"Checksum computation will be extended with hash chains:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"checksum_0 = KMAC(generation_0, runtime_id)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"checksum_N = KMAC(generation_N, checksum_(N-1)) for N > 0"))),(0,r.kt)("p",null,"Hash chains allow us to use the previous checksum as a Merkle proof.\nGiven a verified checksum and a proof, a master secret can be verified\nusing the following formula:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"next_checksum = KMAC(secret, prev_checksum)"))),(0,r.kt)("h3",{id:"master-secret-transaction"},"Master secret transaction"),(0,r.kt)("p",null,"Key manager application will be augmented with a ",(0,r.kt)("inlineCode",{parentName:"p"},"PublishMasterSecret"),"\ntransaction which will accept the proposal for the next generation of the master\nsecret if the following conditions are met:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The proposal's master secret generation number is one greater than the last\naccepted generation, or 0 if no secrets have been accepted so far.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The proposal is intended to be accepted in the upcoming epoch.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Master secret hasn't been proposed in the current epoch.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The rotation period will either expire in the upcoming epoch or has already\nexpired."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The first master secret (generation 0) can be proposed immediately and even\nif the rotation interval is set to 0.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"If the rotation interval is set to 0, rotations are disabled and secrets\ncannot be proposed anymore. To enable them again, update the rotation\ninterval in the policy.")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The master secret is encrypted to the majority of the enclaves that form\nthe committee.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The node proposing the secret is a member of the key manager committee."))),(0,r.kt)("p",null,"If accepted, the next secret can be proposed after the rotation interval\nexpires. Otherwise, the next secret can be proposed in the next epoch."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'MethodPublishMasterSecret = transaction.NewMethodName(\n ModuleName, "PublishMasterSecret", SignedEncryptedMasterSecret{}\n)\n')),(0,r.kt)("h3",{id:"setup"},"Setup"),(0,r.kt)("p",null,"The key manager is initialized with an empty checksum and no nodes.\nEvery node needs to register with an empty checksum to be included\nin the key manager committee. Only members of the committee are\nallowed to generate master secrets and will be able to decrypt\nthe proposals."),(0,r.kt)("h3",{id:"generation"},"Generation"),(0,r.kt)("p",null,"Each keymanager will, at a random time in a given epoch:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Check to see if rotation period has expired. If not, go to step 5.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Check to see if another instance has published a proposal for the upcoming\nepoch. If yes, go to step 5.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Execute a local ",(0,r.kt)("inlineCode",{parentName:"p"},"generate_master_secret")," RPC call. The enclave will,\nin-order:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Verify the master secret generation number.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Randomly select a secret.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Use the light client to query the members of the committee.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Encrypt and checksum the selected secret.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Return ",(0,r.kt)("inlineCode",{parentName:"p"},"GenerateMasterSecretResponse"),"."))),(0,r.kt)("p",{parentName:"li"},"On failure, go to step 1.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Read ",(0,r.kt)("inlineCode",{parentName:"p"},"SignedEncryptedMasterSecret")," from the response and publish it\nin the consensus layer using ",(0,r.kt)("inlineCode",{parentName:"p"},"PublishMasterSecret")," transaction.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"This key manager instance is DONE."))),(0,r.kt)("h3",{id:"replication"},"Replication"),(0,r.kt)("p",null,"Each key manager will listen for the publication of new master secret proposals\nand will, when a new secret is proposed:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Cancel master secret generation scheduled for the current epoch.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Forward the proposal to the enclave.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"The enclave will verify that:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The proposal was published in the consensus layer.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The secret can be decrypted with the enclave's REK key.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The master secret generation number is one greater than the last known\ngeneration.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"The checksum computed from the decrypted secret and the last known\nchecksum matches the one in the proposal."))),(0,r.kt)("p",{parentName:"li"},"If all verifications pass, the enclave will:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Decrypt the secret, encrypt it with SGX sealing key and store\nthe ciphertext locally.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Derive the RSK key for the proposed secret and store it in the memory\ntogether with the computed checksum."))),(0,r.kt)("p",{parentName:"li"},"Otherwise, go to step 5.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Request enclave to initialize again and use the response to register\nwith the forthcoming checksum and RSK key derived from the proposal.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"This key manager instance is DONE."))),(0,r.kt)("h3",{id:"rotation"},"Rotation"),(0,r.kt)("p",null,"Key manager application will try to rotate the master secret every epoch\nas part of the key manager status generation as follows:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Fetch the latest master secret proposal.\nOn failure, go to step 6.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Verify the master secret generation number and epoch of the proposal.\nOn failure, go to step 6."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"The rotation period is not verified here as it is already checked when\nthe secret is proposed. Optionally, we can add this check to cover\nthe case when the policy changes after the secret is proposed."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Count how many nodes have stored the proposal locally."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Compare the checksum of the proposal to the ",(0,r.kt)("inlineCode",{parentName:"li"},"next_checksum")," field in\nthe init response."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Accept the proposal if the majority of the nodes have replicated\nthe proposed secret and announced ",(0,r.kt)("inlineCode",{parentName:"p"},"next_checksum")," in their init status."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Increment the master secret generation number by 1.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Update the last rotation epoch.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Update the checksum.")))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Broadcast the new status."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"If the master secret generation number has advanced, the enclaves will\ntry to apply the proposal they stored locally."))),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Key manager application is DONE."))),(0,r.kt)("h3",{id:"confirmation"},"Confirmation"),(0,r.kt)("p",null,"Each key manager will listen for the key manager status updates and will,\nwhen the master secret generation number advances:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Send the key manager status to the enclave.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"The enclave will:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Check that the master secret generation number is one greater than\nthe last known generation.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Load locally stored proposal for the next master secret or replicate it\nfrom another enclave.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Use the proposal to compute the next checksum.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Verify the computed checksum against the latest key manager status."))),(0,r.kt)("p",{parentName:"li"},"If checksum matches, the enclave will:"),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Encrypt the secret with SGX sealing key using master secret generation\nnumber as additional data and store the ciphertext locally.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Update the last known generation number.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Update the latest checksum and RSK key."))),(0,r.kt)("p",{parentName:"li"},"Otherwise, go to step 1.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"Request enclave to initialize again and use the response to register\nwith the latest checksum and RSK key while leaving the forthcoming\nchecksum and RSK key empty.")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("p",{parentName:"li"},"This key manager instance is DONE."))),(0,r.kt)("h2",{id:"consequences"},"Consequences"),(0,r.kt)("h3",{id:"positive"},"Positive"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Runtimes can periodically or on demand re-encrypt their state using\nthe latest generation of the master secret.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Compromise of an enclave cannot reveal master secrets generated after its\nupgrade or obsolescence.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"If enclave initialization is interrupted or aborted, the subsequent\ninitialization will resume from where the previous one left off.\nThis means that any secrets that have already been replicated and\nverified will not be fetched again.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"When compared to Merkle trees, hash chains provide a straightforward way\nto transition from the current checksum implementation and also enable\nthe use of simpler proofs that can be validated in constant time."))),(0,r.kt)("h3",{id:"negative"},"Negative"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Initialization takes time as all master secrets need to be replicated."),(0,r.kt)("table",{parentName:"li"},(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:"center"},"Number of secrets"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Replication time"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"10"),(0,r.kt)("td",{parentName:"tr",align:"center"},"45 sec")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"100"),(0,r.kt)("td",{parentName:"tr",align:"center"},"52 sec")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"1000"),(0,r.kt)("td",{parentName:"tr",align:"center"},"2 min 45 sec")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"10000"),(0,r.kt)("td",{parentName:"tr",align:"center"},"21 min 17 sec")))),(0,r.kt)("p",{parentName:"li"},"Table 1: Local machine benchmarks (without any network overhead)")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Master secret replication response must contain a Merkle proof for secret\nverification.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Newly accepted master secrets cannot be used immediately to derive runtime\nkeys because key manager enclaves need to confirm them first. When using\nTendermint as a backend, this delay is even greater as the verifier is one\nblock behind."))),(0,r.kt)("h3",{id:"neutral"},"Neutral"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Master secrets need to be replicated in reverse order to ensure all\nsecrets are verified against checksum published in the consensus layer.")))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/c9679863.2896ca0f.js b/assets/js/c9679863.2896ca0f.js new file mode 100644 index 0000000000..a306baac90 --- /dev/null +++ b/assets/js/c9679863.2896ca0f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8719],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>h});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function o(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var s=r.createContext({}),d=function(e){var t=r.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},c=function(e){var t=d(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=d(a),u=n,h=p["".concat(s,".").concat(u)]||p[u]||m[u]||i;return a?r.createElement(h,o(o({ref:t},c),{},{components:a})):r.createElement(h,o({ref:t},c))}));function h(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,o=new Array(i);o[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:n,o[1]=l;for(var d=2;d{a.d(t,{Z:()=>h});var r=a(7294),n=a(6010),i=a(9960),o=a(3438),l=a(3919),s=a(5999);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};function c(e){let{href:t,children:a}=e;return r.createElement(i.Z,{href:t,className:(0,n.Z)("card padding--lg",d.cardContainer)},a)}function p(e){let{href:t,icon:a,title:i,description:o}=e;return r.createElement(c,{href:t},r.createElement("h2",{className:(0,n.Z)("text--truncate",d.cardTitle),title:i},a," ",i),o&&r.createElement("p",{className:(0,n.Z)("text--truncate",d.cardDescription),title:o},o))}function m(e){let{item:t}=e;const a=(0,o.Wl)(t);return a?r.createElement(p,{href:a,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??(0,s.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function u(e){let{item:t}=e;const a=(0,l.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,o.xz)(t.docId??void 0);return r.createElement(p,{href:t.href,icon:a,title:t.label,description:t.description??n?.description})}function h(e){let{item:t}=e;switch(t.type){case"link":return r.createElement(u,{item:t});case"category":return r.createElement(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9268:(e,t,a)=>{a.d(t,{Z:()=>s});var r=a(7294),n=a(6010),i=a(3438),o=a(1564);function l(e){let{className:t}=e;const a=(0,i.jA)();return r.createElement(s,{items:a.items,className:t})}function s(e){const{items:t,className:a}=e;if(!t)return r.createElement(l,e);const s=(0,i.MN)(t);return r.createElement("section",{className:(0,n.Z)("row",a)},s.map(((e,t)=>r.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},r.createElement(o.Z,{item:e})))))}},7525:(e,t,a)=>{a.d(t,{n:()=>i});var r=a(4477);function n(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&n(t.items)}}function i(e){const t=(0,r.E)();if(!t)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in t.docsSidebars)n(t.docsSidebars[e])}if(void 0===globalThis.sidebarItemsMap[e])throw console.log("Registered sidebar items:"),console.log(globalThis.sidebarItemsMap),new Error("Unexpected: sidebar item with href "+e+" does not exist.");return globalThis.sidebarItemsMap[e]}},2313:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>l,metadata:()=>d,toc:()=>p});var r=a(7462),n=(a(7294),a(3905)),i=a(9268),o=a(7525);const l={},s="Emerald ParaTime",d={unversionedId:"dapp/emerald/README",id:"dapp/emerald/README",title:"Emerald ParaTime",description:"The Emerald ParaTime is our official EVM Compatible ParaTime providing smart contract environment with full EVM compatibility.",source:"@site/docs/dapp/emerald/README.mdx",sourceDirName:"dapp/emerald",slug:"/dapp/emerald/",permalink:"/dapp/emerald/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/emerald/README.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Frontend Application",permalink:"/dapp/opl/frontend"},next:{title:"Writing dApps on Emerald",permalink:"/dapp/emerald/writing-dapps-on-emerald"}},c={},p=[{value:"ParaTime Incentives",id:"paratime-incentives",level:2},{value:"Web3 Gateway",id:"web3-gateway",level:2},{value:"Mainnet",id:"mainnet",level:3},{value:"Testnet",id:"testnet",level:3},{value:"See also",id:"see-also",level:2}],m={toc:p},u="wrapper";function h(e){let{components:t,...a}=e;return(0,n.kt)(u,(0,r.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"emerald-paratime"},"Emerald ParaTime"),(0,n.kt)("p",null,"The Emerald ParaTime is our official EVM Compatible ParaTime providing smart contract environment with full EVM compatibility."),(0,n.kt)("p",null,"As the official EVM compatible ParaTime on the Oasis Network, Emerald allows for:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Full EVM compatibility"),(0,n.kt)("li",{parentName:"ul"},"Easy integration with EVM-based dApps, such as DeFi, NFT, Metaverse and crypto gaming"),(0,n.kt)("li",{parentName:"ul"},"Scalability \u2014 increased throughput of transactions"),(0,n.kt)("li",{parentName:"ul"},"Low-cost \u2014 99%+ lower fees than Ethereum"),(0,n.kt)("li",{parentName:"ul"},"Cross-chain bridge to enable cross-chain interoperability (upcoming)")),(0,n.kt)("p",null,"If you're looking for EVM, but with confidentiality,\ncheck out the ",(0,n.kt)("a",{parentName:"p",href:"/dapp/sapphire/"},"Sapphire ParaTime"),"."),(0,n.kt)("h2",{id:"paratime-incentives"},"ParaTime Incentives"),(0,n.kt)("p",null,"Emerald is fully decentralized with node operators distributed globally, and Oasis ROSE will be the native token used for gas fees."),(0,n.kt)("p",null,"The ParaTime will release tokens on-chain to reward nodes for participation. These tokens will be released, per epoch, with the reward being 3 ROSE Tokens per entity per epoch."),(0,n.kt)("p",null,"Epochs are currently being produced at a speed of one per hour. Each node has an approximately 30% chance of being selected by the primary committee to claim the rewards. Hence, a node entity can earn 24 ROSE tokens per day, 720 ROSE tokens per month."),(0,n.kt)("p",null,"The reward program is two years long."),(0,n.kt)("h2",{id:"web3-gateway"},"Web3 Gateway"),(0,n.kt)("p",null,"To get started building on our Emerald ParaTime, you can use our public Web3 gateway, fully compatible with Ethereum's Web3 gateway."),(0,n.kt)("h3",{id:"mainnet"},"Mainnet"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"RPC HTTP endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"https://emerald.oasis.dev")),(0,n.kt)("li",{parentName:"ul"},"RPC WebSockets endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"wss://emerald.oasis.dev/ws")),(0,n.kt)("li",{parentName:"ul"},"Chain ID:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Hex: 0xa516"),(0,n.kt)("li",{parentName:"ul"},"Decimal: 42262"))),(0,n.kt)("li",{parentName:"ul"},"Block explorer: ",(0,n.kt)("a",{parentName:"li",href:"https://explorer.emerald.oasis.dev"},"https://explorer.emerald.oasis.dev"))),(0,n.kt)("button",{class:"button button--primary margin-bottom--md",onClick:()=>{if(!window.ethereum?.request)return alert("Have you installed MetaMask yet? If not, please do so.\n\nComputer: Once it is installed, you will be able to add the ParaTime to your MetaMask.\n\nPhone: Open the website through your MetaMask Browser to add the ParaTime.");window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:"0xa516",chainName:"Oasis Emerald",nativeCurrency:{name:"Emerald Rose",symbol:"ROSE",decimals:18},rpcUrls:["https://emerald.oasis.dev","wss://emerald.oasis.dev/ws"],blockExplorerUrls:["https://explorer.emerald.oasis.dev"]}]})}},"Click here to register Emerald Mainnet to your MetaMask or Brave Wallet"),(0,n.kt)("h3",{id:"testnet"},"Testnet"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"RPC HTTP endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"https://testnet.emerald.oasis.dev")),(0,n.kt)("li",{parentName:"ul"},"RPC WebSockets endpoint: ",(0,n.kt)("inlineCode",{parentName:"li"},"wss://testnet.emerald.oasis.dev/ws")),(0,n.kt)("li",{parentName:"ul"},"Chain ID:",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Hex: 0xa515"),(0,n.kt)("li",{parentName:"ul"},"Decimal: 42261"))),(0,n.kt)("li",{parentName:"ul"},"Block explorer: ",(0,n.kt)("a",{parentName:"li",href:"https://testnet.explorer.emerald.oasis.dev"},"https://testnet.explorer.emerald.oasis.dev"))),(0,n.kt)("button",{class:"button button--primary margin-bottom--md",onClick:()=>{if(!window.ethereum?.request)return alert("Have you installed MetaMask yet? If not, please do so.\n\nComputer: Once it is installed, you will be able to add the ParaTime to your MetaMask.\n\nPhone: Open the website through your MetaMask Browser to add the ParaTime.");window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:"0xa515",chainName:"Oasis Emerald Testnet",nativeCurrency:{name:"TEST",symbol:"TEST",decimals:18},rpcUrls:["https://testnet.emerald.oasis.dev/","wss://testnet.emerald.oasis.dev/ws"],blockExplorerUrls:["https://testnet.explorer.emerald.oasis.dev"]}]})}},"Click here to register Emerald Testnet to your MetaMask or Brave Wallet"),(0,n.kt)("h2",{id:"see-also"},"See also"),(0,n.kt)(i.Z,{items:[(0,o.n)("/general/manage-tokens/how-to-transfer-rose-into-paratime"),(0,o.n)("/node/run-your-node/paratime-node"),(0,o.n)("/node/run-your-node/paratime-client-node"),(0,o.n)("/node/web3"),(0,o.n)("/dapp/sapphire/"),(0,o.n)("/dapp/cipher/")],mdxType:"DocCardList"}))}h.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/cb5a5574.2f3539ae.js b/assets/js/cb5a5574.2f3539ae.js new file mode 100644 index 0000000000..b9614a18a1 --- /dev/null +++ b/assets/js/cb5a5574.2f3539ae.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3049],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),c=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=c(n),d=r,f=u["".concat(s,".").concat(d)]||u[d]||m[d]||o;return n?a.createElement(f,i(i({ref:t},p),{},{components:n})):a.createElement(f,i({ref:t},p))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:r,i[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>m,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var a=n(7462),r=(n(7294),n(3905));const o={title:"Oasis CLI",description:"Powerful CLI for managing Oasis network, nodes, tokens and dapps"},i="Oasis Command Line Interface",l={unversionedId:"general/manage-tokens/cli/README",id:"general/manage-tokens/cli/README",title:"Oasis CLI",description:"Powerful CLI for managing Oasis network, nodes, tokens and dapps",source:"@site/docs/general/manage-tokens/cli/README.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/",permalink:"/general/manage-tokens/cli/",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/README.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Oasis CLI",description:"Powerful CLI for managing Oasis network, nodes, tokens and dapps"},sidebar:"general",previous:{title:"How to Transfer ETH/ERC20 to Emerald ParaTime",permalink:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime"},next:{title:"Setup",permalink:"/general/manage-tokens/cli/setup"}},s={},c=[],p={toc:c},u="wrapper";function m(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"oasis-command-line-interface"},"Oasis Command Line Interface"),(0,r.kt)("p",null,"Oasis command-line interface (CLI) is a powerful all-in-one tool for\ninteracting with the Oasis Network. You can download the latest release\nbinaries from the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/cli/releases"},"GitHub repository"),"."),(0,r.kt)("p",null,"It boasts a number of handy features:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Flexible setup:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"supports Mainnet, Testnet, Localnet or any other Oasis network deployment"),(0,r.kt)("li",{parentName:"ul"},"consensus layer configuration with arbitrary token"),(0,r.kt)("li",{parentName:"ul"},"configuration of custom ParaTimes with arbitrary token"),(0,r.kt)("li",{parentName:"ul"},"connecting to remote (via TCP/IP) or local (Unix socket) Oasis node\ninstance"))),(0,r.kt)("li",{parentName:"ul"},"Powerful wallet features:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"standard token operations (transfers, allowances, deposits, withdrawals and\nbalance queries)"),(0,r.kt)("li",{parentName:"ul"},"file-based wallet with password protection"),(0,r.kt)("li",{parentName:"ul"},"full Ledger hardware wallet support"),(0,r.kt)("li",{parentName:"ul"},"address book"),(0,r.kt)("li",{parentName:"ul"},"generation, signing and submitting transactions in non-interactive\n(headless) mode"),(0,r.kt)("li",{parentName:"ul"},"offline transaction generation for air-gapped machines"),(0,r.kt)("li",{parentName:"ul"},"transaction encryption with X25519-Deoxys-II envelope"),(0,r.kt)("li",{parentName:"ul"},"support for Ed25519, Ethereum-compatible Secp256k1 and Sr25519 signature\nschemes"),(0,r.kt)("li",{parentName:"ul"},"raw, BIP-44, ADR-8 and Ledger's legacy derivation paths"))),(0,r.kt)("li",{parentName:"ul"},"Node operator features:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"Oasis node inspection and healthchecks"),(0,r.kt)("li",{parentName:"ul"},"network governance transactions"),(0,r.kt)("li",{parentName:"ul"},"staking reward schedule transactions"))),(0,r.kt)("li",{parentName:"ul"},"Developer features:",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"built-in testing accounts compatible with the Oasis test runner, the Oasis\nCI and the official sapphire-dev and emerald-dev Docker images"),(0,r.kt)("li",{parentName:"ul"},"Oasis Wasm smart contract code deployment, instantiation, management and\ncalls"),(0,r.kt)("li",{parentName:"ul"},"debugging tools for deployed Wasm contracts"),(0,r.kt)("li",{parentName:"ul"},"inspection of blocks, transactions, results and events")))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/cd9af2e1.d68c4b6c.js b/assets/js/cd9af2e1.d68c4b6c.js new file mode 100644 index 0000000000..f8debfd48b --- /dev/null +++ b/assets/js/cd9af2e1.d68c4b6c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1045],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,g=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return n?r.createElement(g,s(s({ref:t},p),{},{components:n})):r.createElement(g,s({ref:t},p))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,s=new Array(i);s[0]=m;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o[d]="string"==typeof e?e:a,s[1]=o;for(var l=2;l{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const i={},s="Transaction Test Vectors",o={unversionedId:"core/consensus/test-vectors",id:"core/consensus/test-vectors",title:"Transaction Test Vectors",description:"In order to test transaction generation, parsing and signing, we provide a set",source:"@site/docs/core/consensus/test-vectors.md",sourceDirName:"core/consensus",slug:"/core/consensus/test-vectors",permalink:"/core/consensus/test-vectors",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/test-vectors.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Genesis Document",permalink:"/core/consensus/genesis"},next:{title:"Runtime Layer",permalink:"/core/runtime/"}},c={},l=[{value:"Structure",id:"structure",level:2}],p={toc:l},d="wrapper";function u(e){let{components:t,...n}=e;return(0,a.kt)(d,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"transaction-test-vectors"},"Transaction Test Vectors"),(0,a.kt)("p",null,"In order to test transaction generation, parsing and signing, we provide a set\nof test vectors. They can be generated for the following consensus services:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/staking#test-vectors"},"Staking")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/registry#test-vectors"},"Registry")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("a",{parentName:"li",href:"/core/consensus/services/governance#test-vectors"},"Governance"))),(0,a.kt)("h2",{id:"structure"},"Structure"),(0,a.kt)("p",null,"The generated test vectors file is a JSON document which provides an array of\nobjects (test vectors). Each test vector has the following fields:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"kind")," is a human-readable string describing what kind of a transaction the\ngiven test vector is describing (e.g., ",(0,a.kt)("inlineCode",{parentName:"p"},'"Transfer"'),").")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"signature_context")," is the ",(0,a.kt)("a",{parentName:"p",href:"/core/crypto#domain-separation"},"domain separation context")," used for signing the\ntransaction.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"tx")," is the human-readable ",(0,a.kt)("em",{parentName:"p"},"interpreted")," unsigned transaction. Its purpose is\nto make it easier for the implementer to understand what the content of the\ntransaction is. ",(0,a.kt)("strong",{parentName:"p"},"It does not contain the structure that can be serialized\ndirectly (e.g., ","[addresses]"," may be represented as Bech32-encoded strings while\nin the ",(0,a.kt)("a",{parentName:"strong",href:"/core/encoding"},"encoded")," transaction, these would be binary blobs)."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"signed_tx")," is the human-readable signed transaction to make it easier for the\nimplementer to understand how the ",(0,a.kt)("a",{parentName:"p",href:"/core/crypto#envelopes"},"signature envelope")," looks like.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"encoded_tx")," is the CBOR-encoded (since test vectors are in JSON and CBOR\nencoding is a binary encoding it also needs to be Base64-encoded) unsigned\ntransaction.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"encoded_signed_tx")," is the CBOR-encoded (since test vectors are in JSON and\nCBOR encoding is a binary encoding it also needs to be Base64-encoded) signed\ntransaction. ",(0,a.kt)("strong",{parentName:"p"},"This is what is actually broadcast to the network."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"valid")," is a boolean flag indicating whether the given test vector represents\na valid transaction, including:"),(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"transaction having a valid signature,"),(0,a.kt)("li",{parentName:"ul"},"transaction being correctly serialized,"),(0,a.kt)("li",{parentName:"ul"},"transaction passing basic static validation.")),(0,a.kt)("p",{parentName:"li"},(0,a.kt)("em",{parentName:"p"},"NOTE: Even if a transaction passes basic static validation, it may still\n",(0,a.kt)("strong",{parentName:"em"},"not")," be a valid transaction on the given network due to invalid nonce, or\ndue to some specific parameters set on the network."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"signer_private_key")," is the Ed25519 private key that was used to sign the\ntransaction in the test vector.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"signer_public_key")," is the Ed25519 public key corresponding to\n",(0,a.kt)("inlineCode",{parentName:"p"},"signer_private_key"),"."))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ce2c26b3.dde6ff0c.js b/assets/js/ce2c26b3.dde6ff0c.js new file mode 100644 index 0000000000..0d47cd518f --- /dev/null +++ b/assets/js/ce2c26b3.dde6ff0c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1862],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>h});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),m=i,h=d["".concat(l,".").concat(m)]||d[m]||u[m]||r;return n?a.createElement(h,o(o({ref:t},p),{},{components:n})):a.createElement(h,o({ref:t},p))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,o=new Array(r);o[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:i,o[1]=s;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>c});var a=n(7462),i=(n(7294),n(3905));const r={},o="ADR 0017: ParaTime Application Standard Proposal Process",s={unversionedId:"adrs/0017-app-standards",id:"adrs/0017-app-standards",title:"ADR 0017: ParaTime Application Standard Proposal Process",description:"Component",source:"@site/docs/adrs/0017-app-standards.md",sourceDirName:"adrs",slug:"/adrs/0017-app-standards",permalink:"/adrs/0017-app-standards",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0017-app-standards.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0016: Consensus Parameters Change Proposal",permalink:"/adrs/0016-consensus-parameters-change-proposal"},next:{title:"ADR 0020: Governance Support for Delegator Votes",permalink:"/adrs/0020-governance-delegator-votes"}},l={},c=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Naming Conventions",id:"naming-conventions",level:3},{value:"Changes to the ADR template",id:"changes-to-the-adr-template",level:3},{value:"New Section Requirements",id:"new-section-requirements",level:3},{value:"Decision: Specification & Reference Implementation",id:"decision-specification--reference-implementation",level:4},{value:"Security Considerations",id:"security-considerations",level:4},{value:"Acceptance Requirements",id:"acceptance-requirements",level:3},{value:"Alternatives",id:"alternatives",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],p={toc:c},d="wrapper";function u(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"adr-0017-paratime-application-standard-proposal-process"},"ADR 0017: ParaTime Application Standard Proposal Process"),(0,i.kt)("h2",{id:"component"},"Component"),(0,i.kt)("p",null,"ADRs"),(0,i.kt)("h2",{id:"changelog"},"Changelog"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"2022-10-05: Initial version"),(0,i.kt)("li",{parentName:"ul"},"2022-10-12: Accepted")),(0,i.kt)("h2",{id:"status"},"Status"),(0,i.kt)("p",null,"Accepted"),(0,i.kt)("h2",{id:"context"},"Context"),(0,i.kt)("p",null,"Applications running within a ParaTime having a novel runtime environment\n(e.g., Sapphire, Cipher) benefit from interoperability standards. For example,\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/ethereum/EIPs"},"ERCs")," in Ethereum. ADRs are already present in the Oasis ecosystem and so are a\nstarting point, but these are intended for lightweight recording of decisions,\nnot gathering consensus around community contributions. This ADR proposes a\ntemplate and process amendment for ADRs introducing ParaTime-specific\napplication standards."),(0,i.kt)("h2",{id:"decision"},"Decision"),(0,i.kt)("p",null,"ADRs will be used for application standards because they are already well\nsupported within the Oasis ecosystem, and have most of the structure needed\nfor application standards. Although adapting another project's process would be\neasy, having multiple proposal repositories could lead to confusion."),(0,i.kt)("p",null,"For use with application standards, ADRs shall have more structure to make\ncontributions fair and straightforward. Specifically, additional required\nsections and concrete requirements for acceptance."),(0,i.kt)("p",null,"Although community standards are only proposals, the ",(0,i.kt)("em",{parentName:"p"},"Decision")," section will\nkeep its name for compatibility with the existing template. The decision in this\ncontext will be to accept the standard for distribution to a wider audience."),(0,i.kt)("h3",{id:"naming-conventions"},"Naming Conventions"),(0,i.kt)("p",null,"App standard ADRs shall be referred to as ADR-","<","number",">"," regardless of the\ntargeted ParaTime."),(0,i.kt)("h3",{id:"changes-to-the-adr-template"},"Changes to the ADR template"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"add a new ",(0,i.kt)("em",{parentName:"li"},"Apps")," component, which has the ParaTime as its sub-component")),(0,i.kt)("h3",{id:"new-section-requirements"},"New Section Requirements"),(0,i.kt)("h4",{id:"decision-specification--reference-implementation"},"Decision: Specification & Reference Implementation"),(0,i.kt)("p",null,"The ",(0,i.kt)("em",{parentName:"p"},"Decision")," section gets two new sub-sections:"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Specification"),": A complete description of the interface of the standard,\nincluding the threat/trust model, rationale for design decisions, alternative\napproaches, and references to related work. This section will generally be\nmostly prose with sprinkles of code for illustration."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Reference Implementation"),": A basic implementation of the proposed standard\nwritten in a common language that targets the ParaTime runtime environment.\nThe reference implementation in the ADR should be executable."),(0,i.kt)("h4",{id:"security-considerations"},"Security Considerations"),(0,i.kt)("p",null,"This new section details any weak points of the proposal or common security\nflaws that a re-implementation of the specification may run into, as well as\nsuggestions for avoiding security issues."),(0,i.kt)("h3",{id:"acceptance-requirements"},"Acceptance Requirements"),(0,i.kt)("p",null,"Like all ADRs, an Apps component ADR will start as ",(0,i.kt)("em",{parentName:"p"},"Proposed")," and end up merged\nonce ",(0,i.kt)("em",{parentName:"p"},"Accepted"),". An application standard ADR following the above format will be\naccepted once:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"there is consensus within the ParaTime's own community that the standard meets\nits design goals"),(0,i.kt)("li",{parentName:"ul"},"there are no outstanding compatibility or security issues"),(0,i.kt)("li",{parentName:"ul"},"an ADR repo committer has signed off on the structure and format of the ADR")),(0,i.kt)("h2",{id:"alternatives"},"Alternatives"),(0,i.kt)("p",null,"One alternative is to fit the ParaTime-specific application standard proposals\ninto the existing ADR template, but this would cause the ",(0,i.kt)("em",{parentName:"p"},"Decision")," section to\nbecome overloaded with the necessary information in an ad-hoc way."),(0,i.kt)("p",null,"Another alternative is to encourage ParaTimes to do whatever they think most\neffective. That's always allowed, of course, and it may sometimes be useful to\nwholesale copy the best practices of another community. However, if we make the\nADR process convenient enough, the community can focus its collective effort on\nthe single ADR repo."),(0,i.kt)("p",null,"Within the chosen decision, there were many choices of structure from the now\nseveral EIP-like repos. The ones chosen were the minimum we need to get going,\nin the spirit of the lightweight ADR process. If more structure is needed in\nthe future, we can amend this process or switch to a new system entirely, at\nwhich point this ADR shall be marked as ",(0,i.kt)("em",{parentName:"p"},"Superseded"),"."),(0,i.kt)("h2",{id:"consequences"},"Consequences"),(0,i.kt)("h3",{id:"positive"},"Positive"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"The community has a rallying point for standard development."),(0,i.kt)("li",{parentName:"ul"},"We can reuse existing process.")),(0,i.kt)("h3",{id:"negative"},"Negative"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"The app standard process might still not be ideal even after this proposal."),(0,i.kt)("li",{parentName:"ul"},"ADR-NNN naming convention is not forwards compatible.")),(0,i.kt)("h3",{id:"neutral"},"Neutral"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"We will need to maintain additional ADR process going forward.")),(0,i.kt)("h2",{id:"references"},"References"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/ethereum/EIPs"},"Ethereum Improvement Proposals")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://www.rfc-editor.org/pubprocess/"},"RFCs")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/cosmos/ibc/blob/main/spec/ics-template.md"},"Inter-Chain Standards"))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/cef04ba6.93db12dc.js b/assets/js/cef04ba6.93db12dc.js new file mode 100644 index 0000000000..af05cb865d --- /dev/null +++ b/assets/js/cef04ba6.93db12dc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[355],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>h});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=a.createContext({}),l=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=l(e.components);return a.createElement(p.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,p=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),c=l(n),m=o,h=c["".concat(p,".").concat(m)]||c[m]||u[m]||r;return n?a.createElement(h,s(s({ref:t},d),{},{components:n})):a.createElement(h,s({ref:t},d))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,s=new Array(r);s[0]=m;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i[c]="string"==typeof e?e:o,s[1]=i;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>l});var a=n(7462),o=(n(7294),n(3905));const r={},s="ADR 0006: Consensus Governance",i={unversionedId:"adrs/0006-consensus-governance",id:"adrs/0006-consensus-governance",title:"ADR 0006: Consensus Governance",description:"Component",source:"@site/docs/adrs/0006-consensus-governance.md",sourceDirName:"adrs",slug:"/adrs/0006-consensus-governance",permalink:"/adrs/0006-consensus-governance",draft:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0006-consensus-governance.md",tags:[],version:"current",lastUpdatedAt:1692016560,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0005: Runtime Compute Node Slashing",permalink:"/adrs/0005-runtime-compute-slashing"},next:{title:"ADR 0007: Improved Random Beacon",permalink:"/adrs/0007-improved-random-beacon"}},p={},l=[{value:"Component",id:"component",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"State",id:"state",level:3},{value:"Staking",id:"staking",level:4},{value:"Governance",id:"governance",level:4},{value:"Genesis Document",id:"genesis-document",level:3},{value:"Transaction Methods",id:"transaction-methods",level:3},{value:"Submit Proposal",id:"submit-proposal",level:4},{value:"Vote",id:"vote",level:4},{value:"Queries",id:"queries",level:3},{value:"Tallying",id:"tallying",level:3},{value:"Proposal Content Execution",id:"proposal-content-execution",level:3},{value:"Upgrade Proposal",id:"upgrade-proposal",level:4},{value:"Cancel Upgrade Proposal",id:"cancel-upgrade-proposal",level:4},{value:"Consensus Parameters",id:"consensus-parameters",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}],d={toc:l},c="wrapper";function u(e){let{components:t,...n}=e;return(0,o.kt)(c,(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"adr-0006-consensus-governance"},"ADR 0006: Consensus Governance"),(0,o.kt)("h2",{id:"component"},"Component"),(0,o.kt)("p",null,"Oasis Core"),(0,o.kt)("h2",{id:"changelog"},"Changelog"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"2021-03-30: Update name of the CastVote method's body"),(0,o.kt)("li",{parentName:"ul"},"2021-01-06: Update API to include Proposals() method"),(0,o.kt)("li",{parentName:"ul"},"2020-12-08: Updates to match the actual implementation"),(0,o.kt)("li",{parentName:"ul"},"2020-10-27: Voting period in epochs, min upgrade cancellation difference,\nfailed proposal state"),(0,o.kt)("li",{parentName:"ul"},"2020-10-16: Initial draft")),(0,o.kt)("h2",{id:"status"},"Status"),(0,o.kt)("p",null,"Accepted"),(0,o.kt)("h2",{id:"context"},"Context"),(0,o.kt)("p",null,"Currently the consensus layer does not contain any on-chain governance\nmechanism so any network upgrades need to be carefully coordinated off-chain.\nAn on-chain governance mechanism would allow upgrades to be handled in a more\ncontrolled (and automatable) manner without introducing the risk of corrupting\nstate."),(0,o.kt)("h2",{id:"decision"},"Decision"),(0,o.kt)("p",null,"This proposal introduces a minimal on-chain governance mechanism where anyone\ncan submit governance proposals and the validators can vote where one base unit\nof delegated stake counts as one vote."),(0,o.kt)("p",null,"The high-level overview is as follows:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"A new governance API")," is added to the consensus layer and its Tendermint\nbased implementation. It supports transactions for submitting proposals and\nvoting on proposals. It supports queries for listing current proposals and\nvotes for any given proposal.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"Two governance proposal kinds are supported"),", a consensus layer upgrade\nproposal (where the content is basically the existing upgrade descriptor) and\nthe cancellation of a pending upgrade."))),(0,o.kt)("p",null,"A proposal is created through a ",(0,o.kt)("em",{parentName:"p"},"submit proposal")," transaction and requires a\nminimum deposit (which is later refunded in case the proposal passes). Once a\nproposal is successfully submitted the voting period starts. Entities that are\npart of the validator set may cast votes for the proposal. After the voting\nperiod completes, the votes are tallied and the proposal either passes or is\nrejected."),(0,o.kt)("p",null,"In case the proposal passes, the actions specified in the content of the propsal\nare executed. Currently the only actions are scheduling of an upgrade by\npublishing an upgrade descriptor or cancelling a previously passed upgrade."),(0,o.kt)("h3",{id:"state"},"State"),(0,o.kt)("h4",{id:"staking"},"Staking"),(0,o.kt)("p",null,"This proposal adds the following consensus layer state in the staking module:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("strong",{parentName:"li"},"Governance deposits account balance (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x59"),")"),", similar to the common pool.")),(0,o.kt)("h4",{id:"governance"},"Governance"),(0,o.kt)("p",null,"This proposal adds the following consensus layer state in the governance module:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"Next proposal identifier (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x80"),")")),(0,o.kt)("p",{parentName:"li"},"The next proposal identifier is stored as a CBOR-serialized ",(0,o.kt)("inlineCode",{parentName:"p"},"uint64"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"List of proposals (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x81"),")")),(0,o.kt)("p",{parentName:"li"},"Each proposal is stored under a separate storage key with the following key\nformat:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"0x81 \n")),(0,o.kt)("p",{parentName:"li"},"And CBOR-serialized value:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'// ProposalState is the state of the proposal.\ntype ProposalState uint8\n\nconst (\n StateActive ProposalState = 1\n StatePassed ProposalState = 2\n StateRejected ProposalState = 3\n StateFailed ProposalState = 4\n)\n\n// Proposal is a consensus upgrade proposal.\ntype Proposal struct {\n // ID is the unique identifier of the proposal.\n ID uint64 `json:"id"`\n // Submitter is the address of the proposal submitter.\n Submitter staking.Address `json:"submitter"`\n // State is the state of the proposal.\n State ProposalState `json:"state"`\n // Deposit is the deposit attached to the proposal.\n Deposit quantity.Quantity `json:"deposit"`\n\n // Content is the content of the proposal.\n Content ProposalContent `json:"content"`\n\n // CreatedAt is the epoch at which the proposal was created.\n CreatedAt beacon.EpochTime `json:"created_at"`\n // ClosesAt is the epoch at which the proposal will close and votes will\n // be tallied.\n ClosesAt beacon.EpochTime `json:"closes_at"`\n\n // Results are the final tallied results after the voting period has\n // ended.\n Results map[Vote]quantity.Quantity `json:"results,omitempty"`\n // InvalidVotes is the number of invalid votes after tallying.\n InvalidVotes uint64 `json:"invalid_votes,omitempty"`\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"List of active proposals (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x82"),")")),(0,o.kt)("p",{parentName:"li"},"Each active proposal (one that has not yet closed) is stored under a separate\nstorage key with the following key format:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"0x82 \n")),(0,o.kt)("p",{parentName:"li"},"The value is empty as the proposal ID can be inferred from the key.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"List of votes (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x83"),")")),(0,o.kt)("p",{parentName:"li"},"Each vote is stored under a separate storage key with the following key\nformat:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"0x83 \n")),(0,o.kt)("p",{parentName:"li"},"And CBOR-serialized value:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},"// Vote is a governance vote.\ntype Vote uint8\n\nconst (\n VoteYes Vote = 1\n VoteNo Vote = 2\n VoteAbstain Vote = 3\n)\n"))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"List of pending upgrades (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x84"),")")),(0,o.kt)("p",{parentName:"li"},"Each pending upgrade is stored under a separate storage key with the following\nkey format:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre"},"0x84 \n")),(0,o.kt)("p",{parentName:"li"},"The value is empty as the proposal upgrade descriptor can be obtained via\nproposal that can be inferred from the key.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("strong",{parentName:"p"},"Parameters (",(0,o.kt)("inlineCode",{parentName:"strong"},"0x85"),")")),(0,o.kt)("p",{parentName:"li"},"Governance consensus parameters."),(0,o.kt)("p",{parentName:"li"},"With CBOR-serialized value:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'// ConsensusParameters are the governance consensus parameters.\ntype ConsensusParameters struct {\n // GasCosts are the governance transaction gas costs.\n GasCosts transaction.Costs `json:"gas_costs,omitempty"`\n\n // MinProposalDeposit is the number of base units that are deposited when\n // creating a new proposal.\n MinProposalDeposit quantity.Quantity `json:"min_proposal_deposit,omitempty"`\n\n // VotingPeriod is the number of epochs after which the voting for a proposal\n // is closed and the votes are tallied.\n VotingPeriod beacon.EpochTime `json:"voting_period,omitempty"`\n\n // Quorum is he minimum percentage of voting power that needs to be cast on\n // a proposal for the result to be valid.\n Quorum uint8 `json:"quorum,omitempty"`\n\n // Threshold is the minimum percentage of VoteYes votes in order for a\n // proposal to be accepted.\n Threshold uint8 `json:"threshold,omitempty"`\n\n // UpgradeMinEpochDiff is the minimum number of epochs between the current\n // epoch and the proposed upgrade epoch for the upgrade proposal to be valid.\n // This is also the minimum number of epochs between two pending upgrades.\n UpgradeMinEpochDiff beacon.EpochTime `json:"upgrade_min_epoch_diff,omitempty"`\n\n // UpgradeCancelMinEpochDiff is the minimum number of epochs between the current\n // epoch and the proposed upgrade epoch for the upgrade cancellation proposal to be valid.\n UpgradeCancelMinEpochDiff beacon.EpochTime `json:"upgrade_cancel_min_epoch_diff,omitempty"`\n}\n')))),(0,o.kt)("h3",{id:"genesis-document"},"Genesis Document"),(0,o.kt)("p",null,"The genesis document needs to be updated to include a ",(0,o.kt)("inlineCode",{parentName:"p"},"governance")," field with\nany initial state (see ",(0,o.kt)("a",{parentName:"p",href:"#state"},(0,o.kt)("em",{parentName:"a"},"State")),") and consensus parameters (see ",(0,o.kt)("a",{parentName:"p",href:"#consensus-parameters"},(0,o.kt)("em",{parentName:"a"},"Consensus\nParameters")),") for the governance service."),(0,o.kt)("h3",{id:"transaction-methods"},"Transaction Methods"),(0,o.kt)("p",null,"This proposal adds the following transaction methods in the governance module:"),(0,o.kt)("h4",{id:"submit-proposal"},"Submit Proposal"),(0,o.kt)("p",null,"Proposal submission enables a new consensus layer governance proposal to be\ncreated."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"governance.SubmitProposal\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'// ProposalContent is a consensus layer governance proposal content.\ntype ProposalContent struct {\n Upgrade *UpgradeProposal `json:"upgrade,omitempty"`\n CancelUpgrade *CancelUpgradeProposal `json:"cancel_upgrade,omitempty"`\n}\n\n// UpgradeProposal is an upgrade proposal.\ntype UpgradeProposal struct {\n upgrade.Descriptor\n}\n\n// CancelUpgradeProposal is an upgrade cancellation proposal.\ntype CancelUpgradeProposal struct {\n // ProposalID is the identifier of the pending upgrade proposal.\n ProposalID uint64 `json:"proposal_id"`\n}\n')),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Fields:")),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"upgrade")," (optional) specifies an upgrade proposal."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"cancel_upgrade")," (optional) specifies an upgrade cancellation proposal.")),(0,o.kt)("p",null,"Exactly one of the proposal kind fields needs to be non-nil, otherwise the\nproposal is considered malformed."),(0,o.kt)("p",null,"Upon processing any proposal the following steps are first performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The account indicated by the signer is loaded.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the account balance is less than ",(0,o.kt)("inlineCode",{parentName:"p"},"min_proposal_deposit"),", the method call\nfails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrInsufficientBalance"),"."))),(0,o.kt)("p",null,"Upon processing an ",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"UpgradeProposal"))," the following steps are then performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The upgrade descriptor is checked for basic internal validity. If the check\nfails, the method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrInvalidArgument"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The upgrade descriptor's ",(0,o.kt)("inlineCode",{parentName:"p"},"epoch")," field is compared with the current epoch. If\nthe specified epoch is not at least ",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," epochs ahead of\nthe current epoch, the method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrUpgradeTooSoon"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The set of pending upgrades is checked to make sure that no upgrades are\ncurrently pending within ",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," epochs of the upgrade\ndescriptor's ",(0,o.kt)("inlineCode",{parentName:"p"},"epoch")," field. If there is such an existing upgrade pending, the\nmethod call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrUpgradeAlreadyPending"),"."))),(0,o.kt)("p",null,"Upon processing a ",(0,o.kt)("strong",{parentName:"p"},(0,o.kt)("inlineCode",{parentName:"strong"},"CancelUpgradeProposal"))," the following steps are then\nperformed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The set of pending upgrades is checked to make sure that the given upgrade\nproposal is currently pending to be executed. If there is no such upgrade, the\nmethod call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrNoSuchUpgrade"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The upgrade descriptor's ",(0,o.kt)("inlineCode",{parentName:"p"},"epoch")," field is compared with the current epoch. If\nthe specified epoch is not at least ",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_cancel_min_epoch_diff")," epochs\nahead of the current epoch, the method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrUpgradeTooSoon"),"."))),(0,o.kt)("p",null,"Upon processing any proposal the following steps are then performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"min_proposal_deposit")," base units are transferred from the signer's\naccount to the governance service's ",(0,o.kt)("em",{parentName:"p"},"proposal deposit account"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The signer's account is saved.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"A new proposal is created and assigned an identifier.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"ProposalSubmittedEvent")," is emitted with the following\nstructure:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalSubmittedEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Submitter is the staking account address of the submitter.\n Submitter staking.Address `json:"submitter"`\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.TransferEvent")," is emitted, indicating transfer from\nthe submitter's account to the ",(0,o.kt)("em",{parentName:"p"},"proposal deposit account"),"."))),(0,o.kt)("h4",{id:"vote"},"Vote"),(0,o.kt)("p",null,"Voting for submitted consensus layer governance proposals."),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Method name:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"governance.CastVote\n")),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Body:")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalVote struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Vote is the vote.\n Vote Vote `json:"vote"`\n}\n')),(0,o.kt)("p",null,"Upon processing a vote the following steps are performed:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The entity descriptor corresponding to the transaction signer is fetched. In\ncase no such entity exists, the method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrNotEligible"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"It is checked whether any entity's nodes are in the current validator set. In\ncase they are not, the method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrNotEligible"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The proposal identified by ",(0,o.kt)("inlineCode",{parentName:"p"},"id")," is loaded. If the proposal does not exist,\nthe method call fails with ",(0,o.kt)("inlineCode",{parentName:"p"},"ErrNoSuchProposal"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If the proposal's state is not ",(0,o.kt)("inlineCode",{parentName:"p"},"StateActive"),", the method call fails with\n",(0,o.kt)("inlineCode",{parentName:"p"},"ErrVotingIsClosed"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The vote is added to the list of votes. If the vote already exists, it is\noverwritten.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"VoteEvent")," is emitted with the following structure:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type VoteEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // Submitter is the staking account address of the submitter.\n Submitter staking.Address `json:"submitter"`\n // Vote is the cast vote.\n Vote Vote `json:"vote"`\n}\n')))),(0,o.kt)("h3",{id:"queries"},"Queries"),(0,o.kt)("p",null,"This proposal introduces the following query methods in the governance module:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type Backend interface {\n // ActiveProposals returns a list of all proposals that have not yet closed.\n ActiveProposals(ctx context.Context, height int64) ([]*Proposal, error)\n\n // Proposals returns a list of all proposals.\n Proposals(ctx context.Context, height int64) ([]*Proposal, error)\n\n // Proposal looks up a specific proposal.\n Proposal(ctx context.Context, query *ProposalQuery) (*Proposal, error)\n\n // Votes looks up votes for a specific proposal.\n Votes(ctx context.Context, query *ProposalQuery) ([]*VoteEntry, error)\n\n // PendingUpgrades returns a list of all pending upgrades.\n PendingUpgrades(ctx context.Context, height int64) ([]*upgrade.Descriptor, error)\n\n // StateToGenesis returns the genesis state at specified block height.\n StateToGenesis(ctx context.Context, height int64) (*Genesis, error)\n\n // ConsensusParameters returns the governance consensus parameters.\n ConsensusParameters(ctx context.Context, height int64) (*ConsensusParameters, error)\n\n // GetEvents returns the events at specified block height.\n GetEvents(ctx context.Context, height int64) ([]*Event, error)\n\n // WatchEvents returns a channel that produces a stream of Events.\n WatchEvents(ctx context.Context) (<-chan *Event, pubsub.ClosableSubscription, error)\n}\n\n// ProposalQuery is a proposal query.\ntype ProposalQuery struct {\n Height int64 `json:"height"`\n ID uint64 `json:"id"`\n}\n\n// VoteEntry contains data about a cast vote.\ntype VoteEntry struct {\n Voter staking.Address `json:"voter"`\n Vote Vote `json:"vote"`\n}\n\n// Event signifies a governance event, returned via GetEvents.\ntype Event struct {\n Height int64 `json:"height,omitempty"`\n TxHash hash.Hash `json:"tx_hash,omitempty"`\n\n ProposalSubmitted *ProposalSubmittedEvent `json:"proposal_submitted,omitempty"`\n ProposalExecuted *ProposalExecutedEvent `json:"proposal_executed,omitempty"`\n ProposalFinalized *ProposalFinalizedEvent `json:"proposal_finalized,omitempty"`\n Vote *VoteEvent `json:"vote,omitempty"`\n}\n')),(0,o.kt)("h3",{id:"tallying"},"Tallying"),(0,o.kt)("p",null,"In ",(0,o.kt)("inlineCode",{parentName:"p"},"EndBlock")," the list of active proposals is checked to see if there was an\nepoch transition in this block. If there was, the following steps are performed\nfor each proposal that should be closed at the current epoch:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"A mapping of current validator entity addresses to their respective active\nescrow balances is prepared.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"A results mapping from ",(0,o.kt)("inlineCode",{parentName:"p"},"Vote")," to number of votes is initialized in the\nproposal's ",(0,o.kt)("inlineCode",{parentName:"p"},"results")," field.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Votes from the list of votes for the given proposal are iterated and the\naddress of each vote is looked up in the prepared entity address mapping. The\ncorresponding number of votes (on the principle of 1 base unit equals one\nvote) are added to the results mapping based on the voted option. Any votes\nthat are not from the current validator set are ignored and the\n",(0,o.kt)("inlineCode",{parentName:"p"},"invalid_votes")," field is incremented for each such vote.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"In case the percentage of votes relative to the total voting power is less\nthan ",(0,o.kt)("inlineCode",{parentName:"p"},"quorum"),", the proposal is rejected.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"In case the percentage of ",(0,o.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes relative to all valid votes is less\nthan ",(0,o.kt)("inlineCode",{parentName:"p"},"threshold"),", the proposal is rejected.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Otherwise the proposal is passed.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The proposal's status is changed to either ",(0,o.kt)("inlineCode",{parentName:"p"},"StatePassed")," or ",(0,o.kt)("inlineCode",{parentName:"p"},"StateRejected"),"\nand the proposal is saved.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The proposal is removed from the list of active proposals.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"In case the proposal has been passed, the proposal content is executed. If\nproposal execution fails, the proposal's state is changed to ",(0,o.kt)("inlineCode",{parentName:"p"},"StateFailed"),".")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"The corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"ProposalFinalizedEvent")," is emitted with the following\nstructure:"),(0,o.kt)("pre",{parentName:"li"},(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalFinalizedEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n // State is the new proposal state.\n State ProposalState `json:"state"`\n}\n'))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"In case the proposal has been passed, the deposit is transferred back to the\nproposal submitter and a corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.TransferEvent")," is emitted,\nindicating transfer from the ",(0,o.kt)("em",{parentName:"p"},"proposal deposit account")," to the submitter's\naccount.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"In case the proposal has been rejected, the deposit is transferred to the\ncommon pool and a corresponding ",(0,o.kt)("inlineCode",{parentName:"p"},"staking.TransferEvent")," is emitted,\nindicating transfer from the ",(0,o.kt)("em",{parentName:"p"},"proposal deposit account")," to the common pool\naccount."))),(0,o.kt)("h3",{id:"proposal-content-execution"},"Proposal Content Execution"),(0,o.kt)("p",null,"After any proposal is successfully executed the corresponding\n",(0,o.kt)("inlineCode",{parentName:"p"},"ProposalExecutedEvent")," is emitted with the following structure:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-golang"},'type ProposalExecutedEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n}\n')),(0,o.kt)("h4",{id:"upgrade-proposal"},"Upgrade Proposal"),(0,o.kt)("p",null,"The set of pending upgrades is checked to make sure that no upgrades are\ncurrently pending within ",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," of the upgrade descriptor's\n",(0,o.kt)("inlineCode",{parentName:"p"},"epoch")," field. If there is such an existing pending upgrade the upgrade proposal\nexecution fails."),(0,o.kt)("p",null,"When an upgrade proposal is executed, a new entry is added to the list of\npending upgrades using ",(0,o.kt)("inlineCode",{parentName:"p"},"epoch")," as ",(0,o.kt)("inlineCode",{parentName:"p"},""),"."),(0,o.kt)("p",null,"On each epoch transition (as part of ",(0,o.kt)("inlineCode",{parentName:"p"},"BeginBlock"),") it is checked whether a\npending upgrade is scheduled for that epoch. In case it is and we are not\nrunning the new version, the consensus layer will panic. Otherwise, the pending\nupgrade proposal is removed."),(0,o.kt)("h4",{id:"cancel-upgrade-proposal"},"Cancel Upgrade Proposal"),(0,o.kt)("p",null,"When a cancel upgrade proposal is executed, the proposal identified by\n",(0,o.kt)("inlineCode",{parentName:"p"},"proposal_id")," is looked up and removed from the list of pending upgrades. In\ncase the pending upgrade does not exist anymore, no action is performed."),(0,o.kt)("h3",{id:"consensus-parameters"},"Consensus Parameters"),(0,o.kt)("p",null,"This proposal introduces the following new consensus parameters in the\ngovernance module:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"gas_costs")," (transaction.Costs) are the governance transaction gas costs.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"min_proposal_deposit")," (base units) specifies the number of base units that\nare deposited when creating a new proposal.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"voting_period")," (epochs) specifies the number of epochs after which the voting\nfor a proposal is closed and the votes are tallied.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"quorum")," (uint8: ","[","0,100","]",") specifies the minimum percentage of voting power\nthat needs to be cast on a proposal for the result to be valid.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"threshold")," (uint8: ","[","0,100","]",") specifies the minimum percentage of ",(0,o.kt)("inlineCode",{parentName:"p"},"VoteYes"),"\nvotes in order for a proposal to be accepted.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," (epochs) specifies the minimum number of epochs\nbetween the current epoch and the proposed upgrade epoch for the upgrade\nproposal to be valid. Additionally specifies the minimum number of epochs\nbetween two consecutive pending upgrades.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_cancel_min_epoch_diff")," (epochs) specifies the minimum number of\nepochs between the current epoch and the proposed upgrade epoch for the\nupgrade cancellation proposal to be valid."))),(0,o.kt)("p",null,"The following parameter sanity checks are introduced:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Product of ",(0,o.kt)("inlineCode",{parentName:"p"},"quorum")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"threshold")," must be 2/3+.")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},(0,o.kt)("inlineCode",{parentName:"p"},"voting_period")," must be less than ",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_min_epoch_diff")," and\n",(0,o.kt)("inlineCode",{parentName:"p"},"upgrade_cancel_min_epoch_diff"),"."))),(0,o.kt)("h2",{id:"consequences"},"Consequences"),(0,o.kt)("h3",{id:"positive"},"Positive"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The consensus layer can coordinate on upgrades.")),(0,o.kt)("h3",{id:"negative"},"Negative"),(0,o.kt)("h3",{id:"neutral"},"Neutral"),(0,o.kt)("h2",{id:"references"},"References"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d089813a.82685a81.js b/assets/js/d089813a.82685a81.js new file mode 100644 index 0000000000..35fa9ecf55 --- /dev/null +++ b/assets/js/d089813a.82685a81.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6889],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var r=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},m=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,a=e.originalType,l=e.parentName,m=i(e,["components","mdxType","originalType","parentName"]),p=c(n),d=s,h=p["".concat(l,".").concat(d)]||p[d]||u[d]||a;return n?r.createElement(h,o(o({ref:t},m),{},{components:n})):r.createElement(h,o({ref:t},m))}));function h(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var a=n.length,o=new Array(a);o[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[p]="string"==typeof e?e:s,o[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>i,toc:()=>c});var r=n(7462),s=(n(7294),n(3905));const a={},o="Runtime Messages",i={unversionedId:"core/runtime/messages",id:"core/runtime/messages",title:"Runtime Messages",description:"In order to enable runtimes to perform actions in the consensus layer on their",source:"@site/docs/core/runtime/messages.md",sourceDirName:"core/runtime",slug:"/core/runtime/messages",permalink:"/core/runtime/messages",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/messages.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime IDs",permalink:"/core/runtime/identifiers"},next:{title:"Oasis Node",permalink:"/core/oasis-node"}},l={},c=[{value:"Supported Messages",id:"supported-messages",level:2},{value:"Staking Method Call",id:"staking-method-call",level:3},{value:"Limits",id:"limits",level:2}],m={toc:c},p="wrapper";function u(e){let{components:t,...n}=e;return(0,s.kt)(p,(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("h1",{id:"runtime-messages"},"Runtime Messages"),(0,s.kt)("p",null,"In order to enable runtimes to perform actions in the consensus layer on their\nbehalf, they can emit ",(0,s.kt)("em",{parentName:"p"},"messages")," in each round."),(0,s.kt)("h2",{id:"supported-messages"},"Supported Messages"),(0,s.kt)("p",null,"The following sections describe the methods supported by the consensus roothash\nservice."),(0,s.kt)("h3",{id:"staking-method-call"},"Staking Method Call"),(0,s.kt)("p",null,"The staking method call message enables a runtime to call one of the supported\n",(0,s.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#methods"},"staking service methods"),"."),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"Field name:")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre"},"staking\n")),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"Body:")),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-golang"},'type StakingMessage struct {\n cbor.Versioned\n\n Transfer *staking.Transfer `json:"transfer,omitempty"`\n Withdraw *staking.Withdraw `json:"withdraw,omitempty"`\n}\n')),(0,s.kt)("p",null,(0,s.kt)("strong",{parentName:"p"},"Fields:")),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"v")," must be set to ",(0,s.kt)("inlineCode",{parentName:"li"},"0"),"."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"transfer")," indicates that the ",(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/staking#transfer"},(0,s.kt)("inlineCode",{parentName:"a"},"staking.Transfer")," method")," should be executed."),(0,s.kt)("li",{parentName:"ul"},(0,s.kt)("inlineCode",{parentName:"li"},"withdraw")," indicates that the ",(0,s.kt)("a",{parentName:"li",href:"/core/consensus/services/staking#withdraw"},(0,s.kt)("inlineCode",{parentName:"a"},"staking.Withdraw")," method")," should be executed.")),(0,s.kt)("p",null,"Exactly one of the supported method fields needs to be non-nil, otherwise the\nmessage is considered malformed."),(0,s.kt)("h2",{id:"limits"},"Limits"),(0,s.kt)("p",null,"The maximum number of runtime messages that can be emitted in a single round is\nlimited by the ",(0,s.kt)("inlineCode",{parentName:"p"},"executor.max_messages")," option in the runtime descriptor. Its\nupper bound is the ",(0,s.kt)("a",{parentName:"p",href:"/core/consensus/services/roothash#consensus-parameters"},(0,s.kt)("inlineCode",{parentName:"a"},"max_messages")," consensus parameter")," of the roothash service."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d0da959f.537d7298.js b/assets/js/d0da959f.537d7298.js new file mode 100644 index 0000000000..120a3a59bd --- /dev/null +++ b/assets/js/d0da959f.537d7298.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2337],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>h});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),l=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},m=function(e){var t=l(e.components);return a.createElement(p.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),d=l(n),u=r,h=d["".concat(p,".").concat(u)]||d[u]||c[u]||i;return n?a.createElement(h,o(o({ref:t},m),{},{components:n})):a.createElement(h,o({ref:t},m))}));function h(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[d]="string"==typeof e?e:r,o[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>o,default:()=>c,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var a=n(7462),r=(n(7294),n(3905));const i={},o="Damask Upgrade",s={unversionedId:"node/mainnet/damask-upgrade",id:"node/mainnet/damask-upgrade",title:"Damask Upgrade",description:"This document provides an overview of the changes for the Damask Mainnet",source:"@site/docs/node/mainnet/damask-upgrade.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/damask-upgrade",permalink:"/node/mainnet/damask-upgrade",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/damask-upgrade.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"E* Upgrade",permalink:"/node/mainnet/e-upgrade"},next:{title:"Previous Upgrades",permalink:"/node/mainnet/previous-upgrades"}},p={},l=[{value:"Major Features",id:"major-features",level:2},{value:"Mechanics of the Upgrade",id:"mechanics-of-the-upgrade",level:2},{value:"Proposed State Changes",id:"state-changes",level:2},{value:"General",id:"general",level:3},{value:"Registry",id:"registry",level:3},{value:"Root Hash",id:"root-hash",level:3},{value:"Staking",id:"staking",level:3},{value:"Committee Scheduler",id:"committee-scheduler",level:3},{value:"Random Beacon",id:"random-beacon",level:3},{value:"Governance",id:"governance",level:3},{value:"Consensus",id:"consensus",level:3},{value:"Other",id:"other",level:3},{value:"Launch Support",id:"launch-support",level:2}],m={toc:l},d="wrapper";function c(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"damask-upgrade"},"Damask Upgrade"),(0,r.kt)("p",null,"This document provides an overview of the changes for the Damask Mainnet\nupgrade."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The Damask upgrade on Mainnet is scheduled at epoch ",(0,r.kt)("strong",{parentName:"p"},"13402")," which will happen\naround ",(0,r.kt)("strong",{parentName:"p"},"Apr 11, 2022 at 8:30 UTC"),".")),(0,r.kt)("h2",{id:"major-features"},"Major Features"),(0,r.kt)("p",null,"All features for the Damask upgrade are implemented as part of\n",(0,r.kt)("strong",{parentName:"p"},"Oasis Core 22.1.x")," release series which is a consensus protocol-breaking\nrelease."),(0,r.kt)("p",null,"Summary of the major features is as follows:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Random Beacon"),": The random beacon is used by the consensus layer for\nParaTime committee elections and is a critical component in providing\nsecurity for ParaTimes with an open admission policy.\nTo make the random beacon more performant and scalable, the upgrade\ntransitions the election procedure to one that is based on cryptographic\nsortition of Verifiable Random Function (VRF) outputs.\nFor more details, see ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0010-vrf-elections"},"ADR 0010"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"On-Chain Governance"),": The upgrade simplifies the governance by replacing\nseparate quorum and threshold parameters with a single unified stake threshold\nparameter that represents the percentage of ",(0,r.kt)("em",{parentName:"p"},"yes")," votes in terms of total\nvoting power for a governance proposal to pass.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Performance"),": By simplifying the protocol (executor and storage\ncommittees are merged into a single committee) the upgrade improves ParaTime\ncommittee performance and opens the way for even more improvements on the\nParaTime side. It also leads to simplified configuration of ParaTime nodes.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Upgrades"),": After the Damask upgrade, runtime descriptors will\ninclude information regarding supported versions, and the epoch from which\nthey are valid, which will allow ParaTime upgrades to happen without incurring\ndowntime by having upgrades and the descriptor changes pre-staged well in\nadvance of the upgrade epoch.\nFor more details, see ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0013-runtime-upgrades"},"ADR 0013"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"ParaTime Packaging"),": This upgrade changes runtime bundles to be unified\nacross all supported TEE types and self describing so that configuring\nParaTimes is only a matter of passing in the runtime bundle file.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Consensus and ParaTime Communication"),": The upgrade adds support for\nincoming runtime messages where consensus layer transactions can trigger\nactions inside ParaTimes.\nFor more details, see ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0011-incoming-runtime-messages"},"ADR 0011"),"."),(0,r.kt)("p",{parentName:"li"},"The upgrade also adds support for runtime message results which extends the\nresults of the emitted runtime messages with relevant information beyond\nindicating whether the message execution was successful or not.\nFor more details, see ",(0,r.kt)("a",{parentName:"p",href:"/adrs/0012-runtime-message-results"},"ADR 0012"),"."))),(0,r.kt)("p",null,"In addition to the specified additional features, we also propose the\n",(0,r.kt)("strong",{parentName:"p"},"validator set size")," to be ",(0,r.kt)("strong",{parentName:"p"},"increased from")," the current ",(0,r.kt)("strong",{parentName:"p"},"110 to 120")," as\ndiscussed in the\n",(0,r.kt)("a",{parentName:"p",href:"https://oasiscommunity.slack.com/archives/CMUSJCRFA/p1647881564057319?thread_ts=1647448573.197229&cid=CMUSJCRFA"},"Oasis Community Slack #nodeoperators channel"),"."),(0,r.kt)("p",null,"This upgrade marks an important milestone for the Oasis Network, as it sets the\nfoundation for unlocking the network's full capabilities."),(0,r.kt)("h2",{id:"mechanics-of-the-upgrade"},"Mechanics of the Upgrade"),(0,r.kt)("p",null,"On Mar 24, 2022, the Oasis Protocol Foundation submitted the upgrade governance\nproposal with id of ",(0,r.kt)("inlineCode",{parentName:"p"},"2")," which proposed upgrading the network at epoch 13402."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"In addition to submitting the actual governance proposal to the network, Oasis\nProtocol Foundation also published the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community/discussions/30"},"Damask Upgrade Proposal discussion")," to\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community"},"Oasis Community Forum on GitHub"),".")),(0,r.kt)("p",null,"Node operators which had an active validator node in the validator set had 1\nweek to cast their vote."),(0,r.kt)("p",null,"Validators representing more than 88% of the total stake in the consensus\ncommittee participated in the vote, and 100% of them voted ",(0,r.kt)("em",{parentName:"p"},"yes")," for the proposal."),(0,r.kt)("p",null,"The upgrade will be performed by exporting the network's state at the upgrade\nepoch, updating the ",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"genesis document"),", upgrading the Oasis Node\nand the ParaTime binaries and starting a new network from the new genesis file."),(0,r.kt)("p",null,"This will require coordination between node operators and the Oasis Protocol\nFoundation.\nAll nodes will need to configure the new genesis file that they can generate or\nverify independently and reset/archive any existing state from Mainnet."),(0,r.kt)("p",null,"Once enough nodes (representing 2/3+ of stake) have taken this step, the\nupgraded network will start."),(0,r.kt)("p",null,"For the actual steps that node operators need to make on their nodes, see the\n",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/upgrade-log#damask-upgrade"},"Upgrade Log"),"."),(0,r.kt)("h2",{id:"state-changes"},"Proposed State Changes"),(0,r.kt)("p",null,"The following parts of the genesis document will be updated:"),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"This section will be updated with the exact details as we get closer to the\nupgrade.")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For a more detailed explanation of the parameters below, see the\n",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"Genesis Document")," docs.")),(0,r.kt)("h3",{id:"general"},(0,r.kt)("strong",{parentName:"h3"},"General")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"height"))," will be set to the height of the Mainnet state dump + 1,\n",(0,r.kt)("inlineCode",{parentName:"p"},"8048956"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"genesis_time"))," will be set to",(0,r.kt)("inlineCode",{parentName:"p"},"2022-04-11T09:30:00Z"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"chain_id"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-3"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"halt_epoch"))," will be bumped by ",(0,r.kt)("inlineCode",{parentName:"p"},"10000")," (a little more than a year) to\n",(0,r.kt)("inlineCode",{parentName:"p"},"23807"),"."))),(0,r.kt)("h3",{id:"registry"},(0,r.kt)("strong",{parentName:"h3"},"Registry")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes"))," list contains the registered runtimes' descriptors.\nIn this upgrade, all runtime descriptors will be migrated from version ",(0,r.kt)("inlineCode",{parentName:"p"},"2")," to\nversion ",(0,r.kt)("inlineCode",{parentName:"p"},"3"),"."),(0,r.kt)("p",{parentName:"li"},"The migration will be done automatically with the\n",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes.[id=000000000000000000000000000000000000000000000000e2eaa99fc008f87f].deployments.version")),"\nspecifies Emerald ParaTime's version on Mainnet."),(0,r.kt)("p",{parentName:"li"},"It will be upgraded from version 7.1.0 to 8.2.0 and hence the configuration\nneeds to be manually updated to:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},'"version": {\n "major": 8,\n "minor": 2\n},\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.runtimes.[id=000000000000000000000000000000000000000000000000e199119c992377cb].deployments")),"\nspecifies Cipher ParaTime's version and TEE identity on Mainnet."),(0,r.kt)("p",{parentName:"li"},"It will be upgraded from version 1.0.0 to 1.1.0 and hence the configuration\nneeds to be manually updated to:"),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},'"version": {\n "major": 1,\n "minor": 1\n},\n"valid_from": 0,\n"tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggoiJgre0cDF5arUk9wh0X9eGWr5cHb8LY0A3/msmznHc="\n'))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.suspended_runtimes"))," list contains the suspended registered\nruntimes' descriptors. In this upgrade, all runtime descriptors for suspended\nruntimes will be migrated from version ",(0,r.kt)("inlineCode",{parentName:"p"},"2")," to version ",(0,r.kt)("inlineCode",{parentName:"p"},"3"),"."),(0,r.kt)("p",{parentName:"li"},"The migration will be done automatically with the\n",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis")," command.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Inactive registered entities in ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.entities"))," (and their\ncorresponding nodes in ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"registry.nodes")),") that don't pass the\n",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#staking-thresholds"},"minimum staking thresholds")," will be removed."),(0,r.kt)("p",{parentName:"li"},"The removal will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("h3",{id:"root-hash"},(0,r.kt)("strong",{parentName:"h3"},"Root Hash")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.gas_costs.submit_msg"))," is a new parameter that specifies\nthe cost for a submit message transaction. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"1000"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.params.max_in_runtime_messages"))," is a new parameter that\nspecifies the maximum number of incoming messages that can be queued for\nprocessing by a runtime. It will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"128"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"roothash.runtime_state"))," contains the state roots of the runtimes.\nEmpty fields will be omitted."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("h3",{id:"staking"},(0,r.kt)("strong",{parentName:"h3"},"Staking")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.thresholds"))," specifies the minimum number of tokens that\nneed to be staked in order for a particular entity or a particular type of\nnode to participate in the network."),(0,r.kt)("p",{parentName:"li"},"The ",(0,r.kt)("inlineCode",{parentName:"p"},"node-storage")," key is removed since Oasis Core 22.0+ removes separate\nstorage nodes.\nFor more details, see: ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/pull/4308"},"Oasis Core #4308"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.min_transfer"))," is a new parameter that specifies the\nminimum number of tokens one can transfer.\nIt will be set to 10,000,000 base units, or 0.01 ROSE tokens."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.min_transact_balance"))," is a new parameter that specifies\nthe minimum general balance an account must have to be able to perform\ntransactions on the network.\nIt will be set to 0 base units, meaning this requirement is currently not\nenforced."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("h3",{id:"committee-scheduler"},(0,r.kt)("strong",{parentName:"h3"},"Committee Scheduler")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.min_validators"))," is the minimum size of the consensus\ncommittee (i.e. the validator set). It will be increased from ",(0,r.kt)("inlineCode",{parentName:"p"},"15")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"30"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"scheduler.params.max_validators"))," is the maximum size of the consensus\ncommittee (i.e. the validator set). It will be increased from ",(0,r.kt)("inlineCode",{parentName:"p"},"110")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"120"),"."))),(0,r.kt)("h3",{id:"random-beacon"},(0,r.kt)("strong",{parentName:"h3"},"Random Beacon")),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon"))," object contains parameters controlling the new\n",(0,r.kt)("a",{parentName:"p",href:"/adrs/0010-vrf-elections"},"improved VRF-based random beacon")," introduced in the Damask upgrade."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.base"))," is the network's starting epoch. It will be set to the epoch\nof Mainnet's state dump + 1, ",(0,r.kt)("inlineCode",{parentName:"p"},"13402"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.backend"))," configures the random beacon backend to use.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},'"vrf"')," indicating that the beacon implementing\n",(0,r.kt)("a",{parentName:"p",href:"/adrs/0010-vrf-elections"},"VRF-based random beacon")," should be used."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters"))," control the behavior of the new\n",(0,r.kt)("a",{parentName:"p",href:"/adrs/0010-vrf-elections"},"VRF-based random beacon"),":"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.alpha_hq_threshold"))," is minimal number of\nnodes that need to contribute a VRF proof for the beacon's output to be valid.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"20"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.interval"))," is the duration of an epoch.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"600"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.proof_delay"))," is number of blocks since the\nbeginning of an epoch after a node can still submit its VRF proof.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"400"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.vrf_parameters.gas_costs.vrf_prove"))," specifies the cost for\na VRF prove transaction.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"1000"),"."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("p",null,"The ",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"beacon.params.pvss_parameters"))," control the behavior of the\n",(0,r.kt)("a",{parentName:"p",href:"/adrs/0007-improved-random-beacon"},"previous random beacon implementing a PVSS scheme"),"."),(0,r.kt)("p",null,"Since PVSS is no longer supported, all its configuration options are removed\nas well."),(0,r.kt)("h3",{id:"governance"},(0,r.kt)("strong",{parentName:"h3"},"Governance")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.stake_threshold"))," is a new parameter specifying the\nsingle unified stake threshold representing the percentage of ",(0,r.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes\nin terms of total voting power for a governance proposal to pass.\nIt will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"68")," (i.e. 68%)."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.quorum"))," is the minimum percentage of voting power that\nneeds to be cast on a proposal for the result to be valid."),(0,r.kt)("p",{parentName:"li"},"It will be removed since it is being replaced by the single\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.staking_threshold"))," parameter."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.threshold"))," is the minimum percentage of ",(0,r.kt)("inlineCode",{parentName:"p"},"VoteYes")," votes\nin order for a proposal to be accepted."),(0,r.kt)("p",{parentName:"li"},"It will be removed since it is being replaced by the single\n",(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"governance.params.staking_threshold"))," parameter."),(0,r.kt)("p",{parentName:"li"},"This will be done automatically with the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node debug fix-genesis"),"\ncommand."))),(0,r.kt)("h3",{id:"consensus"},(0,r.kt)("strong",{parentName:"h3"},"Consensus")),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"strong"},"consensus.params.state_checkpoint_interval"))," parameter controls the\ninterval (in blocks) on which state checkpoints should be taken. It will be\nincreased from ",(0,r.kt)("inlineCode",{parentName:"li"},"10000")," to ",(0,r.kt)("inlineCode",{parentName:"li"},"100000")," to improve nodes' performance since\ncomputing checkpoints is I/O intensive.")),(0,r.kt)("h3",{id:"other"},"Other"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"extra_data"))," will be set back to the value in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18"},"Mainnet genesis file"),"\nto include the Oasis Network's genesis quote:"),(0,r.kt)("p",{parentName:"li"},(0,r.kt)("em",{parentName:"p"},"\u201d"),(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F"},(0,r.kt)("em",{parentName:"a"},"Quis custodiet ipsos custodes?")),(0,r.kt)("em",{parentName:"p"},"\u201d ","[","submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre"},'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n')))),(0,r.kt)("h2",{id:"launch-support"},"Launch Support"),(0,r.kt)("p",null,"The Oasis team will be offering live video support during the Damask upgrade.\nVideo call link and calendar details will be shared with node operators via\nemail and Slack."),(0,r.kt)("p",null,"For any additional support, please reach out via the\n",(0,r.kt)("a",{parentName:"p",href:"/get-involved/"},(0,r.kt)("strong",{parentName:"a"},"#nodeoperators")," Oasis Community Slack channel")," with\nyour questions, comments, and feedback related to Damask upgrade."),(0,r.kt)("p",null,"To follow the network, please use one of the many\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards"},"community block explorers"),"."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d18a0ae3.42bbe085.js b/assets/js/d18a0ae3.42bbe085.js new file mode 100644 index 0000000000..edefd9b258 --- /dev/null +++ b/assets/js/d18a0ae3.42bbe085.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8119],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=a.createContext({}),d=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return a.createElement(l.Provider,{value:n},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},c=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),u=d(t),c=r,h=u["".concat(l,".").concat(c)]||u[c]||m[c]||i;return t?a.createElement(h,o(o({ref:n},p),{},{components:t})):a.createElement(h,o({ref:n},p))}));function h(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=c;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[u]="string"==typeof e?e:r,o[1]=s;for(var d=2;d{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>m,frontMatter:()=>i,metadata:()=>s,toc:()=>d});var a=t(7462),r=(t(7294),t(3905));const i={},o="Handling Network Upgrades",s={unversionedId:"node/run-your-node/maintenance/handling-network-upgrades",id:"node/run-your-node/maintenance/handling-network-upgrades",title:"Handling Network Upgrades",description:"Changes between the major consensus network versions are backward and forward",source:"@site/docs/node/run-your-node/maintenance/handling-network-upgrades.md",sourceDirName:"node/run-your-node/maintenance",slug:"/node/run-your-node/maintenance/handling-network-upgrades",permalink:"/node/run-your-node/maintenance/handling-network-upgrades",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/handling-network-upgrades.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Wiping Node State",permalink:"/node/run-your-node/maintenance/wiping-node-state"},next:{title:"Adding or Removing Nodes",permalink:"/node/run-your-node/maintenance/adding-or-removing-nodes"}},l={},d=[{value:"Reaching Upgrade Epoch",id:"reaching-upgrade-epoch",level:2},{value:"Preparing New Genesis File and Wiping State",id:"preparing-new-genesis-file-and-wiping-state",level:2},{value:"Patching Dumped State",id:"patching-dumped-state",level:3},{value:"Download and Verify the Provided Genesis File",id:"verify-genesis",level:3},{value:"Example diff for Mainnet Beta to Mainnet network upgrade",id:"example-diff-for-mainnet-beta-to-mainnet-network-upgrade",level:4},{value:"Wiping State",id:"wiping-state",level:3},{value:"Updating ParaTimes",id:"updating-paratimes",level:2},{value:"Start Your Node",id:"start-your-node",level:2},{value:"Clean Up",id:"clean-up",level:2}],p={toc:d},u="wrapper";function m(e){let{components:n,...t}=e;return(0,r.kt)(u,(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"handling-network-upgrades"},"Handling Network Upgrades"),(0,r.kt)("p",null,"Changes between the major consensus network versions are backward and forward\nbreaking. You have to always run ",(0,r.kt)("strong",{parentName:"p"},"a specific version of the Oasis Core to\nfetch and validate the blocks matching the specific consensus network version"),"."),(0,r.kt)("p",null,"There are two kinds of consensus network upgrades that can occur:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"Seamless upgrade"),": on-chain upgrade without resetting the consensus state or\nchanging the genesis document (e.g. ",(0,r.kt)("a",{parentName:"li",href:"/node/testnet/upgrade-log#2022-04-04-upgrade"},"Testnet upgrade 2022-04-04"),", ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/upgrade-log#2021-08-31-upgrade"},"Mainnet\nupgrade 2021-08-31"),")."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"Dump & restore upgrade"),": requires wiping state and starting the upgraded\nnetwork from a fresh genesis document (e.g. ",(0,r.kt)("a",{parentName:"li",href:"/node/mainnet/upgrade-log#damask-upgrade"},"Mainnet upgrade 2022-04-11\n(Damask)"),", ",(0,r.kt)("a",{parentName:"li",href:"/node/testnet/upgrade-log#2022-03-03-upgrade"},"Testnet upgrade 2022-03-03"),").")),(0,r.kt)("p",null,"The specific Oasis Core version requirements also impact the way how you\n",(0,r.kt)("strong",{parentName:"p"},"initially sync your node with the network"),":"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"If the last network upgrade was a dump & restore one, then your node will\ncomplete the synchronization automatically by fetching and validating all\nblocks following the state in the genesis document."),(0,r.kt)("li",{parentName:"ul"},"If the last network upgrade was a seamless one, you will first need to\ndownload the older version of the Oasis Core to sync the initial blocks\nand then sequentially perform seamless upgrade(s).")),(0,r.kt)("p",null,"For example, at time of writing this guide in order to sync your node from\nscratch on the ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet network")," you needed to do the\nfollowing:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Download the genesis document and run Oasis Core 22.0.x which synced\nblocks from epoch 14209 through (excluding) upgrade epoch 15056."),(0,r.kt)("li",{parentName:"ul"},"Wait until the node automatically stopped, then upgrade to Oasis Core\n22.2.x which synced the blocks from epoch 15056 onwards.")),(0,r.kt)("p",null,"The expected versions of the Oasis Core to sync your node from the latest\ngenesis document on the Mainnet and Testnet are always published on the\n",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," and ",(0,r.kt)("a",{parentName:"p",href:"/node/testnet/"},"Testnet Parameters")," pages respectively."),(0,r.kt)("h2",{id:"reaching-upgrade-epoch"},"Reaching Upgrade Epoch"),(0,r.kt)("p",null,"Once a ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/network#governance-cast-vote"},"governance proposal")," is accepted the node will automatically stop when\nreaching the ",(0,r.kt)("strong",{parentName:"p"},"upgrade epoch")," specified in the proposal. The node will\nwrite something like this in the log:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{"caller":"mux.go:426","level":"debug","module":"abci-mux","msg":"dispatching halt hooks for upgrade","ts":"2022-05-06T13:11:41.721994647Z"}\n')),(0,r.kt)("p",null,"and on the error output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-text"},"panic: upgrade: reached upgrade epoch\n")),(0,r.kt)("p",null,"The state of the network at the upgrade epoch height will be automatically\nexported into a genesis file located in\n",(0,r.kt)("inlineCode",{parentName:"p"},"/exports/genesis--at-.json"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"CHAIN_ID")," is the chain ID of the network and ",(0,r.kt)("inlineCode",{parentName:"p"},"LATEST_HEIGHT")," is the\nheight of the last consensus block before the upgrade epoch. This command,\ndepending on the size of the state, may take some time to finish."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"While waiting for the network upgrade epoch, you can check the current height\nand epoch by running:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/serverdir/node/internal.sock\n")),(0,r.kt)("p",{parentName:"admonition"},"and observe the value of the ",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.latest_height")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"consensus.latest_epoch")," fields respectively.")),(0,r.kt)("p",null,"Once the upgrade epoch is reached, follow the instructions in the corresponding\n",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/upgrade-log"},"upgrade log"),"."),(0,r.kt)("h2",{id:"preparing-new-genesis-file-and-wiping-state"},"Preparing New Genesis File and Wiping State"),(0,r.kt)("p",null,"For dump & restore upgrades, the exported genesis file needs to be patched and\nverified accordingly. Then, we wipe the existing consensus state including the\nhistory of all transactions and let the node reload the state from the genesis\nfile."),(0,r.kt)("h3",{id:"patching-dumped-state"},"Patching Dumped State"),(0,r.kt)("p",null,"First, let's run a built-in helper which migrates and updates parts of the\ngenesis file which changed in the new version of Oasis Core. We will provide\nthe dumped genesis file as the input and write the new version of the genesis\nfile into ",(0,r.kt)("inlineCode",{parentName:"p"},"genesis_dump.json"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node debug fix-genesis --genesis.file genesis--at-.json --genesis.new_file genesis_dump.json\n")),(0,r.kt)("p",null,"Other parts of the genesis need to be updated manually, as described in each\nupgrade's ",(0,r.kt)("em",{parentName:"p"},"Proposed State Changes")," section (e.g. ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/damask-upgrade#proposed-state-changes"},"Damask upgrade's Proposed\nState Changes"),", ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/previous-upgrades/cobalt-upgrade#proposed-state-changes"},"Cobalt upgrade's Proposed State Changes"),")."),(0,r.kt)("h3",{id:"verify-genesis"},"Download and Verify the Provided Genesis File"),(0,r.kt)("p",null,"In addition, download the new genesis file linked in the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),"\nand save it as ",(0,r.kt)("inlineCode",{parentName:"p"},"/serverdir/etc/genesis.json"),"."),(0,r.kt)("p",null,"Compare the dumped state with the downloaded genesis file:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"diff --unified=3 genesis_dump.json genesis.json\n")),(0,r.kt)("p",null,"If you obtain the same result, then you have successfully verified the provided\ngenesis file!"),(0,r.kt)("h4",{id:"example-diff-for-mainnet-beta-to-mainnet-network-upgrade"},"Example diff for Mainnet Beta to Mainnet network upgrade"),(0,r.kt)("p",null,"Let's look at what ",(0,r.kt)("inlineCode",{parentName:"p"},"diff")," returned before performing manual changes to the\ngenesis file for the Mainnet network upgrade:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-diff"},'--- genesis_dump.json 2020-11-16 17:49:46.864554271 +0100\n+++ genesis.json 2020-11-16 17:49:40.353496022 +0100\n@@ -1,7 +1,7 @@\n {\n "height": 702000,\n- "genesis_time": "2020-11-18T13:38:00Z",\n- "chain_id": "mainnet-beta-2020-10-01-1601568000",\n+ "genesis_time": "2020-11-18T16:00:00Z",\n+ "chain_id": "oasis-1",\n "epochtime": {\n "params": {\n "interval": 600\n@@ -2506,1563 +2506,1779 @@\n "debonding_interval": 336,\n "reward_schedule": [\n {\n- "until": 3696,\n- "scale": "1595"\n+ "until": 4842,\n+ "scale": "2081"\n },\n {\n- "until": 3720,\n- "scale": "1594"\n+ "until": 4866,\n+ "scale": "2080"\n },\n\n ... trimmed ...\n\n {\n- "until": 35712,\n+ "until": 36882,\n "scale": "2"\n },\n {\n- "until": 35760,\n+ "until": 36930,\n "scale": "1"\n }\n ],\n@@ -4087,7 +4303,6 @@\n "transfer": 1000\n },\n "min_delegation": "100000000000",\n- "disable_transfers": true,\n "fee_split_weight_propose": "2",\n "fee_split_weight_vote": "1",\n "fee_split_weight_next_propose": "1",\n@@ -4097,7 +4312,7 @@\n "token_symbol": "ROSE",\n "token_value_exponent": 9,\n "total_supply": "10000000000000000000",\n- "common_pool": "1835039672187348312",\n+ "common_pool": "2285039672187348312",\n "last_block_fees": "0",\n "ledger": {\n "oasis1qp0l8r2s3076n4xrq8av0uuqegj7z9kq55gu5exy": {\n@@ -6419,7 +6634,7 @@\n },\n "oasis1qrad7s7nqm4gvyzr8yt2rdk0ref489rn3vn400d6": {\n "general": {\n- "balance": "1633038701000000000"\n+ "balance": "1183038701000000000"\n },\n "escrow": {\n "active": {\n@@ -9862,6 +10077,8 @@\n }\n }\n },\n- "halt_epoch": 1440,\n- "extra_data": null\n+ "halt_epoch": 9940,\n+ "extra_data": {\n+ "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n+ }\n }\n')),(0,r.kt)("p",null,"We can observe that the provided genesis file mostly updates some particular\nnetwork parameters. In addition, some ROSE tokens were transferred from an\naccount to the Common Pool. All other things remained unchanged."),(0,r.kt)("p",null,"Let's break down the diff and explain what has changed."),(0,r.kt)("p",null,"The following genesis file fields will always change on a network upgrade:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"chain_id"),": A unique ID of the network. Mainnet upgrades follow a pattern ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-1"),", ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-2"),", ..."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"genesis_time"),": Time from which the genesis file is valid."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"halt_epoch"),": The epoch when the node will stop functioning. We set this to\nintentionally force an upgrade.")),(0,r.kt)("p",null,"The following fields were a particular change in this upgrade:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"staking.params.reward_schedule"),": This field describes the staking reward\nmodel. It was changed to start at 20% (annualized) and range from 20% to 2%\nover the first 4 years of the network. For more details, see the ",(0,r.kt)("a",{parentName:"li",href:"/general/oasis-network/token-metrics-and-distribution"},"Token\nMetrics and Distribution")," doc."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"staking.params.disable_transfers"),": This field was removed to enable token\ntransfers."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"staking.common_pool"),": This field represents the Common Pool. Its balance was\nincreased by 450M ROSE to fund increased staking rewards."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"staking.ledger.oasis1qrad7s7nqm4gvyzr8yt2rdk0ref489rn3vn400d6"),": This field\ncorresponds to the Community and Ecosystem Wallet. Its ",(0,r.kt)("inlineCode",{parentName:"li"},"general.balance")," was\nreduced by 450M ROSE and transferred to the Common Pool to fund increased\nstaking rewards."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"extra_data"),": This field can hold network's extra data, but is currently\nignored everywhere. For this upgrade, we changed it back to the value in the\nMainnet Beta genesis file to include the Oasis network's genesis quote:\n",(0,r.kt)("em",{parentName:"li"},"\u201d"),(0,r.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F"},(0,r.kt)("em",{parentName:"a"},"Quis custodiet ipsos custodes?")),(0,r.kt)("em",{parentName:"li"},"\u201d ","[","submitted by Oasis Community Member Daniyar Borangaziyev","]","."))),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The balances in the genesis file are enumerated in base units with 1 ROSE token\nequaling 10^9 (i.e. billion) base units. For more details, see the\n",(0,r.kt)("a",{parentName:"p",href:"/node/genesis-doc#parameters"},"Genesis Document"),".")),(0,r.kt)("h3",{id:"wiping-state"},"Wiping State"),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"We do not suggest that you wipe ",(0,r.kt)("em",{parentName:"p"},"all")," state. You might lose node identities and\nkeys if you do it this way.")),(0,r.kt)("p",null,"The process is described in the\n",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity"},"Wiping Node State"),"\ndocument."),(0,r.kt)("h2",{id:"updating-paratimes"},"Updating ParaTimes"),(0,r.kt)("p",null,"If you are running a compute or a client ParaTime node, you will often need to\nupgrade the ParaTime. The required ParaTime versions are stored in the network\nregistry. The command below queries the registry and extracts the version\ninformation for the Paratime\n",(0,r.kt)("inlineCode",{parentName:"p"},"00000000000000000000000000000000000000000000000072c8215e60d5bca7"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node registry runtime list -v -a unix:/serverdir/node/internal.sock \\| \njq 'select(.id==\"00000000000000000000000000000000000000000000000072c8215e60d5bca7\") | .deployments'\n")),(0,r.kt)("p",null,"At time of writing the Emerald ParaTime on Testnet has the following record:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'[\n {\n "version": {\n "major": 7,\n "minor": 1\n },\n "valid_from": 14320\n },\n {\n "version": {\n "major": 8\n },\n "valid_from": 15056\n }\n]\n')),(0,r.kt)("p",null,"The record above specifies that after epoch 14320, Emerald version 7.1.0 is\nrequired and from epoch 15056, Emerald 8.0.0. If you are running a compute\nnode, ",(0,r.kt)("strong",{parentName:"p"},"the installed ParaTime version must match exactly the ParaTime version\nin the registry"),"! If you are running a client node, ParaTime state syncing\nwill be performed regardless of the version installed."),(0,r.kt)("p",null,"Oasis node supports configuring multiple versions of ParaTime bundles, for\nexample: "),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"runtime:\n paths:\n - /path/to/emerald-paratime-7.1.0-testnet.orc\n - /path/to/emerald-paratime-8.0.0-testnet.orc\n")),(0,r.kt)("p",null,"The node will then automatically run the correct version of the ParaTime as\nspecified in the registry."),(0,r.kt)("h2",{id:"start-your-node"},"Start Your Node"),(0,r.kt)("p",null,"This will depend on your process manager. If you don't have a process manager,\nyou should use one. However, to start the node without a process manager you\ncan start the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Oasis Node")," like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /serverdir/etc/config.yml\n")),(0,r.kt)("h2",{id:"clean-up"},"Clean Up"),(0,r.kt)("p",null,"After you're comfortable with your node deployment, you can remove the old\nOasis Core version and the intermediate\n",(0,r.kt)("inlineCode",{parentName:"p"},"genesis--at-.json")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"genesis_dump.json")," files."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d31e1216.2350258b.js b/assets/js/d31e1216.2350258b.js new file mode 100644 index 0000000000..3d084cb573 --- /dev/null +++ b/assets/js/d31e1216.2350258b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8080],{5980:o=>{o.exports=JSON.parse('{"title":"Common Functionality","slug":"core/common-functionality","permalink":"/core/common-functionality","navigation":{"previous":{"title":"oasis-node CLI","permalink":"/core/oasis-node/cli"},"next":{"title":"Encoding","permalink":"/core/encoding"}}}')}}]); \ No newline at end of file diff --git a/assets/js/d60ba3f8.86583462.js b/assets/js/d60ba3f8.86583462.js new file mode 100644 index 0000000000..14235a3395 --- /dev/null +++ b/assets/js/d60ba3f8.86583462.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[97],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>k});var n=a(7294);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var s=n.createContext({}),o=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},d=function(e){var t=o(e.components);return n.createElement(s.Provider,{value:t},e.children)},m="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,i=e.mdxType,r=e.originalType,s=e.parentName,d=p(e,["components","mdxType","originalType","parentName"]),m=o(a),u=i,k=m["".concat(s,".").concat(u)]||m[u]||c[u]||r;return a?n.createElement(k,l(l({ref:t},d),{},{components:a})):n.createElement(k,l({ref:t},d))}));function k(e,t){var a=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=a.length,l=new Array(r);l[0]=u;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p[m]="string"==typeof e?e:i,l[1]=p;for(var o=2;o{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>c,frontMatter:()=>r,metadata:()=>p,toc:()=>o});var n=a(7462),i=(a(7294),a(3905));const r={description:"Additional Sapphire precompiles for encryption and confidentiality"},l="Precompiles",p={unversionedId:"dapp/sapphire/precompiles",id:"dapp/sapphire/precompiles",title:"Precompiles",description:"Additional Sapphire precompiles for encryption and confidentiality",source:"@site/docs/dapp/sapphire/precompiles.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/precompiles",permalink:"/dapp/sapphire/precompiles",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/precompiles.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Additional Sapphire precompiles for encryption and confidentiality"},sidebar:"developers",previous:{title:"Gasless Transactions",permalink:"/dapp/sapphire/gasless"},next:{title:"Standard Contract Addresses",permalink:"/dapp/sapphire/addresses"}},s={},o=[{value:"Library",id:"library",level:2},{value:"Generating Pseudo-Random Bytes",id:"generating-pseudo-random-bytes",level:2},{value:"Implementation Details",id:"implementation-details",level:3},{value:"X25519 Key Derivation",id:"x25519-key-derivation",level:2},{value:"Example",id:"example",level:3},{value:"Deoxys-II Encryption",id:"deoxys-ii-encryption",level:2},{value:"Example",id:"example-1",level:3},{value:"Signing Keypairs Generation",id:"signing-keypairs-generation",level:2},{value:"Gas Cost",id:"gas-cost",level:3},{value:"Public Key Format",id:"public-key-format",level:3},{value:"Example",id:"example-2",level:3},{value:"Message Signing",id:"message-signing",level:2},{value:"Signing Algorithms",id:"signing-algorithms",level:3},{value:"Example",id:"example-3",level:3},{value:"Signature Verification",id:"signature-verification",level:2},{value:"Gas Cost",id:"gas-cost-1",level:3},{value:"Example",id:"example-4",level:3},{value:"SHA-512",id:"sha-512",level:2},{value:"Gas Cost",id:"gas-cost-2",level:3},{value:"Example",id:"example-5",level:3},{value:"SHA-512/256",id:"sha-512256",level:2},{value:"Gas Cost",id:"gas-cost-3",level:3},{value:"Example",id:"example-6",level:3},{value:"Subcall",id:"subcall",level:2},{value:"Gas Cost",id:"gas-cost-4",level:3},{value:"Example",id:"example-7",level:3}],d={toc:o},m="wrapper";function c(e){let{components:t,...a}=e;return(0,i.kt)(m,(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"precompiles"},"Precompiles"),(0,i.kt)("p",null,"In addition to the standard EVM precompiles, Sapphire provides a number\nof further cryptography-related ones to make some operations easier and\ncheaper to perform: x25519 key derivation, Deoxys-II-based encryption\nand decryption, signing key generation, message digest signing and\nverification."),(0,i.kt)("p",null,"These can be called in the same way as other precompiles by dispatching\ncalls to specific well-known contract addresses, as described below."),(0,i.kt)("p",null,"Input parameters should be packed into a contiguous memory region with\neach chunk of data padded to 32 bytes as usual. The recommended way to\nconstruct parameter byte sequences in Solidity is with ",(0,i.kt)("inlineCode",{parentName:"p"},"abi.encode")," and\n",(0,i.kt)("inlineCode",{parentName:"p"},"abi.decode"),", which will transparently handle things like putting\n",(0,i.kt)("inlineCode",{parentName:"p"},"bytes")," lengths in the correct position."),(0,i.kt)("h2",{id:"library"},"Library"),(0,i.kt)("p",null,"While it is possible to call the precompiles directly using Yul or, for\nexample, ",(0,i.kt)("inlineCode",{parentName:"p"},"abi.encode")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"abi.decode")," in Solidity, we recommend always\nusing the ",(0,i.kt)("inlineCode",{parentName:"p"},"contracts/Sapphire.sol")," wrapper library for a more comfortable\nexperience. The examples below are written against it. The library is provided\nby the ",(0,i.kt)("inlineCode",{parentName:"p"},"@oasisprotocol/sapphire-contracts")," npm package."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"yarn add -D @oasisprotocol/sapphire-contracts\n")),(0,i.kt)("p",null,"Then, you can use the wrapper library inside your ",(0,i.kt)("inlineCode",{parentName:"p"},".sol")," contract file as\nfollows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'pragma solidity ^0.8.13;\n\nimport "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";\n\ncontract Test {\n constructor() {}\n function test() public view returns (bytes32) {\n return Sapphire.deriveSymmetricKey("public key as bytes32", "private key as bytes32");\n }\n}\n')),(0,i.kt)("p",null,"Feel free to discover other convenient libraries for Solidity inside the\n",(0,i.kt)("inlineCode",{parentName:"p"},"contracts/")," folder of the\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime"},"Oasis Sapphire repository"),"!"),(0,i.kt)("h2",{id:"generating-pseudo-random-bytes"},"Generating Pseudo-Random Bytes"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000001")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"uint num_bytes, bytes pers")),(0,i.kt)("li",{parentName:"ul"},"Gas cost: 10,000 minimum plus 240 per output word plus 60 per word of\nthe personalization string.")),(0,i.kt)("p",null,"Generate ",(0,i.kt)("inlineCode",{parentName:"p"},"num_bytes")," pseudo-random bytes, with an optional personalization\nstring (",(0,i.kt)("inlineCode",{parentName:"p"},"pers"),") added into the hashing algorithm to increase domain separation\nwhen needed."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'bytes memory randomPad = Sapphire.randomBytes(64, "");\n')),(0,i.kt)("h3",{id:"implementation-details"},"Implementation Details"),(0,i.kt)("admonition",{title:"Prior to 0.6.0",type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"All view queries and simulated transactions (via ",(0,i.kt)("inlineCode",{parentName:"p"},"eth_call"),") would receive the\nsame entropy in-between blocks if they use the same ",(0,i.kt)("inlineCode",{parentName:"p"},"num_bytes")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"pers")," parameters.\nIf your contract requires confidentiality you should generate a secret in the constructor\nto be used with view calls:"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},"Sapphire.randomBytes(64, abi.encodePacked(msg.sender, this.perContactSecret));\n"))),(0,i.kt)("p",null,'The mode (e.g. simulation or \'view call\' vs transaction execution) is fed to TupleHash (among other\nblock-dependent components) to derive the "key id", which is then used to derive a per-block VRF key\nfrom epoch-ephemeral entropy (using KMAC256 and cSHAKE) so a different "key id" will result in a\nunique per-block VRF key. This per-block VRF key is then used to create the per-block root RNG which\nis then used to derive domain-separated (using Merlin transcripts) per-transaction random RNGs which\nare then exposed via this precompile. The KMAC, cSHAKE and TupleHash algorithms are SHA-3 derived functions\ndefined in ',(0,i.kt)("a",{parentName:"p",href:"https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf"},"NIST Special Publication 800-185"),"."),(0,i.kt)("h2",{id:"x25519-key-derivation"},"X25519 Key Derivation"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000002")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"bytes32 public_key, bytes32 private_key")),(0,i.kt)("li",{parentName:"ul"},"Gas cost: 100,000")),(0,i.kt)("h3",{id:"example"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},"bytes32 publicKey = ... ;\nbytes32 privateKey = ... ;\nbytes32 symmetric = Sapphire.deriveSymmetricKey(publicKey, privateKey);\n")),(0,i.kt)("h2",{id:"deoxys-ii-encryption"},"Deoxys-II Encryption"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Encryption precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000003")),(0,i.kt)("li",{parentName:"ul"},"Decryption precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000004")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"bytes32 key, bytes32 nonce, bytes text_or_ciphertext, bytes additional_data")),(0,i.kt)("li",{parentName:"ul"},"Gas cost: 50,000 minimum plus 100 per word of input")),(0,i.kt)("h3",{id:"example-1"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'bytes32 key = ... ;\nbytes32 nonce = ... ;\nbytes memory text = "plain text";\nbytes memory ad = "additional data";\nbytes memory encrypted = Sapphire.encrypt(key, nonce, text, ad);\nbytes memory decrypted = Sapphire.decrypt(key, nonce, encrypted, ad);\n')),(0,i.kt)("h2",{id:"signing-keypairs-generation"},"Signing Keypairs Generation"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000005")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"uint method, bytes seed")),(0,i.kt)("li",{parentName:"ul"},"Return value: ",(0,i.kt)("inlineCode",{parentName:"li"},"bytes public_key, bytes private_key")),(0,i.kt)("li",{parentName:"ul"},"Gas cost: method-dependent base cost, see below")),(0,i.kt)("p",null,"The available methods are items in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Sapphire.SigningAlg")," enum. Note,\nhowever, that the generation method ignores subvariants, so all three\ned25519-based are equivalent, and all secp256k1 & secp256r1 based methods are\nequivalent. ",(0,i.kt)("inlineCode",{parentName:"p"},"Sr25519")," is not available and will return an error."),(0,i.kt)("h3",{id:"gas-cost"},"Gas Cost"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Ed25519: 1,000 gas",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"0")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Oasis"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"1")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Pure"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"2")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519PrehashedSha512"),")"))),(0,i.kt)("li",{parentName:"ul"},"Secp256k1: 1,500 gas.",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"3")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1Oasis"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"4")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedKeccak256"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"5")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedSha256"),")"))),(0,i.kt)("li",{parentName:"ul"},"Secp256r1: 4,000 gas",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"7")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256r1PrehashedSha256"),")")))),(0,i.kt)("h3",{id:"public-key-format"},"Public Key Format"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Ed25519: 32 bytes"),(0,i.kt)("li",{parentName:"ul"},"Secp256k1 & Secp256r1: 33 bytes, compressed format (0x02 or 0x03 prefix, then 32 byte X coordinate)")),(0,i.kt)("h3",{id:"example-2"},"Example"),(0,i.kt)("p",null,"Using the Sapphire library:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'bytes memory seed = hex"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";\nbytes memory publicKey;\nbytes memory privateKey;\n(publicKey, privateKey) = Sapphire.generateSigningKeyPair(Sapphire.SigningAlg.Ed25519Pure, seed);\n')),(0,i.kt)("h2",{id:"message-signing"},"Message Signing"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000006")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"uint method, bytes private_key, bytes context_or_digest, bytes message")),(0,i.kt)("li",{parentName:"ul"},"Gas cost: see below for the method-dependent base cost, plus 8 gas per 32 bytes of context and message except digest.")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"context_or_digest")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"messages")," parameters change in meaning slightly\ndepending on the method requested. For methods that take a context in addition\nto the message you must pass the context in the ",(0,i.kt)("inlineCode",{parentName:"p"},"context_or_digest")," parameter\nand use ",(0,i.kt)("inlineCode",{parentName:"p"},"message")," as expected. For methods that take a pre-existing hash of the\nmessage, pass that in ",(0,i.kt)("inlineCode",{parentName:"p"},"context_or_digest")," and leave ",(0,i.kt)("inlineCode",{parentName:"p"},"message")," empty.\nSpecifically the ",(0,i.kt)("inlineCode",{parentName:"p"},"Ed25519Oasis")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"Secp256k1Oasis")," variants take both a\ncontext and a message (each are variable length ",(0,i.kt)("inlineCode",{parentName:"p"},"bytes"),"), the context serves as\na domain separator."),(0,i.kt)("h3",{id:"signing-algorithms"},"Signing Algorithms"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"0")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Oasis"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"1,500 gas"),(0,i.kt)("li",{parentName:"ul"},"variable length context and message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"1")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Pure"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"1,500 gas"),(0,i.kt)("li",{parentName:"ul"},"empty context, variable length message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"2")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519PrehashedSha512"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"1,500 gas"),(0,i.kt)("li",{parentName:"ul"},"pre-existing SHA-512 hash (64 bytes) as context, empty message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"3")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1Oasis"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"3,000 gas"),(0,i.kt)("li",{parentName:"ul"},"variable length context and message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"4")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedKeccak256"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"3,000 gas"),(0,i.kt)("li",{parentName:"ul"},"pre-existing hash (32 bytes) as context, empty message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"5")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedSha256"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"3,000 gas"),(0,i.kt)("li",{parentName:"ul"},"pre-existing hash (32 bytes) as context, empty message"))),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"7")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256r1PrehashedSha256"),")",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"9,000 gas"),(0,i.kt)("li",{parentName:"ul"},"pre-existing hash (32 bytes) as context, empty message")))),(0,i.kt)("h3",{id:"example-3"},"Example"),(0,i.kt)("p",null,"Using the Sapphire library:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'Sapphire.SigningAlg alg = Sapphire.SigningAlg.Ed25519Pure;\nbytes memory pk;\nbytes memory sk;\n(pk, sk) = Sapphire.generateSigningKeyPair(alg, Sapphire.randomBytes(32, ""));\nbytes memory signature = Sapphire.sign(alg, sk, "", "signed message");\n')),(0,i.kt)("h2",{id:"signature-verification"},"Signature Verification"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000007")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"uint method, bytes public_key, bytes context_or_digest, bytes message, bytes signature"))),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"method"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"context_or_digest")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"message")," parameters have the same meaning\nas described above in the Message Signing section."),(0,i.kt)("h3",{id:"gas-cost-1"},"Gas Cost"),(0,i.kt)("p",null,"The algorithm-specific base cost below, with an additional 8 gas per 32 bytes of\n",(0,i.kt)("inlineCode",{parentName:"p"},"context")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"message")," for the ",(0,i.kt)("inlineCode",{parentName:"p"},"Ed25519Oasis"),", ",(0,i.kt)("inlineCode",{parentName:"p"},"Ed25519Pure")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"Secp256k1Oasis")," algorithms."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Ed25519: 2,000 gas",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"0")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Oasis"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"1")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519Pure"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"2")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Ed25519PrehashedSha512"),")"))),(0,i.kt)("li",{parentName:"ul"},"Secp256k1: 3,000 gas",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"3")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1Oasis"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"4")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedKeccak256"),")"),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"5")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256k1PrehashedSha256"),")"))),(0,i.kt)("li",{parentName:"ul"},"Secp256r1: 7,900 gas",(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"7")," (",(0,i.kt)("inlineCode",{parentName:"li"},"Secp256r1PrehashedSha256"),")")))),(0,i.kt)("h3",{id:"example-4"},"Example"),(0,i.kt)("p",null,"Using the Sapphire library:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'Sapphire.SigningAlg alg = Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;\nbytes memory pk;\nbytes memory sk;\nbytes memory digest = abi.encodePacked(keccak256("signed message"));\n(pk, sk) = Sapphire.generateSigningKeyPair(alg, Sapphire.randomBytes(32, ""));\nbytes memory signature = Sapphire.sign(alg, sk, digest, "");\nrequire( Sapphire.verify(alg, pk, digest, "", signature) );\n')),(0,i.kt)("h2",{id:"sha-512"},"SHA-512"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000101")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"bytes input_data"))),(0,i.kt)("p",null,"Hash the input data with SHA-512, according to ",(0,i.kt)("a",{parentName:"p",href:"https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf"},"NIST.FIPS.180-4")),(0,i.kt)("admonition",{title:"SHA-512 is vulnerable to length-extension attacks",type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"The SHA-512/256 variant (below) is not vulnerable to ",(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Length_extension_attack"},"length-extension attacks"),".\nLength extension attacks are relevant if, among other things, you are computing\nthe hash of a secret message or computing merkle trees.")),(0,i.kt)("h3",{id:"gas-cost-2"},"Gas Cost"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"115 gas, then 13 gas per word")),(0,i.kt)("h3",{id:"example-5"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'bytes memory result = sha512(abi.encodePacked("input data"));\n')),(0,i.kt)("h2",{id:"sha-512256"},"SHA-512/256"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000102")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"bytes input_data"))),(0,i.kt)("p",null,"Hash the input data with SHA-512/256, according to ",(0,i.kt)("a",{parentName:"p",href:"https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf"},"NIST.FIPS.180-4")),(0,i.kt)("h3",{id:"gas-cost-3"},"Gas Cost"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"115 gas, then 13 gas per word")),(0,i.kt)("h3",{id:"example-6"},"Example"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'bytes32 result = sha512_256(abi.encodePacked("input data"));\n')),(0,i.kt)("h2",{id:"subcall"},"Subcall"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Precompile address: ",(0,i.kt)("inlineCode",{parentName:"li"},"0x0100000000000000000000000000000000000102")),(0,i.kt)("li",{parentName:"ul"},"Parameters: ",(0,i.kt)("inlineCode",{parentName:"li"},"string method, bytes cborEncodedParams"))),(0,i.kt)("p",null,"Subcall performs an Oasis SDK call. This allows Sapphire contracts to interact\nwith the Consensus layer and other modules supported by the SDK. For more\ninformation about the specific modules and their available calls see the Oasis\nSDK ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk/src/modules"},"source code"),"."),(0,i.kt)("h3",{id:"gas-cost-4"},"Gas Cost"),(0,i.kt)("p",null,"Varies per operation, refer to the oasis-sdk ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk/src/modules"},"source code"),"."),(0,i.kt)("h3",{id:"example-7"},"Example"),(0,i.kt)("p",null,"TODO: an example"))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d632a858.c59788bc.js b/assets/js/d632a858.c59788bc.js new file mode 100644 index 0000000000..da91f8650a --- /dev/null +++ b/assets/js/d632a858.c59788bc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4426],{3905:(t,e,r)=>{r.d(e,{Zo:()=>c,kt:()=>m});var o=r(7294);function n(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function a(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,o)}return r}function i(t){for(var e=1;e=0||(n[r]=t[r]);return n}(t,e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(n[r]=t[r])}return n}var p=o.createContext({}),s=function(t){var e=o.useContext(p),r=e;return t&&(r="function"==typeof t?t(e):i(i({},e),t)),r},c=function(t){var e=s(t.components);return o.createElement(p.Provider,{value:e},t.children)},u="mdxType",d={inlineCode:"code",wrapper:function(t){var e=t.children;return o.createElement(o.Fragment,{},e)}},h=o.forwardRef((function(t,e){var r=t.components,n=t.mdxType,a=t.originalType,p=t.parentName,c=l(t,["components","mdxType","originalType","parentName"]),u=s(r),h=n,m=u["".concat(p,".").concat(h)]||u[h]||d[h]||a;return r?o.createElement(m,i(i({ref:e},c),{},{components:r})):o.createElement(m,i({ref:e},c))}));function m(t,e){var r=arguments,n=e&&e.mdxType;if("string"==typeof t||n){var a=r.length,i=new Array(a);i[0]=h;var l={};for(var p in e)hasOwnProperty.call(e,p)&&(l[p]=e[p]);l.originalType=t,l[u]="string"==typeof t?t:n,i[1]=l;for(var s=2;s{r.r(e),r.d(e,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var o=r(7462),n=(r(7294),r(3905));const a={description:"How to build your first dApp on OPL"},i="Overview",l={unversionedId:"dapp/opl/introduction",id:"dapp/opl/introduction",title:"Overview",description:"How to build your first dApp on OPL",source:"@site/docs/dapp/opl/introduction.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/introduction",permalink:"/dapp/opl/introduction",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/introduction.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"How to build your first dApp on OPL"},sidebar:"developers",previous:{title:"Oasis Privacy Layer",permalink:"/dapp/opl/"},next:{title:"Setup",permalink:"/dapp/opl/setup"}},p={},s=[{value:"Getting Started",id:"getting-started",level:2}],c={toc:s},u="wrapper";function d(t){let{components:e,...r}=t;return(0,n.kt)(u,(0,o.Z)({},c,r,{components:e,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"overview"},"Overview"),(0,n.kt)("p",null,"On-chain voting is the basis for any decentralized autonomous organization\n(DAO) that would like to foster bottom-up decision making.\nIn this tutorial, you will create a ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Secret_ballot"},"secret ballot"),"\ndApp that can only be built with the Oasis Privacy Layer."),(0,n.kt)("p",null,"Why is this important? ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Secret_ballot"},"Privacy"),"\nprotects the voter (DAO token holder) from intimidation and bullying when\nexercising their right of participation, such as on a protocol.\nVote organizers can encourage participation with ballots not only by protecting\nthe identity of voters, but also by sealing the results of an ongoing\nvote, giving the same weight to the first and last votes."),(0,n.kt)("h2",{id:"getting-started"},"Getting Started"),(0,n.kt)("p",null,"If you have made a dApp before, then you likely know most if not all of\nthe tools covered here! But even if you haven't used all of these tools listed,\nyou should still keep going! We will do this together."),(0,n.kt)("p",null,"By the end of this tutorial, we will have:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"written smart contracts using the OPL ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/OPL.sol"},"library")),(0,n.kt)("li",{parentName:"ul"},"used ",(0,n.kt)("a",{parentName:"li",href:"https://hardhat.org/docs"},"Hardhat")," development environment for OPL"),(0,n.kt)("li",{parentName:"ul"},"used ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/wighawag/hardhat-deploy"},"Hardhat Deploy")," to deploy\nsmarts contracts to a testnet."),(0,n.kt)("li",{parentName:"ul"},"used ",(0,n.kt)("a",{parentName:"li",href:"https://www.pinata.cloud"},"Pinata"),"\nto store simple JSON data. Not everything has to go on a blockchain."),(0,n.kt)("li",{parentName:"ul"},"used ",(0,n.kt)("a",{parentName:"li",href:"https://im-docs.celer.network/developer/celer-im-overview"},"Celer")," to\npass messages cross multiple chains"),(0,n.kt)("li",{parentName:"ul"},"built a simple ",(0,n.kt)("a",{parentName:"li",href:"https://vuejs.org/guide/introduction.html"},"Vue.JS"),"\napp to interact with our dApp through ",(0,n.kt)("a",{parentName:"li",href:"https://docs.metamask.io/wallet"},"MetaMask"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d940ecbe.7fb19e15.js b/assets/js/d940ecbe.7fb19e15.js new file mode 100644 index 0000000000..e9be24b96d --- /dev/null +++ b/assets/js/d940ecbe.7fb19e15.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[198],{1094:e=>{e.exports=JSON.parse('{"title":"3rd Party Custody & Wallets","description":"This document provides an overview of 3rd party custody and wallet solutions supported by the Oasis Network for managing ROSE tokens.","slug":"general/manage-tokens/holding-rose-tokens","permalink":"/general/manage-tokens/holding-rose-tokens","navigation":{"previous":{"title":"Browser Extension","permalink":"/general/manage-tokens/oasis-wallets/browser-extension"},"next":{"title":"Custody Providers","permalink":"/general/manage-tokens/holding-rose-tokens/custody-providers"}}}')}}]); \ No newline at end of file diff --git a/assets/js/d941f4da.af26cff6.js b/assets/js/d941f4da.af26cff6.js new file mode 100644 index 0000000000..1185b54326 --- /dev/null +++ b/assets/js/d941f4da.af26cff6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2978],{3905:(e,t,a)=>{a.d(t,{Zo:()=>h,kt:()=>m});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function s(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=r.createContext({}),p=function(e){var t=r.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},h=function(e){var t=p(e.components);return r.createElement(i.Provider,{value:t},e.children)},c="mdxType",g={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,i=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),c=p(a),u=n,m=c["".concat(i,".").concat(u)]||c[u]||g[u]||o;return a?r.createElement(m,s(s({ref:t},h),{},{components:a})):r.createElement(m,s({ref:t},h))}));function m(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,s=new Array(o);s[0]=u;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[c]="string"==typeof e?e:n,s[1]=l;for(var p=2;p{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>s,default:()=>g,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=a(7462),n=(a(7294),a(3905));const o={},s="Release Process",l={unversionedId:"core/release-process",id:"core/release-process",title:"Release Process",description:"The following steps should be followed when preparing a release.",source:"@site/docs/core/release-process.md",sourceDirName:"core",slug:"/core/release-process",permalink:"/core/release-process",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/release-process.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Processes",permalink:"/core/processes"},next:{title:"Versioning",permalink:"/core/versioning"}},i={},p=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Tooling",id:"tooling",level:2},{value:"Preparing a Regular Release",id:"preparing-a-regular-release",level:2},{value:"Bump Protocol Versions",id:"bump-protocol-versions",level:3},{value:"Prepare the Change Log",id:"prepare-the-change-log",level:3},{value:"Tag Next Release",id:"tag-next-release",level:3},{value:"Ensure GitHub Release Was Published",id:"ensure-github-release-was-published",level:3},{value:"Create stable/YY.MINOR.x Branch",id:"create-stableyyminorx-branch",level:3},{value:"Preparing a Bugfix/Stable Release",id:"preparing-a-bugfixstable-release",level:2},{value:"Back-port Changes",id:"back-port-changes",level:3},{value:"Prepare Change Log for Bugfix/Stable Release",id:"prepare-change-log-for-bugfixstable-release",level:3},{value:"Tag Bugfix/Stable Release",id:"tag-bugfixstable-release",level:3},{value:"Ensure GitHub Release for Bugfix/Stable Release Was Published",id:"ensure-github-release-for-bugfixstable-release-was-published",level:3}],h={toc:p},c="wrapper";function g(e){let{components:t,...a}=e;return(0,n.kt)(c,(0,r.Z)({},h,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"release-process"},"Release Process"),(0,n.kt)("p",null,"The following steps should be followed when preparing a release."),(0,n.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,n.kt)("p",null,"Our release process relies on some tooling that needs to be available on a\nmaintainer's system:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.python.org/"},"Python")," 3.6+."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/towncrier"},"Oasis' towncrier fork"),"."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/lgiordani/punch"},"Punch")," 2.0.x.")),(0,n.kt)("p",null,"Most systems should already have ",(0,n.kt)("a",{parentName:"p",href:"https://www.python.org/"},"Python")," pre-installed."),(0,n.kt)("p",null,"To install ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/towncrier"},"Oasis' towncrier fork")," and ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/lgiordani/punch"},"Punch"),", use ",(0,n.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/"},"pip"),":"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"pip3 install --upgrade \\\n https://github.com/oasisprotocol/towncrier/archive/oasis-master.tar.gz \\\n punch.py~=2.0.0\n")),(0,n.kt)("p",null,"You might want to install the packages to a ",(0,n.kt)("a",{parentName:"p",href:"https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments"},"Python virtual environment")," or\nvia so-called ",(0,n.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/user_guide/#user-installs"},"User install")," (i.e. isolated to the current user)."),(0,n.kt)("h2",{id:"tooling"},"Tooling"),(0,n.kt)("p",null,"Our ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," tooling has some targets that automate parts of the release process\nand try to make it less error-prone:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"changelog"),": Bumps project's version with the ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/lgiordani/punch"},"Punch")," utility and assembles\nthe ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md"},"Change Log")," from the ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md"},"Change Log Fragments")," using the\n",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/towncrier"},"towncrier")," utility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"release-tag"),": After performing a bunch of sanity checks, it tags the git\norigin remote's release branch's ",(0,n.kt)("inlineCode",{parentName:"li"},"HEAD")," with the ",(0,n.kt)("inlineCode",{parentName:"li"},"v")," tag and\npushes it to the remote."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"release-stable-branch"),": Creates and pushes a stable branch for the current\nrelease.")),(0,n.kt)("p",null,"Note that all above targets depend on the ",(0,n.kt)("inlineCode",{parentName:"p"},"fetch-git")," target which fetches the\nlatest changes (including tags) from the git origin remote to ensure the\ncomputed next version and other things are always up-to-date."),(0,n.kt)("p",null,"The version of the Oasis Core's next release is computed automatically using\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/lgiordani/punch"},"Punch")," utility according to the project's ",(0,n.kt)("a",{parentName:"p",href:"/core/versioning"},"Versioning")," scheme."),(0,n.kt)("p",null,"The ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," Make target checks the name of the branch on which the release\nis being made to know which part of the project's version to bump."),(0,n.kt)("p",null,"To customize the release process, one can set the following environment\nvariables:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"GIT_ORIGIN_REMOTE")," (default: ",(0,n.kt)("inlineCode",{parentName:"li"},"origin"),"): Name of the git remote pointing to\nthe canonical upstream git repository."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"RELEASE_BRANCH")," (default: ",(0,n.kt)("inlineCode",{parentName:"li"},"master"),"): Name of the branch where to tag the next\nrelease.")),(0,n.kt)("h2",{id:"preparing-a-regular-release"},"Preparing a Regular Release"),(0,n.kt)("h3",{id:"bump-protocol-versions"},"Bump Protocol Versions"),(0,n.kt)("p",null,"Before a release, make sure that the proper protocol versions were bumped\ncorrectly (see ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go"},(0,n.kt)("inlineCode",{parentName:"a"},"go/common/version/version.go")),"). If not, make a pull request\nthat bumps the respective version(s) before proceeding with the release process."),(0,n.kt)("h3",{id:"prepare-the-change-log"},"Prepare the Change Log"),(0,n.kt)("p",null,"Before a release, all ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md"},"Change Log fragments")," should be assembled into a new\nsection of the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md"},"Change Log")," using the ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," target."),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog"),", and then run ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make"),":"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b changelog\nmake changelog\n")),(0,n.kt)("p",null,"Review the staged changes and make appropriate adjustment to the Change Log\n(e.g. re-order entries, make formatting/spelling fixes, ...)."),(0,n.kt)("p",null,"Replace the ",(0,n.kt)("inlineCode",{parentName:"p"},"")," strings in the protocol versions table just below the\nnext version's heading with appropriate protocol versions as defined in\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go"},"go/common/version/version.go")," file."),(0,n.kt)("p",null,"For example:"),(0,n.kt)("table",null,(0,n.kt)("thead",{parentName:"table"},(0,n.kt)("tr",{parentName:"thead"},(0,n.kt)("th",{parentName:"tr",align:"left"},"Protocol"),(0,n.kt)("th",{parentName:"tr",align:"center"},"Version"))),(0,n.kt)("tbody",{parentName:"table"},(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:"left"},"Consensus"),(0,n.kt)("td",{parentName:"tr",align:"center"},"4.0.0")),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:"left"},"Runtime Host"),(0,n.kt)("td",{parentName:"tr",align:"center"},"2.0.0")),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:"left"},"Runtime Committee"),(0,n.kt)("td",{parentName:"tr",align:"center"},"2.0.0")))),(0,n.kt)("p",null,"After you are content with the changes, commit them, push them to the origin\nand make a pull request."),(0,n.kt)("p",null,"Once the pull request had been reviewed and merged, proceed to the next step."),(0,n.kt)("h3",{id:"tag-next-release"},"Tag Next Release"),(0,n.kt)("p",null,"To create a signed git tag from the latest commit in origin remote's ",(0,n.kt)("inlineCode",{parentName:"p"},"master"),"\nbranch, use:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-tag\n")),(0,n.kt)("p",null,"This command will perform a bunch of sanity checks to prevent common errors\nwhile tagging the next release."),(0,n.kt)("p",null,"After those checks have passed, it will ask for confirmation before proceeding."),(0,n.kt)("h3",{id:"ensure-github-release-was-published"},"Ensure GitHub Release Was Published"),(0,n.kt)("p",null,"After the tag with the next release is pushed to the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"canonical git repository"),",\nthe GitHub Actions ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/.github/workflows/release.yml"},"Release manager workflow")," is triggered which uses the\n",(0,n.kt)("a",{parentName:"p",href:"https://goreleaser.com/"},"GoReleaser")," tool to automatically build the binaries, prepare archives and\nchecksums, and publish a GitHub Release that accompanies the versioned git tag."),(0,n.kt)("p",null,"Browse to ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases"},"Oasis Core's releases page")," and make sure the new release is properly\npublished."),(0,n.kt)("h3",{id:"create-stableyyminorx-branch"},"Create ",(0,n.kt)("inlineCode",{parentName:"h3"},"stable/YY.MINOR.x")," Branch"),(0,n.kt)("p",null,"To prepare a new stable branch from the new release tag and push it to the\norigin remote, use:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-stable-branch\n")),(0,n.kt)("p",null,"This command will perform sanity checks to prevent common errors."),(0,n.kt)("p",null,"After those checks have passed, it will ask for confirmation before proceeding."),(0,n.kt)("h2",{id:"preparing-a-bugfixstable-release"},"Preparing a Bugfix/Stable Release"),(0,n.kt)("p",null,"As mentioned in the ",(0,n.kt)("a",{parentName:"p",href:"/core/versioning"},"Versioning")," documentation, sometimes we will want to\nback-port some fixes (e.g. a security fix) and (backwards compatible) changes\nfrom an upcoming release and release them without also releasing all the other\n(potentially breaking) changes."),(0,n.kt)("p",null,"Set the ",(0,n.kt)("inlineCode",{parentName:"p"},"RELEASE_BRANCH")," environment variable to the name of the stable branch\nof the ",(0,n.kt)("inlineCode",{parentName:"p"},"YY.MINOR")," release you want to back-port the changes to, e.g.\n",(0,n.kt)("inlineCode",{parentName:"p"},"stable/21.2.x"),", and export it:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},'export RELEASE_BRANCH="stable/21.2.x"\n')),(0,n.kt)("h3",{id:"back-port-changes"},"Back-port Changes"),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"backport-foo-${RELEASE_BRANCH#stable/}"),", from the\n",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b backport-foo-${RELEASE_BRANCH#stable/} ${RELEASE_BRANCH}\n")),(0,n.kt)("p",null,"After back-porting all the desired changes, push it to the origin and make a\npull request against the ",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch."),(0,n.kt)("h3",{id:"prepare-change-log-for-bugfixstable-release"},"Prepare Change Log for Bugfix/Stable Release"),(0,n.kt)("p",null,"As with a regular release, the back-ported changes should include the\ncorresponding ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md"},"Change Log Fragments")," that need to be assembled into a new\nsection of the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md"},"Change Log")," using the ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," target."),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog-${RELEASE_BRANCH#stable/}"),", from the\n",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b changelog-${RELEASE_BRANCH#stable/} ${RELEASE_BRANCH}\n")),(0,n.kt)("p",null,"Then run ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make"),"'s ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," target:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make changelog\n")),(0,n.kt)("p",null,(0,n.kt)("em",{parentName:"p"},"NOTE: The ",(0,n.kt)("inlineCode",{parentName:"em"},"changelog")," Make target will bump the ",(0,n.kt)("inlineCode",{parentName:"em"},"MICRO")," part of the version\nautomatically.")),(0,n.kt)("p",null,"Replace the ",(0,n.kt)("inlineCode",{parentName:"p"},"")," strings in the protocol versions table just below the\nnext version's heading with appropriate protocol versions as defined in\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go"},"go/common/version/version.go")," file."),(0,n.kt)("p",null,"After reviewing the staged changes, commit them, push the changes to the origin\nand make a pull request against the ",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch."),(0,n.kt)("p",null,"Once the pull request had been reviewed and merged, proceed to the next step."),(0,n.kt)("h3",{id:"tag-bugfixstable-release"},"Tag Bugfix/Stable Release"),(0,n.kt)("p",null,"As with a regular release, create a signed git tag from the latest commit in\norigin remote's release branch by running the ",(0,n.kt)("inlineCode",{parentName:"p"},"release-tag")," Make target:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-tag\n")),(0,n.kt)("p",null,"After the sanity checks have passed, it will ask for confirmation before\nproceeding."),(0,n.kt)("h3",{id:"ensure-github-release-for-bugfixstable-release-was-published"},"Ensure GitHub Release for Bugfix/Stable Release Was Published"),(0,n.kt)("p",null,"Similar to a regular release, after the tag with the next release is pushed to\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"canonical git repository"),", the GitHub Actions ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/.github/workflows/release.yml"},"Release manager workflow")," is\ntriggered which uses the ",(0,n.kt)("a",{parentName:"p",href:"https://goreleaser.com/"},"GoReleaser")," tool to automatically build a new release."),(0,n.kt)("p",null,"Browse to ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases"},"Oasis Core's releases page")," and make sure the new bugfix/stable\nrelease is properly published."))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d95a60a6.885f6c6a.js b/assets/js/d95a60a6.885f6c6a.js new file mode 100644 index 0000000000..20b4d956e5 --- /dev/null +++ b/assets/js/d95a60a6.885f6c6a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6608],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>k});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var l=n.createContext({}),p=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},m="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),m=p(a),u=r,k=m["".concat(l,".").concat(u)]||m[u]||c[u]||i;return a?n.createElement(k,o(o({ref:t},d),{},{components:a})):n.createElement(k,o({ref:t},d))}));function k(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[m]="string"==typeof e?e:r,o[1]=s;for(var p=2;p{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>c,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var n=a(7462),r=(a(7294),a(3905));const i={},o="Upgrade to Mainnet",s={unversionedId:"node/mainnet/previous-upgrades/mainnet-upgrade",id:"node/mainnet/previous-upgrades/mainnet-upgrade",title:"Upgrade to Mainnet",description:"This document provides an overview of the proposed criteria and changes to upgrade from Mainnet Beta to Mainnet. This has been reviewed and approved by community members and validators of the Oasis Network and is being reproduced and summarized here for easy access.",source:"@site/docs/node/mainnet/previous-upgrades/mainnet-upgrade.md",sourceDirName:"node/mainnet/previous-upgrades",slug:"/node/mainnet/previous-upgrades/mainnet-upgrade",permalink:"/node/mainnet/previous-upgrades/mainnet-upgrade",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/previous-upgrades/mainnet-upgrade.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Cobalt Upgrade",permalink:"/node/mainnet/previous-upgrades/cobalt-upgrade"},next:{title:"Upgrade Log",permalink:"/node/mainnet/upgrade-log"}},l={},p=[{value:"Criteria for Mainnet",id:"criteria-for-mainnet",level:2},{value:"Mechanics of Upgrading to Mainnet",id:"mechanics-of-upgrading-to-mainnet",level:2},{value:"Proposed Changes From Mainnet Beta to Mainnet",id:"proposed-changes-from-mainnet-beta-to-mainnet",level:2},{value:"Mainnet Launch Support",id:"mainnet-launch-support",level:2}],d={toc:p},m="wrapper";function c(e){let{components:t,...a}=e;return(0,r.kt)(m,(0,n.Z)({},d,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"upgrade-to-mainnet"},"Upgrade to Mainnet"),(0,r.kt)("p",null,"This document provides an overview of the proposed criteria and changes to upgrade from Mainnet Beta to Mainnet. This has been ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/community/discussions/1"},"reviewed and approved by community members and validators of the Oasis Network")," and is being reproduced and summarized here for easy access."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"As proposed by the community, the upgrade from Mainnet Beta to Mainnet will kick off on November 18, 2020 at 16:00 UTC.")),(0,r.kt)("h2",{id:"criteria-for-mainnet"},"Criteria for Mainnet"),(0,r.kt)("p",null,"In order to transition from Mainnet Beta to Mainnet, community members have collectively suggested the following criteria be met. This is a collection of community feedback."),(0,r.kt)("ul",{className:"contains-task-list"},(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","Validators representing more than 2/3 of stake in the initial consensus committee successfully get online to launch Mainnet Beta."),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","Beta network runs successfully for at least 10 days."),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","No major security risks on the Beta Network have been discovered or otherwise unremediated and untested in the past 10 days."),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","At least 50 validators run on the Network.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"Throughout Mainnet Beta there have been between 75 and 77 active validators on the network.")))),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","There are NO Oasis Protocol Foundation or Oasis Labs nodes serving as validators."),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","At least one block explorer exists to track network stability, transactions, and validator activity.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"There is much more. See")," ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards"},(0,r.kt)("em",{parentName:"a"},"Block Explorers & Validator Leaderboards"))," ",(0,r.kt)("em",{parentName:"li"},"part of our docs.")))),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","At least one qualified custodian supports the native ROSE token.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"Currently, Anchorage and Finoa support the ROSE token. See")," ",(0,r.kt)("a",{parentName:"li",href:"/general/manage-tokens/holding-rose-tokens/custody-providers"},(0,r.kt)("em",{parentName:"a"},"Custody Providers"))," ",(0,r.kt)("em",{parentName:"li"},"part of our docs.")))),(0,r.kt)("li",{parentName:"ul",className:"task-list-item"},(0,r.kt)("input",{parentName:"li",type:"checkbox",checked:!0,disabled:!0})," ","At least one web wallet or hardware wallet supports native ROSE token.",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"Currently, Bitpie mobile wallet and RockX Ledger-backed web wallet are available and support ROSE token transfers. Support for staking and delegation is in development. See")," ",(0,r.kt)("a",{parentName:"li",href:"../../../general/manage-tokens/holding-rose-tokens/"},(0,r.kt)("em",{parentName:"a"},"3rd Party Wallets"))," ",(0,r.kt)("em",{parentName:"li"},"and")," ",(0,r.kt)("a",{parentName:"li",href:"/general/manage-tokens/oasis-wallets/"},(0,r.kt)("em",{parentName:"a"},"Oasis Wallets"))," ",(0,r.kt)("em",{parentName:"li"},"parts of our docs."))))),(0,r.kt)("h2",{id:"mechanics-of-upgrading-to-mainnet"},"Mechanics of Upgrading to Mainnet"),(0,r.kt)("p",null,"Upgrading from Mainnet Beta to Mainnet will require a coordinated upgrade of the Network. All nodes will need to configure a new genesis file that they can generate or verify independently and reset/archive any state from Mainnet Beta. Once enough (representing 2/3+ of stake) nodes have taken this step, the network will start."),(0,r.kt)("h2",{id:"proposed-changes-from-mainnet-beta-to-mainnet"},"Proposed Changes From Mainnet Beta to Mainnet"),(0,r.kt)("p",null,"The Mainnet genesis file is intended to be as close as possible to the state of the Mainnet Beta network at the time of upgrade. That includes retaining validator token balances, retaining genesis file wallet allocations, and block height at time of the snapshot."),(0,r.kt)("p",null,"In addition, after receiving additional feedback from the community, the Oasis Protocol Foundation has proposed to increase the staking rewards model. In the new proposed model staking rewards will start at 20% (annualized) and range from 20% to 2% over the first 4 years of the network (see more in updated ",(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/token-metrics-and-distribution"},"Token Metrics and Distribution")," doc)."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The following parts of the genesis file will be updated:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"height"))," will remain the same as at the time of the snapshot of Mainnet Beta, i.e. ",(0,r.kt)("inlineCode",{parentName:"p"},"702000"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"genesis_time"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"2020-11-18T16:00:00Z"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"chain_id"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-1"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"halt_epoch"))," will be set to ",(0,r.kt)("inlineCode",{parentName:"p"},"9940")," (approximately 1 year from Mainnet launch).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.disable_transfers"))," will be omitted (or set to",(0,r.kt)("inlineCode",{parentName:"p"},"false)"),"to enable transfers.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.params.reward_schedule"))," will be updated to reflect the updated reward schedule as mentioned above.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.common_pool"))," will be increased by 450M ROSE to fund increased staking rewards.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"staking.ledger.oasis1qrad7s7nqm4gvyzr8yt2rdk0ref489rn3vn400d6")),", which corresponds to the Community and Ecosystem Wallet, will have its ",(0,r.kt)("inlineCode",{parentName:"p"},"general.balance")," reduced by 450M ROSE to ",(0,r.kt)("inlineCode",{parentName:"p"},"1183038701000000000")," and transferred to the Common Pool to fund increased staking rewards.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},(0,r.kt)("inlineCode",{parentName:"strong"},"extra_data"))," will be set back to the value in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/download/2020-10-01/genesis.json"},"Mainnet Beta genesis file")," to include the Oasis network's genesis quote: ",(0,r.kt)("em",{parentName:"p"},"\u201d"),(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F"},(0,r.kt)("em",{parentName:"a"},"Quis custodiet ipsos custodes?")),(0,r.kt)("em",{parentName:"p"},"\u201d ","[","submitted by Oasis Community Member Daniyar Borangaziyev","]",":")),(0,r.kt)("pre",{parentName:"li"},(0,r.kt)("code",{parentName:"pre",className:"language-diff"},' "extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n }\n'))))),(0,r.kt)("p",null,"See the updated ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," for the published Mainnet genesis file."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"For more detailed instructions how to verify the provided Mainnet genesis file by comparing it to network state dump, see the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/maintenance/handling-network-upgrades#example-diff-for-mainnet-beta-to-mainnet-network-upgrade"},"Handling Network Upgrades")," guide.")),(0,r.kt)("p",null,"Mainnet will use ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.2"},(0,r.kt)("strong",{parentName:"a"},"Oasis Core 20.12.2")),"."),(0,r.kt)("h2",{id:"mainnet-launch-support"},"Mainnet Launch Support"),(0,r.kt)("p",null,"The Oasis team will be offering live video support during the launch of Mainnet. Video call link and calendar details will be shared with node operators via email and Slack."),(0,r.kt)("p",null,"For any additional support, please reach out via the ",(0,r.kt)("a",{parentName:"p",href:"/get-involved/"},(0,r.kt)("strong",{parentName:"a"},"#node-operators")," channel at the Oasis Network Community server on Discord")," with your questions, comments, and feedback related to Mainnet."),(0,r.kt)("p",null,"To follow the network, please use one of the many community block explorers including ",(0,r.kt)("a",{parentName:"p",href:"https://www.oasisscan.com/"},"oasisscan.com"),"."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/db582d92.b4436f5f.js b/assets/js/db582d92.b4436f5f.js new file mode 100644 index 0000000000..1426db0b97 --- /dev/null +++ b/assets/js/db582d92.b4436f5f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6466],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>h});var r=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=r.createContext({}),l=function(e){var n=r.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},u=function(e){var n=l(e.components);return r.createElement(s.Provider,{value:n},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},c=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=d(e,["components","mdxType","originalType","parentName"]),p=l(t),c=a,h=p["".concat(s,".").concat(c)]||p[c]||m[c]||i;return t?r.createElement(h,o(o({ref:n},u),{},{components:t})):r.createElement(h,o({ref:n},u))}));function h(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=c;var d={};for(var s in n)hasOwnProperty.call(n,s)&&(d[s]=n[s]);d.originalType=e,d[p]="string"==typeof e?e:a,o[1]=d;for(var l=2;l{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>m,frontMatter:()=>i,metadata:()=>d,toc:()=>l});var r=t(7462),a=(t(7294),t(3905));const i={},o="Key Manager Node",d={unversionedId:"node/run-your-node/keymanager-node/README",id:"node/run-your-node/keymanager-node/README",title:"Key Manager Node",description:"These instructions are for setting up a key manager node. Key manager nodes run a special runtime that provides confidentiality to other ParaTimes. If you want to run a validator node instead, see the instructions for running a validator node. Similarly, if you want to run a ParaTime node instead, see the instructions for running a ParaTime node.",source:"@site/docs/node/run-your-node/keymanager-node/README.md",sourceDirName:"node/run-your-node/keymanager-node",slug:"/node/run-your-node/keymanager-node/",permalink:"/node/run-your-node/keymanager-node/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/keymanager-node/README.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"ParaTime Client Node",permalink:"/node/run-your-node/paratime-client-node"},next:{title:"Signing Key Manager Policy",permalink:"/node/run-your-node/keymanager-node/signing-key-manager-policy"}},s={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Setting up Trusted Execution Environment (TEE)",id:"setting-up-trusted-execution-environment-tee",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Checking Node Status",id:"checking-node-status",level:2}],u={toc:l},p="wrapper";function m(e){let{components:n,...t}=e;return(0,a.kt)(p,(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"key-manager-node"},"Key Manager Node"),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"These instructions are for setting up a ",(0,a.kt)("em",{parentName:"p"},"key manager")," node. Key manager nodes run a special runtime that provides confidentiality to other ParaTimes. If you want to run a ",(0,a.kt)("em",{parentName:"p"},"validator")," node instead, see the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"instructions for running a validator node"),". Similarly, if you want to run a ",(0,a.kt)("em",{parentName:"p"},"ParaTime")," node instead, see the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"instructions for running a ParaTime node"),".")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"At time of writing the key manager ParaTime is deployed only on the Testnet to support Cipher and Sapphire ParaTimes, and limited to be run by trustworthy partners.")),(0,a.kt)("p",null,"This guide will cover setting up your key manager node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools."),(0,a.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,a.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,a.kt)("a",{parentName:"p",href:"../prerequisites"},"Prerequisites")," and ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/non-validator-node"},"Run a Non-validator Node")," sections and have:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Oasis Node binary installed on your system and a dedicated non-root user that will run your Oasis Node."),(0,a.kt)("li",{parentName:"ul"},"The chosen top-level ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/")," working directory prepared (feel free to name it as you wish, e.g. ",(0,a.kt)("inlineCode",{parentName:"li"},"/srv/oasis/"),") with:",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"etc"),": This will store the node configuration and genesis file."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"data"),": This will store the data directory needed by Oasis Node, including your node identity and the blockchain state. The directory permissions should be ",(0,a.kt)("inlineCode",{parentName:"li"},"rwx------"),"."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"bin"),": This will store binaries needed by Oasis Node for running the ParaTimes."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"runtimes"),": This will store the ParaTime bundles."))),(0,a.kt)("li",{parentName:"ul"},"Downloaded or compiled the correct versions of everything according to ",(0,a.kt)("a",{parentName:"li",href:"/node/mainnet/"},"Mainnet Network Parameters"),":",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"The genesis file copied to ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/etc/genesis.json"),"."),(0,a.kt)("li",{parentName:"ul"},"The binaries needed by Oasis Node for running the ParaTimes copied to ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/bin/"),"."),(0,a.kt)("li",{parentName:"ul"},"The key manager ParaTime bundle (",(0,a.kt)("inlineCode",{parentName:"li"},".orc")," extension) copied to ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/runtimes/"),"."))),(0,a.kt)("li",{parentName:"ul"},"Initialized a new node and updated your entity registration by following the ",(0,a.kt)("a",{parentName:"li",href:"/node/run-your-node/paratime-node#register-a-new-entity-or-update-your-entity-registration"},"Register a New Entity or Update Your Entity Registration")," instructions.",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"The entity descriptor file copied to ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/etc/entity.json"),".")))),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Reading the rest of the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"validator node setup instructions")," and ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/paratime-node"},"ParaTime node setup instructions")," may also be useful.")),(0,a.kt)("h3",{id:"setting-up-trusted-execution-environment-tee"},"Setting up Trusted Execution Environment (TEE)"),(0,a.kt)("p",null,"The key manager ParaTime requires the use of a TEE. See the ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"},"Set up trusted execution environment")," doc for instructions on how to set it up before proceeding."),(0,a.kt)("h2",{id:"configuration"},"Configuration"),(0,a.kt)("p",null,"In order to configure the node create the ",(0,a.kt)("inlineCode",{parentName:"p"},"/node/etc/config.yml")," file with the following content:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},'datadir: /node/data\n\nlog:\n level:\n default: info\n tendermint: info\n tendermint/context: error\n format: JSON\n\ngenesis:\n file: /node/etc/genesis.json\n\nconsensus:\n tendermint:\n core:\n listen_address: tcp://0.0.0.0:26656\n\n # The external IP that is used when registering this node to the network.\n # NOTE: If you are using the Sentry node setup, this option should be\n # omitted.\n external_address: tcp://{{ external_address }}:26656\n\n p2p:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n seed:\n - "{{ seed_node_address }}"\n\nruntime:\n mode: keymanager\n paths:\n # Path to the key manager ParaTime bundle.\n - "{{ keymanager_runtime_orc_path }}"\n\n # The following section is required for ParaTimes which are running inside the\n # Intel SGX Trusted Execution Environment.\n sgx:\n loader: /node/bin/oasis-core-runtime-loader\n\nworker:\n registration:\n # In order for the node to register itself, the entity.json of the entity\n # used to provision the node must be available on the node.\n entity: /node/etc/entity.json\n\n keymanager:\n runtime:\n id: "{{ keymanager_runtime_id }}"\n\n p2p:\n # External P2P configuration.\n port: 20104\n addresses:\n # The external IP that is used when registering this node to the network.\n - "{{ external_address }}:20104"\n\n# The following section is required for ParaTimes which are running inside the\n# Intel SGX Trusted Execution Environment.\nias:\n proxy:\n address:\n # List of IAS proxies to connect to.\n # NOTE: You can add additional IAS proxies to this list if you want.\n - "{{ ias_proxy_address }}"\n')),(0,a.kt)("p",null,"Before using this configuration you should collect the following information to replace the ",(0,a.kt)("inlineCode",{parentName:"p"},"{{ ... }}")," variables present in the configuration file:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"{{ external_address }}"),": The external IP you used when registering this node."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"{{ seed_node_address }}"),": The seed node address in the form ",(0,a.kt)("inlineCode",{parentName:"li"},"ID@IP:port"),".",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"You can find the current Oasis Seed Node address in the ",(0,a.kt)("a",{parentName:"li",href:"/node/mainnet/"},"Network Parameters"),"."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"{{ keymanager_runtime_orc_path }}"),": Path to the key manager ",(0,a.kt)("a",{parentName:"li",href:"/node/run-your-node/paratime-node#the-paratime-bundle"},"ParaTime bundle")," of the form ",(0,a.kt)("inlineCode",{parentName:"li"},"/node/runtimes/foo-paratime.orc"),".",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"You can find the current Oasis-supported key manager ParaTime in the ",(0,a.kt)("a",{parentName:"li",href:"/node/mainnet/#paratimes"},"Mainnet Network Paramers"),"."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"{{ keymanager_runtime_id }}"),": Runtime identified for the key manager ParaTime.",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"You can find the current Oasis-supported key manager ParaTime identifiers in the ",(0,a.kt)("a",{parentName:"li",href:"/node/mainnet/#paratimes"},"Mainnet Network Paramers"),"."))),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"{{ ias_proxy_address }}"),": The IAS proxy address in the form ",(0,a.kt)("inlineCode",{parentName:"li"},"ID@HOST:port"),".",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"You can find the current Oasis IAS proxy address in the ",(0,a.kt)("a",{parentName:"li",href:"/node/mainnet/#cipher-paratime"},"Mainnet Network Parameters"),"."),(0,a.kt)("li",{parentName:"ul"},"If you want, you can also ",(0,a.kt)("a",{parentName:"li",href:"/node/run-your-node/ias-proxy"},"run your own IAS proxy"),".")))),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Make sure the ",(0,a.kt)("inlineCode",{parentName:"p"},"worker.p2p.port")," (default: ",(0,a.kt)("inlineCode",{parentName:"p"},"9200"),") port is exposed and publicly\naccessible on the internet (for ",(0,a.kt)("inlineCode",{parentName:"p"},"TCP")," traffic).")),(0,a.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,a.kt)("p",null,"You can start the node by running the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,a.kt)("h2",{id:"checking-node-status"},"Checking Node Status"),(0,a.kt)("p",null,"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node control status -a unix:/node/data/internal.sock\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/dcfcc267.6c37de77.js b/assets/js/dcfcc267.6c37de77.js new file mode 100644 index 0000000000..f61d02a03b --- /dev/null +++ b/assets/js/dcfcc267.6c37de77.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3821],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var a=r.createContext({}),u=function(e){var t=r.useContext(a),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=u(e.components);return r.createElement(a.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),c=u(n),m=o,f=c["".concat(a,".").concat(m)]||c[m]||d[m]||s;return n?r.createElement(f,l(l({ref:t},p),{},{components:n})):r.createElement(f,l({ref:t},p))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var s=n.length,l=new Array(s);l[0]=m;var i={};for(var a in t)hasOwnProperty.call(t,a)&&(i[a]=t[a]);i.originalType=e,i[c]="string"==typeof e?e:o,l[1]=i;for(var u=2;u{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>i,toc:()=>u});var r=n(7462),o=(n(7294),n(3905));const s={},l="Running Tests",i={unversionedId:"core/development-setup/running-tests",id:"core/development-setup/running-tests",title:"Running Tests",description:"Before proceeding, make sure to look at the [prerequisites] required for running",source:"@site/docs/core/development-setup/running-tests.md",sourceDirName:"core/development-setup",slug:"/core/development-setup/running-tests",permalink:"/core/development-setup/running-tests",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/running-tests.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Running Tests and Development Networks",permalink:"/core/development-setup/running-tests-and-development-networks"},next:{title:"Local Network Runner",permalink:"/core/development-setup/oasis-net-runner"}},a={},u=[{value:"Tests",id:"tests",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}],p={toc:u},c="wrapper";function d(e){let{components:t,...n}=e;return(0,o.kt)(c,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"running-tests"},"Running Tests"),(0,o.kt)("p",null,"Before proceeding, make sure to look at the ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/prerequisites"},"prerequisites")," required for running\nan Oasis Core environment followed by ",(0,o.kt)("a",{parentName:"p",href:"/core/development-setup/building"},"build instructions")," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."),(0,o.kt)("h2",{id:"tests"},"Tests"),(0,o.kt)("p",null,"After you've built everything, you can use the following commands to run tests."),(0,o.kt)("p",null,"To run all unit tests:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make test-unit\n")),(0,o.kt)("p",null,"To run end-to-end tests locally:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make test-e2e\n")),(0,o.kt)("p",null,"To run all tests:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"make test\n")),(0,o.kt)("p",null,"To execute tests using SGX set the following environmental variable before\nrunning the tests:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"export OASIS_TEE_HARDWARE=intel-sgx\n")),(0,o.kt)("h2",{id:"troubleshooting"},"Troubleshooting"),(0,o.kt)("p",null,"Check the console output for mentions of a path of the form\n",(0,o.kt)("inlineCode",{parentName:"p"},"/tmp/oasis-test-runnerXXXXXXXXX")," (where each ",(0,o.kt)("inlineCode",{parentName:"p"},"X")," is a digit).\nThat's the log directory. Start with coarsest-level debug output in\n",(0,o.kt)("inlineCode",{parentName:"p"},"console.log")," files:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"cat $(find /tmp/oasis-test-runnerXXXXXXXXX -name console.log) | less\n")),(0,o.kt)("p",null,"For even more output, check the other ",(0,o.kt)("inlineCode",{parentName:"p"},"*.log")," files."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/de2ae66a.5048cffb.js b/assets/js/de2ae66a.5048cffb.js new file mode 100644 index 0000000000..d80ec2efaf --- /dev/null +++ b/assets/js/de2ae66a.5048cffb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4139],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var s=t(7294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);n&&(s=s.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,s)}return t}function r(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var c=s.createContext({}),l=function(e){var n=s.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},p=function(e){var n=l(e.components);return s.createElement(c.Provider,{value:n},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return s.createElement(s.Fragment,{},n)}},m=s.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),d=l(t),m=a,h=d["".concat(c,".").concat(m)]||d[m]||u[m]||i;return t?s.createElement(h,r(r({ref:n},p),{},{components:t})):s.createElement(h,r({ref:n},p))}));function h(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,r=new Array(i);r[0]=m;var o={};for(var c in n)hasOwnProperty.call(n,c)&&(o[c]=n[c]);o.originalType=e,o[d]="string"==typeof e?e:a,r[1]=o;for(var l=2;l{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>l});var s=t(7462),a=(t(7294),t(3905));const i={},r="Genesis Document",o={unversionedId:"core/consensus/genesis",id:"core/consensus/genesis",title:"Genesis Document",description:"The genesis document contains a set of parameters that outline the initial state",source:"@site/docs/core/consensus/genesis.md",sourceDirName:"core/consensus",slug:"/core/consensus/genesis",permalink:"/core/consensus/genesis",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/genesis.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Key Manager",permalink:"/core/consensus/services/keymanager"},next:{title:"Transaction Test Vectors",permalink:"/core/consensus/test-vectors"}},c={},l=[{value:"Genesis Document's Hash",id:"genesis-documents-hash",level:2},{value:"Genesis File",id:"genesis-file",level:2},{value:"Canonical Form",id:"canonical-form",level:3}],p={toc:l},d="wrapper";function u(e){let{components:n,...t}=e;return(0,a.kt)(d,(0,s.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"genesis-document"},"Genesis Document"),(0,a.kt)("p",null,"The genesis document contains a set of parameters that outline the initial state\nof the ",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer")," and its services."),(0,a.kt)("p",null,"For more details about the actual genesis document's API, see\n",(0,a.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/genesis/api"},"genesis API documentation"),"."),(0,a.kt)("h2",{id:"genesis-documents-hash"},"Genesis Document's Hash"),(0,a.kt)("p",null,"The genesis document's hash is computed as:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"Base16(SHA512-256(CBOR()))\n")),(0,a.kt)("p",null,"where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"Base16()")," represents the hex encoding function,"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"SHA512-256()")," represents the SHA-512/256 hash function as described in\n",(0,a.kt)("a",{parentName:"li",href:"/core/crypto#hash-functions"},"Cryptography")," documentation,"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"CBOR()")," represents the ",(0,a.kt)("em",{parentName:"li"},"canonical")," CBOR encoding function as described in\n",(0,a.kt)("a",{parentName:"li",href:"/core/encoding"},"Serialization")," documentation, and"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"")," represents a given genesis document.")),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"This should not be confused with a SHA-1 or a SHA-256 checksum of a\n",(0,a.kt)("a",{parentName:"p",href:"#genesis-file"},"genesis file")," that is used to check if the downloaded genesis file is correct.")),(0,a.kt)("p",null,"This hash is also used for ",(0,a.kt)("a",{parentName:"p",href:"/core/crypto#chain-domain-separation"},"chain domain separation")," as the last\npart of the ",(0,a.kt)("a",{parentName:"p",href:"/core/crypto#domain-separation"},"domain separation")," context."),(0,a.kt)("h2",{id:"genesis-file"},"Genesis File"),(0,a.kt)("p",null,"A genesis file is a JSON file corresponding to a serialized genesis document."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"For a high-level overview of the genesis file, its sections, parameters and\nthe parameter values that are used for the Oasis Network, see:\n",(0,a.kt)("a",{parentName:"p",href:"/node/genesis-doc"},"Genesis File Overview"),".")),(0,a.kt)("h3",{id:"canonical-form"},"Canonical Form"),(0,a.kt)("p",null,"The ",(0,a.kt)("em",{parentName:"p"},"canonical")," form of a genesis file is the pretty-printed JSON file with\n2-space indents ending with a newline, where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Struct fields are encoded in the order in which they are defined in the\ncorresponding struct definitions."),(0,a.kt)("p",{parentName:"li"},"The genesis document is defined by the ",(0,a.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/genesis/api#Document"},(0,a.kt)("inlineCode",{parentName:"a"},"genesis/api.Document"))," struct which\ncontains pointers to other structs defining the genesis state of all\n",(0,a.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer")," services.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Maps have their keys converted to strings which are then encoded in\nlexicographical order."),(0,a.kt)("p",{parentName:"li"},"This is Go's default behavior. For more details, see\n",(0,a.kt)("a",{parentName:"p",href:"https://golang.org/pkg/encoding/json/#Marshal"},(0,a.kt)("inlineCode",{parentName:"a"},"encoding/json.Marshal()")),"'s documentation."))),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"This should not be confused with the ",(0,a.kt)("em",{parentName:"p"},"canonical")," CBOR encoding of the genesis\ndocument that is used to derive the domain separation context as described\nin the ",(0,a.kt)("a",{parentName:"p",href:"#genesis-documents-hash"},"Genesis Document's Hash")," section.")),(0,a.kt)("p",null,"This form is used to enable simple diffing/patching with the standard Unix tools\n(i.e. ",(0,a.kt)("inlineCode",{parentName:"p"},"diff"),"/",(0,a.kt)("inlineCode",{parentName:"p"},"patch"),")."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e27d89bb.f40f128a.js b/assets/js/e27d89bb.f40f128a.js new file mode 100644 index 0000000000..ff7cef50c0 --- /dev/null +++ b/assets/js/e27d89bb.f40f128a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[974],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>h});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),d=p(n),g=i,h=d["".concat(l,".").concat(g)]||d[g]||u[g]||o;return n?r.createElement(h,s(s({ref:t},c),{},{components:n})):r.createElement(h,s({ref:t},c))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,s=new Array(o);s[0]=g;var a={};for(var l in t)hasOwnProperty.call(t,l)&&(a[l]=t[l]);a.originalType=e,a[d]="string"==typeof e?e:i,s[1]=a;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>p});var r=n(7462),i=(n(7294),n(3905));const o={},s="Registry",a={unversionedId:"core/consensus/services/registry",id:"core/consensus/services/registry",title:"Registry",description:"The registry service is responsible for managing a registry of runtime, entity",source:"@site/docs/core/consensus/services/registry.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/registry",permalink:"/core/consensus/services/registry",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/registry.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Staking",permalink:"/core/consensus/services/staking"},next:{title:"Committee Scheduler",permalink:"/core/consensus/services/scheduler"}},l={},p=[{value:"Resources",id:"resources",level:2},{value:"Entities and Nodes",id:"entities-and-nodes",level:3},{value:"Runtimes",id:"runtimes",level:3},{value:"Methods",id:"methods",level:2},{value:"Register Entity",id:"register-entity",level:3},{value:"Deregister Entity",id:"deregister-entity",level:3},{value:"Register Node",id:"register-node",level:3},{value:"Unfreeze Node",id:"unfreeze-node",level:3},{value:"Register Runtime",id:"register-runtime",level:3},{value:"Events",id:"events",level:2},{value:"Test Vectors",id:"test-vectors",level:2}],c={toc:p},d="wrapper";function u(e){let{components:t,...n}=e;return(0,i.kt)(d,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"registry"},"Registry"),(0,i.kt)("p",null,"The registry service is responsible for managing a registry of runtime, entity\nand node public keys and metadata."),(0,i.kt)("p",null,"The service interface definition lives in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/api"},(0,i.kt)("inlineCode",{parentName:"a"},"go/registry/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc"},"consensus service API documentation"),"."),(0,i.kt)("h2",{id:"resources"},"Resources"),(0,i.kt)("p",null,"The registry service manages different kinds of resources which are described\nfrom a high level perspective in this section."),(0,i.kt)("h3",{id:"entities-and-nodes"},"Entities and Nodes"),(0,i.kt)("p",null,"An entity managed by the registry service is a key pair that owns resources in\nthe registry. It can represent an organization or an individual with ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking"},"stake")," on\nthe network."),(0,i.kt)("p",null,"Currently, an entity can own the following types of resources:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"nodes and"),(0,i.kt)("li",{parentName:"ul"},"runtimes.")),(0,i.kt)("p",null,"A node is a device (process running in a VM, on bare metal, in a container,\netc.) that is participating in a committee on the Oasis Core network. It is\nidentified by its own key pair."),(0,i.kt)("p",null,"The reason for separating entities from nodes is to enable separation of\nconcerns. Both nodes and entities require stake to operate (e.g., to be\nregistered in the registry and be eligible for specific roles). While entities\nhave their own (or ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#delegation"},"delegated"),") stake, nodes use stake provided by entities that\noperate them. Nodes need to periodically refresh their resource descriptor in\nthe registry in order for it to remain fresh and to do this they need to have\nonline access to their corresponding private key(s)."),(0,i.kt)("p",null,"On the other hand entities' private keys are more sensitive as they can be used\nto manage stake and other resources. For this reason they should usually be kept\noffline and having entities as separate resources enables that."),(0,i.kt)("h3",{id:"runtimes"},"Runtimes"),(0,i.kt)("p",null,"A ",(0,i.kt)("a",{parentName:"p",href:"/core/runtime/"},"runtime")," is effectively a replicated application with shared state. The\nregistry resource describes a runtime's operational parameters, including its\nidentifier, kind, admission policy, committee scheduling, storage, governance\nmodel, etc. For a full description of the runtime descriptor see\n",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime"},"the ",(0,i.kt)("inlineCode",{parentName:"a"},"Runtime")," structure"),"."),(0,i.kt)("p",null,"The chosen governance model indicates how the runtime descriptor can be updated\nin the future."),(0,i.kt)("p",null,"There are currently three supported governance models:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Entity governance")," where the runtime owner is the only one who can update\nthe runtime descriptor via ",(0,i.kt)("inlineCode",{parentName:"p"},"registry.RegisterRuntime")," method calls.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Runtime-defined governance")," where the runtime itself is the only one who\ncan update the runtime descriptor by emitting a runtime message.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Consensus layer governance")," where only the consensus layer itself can\nupdate the runtime descriptor through network governance."))),(0,i.kt)("h2",{id:"methods"},"Methods"),(0,i.kt)("p",null,"The following sections describe the methods supported by the consensus registry\nservice."),(0,i.kt)("h3",{id:"register-entity"},"Register Entity"),(0,i.kt)("p",null,"Entity registration enables a new entity to be created. A new register entity\ntransaction can be generated using ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterEntityTx"},(0,i.kt)("inlineCode",{parentName:"a"},"NewRegisterEntityTx")),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"registry.RegisterEntity\n")),(0,i.kt)("p",null,"The body of a register entity transaction must be a ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#SignedEntity"},(0,i.kt)("inlineCode",{parentName:"a"},"SignedEntity"))," structure,\nwhich is a ",(0,i.kt)("a",{parentName:"p",href:"/core/crypto#signed-envelope"},"signed envelope")," containing an ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#Entity"},(0,i.kt)("inlineCode",{parentName:"a"},"Entity"))," descriptor. The signer of\nthe entity MUST be the same as the signer of the transaction."),(0,i.kt)("p",null,"Registering an entity may require sufficient stake in the entity's\n",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#escrow"},"escrow account"),"."),(0,i.kt)("h3",{id:"deregister-entity"},"Deregister Entity"),(0,i.kt)("p",null,"Entity deregistration enables an existing entity to be removed. A new deregister\nentity transaction can be generated using ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewDeregisterEntityTx"},(0,i.kt)("inlineCode",{parentName:"a"},"NewDeregisterEntityTx")),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"registry.DeregisterEntity\n")),(0,i.kt)("p",null,"The body of a register entity transaction must be ",(0,i.kt)("inlineCode",{parentName:"p"},"nil"),". The entity is implied\nto be the signer of the transaction."),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"If an entity still has either nodes or runtimes registered, it is not possible\nto deregister an entity and such a transaction will fail.")),(0,i.kt)("h3",{id:"register-node"},"Register Node"),(0,i.kt)("p",null,"Node registration enables a new node to be created. A new register node\ntransaction can be generated using ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterNodeTx"},(0,i.kt)("inlineCode",{parentName:"a"},"NewRegisterNodeTx")),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"registry.RegisterNode\n")),(0,i.kt)("p",null,"The body of a register entity transaction must be a ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#MultiSignedNode"},(0,i.kt)("inlineCode",{parentName:"a"},"MultiSignedNode")),"\nstructure, which is a ",(0,i.kt)("a",{parentName:"p",href:"/core/crypto#multi-signed-envelope"},"multi-signed envelope")," containing a ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node"},(0,i.kt)("inlineCode",{parentName:"a"},"Node"))," descriptor.\nThe signer of the transaction MUST be the node identity key."),(0,i.kt)("p",null,"The owning entity MUST have the given node identity public key whitelisted in\nthe ",(0,i.kt)("inlineCode",{parentName:"p"},"Nodes")," field in its ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#Entity"},(0,i.kt)("inlineCode",{parentName:"a"},"Entity"))," descriptor."),(0,i.kt)("p",null,"The node descriptor structure MUST be signed by all of the following keys:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Node identity key."),(0,i.kt)("li",{parentName:"ul"},"Consensus key."),(0,i.kt)("li",{parentName:"ul"},"TLS key."),(0,i.kt)("li",{parentName:"ul"},"P2P key.")),(0,i.kt)("p",null,"Registering a node may require sufficient stake in the owning entity's\n",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#escrow"},"escrow account"),". There are two kinds of thresholds that the node may need to\nsatisfy:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Global thresholds are the same for all runtimes and are defined by the\nconsensus parameters (see ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#ConsensusParameters.Thresholds"},(0,i.kt)("inlineCode",{parentName:"a"},"Thresholds")," in staking consensus parameters"),").")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"In ",(0,i.kt)("em",{parentName:"p"},"addition")," to the global thresholds, each runtime the node is registering\nfor may define their own thresholds. The runtime-specific thresholds are\ndefined in the ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime.Staking"},(0,i.kt)("inlineCode",{parentName:"a"},"Staking")," field")," in the runtime descriptor."))),(0,i.kt)("p",null,"In case the node is registering for multiple runtimes, it needs to satisfy the\nsum of thresholds of all the runtimes it is registering for."),(0,i.kt)("h3",{id:"unfreeze-node"},"Unfreeze Node"),(0,i.kt)("p",null,"Node unfreezing enables a previously frozen (e.g., due to slashing) node to be\nthawed so it can again be eligible for committee elections. A new unfreeze node\ntransaction can be generated using ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewUnfreezeNodeTx"},(0,i.kt)("inlineCode",{parentName:"a"},"NewUnfreezeNodeTx")),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"registry.UnfreezeNode\n")),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Body:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-golang"},'type UnfreezeNode struct {\n NodeID signature.PublicKey `json:"node_id"`\n}\n')),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Fields:")),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"node_id")," specifies the node identifier of the node to thaw.")),(0,i.kt)("p",null,"The transaction signer MUST be the entity key that owns the node."),(0,i.kt)("p",null,"Thawing a node requires that the node's freeze period has already passed. The\nfreeze period for any given attributable fault (e.g., double signing) is a\nconsensus parameter (see ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#ConsensusParameters.Slashing"},(0,i.kt)("inlineCode",{parentName:"a"},"Slashing")," in staking consensus parameters"),")."),(0,i.kt)("h3",{id:"register-runtime"},"Register Runtime"),(0,i.kt)("p",null,"Runtime registration enables a new runtime to be created. A new register\nruntime transaction can be generated using ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterRuntimeTx"},(0,i.kt)("inlineCode",{parentName:"a"},"NewRegisterRuntimeTx")),"."),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Method name:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"registry.RegisterRuntime\n")),(0,i.kt)("p",null,"The body of a register runtime transaction must be a ",(0,i.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime"},(0,i.kt)("inlineCode",{parentName:"a"},"Runtime"))," descriptor.\nThe signer of the transaction MUST be the owning entity key."),(0,i.kt)("p",null,"Registering a runtime may require sufficient stake in either the owning\nentity's (when entity governance is used) or the runtime's (when runtime\ngovernance is used) ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#escrow"},"escrow account"),"."),(0,i.kt)("p",null,"Changing the governance model from entity governance to runtime governance is\nallowed. Any other governance model changes are not allowed."),(0,i.kt)("h2",{id:"events"},"Events"),(0,i.kt)("h2",{id:"test-vectors"},"Test Vectors"),(0,i.kt)("p",null,"To generate test vectors for various registry ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/transactions"},"transactions"),", run:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"make -C go registry/gen_vectors\n")),(0,i.kt)("p",null,"For more information about the structure of the test vectors see the section\non ",(0,i.kt)("a",{parentName:"p",href:"/core/consensus/test-vectors"},"Transaction Test Vectors"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e27f323d.bbdcdee1.js b/assets/js/e27f323d.bbdcdee1.js new file mode 100644 index 0000000000..cc987b9624 --- /dev/null +++ b/assets/js/e27f323d.bbdcdee1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1354],{3905:(t,e,a)=>{a.d(e,{Zo:()=>d,kt:()=>k});var n=a(7294);function r(t,e,a){return e in t?Object.defineProperty(t,e,{value:a,enumerable:!0,configurable:!0,writable:!0}):t[e]=a,t}function l(t,e){var a=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),a.push.apply(a,n)}return a}function i(t){for(var e=1;e=0||(r[a]=t[a]);return r}(t,e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,a)&&(r[a]=t[a])}return r}var p=n.createContext({}),s=function(t){var e=n.useContext(p),a=e;return t&&(a="function"==typeof t?t(e):i(i({},e),t)),a},d=function(t){var e=s(t.components);return n.createElement(p.Provider,{value:e},t.children)},m="mdxType",u={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},c=n.forwardRef((function(t,e){var a=t.components,r=t.mdxType,l=t.originalType,p=t.parentName,d=o(t,["components","mdxType","originalType","parentName"]),m=s(a),c=r,k=m["".concat(p,".").concat(c)]||m[c]||u[c]||l;return a?n.createElement(k,i(i({ref:e},d),{},{components:a})):n.createElement(k,i({ref:e},d))}));function k(t,e){var a=arguments,r=e&&e.mdxType;if("string"==typeof t||r){var l=a.length,i=new Array(l);i[0]=c;var o={};for(var p in e)hasOwnProperty.call(e,p)&&(o[p]=e[p]);o.originalType=t,o[m]="string"==typeof t?t:r,i[1]=o;for(var s=2;s{a.r(e),a.d(e,{assets:()=>p,contentTitle:()=>i,default:()=>u,frontMatter:()=>l,metadata:()=>o,toc:()=>s});var n=a(7462),r=(a(7294),a(3905));const l={},i="Oasis Privacy Layer",o={unversionedId:"dapp/opl/README",id:"dapp/opl/README",title:"Oasis Privacy Layer",description:"The Oasis Privacy Layer (OPL) is an EVM-compatible privacy solution that",source:"@site/docs/dapp/opl/README.md",sourceDirName:"dapp/opl",slug:"/dapp/opl/",permalink:"/dapp/opl/",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/README.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"developers",previous:{title:"Standard Contract Addresses",permalink:"/dapp/sapphire/addresses"},next:{title:"Overview",permalink:"/dapp/opl/introduction"}},p={},s=[{value:"Quickstart",id:"quickstart",level:2},{value:"Monitoring",id:"monitoring",level:2},{value:"Mainnet Deployment",id:"mainnet-deployment",level:2},{value:"Supported Networks",id:"supported-networks",level:2},{value:"Mainnets",id:"mainnets",level:3},{value:"Testnets",id:"testnets",level:3}],d={toc:s},m="wrapper";function u(t){let{components:e,...l}=t;return(0,r.kt)(m,(0,n.Z)({},d,l,{components:e,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"oasis-privacy-layer"},"Oasis Privacy Layer"),(0,r.kt)("p",null,"The Oasis Privacy Layer (OPL) is an EVM-compatible privacy solution that\nempowers developers to add new functionality to smart contracts on the most\npopular EVM networks like Ethereum, BNB Chain, and Polygon with encrypted\ntransactions and confidential state."),(0,r.kt)("p",null,"By using ",(0,r.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-contracts"},"a Solidity library"),"\nthat integrates ",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/sapphire"},"Sapphire")," into your existing and future Web3 applications,\ndevelopers on any supported network can seamlessly add confidential state and\nselective disclosures to their dApps when using contract a deployed on Sapphire\nwithout leaving their existing networks."),(0,r.kt)("p",null,"For more information about OPL and to catch the latest news, please visit the\n",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/opl"},"official OPL page"),"."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Privacy Layer diagram",src:a(7817).Z,width:"1081",height:"1081"})),(0,r.kt)("p",null,"The user submits a transaction on the Home network to a contract which uses\n",(0,r.kt)("inlineCode",{parentName:"p"},"postMessage")," to notify the SGN that it should approve the cross-chain message.\nThe Executor waits, when the SGN approves the message the Executor submits a\ntransaction to the target contract on Sapphire."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Transaction Flow",src:a(8678).Z,width:"1124",height:"387"})),(0,r.kt)("p",null,"The Home Contract pays the SGN to watch and approve the message, but the\nExecutor needs to be run by somebody willing to pay for the gas to submit\ntransactions to the destination chain."),(0,r.kt)("h2",{id:"quickstart"},"Quickstart"),(0,r.kt)("p",null,"A pair of contracts are linked bidirectionally 1-1 to each other across chains,\nwith one end on Sapphire and the other on a supported EVM-compatible chain (the\nHome Network). They can post and receive messages to & from each other using the\nmessage-passing bridge, but must register endpoints to define which messages\nthey handle from each other."),(0,r.kt)("p",null,"Start by adding the ",(0,r.kt)("a",{parentName:"p",href:"http://npmjs.com/package/@oasisprotocol/sapphire-contracts"},(0,r.kt)("inlineCode",{parentName:"a"},"@oasisprotocol/sapphire-contracts"))," NPM package to your\nHardhat or Truffle project so you can import ",(0,r.kt)("inlineCode",{parentName:"p"},"OPL.sol"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"pnpm add @oasisprotocol/sapphire-contracts\n")),(0,r.kt)("p",null,"Then define the two contracts, starting with a contract on Sapphire which runs\ninside the confidential enclave and can be called via the ",(0,r.kt)("inlineCode",{parentName:"p"},"secretExample"),"\nhandler. Use the constructor to provide the Sapphire contract with the location\n(address and chain) of the contract on the Home network:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},'import {Enclave, Result, autoswitch} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol";\n\ncontract SapphireContract is Enclave {\n constructor(address otherEnd, string chain) Enclave(otherEnd, autoswitch(chain)) {\n registerEndpoint("secretExample", on_example);\n }\n function on_example(bytes calldata _args) internal returns (Result) {\n (uint256 a, bool b) = abi.decode(args, (uint256, bool));\n // TODO: do confidential things here\n return Result.Success;\n }\n}\n')),(0,r.kt)("p",null,"Then on the other chain, define your contract which can be called via\n",(0,r.kt)("inlineCode",{parentName:"p"},"triggerExample")," to send a message to the contract on Sapphire using the\n",(0,r.kt)("inlineCode",{parentName:"p"},"postMessage")," interface."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},'import {Host, Result} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol";\n\ncontract HomeContract is Host {\n constructor(address otherEnd) Host(otherEnd) {\n }\n function triggerExample (uint256 a, bool b) external payable {\n postMessage("secretExample", abi.encode(a, b));\n }\n}\n')),(0,r.kt)("p",null,"After a few minutes the bridge will detect and then the executor will invoke the\n",(0,r.kt)("inlineCode",{parentName:"p"},"SapphireContract.on_example")," method."),(0,r.kt)("h2",{id:"monitoring"},"Monitoring"),(0,r.kt)("p",null,"The Celer IM Scan API can be used to retrieve status and message details by\nproviding the globally unique transaction ID from the chain which originated the\nmessage."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"https://api.celerscan.com/scan/searchByTxHash?tx=0x...\n")),(0,r.kt)("p",null,"For details of the response format, see the ",(0,r.kt)("a",{parentName:"p",href:"https://im-docs.celer.network/developer/development-guide/query-im-tx-status"},"Query IM Tx Status")," page of the\nCeler Inter-Chain Message (IM) documentation. Using this API lets you to check\nif messages have been delivered."),(0,r.kt)("h2",{id:"mainnet-deployment"},"Mainnet Deployment"),(0,r.kt)("p",null,"It is necessary to run a ",(0,r.kt)("a",{parentName:"p",href:"https://im-docs.celer.network/developer/development-guide/message-executor"},"Message Executor")," which monitors the Celer ",(0,r.kt)("em",{parentName:"p"},"State\nGuardian Network")," (SGN) for cross-chain messages and then submits the proof\non-chain to deliver them to the target contract."),(0,r.kt)("p",null,"If you are participating in a Hackathon or Grant, ",(0,r.kt)("a",{parentName:"p",href:"https://form.typeform.com/to/RsiUR9Xz"},"please fill out the relay\nrequest form")," to be allowed to use the\nshared Message Executor."),(0,r.kt)("h2",{id:"supported-networks"},"Supported Networks"),(0,r.kt)("h3",{id:"mainnets"},"Mainnets"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Name"),(0,r.kt)("th",{parentName:"tr",align:null},"Int ID"),(0,r.kt)("th",{parentName:"tr",align:null},"Hex ID"),(0,r.kt)("th",{parentName:"tr",align:null},"autoswitch name"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Ape"),(0,r.kt)("td",{parentName:"tr",align:null},"16350"),(0,r.kt)("td",{parentName:"tr",align:null},"0x3fde"),(0,r.kt)("td",{parentName:"tr",align:null},"ape")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Arbitrum Nova"),(0,r.kt)("td",{parentName:"tr",align:null},"42170"),(0,r.kt)("td",{parentName:"tr",align:null},"0xa4ba"),(0,r.kt)("td",{parentName:"tr",align:null},"arbitrum-nova")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Arbitrum One"),(0,r.kt)("td",{parentName:"tr",align:null},"42161"),(0,r.kt)("td",{parentName:"tr",align:null},"a4b1"),(0,r.kt)("td",{parentName:"tr",align:null},"arbitrum-one")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Astar"),(0,r.kt)("td",{parentName:"tr",align:null},"592"),(0,r.kt)("td",{parentName:"tr",align:null},"0x250"),(0,r.kt)("td",{parentName:"tr",align:null},"astar")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Aurora"),(0,r.kt)("td",{parentName:"tr",align:null},"1313161554"),(0,r.kt)("td",{parentName:"tr",align:null},"0x4e454152"),(0,r.kt)("td",{parentName:"tr",align:null},"aurora")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Avalanche"),(0,r.kt)("td",{parentName:"tr",align:null},"43114"),(0,r.kt)("td",{parentName:"tr",align:null},"0xa86a"),(0,r.kt)("td",{parentName:"tr",align:null},"avalanche")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Binance Smart Chain"),(0,r.kt)("td",{parentName:"tr",align:null},"56"),(0,r.kt)("td",{parentName:"tr",align:null},"0x38"),(0,r.kt)("td",{parentName:"tr",align:null},"bsc")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Ethereum"),(0,r.kt)("td",{parentName:"tr",align:null},"1"),(0,r.kt)("td",{parentName:"tr",align:null},"0x1"),(0,r.kt)("td",{parentName:"tr",align:null},"ethereum")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Fantom"),(0,r.kt)("td",{parentName:"tr",align:null},"250"),(0,r.kt)("td",{parentName:"tr",align:null},"0xfa"),(0,r.kt)("td",{parentName:"tr",align:null},"fantom")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Filecoin"),(0,r.kt)("td",{parentName:"tr",align:null},"314"),(0,r.kt)("td",{parentName:"tr",align:null},"0x13a"),(0,r.kt)("td",{parentName:"tr",align:null},"filecoin")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Milkomeda C1"),(0,r.kt)("td",{parentName:"tr",align:null},"2001"),(0,r.kt)("td",{parentName:"tr",align:null},"0x7d1"),(0,r.kt)("td",{parentName:"tr",align:null},"milkomeda")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Moonriver"),(0,r.kt)("td",{parentName:"tr",align:null},"1285"),(0,r.kt)("td",{parentName:"tr",align:null},"0x505"),(0,r.kt)("td",{parentName:"tr",align:null},"moonriver")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Polygon"),(0,r.kt)("td",{parentName:"tr",align:null},"137"),(0,r.kt)("td",{parentName:"tr",align:null},"0x89"),(0,r.kt)("td",{parentName:"tr",align:null},"polygon")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Sapphire"),(0,r.kt)("td",{parentName:"tr",align:null},"23294"),(0,r.kt)("td",{parentName:"tr",align:null},"0x5afe"),(0,r.kt)("td",{parentName:"tr",align:null},"sapphire")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Syscoin"),(0,r.kt)("td",{parentName:"tr",align:null},"57"),(0,r.kt)("td",{parentName:"tr",align:null},"0x39"),(0,r.kt)("td",{parentName:"tr",align:null},"syscoin")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Polygon zkEVM"),(0,r.kt)("td",{parentName:"tr",align:null},"1101"),(0,r.kt)("td",{parentName:"tr",align:null},"0x44d"),(0,r.kt)("td",{parentName:"tr",align:null},"polygon-zkevm")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Optimism"),(0,r.kt)("td",{parentName:"tr",align:null},"10"),(0,r.kt)("td",{parentName:"tr",align:null},"0xa"),(0,r.kt)("td",{parentName:"tr",align:null},"optimism")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"zkSync Era"),(0,r.kt)("td",{parentName:"tr",align:null},"324"),(0,r.kt)("td",{parentName:"tr",align:null},"0x144"),(0,r.kt)("td",{parentName:"tr",align:null},"zksync-era")))),(0,r.kt)("h3",{id:"testnets"},"Testnets"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Name"),(0,r.kt)("th",{parentName:"tr",align:null},"Int ID"),(0,r.kt)("th",{parentName:"tr",align:null},"Hex ID"),(0,r.kt)("th",{parentName:"tr",align:null},"autoswitch name"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Arbitrum Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"421611"),(0,r.kt)("td",{parentName:"tr",align:null},"0x66eeb"),(0,r.kt)("td",{parentName:"tr",align:null},"arbitrum-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Avalanche C-Chain Fuji Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"43113"),(0,r.kt)("td",{parentName:"tr",align:null},"0xa869"),(0,r.kt)("td",{parentName:"tr",align:null},"avalanche-fuji")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"BSC Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"97"),(0,r.kt)("td",{parentName:"tr",align:null},"0x61"),(0,r.kt)("td",{parentName:"tr",align:null},"bsc-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ConsenSys zkEVM Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"59140"),(0,r.kt)("td",{parentName:"tr",align:null},"0xe704"),(0,r.kt)("td",{parentName:"tr",align:null},"zkevm-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Dexalot Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"432201"),(0,r.kt)("td",{parentName:"tr",align:null},"0x69849"),(0,r.kt)("td",{parentName:"tr",align:null},"dexalot-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Fantom Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"4002"),(0,r.kt)("td",{parentName:"tr",align:null},"0xfa2"),(0,r.kt)("td",{parentName:"tr",align:null},"fantom-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Filecoin Hyperspace Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"3141"),(0,r.kt)("td",{parentName:"tr",align:null},"0xc45"),(0,r.kt)("td",{parentName:"tr",align:null},"filecoin-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"FNCY Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"923018"),(0,r.kt)("td",{parentName:"tr",align:null},"0xe158a"),(0,r.kt)("td",{parentName:"tr",align:null},"fncy-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Godwoken Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"71401"),(0,r.kt)("td",{parentName:"tr",align:null},"0x116e9"),(0,r.kt)("td",{parentName:"tr",align:null},"godwoken-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Goerli Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"5"),(0,r.kt)("td",{parentName:"tr",align:null},"0x5"),(0,r.kt)("td",{parentName:"tr",align:null},"goerli")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Polygon Mumbai Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"80001"),(0,r.kt)("td",{parentName:"tr",align:null},"0x13881"),(0,r.kt)("td",{parentName:"tr",align:null},"polygon-mumbai")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Polygon zkEVM Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"1442"),(0,r.kt)("td",{parentName:"tr",align:null},"0x5a2"),(0,r.kt)("td",{parentName:"tr",align:null},"zkevm-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Sapphire Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"23295"),(0,r.kt)("td",{parentName:"tr",align:null},"0x5aff"),(0,r.kt)("td",{parentName:"tr",align:null},"sapphire-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Scroll Alpha Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"534353"),(0,r.kt)("td",{parentName:"tr",align:null},"0x82751"),(0,r.kt)("td",{parentName:"tr",align:null},"scroll-testnet")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"Shibuya Testnet"),(0,r.kt)("td",{parentName:"tr",align:null},"81"),(0,r.kt)("td",{parentName:"tr",align:null},"0x51"),(0,r.kt)("td",{parentName:"tr",align:null},"shibuya-testnet")))),(0,r.kt)("p",null,"In the following sections we will look at a concrete example on how to build a\nconfidential, cross-chain DAO-voting dApp from scratch using the Oasis Privacy Layer!"))}u.isMDXComponent=!0},8678:(t,e,a)=>{a.d(e,{Z:()=>n});const n=a.p+"assets/images/opl-contract-flow.mmd-57ad04dbec00703789880a36eea87e94.svg"},7817:(t,e,a)=>{a.d(e,{Z:()=>n});const n=a.p+"assets/images/privacy-layer-diagram-5b87a6dff417d5a4074bd6fdee9dce7e.png"}}]); \ No newline at end of file diff --git a/assets/js/e2e2c701.2adc59da.js b/assets/js/e2e2c701.2adc59da.js new file mode 100644 index 0000000000..6f9dec944f --- /dev/null +++ b/assets/js/e2e2c701.2adc59da.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[9116],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>y});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=a.createContext({}),l=function(e){var t=a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=l(e.components);return a.createElement(c.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=r,y=d["".concat(c,".").concat(m)]||d[m]||u[m]||o;return n?a.createElement(y,i(i({ref:t},p),{},{components:n})):a.createElement(y,i({ref:t},p))}));function y(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[d]="string"==typeof e?e:r,i[1]=s;for(var l=2;l{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>l});var a=n(7462),r=(n(7294),n(3905));const o={},i="Key Manager",s={unversionedId:"core/consensus/services/keymanager",id:"core/consensus/services/keymanager",title:"Key Manager",description:"The key manager service is responsible for coordinating the SGX-based key",source:"@site/docs/core/consensus/services/keymanager.md",sourceDirName:"core/consensus/services",slug:"/core/consensus/services/keymanager",permalink:"/core/consensus/services/keymanager",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/keymanager.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Root Hash",permalink:"/core/consensus/services/roothash"},next:{title:"Genesis Document",permalink:"/core/consensus/genesis"}},c={},l=[{value:"Policies",id:"policies",level:2},{value:"Methods",id:"methods",level:2},{value:"Update Policy",id:"update-policy",level:3},{value:"Events",id:"events",level:2}],p={toc:l},d="wrapper";function u(e){let{components:t,...n}=e;return(0,r.kt)(d,(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"key-manager"},"Key Manager"),(0,r.kt)("p",null,"The key manager service is responsible for coordinating the SGX-based key\nmanager runtimes. It stores and publishes policy documents and status updates\nrequired for key manager replication."),(0,r.kt)("p",null,"The service interface definition lives in ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/keymanager/api"},(0,r.kt)("inlineCode",{parentName:"a"},"go/keymanager/api")),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc"},"consensus service API documentation"),"."),(0,r.kt)("h2",{id:"policies"},"Policies"),(0,r.kt)("p",null,"A key manager policy document defines the policy that key manager\nimplementations use to enforce access control to key material. At this point the\npolicy document is specifically designed to work with our Intel SGX-based key\nmanager runtime."),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#PolicySGX"},"policy document")," specifies the following access control policies that are\nenforced by the key manager runtime based on the calling enclave identity:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Enclaves that may query private keys.")," These are usually enclave identities\nof confidential runtimes that need access to per-runtime private keys to\ndecrypt state.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("strong",{parentName:"p"},"Enclaves that may replicate the master secret.")," These are usually enclave\nidentities of new key manager enclave versions, to support upgrades. Own\nenclave identity is implied (to allow key manager replication) and does not\nneed to be explicitly specified."))),(0,r.kt)("p",null,"In order for the policy to be valid and accepted by a key manager enclave it\nmust be signed by a configured threshold of keys. Both the threshold and the\nauthorized public keys that can sign the policy are hardcoded in the key manager\nenclave."),(0,r.kt)("h2",{id:"methods"},"Methods"),(0,r.kt)("h3",{id:"update-policy"},"Update Policy"),(0,r.kt)("p",null,"Policy update enables the key manager runtime owning entity to update the\ncurrent key manager policy. A new update policy transaction can be generated\nusing ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#NewUpdatePolicyTx"},(0,r.kt)("inlineCode",{parentName:"a"},"NewUpdatePolicyTx")),"."),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Method name:")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"keymanager.UpdatePolicy\n")),(0,r.kt)("p",null,"The body of an update policy transaction must be a ",(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#SignedPolicySGX"},(0,r.kt)("inlineCode",{parentName:"a"},"SignedPolicySGX"))," which is\na signed key manager access control policy. The signer of the transaction must\nbe the key manager runtime's owning entity."),(0,r.kt)("h2",{id:"events"},"Events"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e607d64f.3a99e3fd.js b/assets/js/e607d64f.3a99e3fd.js new file mode 100644 index 0000000000..7159afdb71 --- /dev/null +++ b/assets/js/e607d64f.3a99e3fd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7581],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>u});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,s=e.originalType,l=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=p(n),h=r,u=d["".concat(l,".").concat(h)]||d[h]||m[h]||s;return n?a.createElement(u,o(o({ref:t},c),{},{components:n})):a.createElement(u,o({ref:t},c))}));function u(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var s=n.length,o=new Array(s);o[0]=h;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[d]="string"==typeof e?e:r,o[1]=i;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>m,frontMatter:()=>s,metadata:()=>i,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const s={description:"Submitting transactions without paying for fees"},o="Gasless Transactions",i={unversionedId:"dapp/sapphire/gasless",id:"dapp/sapphire/gasless",title:"Gasless Transactions",description:"Submitting transactions without paying for fees",source:"@site/docs/dapp/sapphire/gasless.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/gasless",permalink:"/dapp/sapphire/gasless",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/gasless.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"Submitting transactions without paying for fees"},sidebar:"developers",previous:{title:"Browser Support",permalink:"/dapp/sapphire/browser"},next:{title:"Precompiles",permalink:"/dapp/sapphire/precompiles"}},l={},p=[{value:"On-Chain Signer",id:"on-chain-signer",level:2},{value:"EIP155Signer",id:"eip155signer",level:3},{value:"Gasless Proxy Contract",id:"gasless-proxy-contract",level:3},{value:"Simple Gasless Commenting dApp",id:"simple-gasless-commenting-dapp",level:3},{value:"Gasless Proxy in Production",id:"gasless-proxy-in-production",level:3},{value:"Confidentiality",id:"confidentiality",level:4},{value:"Gas Cost and Gas Limit",id:"gas-cost-and-gas-limit",level:4},{value:"Allowed Transactions",id:"allowed-transactions",level:4},{value:"Access Control",id:"access-control",level:4},{value:"Multiple Signers",id:"multiple-signers",level:4},{value:"Gas Station Network",id:"gas-station-network",level:2},{value:"Package Install",id:"package-install",level:3},{value:"Deploy GSN",id:"deploy-gsn",level:3},{value:"Start GSN Relay Server",id:"start-gsn-relay-server",level:3},{value:"Fund and Register GSN Relay Server",id:"fund-and-register-gsn-relay-server",level:3},{value:"Send Testing Relayed Requests:",id:"send-testing-relayed-requests",level:3},{value:"Writing a GSN-enabled Smart Contract",id:"writing-a-gsn-enabled-smart-contract",level:3}],c={toc:p},d="wrapper";function m(e){let{components:t,...s}=e;return(0,r.kt)(d,(0,a.Z)({},c,s,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"gasless-transactions"},"Gasless Transactions"),(0,r.kt)("p",null,"When you submit a transaction to a blockchain, you need to pay certain fee\n(called ",(0,r.kt)("em",{parentName:"p"},"gas")," in Ethereum jargon). Since only the transactions with the highest\nfee will be included in the block, this mechanism effectively prevents denial\nof service attacks on the network. On the other hand, paying for gas requires\nfrom the user that they have certain amount of blockchain-native tokens\navailable in their wallet which may not be feasible."),(0,r.kt)("p",null,"In this chapter we will learn how the user signs and sends their transaction to\na ",(0,r.kt)("em",{parentName:"p"},"relayer"),". The relayer then wraps the original signed transaction into a new\n",(0,r.kt)("em",{parentName:"p"},"meta-transaction")," (see ",(0,r.kt)("a",{parentName:"p",href:"https://eips.ethereum.org/EIPS/eip-2771"},"ERC-2771")," for details), signs it and pays for the\nnecessary transaction fees. When the transaction is submitted the on-chain\nrecipient contract decodes the meta-transaction, verifies both signatures and\nexecutes the original transaction."),(0,r.kt)("p",null,"Oasis Sapphire supports two transaction relaying methods: The ",(0,r.kt)("strong",{parentName:"p"},"on-chain\nsigner")," exposes the Oasis-specific contract state encryption functionality\nwhile the ",(0,r.kt)("strong",{parentName:"p"},"gas station network")," method is a standardized approach known in\nother blockchains as well."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The gas station network implementation on Sapphire is still in early beta. Some\nfeatures such as the browser support are not fully implemented yet.")),(0,r.kt)("h2",{id:"on-chain-signer"},"On-Chain Signer"),(0,r.kt)("p",null,"The on-chain signer is a smart contract which receives the user's transaction,\nchecks whether the transaction is valid, wraps it into a meta-transaction\n(which includes paying for the transaction fee) and returns it back to the user\nin ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md"},"EIP-155")," format. These steps are executed as a confidential call. Finally,\nthe user submits the generated transaction to the network."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Diagram of the On-Chain Signing",src:n(773).Z,width:"914",height:"323"})),(0,r.kt)("h3",{id:"eip155signer"},"EIP155Signer"),(0,r.kt)("p",null,"To sign a transaction, the Sapphire's ",(0,r.kt)("inlineCode",{parentName:"p"},"EIP155Signer")," library bundled along the\n",(0,r.kt)("inlineCode",{parentName:"p"},"@oasisprotocol/sapphire-contract")," package comes with the following helper which\nreturns a raw, RLP-encoded, signed transaction ready to be broadcast:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},"function sign(address publicAddress, bytes32 secretKey, EthTx memory transaction) internal view returns (bytes memory);\n")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"publicAddress")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"secretKey")," are the signer's address and their private key\nused to sign a meta-transaction (and pay for the fees). We will store these\nsensitive data inside the encrypted smart contract state together with the\nsigner's ",(0,r.kt)("inlineCode",{parentName:"p"},"nonce")," field in the following struct:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},"struct EthereumKeypair {\n address addr;\n bytes32 secret;\n uint64 nonce;\n}\n")),(0,r.kt)("p",null,"The last ",(0,r.kt)("inlineCode",{parentName:"p"},"transaction")," parameter in the ",(0,r.kt)("inlineCode",{parentName:"p"},"sign()")," function is the transaction\nencoded in a format based on ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md"},"EIP-155"),". This can either be the original user's\ntransaction or a meta-transaction."),(0,r.kt)("h3",{id:"gasless-proxy-contract"},"Gasless Proxy Contract"),(0,r.kt)("p",null,"The following snippet is a complete ",(0,r.kt)("em",{parentName:"p"},"Gasless")," contract for wrapping the user's\ntransactions (",(0,r.kt)("inlineCode",{parentName:"p"},"makeProxyTx()"),") and executing them (",(0,r.kt)("inlineCode",{parentName:"p"},"proxy()"),"). The signer's\nprivate key containing enough balance to cover transaction fees should be\nprovided in the constructor."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},'import {EIP155Signer} from "@oasisprotocol/sapphire-contracts/contracts/EIP155Signer.sol";\n\nstruct EthereumKeypair {\n address addr;\n bytes32 secret;\n uint64 nonce;\n}\n\nstruct EthTx {\n uint64 nonce;\n uint256 gasPrice;\n uint64 gasLimit;\n address to;\n uint256 value;\n bytes data;\n uint256 chainId;\n}\n\n// Proxy for gasless transaction.\ncontract Gasless {\n EthereumKeypair private kp;\n\n function setKeypair(EthereumKeypair memory keypair) external payable {\n kp = keypair;\n }\n\n function makeProxyTx(address innercallAddr, bytes memory innercall)\n external\n view\n returns (bytes memory output)\n {\n bytes memory data = abi.encode(innercallAddr, innercall);\n\n // Call will invoke proxy().\n return\n EIP155Signer.sign(\n kp.addr,\n kp.secret,\n EIP155Signer.EthTx({\n nonce: kp.nonce,\n gasPrice: 100_000_000_000,\n gasLimit: 250000,\n to: address(this),\n value: 0,\n data: abi.encodeCall(this.proxy, data),\n chainId: block.chainid\n })\n );\n }\n\n function proxy(bytes memory data) external payable {\n (address addr, bytes memory subcallData) = abi.decode(\n data,\n (address, bytes)\n );\n (bool success, bytes memory outData) = addr.call{value: msg.value}(\n subcallData\n );\n if (!success) {\n // Add inner-transaction meaningful data in case of error.\n assembly {\n revert(add(outData, 32), mload(outData))\n }\n }\n kp.nonce += 1;\n }\n}\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The snippet above only runs on Sapphire Mainnet, Testnet or Localnet.\n",(0,r.kt)("inlineCode",{parentName:"p"},"EIP155Signer.sign()")," is not supported on other EVM chains.")),(0,r.kt)("h3",{id:"simple-gasless-commenting-dapp"},"Simple Gasless Commenting dApp"),(0,r.kt)("p",null,"Let's see how we can implement on-chain signer for a gasless commenting dApp\nlike this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-solidity"},"contract CommentBox {\n string[] public comments;\n\n function comment(string memory commentText) external {\n comments.push(commentText);\n }\n}\n")),(0,r.kt)("p",null,"Then, the TypeScript code on a client side for submitting a comment in a gasless\nfashion would look like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-typescript"},"const CommentBox = await ethers.getContractFactory(\"CommentBox\");\nconst commentBox = await CommentBox.deploy();\nconst Gasless = await ethers.getContractFactory(\"Gasless\");\nconst gasless = await Gasless.deploy();\n\n// Set the keypair used to sign the meta-transaction.\nawait gasless.setKeypair({\n addr: \"70997970C51812dc3A010C7d01b50e0d17dc79C8\",\n secret: Uint8Array.from(Buffer.from(\"59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d\", 'hex')),\n nonce: 0,\n});\n\nconst innercall = commentBox.interface.encodeFunctionData('comment', ['Hello, free world!']);\nconst tx = await gasless.makeProxyTx(commentBox.address, innercall);\n\nconst plainProvider = new ethers.providers.JsonRpcProvider(ethers.provider.connection);\nconst plainResp = await plainProvider.sendTransaction(tx);\n\nconst receipt = await ethers.provider.waitForTransaction(plainResp.hash);\nif (!receipt || receipt.status != 1) throw new Error('tx failed');\n")),(0,r.kt)("admonition",{title:"Example",type:"info"},(0,r.kt)("p",{parentName:"admonition"},"You can download a complete on-chain signer example based on the above snippets\nfrom the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/onchain-signer"},"Sapphire ParaTime examples")," repository.")),(0,r.kt)("h3",{id:"gasless-proxy-in-production"},"Gasless Proxy in Production"),(0,r.kt)("p",null,"The snippets above have shown how the on-chain signer can generate and sign a\nmeta-transaction for arbitrary transaction. In production environment however,\nyou must consider the following:"),(0,r.kt)("h4",{id:"confidentiality"},"Confidentiality"),(0,r.kt)("p",null,"Both the inner- and the meta-transaction are stored on-chain unencrypted. Use\n",(0,r.kt)("inlineCode",{parentName:"p"},"Sapphire.encrypt()")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Sapphire.decrypt()")," call on the inner-transaction with\nan encryption key generated and stored inside a confidential contract state."),(0,r.kt)("h4",{id:"gas-cost-and-gas-limit"},"Gas Cost and Gas Limit"),(0,r.kt)("p",null,"The gas cost and the gas limit in our snippet were hardcoded inside the\ncontract. Ideally the gas cost should be dynamically adjusted by an oracle and\nthe gas limit determined based on the type of transactions. ",(0,r.kt)("strong",{parentName:"p"},"Never let gas cost\nand limit to be freely defined by the user, since they can drain your relayer's\naccount.")),(0,r.kt)("h4",{id:"allowed-transactions"},"Allowed Transactions"),(0,r.kt)("p",null,"Your relayer will probably be used for transactions of a specific contract only.\nOne approach is to store the allowed address of the target contract and ",(0,r.kt)("strong",{parentName:"p"},"only\nallow calls to this contract address"),"."),(0,r.kt)("h4",{id:"access-control"},"Access Control"),(0,r.kt)("p",null,"You can either whitelist specific addresses of the users in the relayer contract\nor implement the access control in the target contract. In the latter case, the\nrelayer's ",(0,r.kt)("inlineCode",{parentName:"p"},"makeProxyTx()")," should simulate the execution of the inner-transaction\nand generate the meta-transaction only if it inner-transaction succeeded."),(0,r.kt)("h4",{id:"multiple-signers"},"Multiple Signers"),(0,r.kt)("p",null,"Only one transaction per block can be relayed by the same signer since the order\nof the transactions is not deterministic and nonces could mismatch. To overcome\nthis, relayer can randomly pick a signer from the ",(0,r.kt)("strong",{parentName:"p"},"pool of signers"),". When the\ntransaction is relayed, don't forget to reimburse the signer of the transaction!"),(0,r.kt)("admonition",{title:"Example",type:"info"},(0,r.kt)("p",{parentName:"admonition"},"All the above points are considered in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/demo-voting"},"Demo Voting dApp"),".\nYou can explore the code and also try out a deployed gasless version of the\nvoting dApp on the ",(0,r.kt)("a",{parentName:"p",href:"https://playground.oasis.io/demo-voting"},"Oasis Playground site"),". The access\ncontrol list is configured so that anyone can vote on any poll and only poll\ncreators can close the poll.")),(0,r.kt)("h2",{id:"gas-station-network"},"Gas Station Network"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://docs.opengsn.org"},"Gas Station Network")," (GSN) was adapted to work with\nSapphire in a forked ",(0,r.kt)("inlineCode",{parentName:"p"},"@oasislabs/opengsn-cli")," package. The diagram below\nillustrates a flow for signing a transaction by using a GSN",(0,r.kt)("sup",{parentName:"p",id:"fnref-1"},(0,r.kt)("a",{parentName:"sup",href:"#fn-1",className:"footnote-ref"},"1")),"."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Diagram of the Gas Station Network Flow",src:n(1122).Z,width:"1624",height:"927"})),(0,r.kt)("h3",{id:"package-install"},"Package Install"),(0,r.kt)("p",null,"Starting with an empty folder, let us install the\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasislabs/gsn"},"Oasis fork of the GSN command line tool")," by\nusing the following commands:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"pnpm init\npnpm install -D @oasislabs/opengsn-cli\n")),(0,r.kt)("p",null,"Next, we will export our hex-encoded private key (",(0,r.kt)("strong",{parentName:"p"},"without")," the leading ",(0,r.kt)("inlineCode",{parentName:"p"},"0x"),")\nfor deploying the gas station network as an environment variable:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"export PRIVATE_KEY=...\n")),(0,r.kt)("h3",{id:"deploy-gsn"},"Deploy GSN"),(0,r.kt)("p",null,"Deploy GSN relaying contracts along with the test paymaster using a\ntest token. Use the address of your account as ",(0,r.kt)("inlineCode",{parentName:"p"},"--burnAddress")," and\n",(0,r.kt)("inlineCode",{parentName:"p"},"--devAddress")," parameters:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn deploy --network sapphire_testnet --burnAddress 0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204 --devAddress 0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204 --testToken true --testPaymaster true --yes --privateKeyHex $PRIVATE_KEY\n")),(0,r.kt)("p",null,"After the command finishes successfully, you should find the addreses of\ndeployed contracts at the end:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"}," Deployed TestRecipient at address 0x594cd6354b23A5200a57355072E2A5B15354ee21\n \n RelayHub: 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 \n RelayRegistrar: 0x196036FBeC1dA841C60145Ce12b0c66078e141E6\n StakeManager: 0x6763c3fede9EBBCFbE4FEe6a4DE6C326ECCdacFc\n Penalizer: 0xA58A0D302e470490c064EEd5f752Df4095d3A002\n Forwarder: 0x59001d07a1Cd4836D22868fcc0dAf3732E93be81\n TestToken (test only): 0x6Ed21672c0c26Daa32943F7b1cA1f1d0ABdbac66\n Paymaster (Default): 0x8C06261f58a024C958d42df89be7195c8690008d\n")),(0,r.kt)("h3",{id:"start-gsn-relay-server"},"Start GSN Relay Server"),(0,r.kt)("p",null,"Now we are ready to start our own relay server by using the following command.\nUse the newly deployed:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"RelayHub")," address for ",(0,r.kt)("inlineCode",{parentName:"li"},"--relayHubAddress"),","),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"TestToken")," address for ",(0,r.kt)("inlineCode",{parentName:"li"},"--managerStakeTokenAddress"),","),(0,r.kt)("li",{parentName:"ul"},"address of your account for ",(0,r.kt)("inlineCode",{parentName:"li"},"--owner-address"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn relayer-run --relayHubAddress 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --managerStakeTokenAddress 0x6Ed21672c0c26Daa32943F7b1cA1f1d0ABdbac66 --ownerAddress '0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204' --ethereumNodeUrl 'https://testnet.sapphire.oasis.dev' --workdir .\n")),(0,r.kt)("h3",{id:"fund-and-register-gsn-relay-server"},"Fund and Register GSN Relay Server"),(0,r.kt)("p",null,"The first thing is to fund your relay server so that it has enough native\ntokens to pay for others' transactions. Let's fund the paymaster with\n",(0,r.kt)("strong",{parentName:"p"},"5 tokens"),". Use the ",(0,r.kt)("inlineCode",{parentName:"p"},"RelayHub")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Paymaster")," addresses for ",(0,r.kt)("inlineCode",{parentName:"p"},"--hub"),"\nand ",(0,r.kt)("inlineCode",{parentName:"p"},"--paymaster")," values:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn paymaster-fund --network sapphire_testnet --hub 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --paymaster 0x8C06261f58a024C958d42df89be7195c8690008d --privateKeyHex $PRIVATE_KEY --amount 5000000000000000000\n")),(0,r.kt)("p",null,"You can check the balance of the paymaster by running:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn paymaster-balance --network sapphire_testnet --hub 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --paymaster 0x8C06261f58a024C958d42df89be7195c8690008d\n")),(0,r.kt)("p",null,"Next, we need to register the relay server with the your desired ",(0,r.kt)("inlineCode",{parentName:"p"},"relayUrl")," by\nstaking the ",(0,r.kt)("inlineCode",{parentName:"p"},"token")," the relayHub requires."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn relayer-register --network sapphire_testnet --relayUrl 'http://localhost:8090' --token 0x6Ed21672c0c26Daa32943F7b1cA1f1d0ABdbac66 --wrap true --privateKeyHex $PRIVATE_KEY\n")),(0,r.kt)("p",null,"After this step, your relay server should be ready to take incoming relay\nrequests and forward them to the relay hub on Sapphire Testnet."),(0,r.kt)("h3",{id:"send-testing-relayed-requests"},"Send Testing Relayed Requests:"),(0,r.kt)("p",null,"We can test whether a relayed request can be forwarded and processed correctly.\nScroll up to find the GSN deployment response and use the following parameters:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Forwarder")," as ",(0,r.kt)("inlineCode",{parentName:"li"},"--to"),","),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Paymaster")," as ",(0,r.kt)("inlineCode",{parentName:"li"},"--paymaster"),","),(0,r.kt)("li",{parentName:"ul"},"your account address as ",(0,r.kt)("inlineCode",{parentName:"li"},"--from"))),(0,r.kt)("p",null,"Parameters matching our deployment would be:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"npx gsn send-request --network sapphire_testnet --abiFile 'node_modules/@oasislabs/opengsn-cli/dist/compiled/TestRecipient.json' --method emitMessage --methodParams 'hello world!' --to 0x594cd6354b23A5200a57355072E2A5B15354ee21 --paymaster 0x8C06261f58a024C958d42df89be7195c8690008d --privateKeyHex $PRIVATE_KEY --from 0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204 --gasLimit 150000 --gasPrice 100\n")),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"More detailed explanations of these GSN commands and parameters can be found on\nthe ",(0,r.kt)("a",{parentName:"p",href:"https://docs.opengsn.org/javascript-client/gsn-helpers.html"},"upstream OpenGSN website"),".")),(0,r.kt)("h3",{id:"writing-a-gsn-enabled-smart-contract"},"Writing a GSN-enabled Smart Contract"),(0,r.kt)("p",null,"First, install the OpenGSN contracts package:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"pnpm install -D @opengsn/contracts@3.0.0-beta.2\n")),(0,r.kt)("p",null,"Then follow the remainder of the steps from the\n",(0,r.kt)("a",{parentName:"p",href:"https://docs.opengsn.org/contracts/#receiving-a-relayed-call"},"upstream OpenGSN docs"),"."),(0,r.kt)("div",{className:"footnotes"},(0,r.kt)("hr",{parentName:"div"}),(0,r.kt)("ol",{parentName:"div"},(0,r.kt)("li",{parentName:"ol",id:"fn-1"},"The GSN flow diagram is courtesy of ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/opengsn/docs"},"OpenGSN documentation"),".",(0,r.kt)("a",{parentName:"li",href:"#fnref-1",className:"footnote-backref"},"\u21a9")))))}m.isMDXComponent=!0},1122:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/gasless-gsn-flow-ce9d704c33063bf100cc9d483f696a95.jpg"},773:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/gasless-on-chain-signer-3f3b75e0b9fddb83e45c51d52ee5a8bd.svg"}}]); \ No newline at end of file diff --git a/assets/js/e6c3daa2.637e2b08.js b/assets/js/e6c3daa2.637e2b08.js new file mode 100644 index 0000000000..542d5d794b --- /dev/null +++ b/assets/js/e6c3daa2.637e2b08.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3051],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>m});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function s(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var i=n.createContext({}),c=function(e){var t=n.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},d=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},g=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,o=e.originalType,i=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),p=c(a),g=r,m=p["".concat(i,".").concat(g)]||p[g]||u[g]||o;return a?n.createElement(m,s(s({ref:t},d),{},{components:a})):n.createElement(m,s({ref:t},d))}));function m(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=a.length,s=new Array(o);s[0]=g;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[p]="string"==typeof e?e:r,s[1]=l;for(var c=2;c{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=a(7462),r=(a(7294),a(3905));const o={},s="Self-Custody With Ledger Hardware Wallet",l={unversionedId:"general/manage-tokens/holding-rose-tokens/ledger-wallet",id:"general/manage-tokens/holding-rose-tokens/ledger-wallet",title:"Self-Custody With Ledger Hardware Wallet",description:"This is a general documentation that will help users setup [Ledger] hadware",source:"@site/docs/general/manage-tokens/holding-rose-tokens/ledger-wallet.md",sourceDirName:"general/manage-tokens/holding-rose-tokens",slug:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",permalink:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/holding-rose-tokens/ledger-wallet.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Custody Providers",permalink:"/general/manage-tokens/holding-rose-tokens/custody-providers"},next:{title:"How to Transfer ROSE into a ParaTime",permalink:"/general/manage-tokens/how-to-transfer-rose-into-paratime"}},i={},c=[{value:"Setup your Ledger device and Install Oasis App",id:"setup-your-ledger-device-and-install-oasis-app",level:2},{value:"Manage Your Tokens",id:"manage-your-tokens",level:2},{value:"Using Oasis Wallets",id:"using-oasis-wallets",level:3},{value:"Receive ROSE",id:"receive-rose",level:4},{value:"Send ROSE",id:"send-rose",level:4},{value:"Using Oasis CLI Tools",id:"using-oasis-cli-tools",level:3}],d={toc:c},p="wrapper";function u(e){let{components:t,...o}=e;return(0,r.kt)(p,(0,n.Z)({},d,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"self-custody-with-ledger-hardware-wallet"},"Self-Custody With Ledger Hardware Wallet"),(0,r.kt)("p",null,"This is a general documentation that will help users setup ",(0,r.kt)("a",{parentName:"p",href:"https://www.ledger.com"},"Ledger")," hadware\nwallets with Oasis Network. Ledger Live software doesn't support Oasis (ROSE)\ntokens natively yet. In this guide we will install Oasis app via Ledger Live to\nopen and access wallet with one or multiple accounts via our official\n",(0,r.kt)("a",{parentName:"p",href:"https://www.ledger.com"},"Oasis Wallet - Web"),"."),(0,r.kt)("h2",{id:"setup-your-ledger-device-and-install-oasis-app"},"Setup your Ledger device and Install Oasis App"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"To use your ",(0,r.kt)("a",{parentName:"li",href:"https://www.ledger.com"},"Ledger")," wallet to hold your ROSE tokens, you will have to\ninstall ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/Zondax/ledger-oasis"},"Oasis app")," on your Ledger wallet via ",(0,r.kt)("a",{parentName:"li",href:"https://www.ledger.com/ledger-live/"},"Ledger Live"),"'s Manager. You need\nto connect your Ledger to your device and unlock it with your PIN code first.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Unlock ledger",src:a(7745).Z,width:"2302",height:"1738"})),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The Oasis app requires an up-to-date firmware on your Ledger wallet:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"At least ",(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360014980580-Ledger-Nano-X-firmware-release-notes"},"version 2.0.0")," released on Oct 21, 2021 on a Nano X device."),(0,r.kt)("li",{parentName:"ul"},"At least ",(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360010446000-Ledger-Nano-S-firmware-release-notes"},"version 2.1.0")," released on Nov 30, 2021 on a Nano S device."),(0,r.kt)("li",{parentName:"ul"},"At least ",(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/4494540771997-Ledger-Nano-S-Plus-Firmware-Release-Notes"},"version 1.0.4")," released on Sep 27, 2022 on a Nano S Plus device.")),(0,r.kt)("p",{parentName:"admonition"},"Follow Ledger's instructions for updating the firmware on your Ledger wallet:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360013349800"},"Nano X")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/360002731113-Update-Ledger-Nano-S-firmware"},"Nano S")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://support.ledger.com/hc/en-us/articles/4445777839901-Update-Ledger-Nano-S-Plus-firmware"},"Nano S Plus")))),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"To find the Oasis app in the Ledger Live App catalog, you need to Allow\nLedger Manager on your Ledger device first, then you will be able to click App\ncatalog and search for ",(0,r.kt)("em",{parentName:"li"},"Oasis"),":")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Allow Ledger Manager",src:a(3351).Z,width:"2296",height:"1740"}),"\n",(0,r.kt)("img",{alt:"Search app in catalog..",src:a(4808).Z,width:"2298",height:"1744"})),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"Install ",(0,r.kt)("em",{parentName:"li"},"Oasis")," app")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Install Oasis app",src:a(8114).Z,width:"2296",height:"1744"})),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"After the installation is completed, take your Ledger device, navigate to ",(0,r.kt)("em",{parentName:"li"},"Oasis"),"\napp and use both buttons to open the app. Your Ledger device is ready\nwhen you will see ",(0,r.kt)("em",{parentName:"li"},'"Oasis Ready"')," message.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Ready",src:a(3493).Z,width:"640",height:"480"})),(0,r.kt)("p",null,"The Oasis app will use the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki"},"BIP 39")," mnemonic seed stored secretly on your\nLedger hardware wallet to generate the private & public key pairs for your\nOasis accounts. Make sure you backed up the mnemonic when you first initialized\nyour Ledger device!"),(0,r.kt)("h2",{id:"manage-your-tokens"},"Manage Your Tokens"),(0,r.kt)("h3",{id:"using-oasis-wallets"},"Using Oasis Wallets"),(0,r.kt)("p",null,"This is a simpler option since it allows you to connect to your Ledger wallet\nvia a web application or a browser extension."),(0,r.kt)("p",null,"In the example below we will use Oasis Wallet - Web. To learn more about other\nfeatures of the Oasis Wallets, please read the ",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/"},"Oasis Wallets")," doc."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Navigate to ",(0,r.kt)("a",{parentName:"li",href:"https://wallet.oasis.io"},"wallet.oasis.io")," and click on the ",(0,r.kt)("em",{parentName:"li"},"Open wallet")," button.\nThen, click on ",(0,r.kt)("em",{parentName:"li"},"Ledger")," when asked how to open your wallet.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Open wallet -> Ledger",src:a(7761).Z,width:"3024",height:"1676"})),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"In the next step, click on the ",(0,r.kt)("em",{parentName:"li"},"Select accounts to open")," button. Your\nbrowser will open a pop-up window where you will have to select your Ledger\ndevice. Finally, click on ",(0,r.kt)("em",{parentName:"li"},"Connect"),".")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Select Ledger device and Connect",src:a(5349).Z,width:"3024",height:"1740"})),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"This step requires that your Ledger shows the ",(0,r.kt)("em",{parentName:"p"},"Oasis Ready")," message. After a\nwhile your device may lock for safety reasons and you will need to unlock it to\nperform this and subsequent steps.")),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"After connecting your Ledger to Oasis Wallet - Web another pop-up will appear\nwhere you can choose to open one or more ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis1")," accounts derived from the seed\nstored on your Ledger.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Select one or more accounts",src:a(4223).Z,width:"3024",height:"1742"})),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"The account from your Ledger device is now opened. If you import multiple\naccounts, you can switch between them by clicking on the account address in\nthe top-right corner.\nOur demo account is empty.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Selected accounts are opened",src:a(8555).Z,width:"3024",height:"1890"})),(0,r.kt)("ol",{start:5},(0,r.kt)("li",{parentName:"ol"},"Now you can use your Ledger to receive, send or delegate ROSE.\nIn this example, we have received 111 ROSE to our Ledger account.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Exploring transactions",src:a(5023).Z,width:"3024",height:"1892"})),(0,r.kt)("h4",{id:"receive-rose"},"Receive ROSE"),(0,r.kt)("p",null,"Once you have successfully opened your Oasis account from Ledger,\nyou can start receiving ROSE by sharing your account address."),(0,r.kt)("p",null,"You can simply copy your opened account address or scan QR code."),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Ledger -> Receive ROSE Account address",src:a(8021).Z,width:"3024",height:"1732"})),(0,r.kt)("h4",{id:"send-rose"},"Send ROSE"),(0,r.kt)("p",null,"To send your ROSE from your Oasis Ledger account to another Oasis consensus\naddress, you have to follow these steps:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Enter destination consensus address into Recipient field, Enter amount\nof ROSE you want to send and Click on Send button.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Ledger -> Send ROSE",src:a(8428).Z,width:"3024",height:"1732"})),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"Then a pop-up window will appear where you need to Confirm transaction.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Ledger -> Confirm TX",src:a(1473).Z,width:"3024",height:"1732"})),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"On your Ledger device carefully review transaction details and make sure they\nmatch the ones on your computer. Navigate to the screen where you will see the\nAPPROVE button. Use the two buttons to approve your transaction.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Ledger -> Approve TX",src:a(7587).Z,width:"1280",height:"960"})),(0,r.kt)("ol",{start:4},(0,r.kt)("li",{parentName:"ol"},"You can verify if ROSE were successfully sent by checking latest transactions\nor opening the receiving account.")),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Oasis Wallet - Web -> Ledger -> Verify Balance",src:a(9491).Z,width:"3024",height:"1734"})),(0,r.kt)("h3",{id:"using-oasis-cli-tools"},"Using Oasis CLI Tools"),(0,r.kt)("p",null,"This is a more powerful option that allows performing not just token-related\ntasks (sending, staking, ParaTime deposits and withdrawals), but also generating\nand/or signing raw transactions, multi-signatures, network governance\noperations etc."),(0,r.kt)("p",null,"Ledger is supported by the Oasis CLI. Follow the instructions in the\n",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/"},"Oasis CLI Tools")," page to learn more."))}u.isMDXComponent=!0},3493:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg"},3351:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/live_allow_ledger_manager-30797e705e2068c9c7ee2b6eed02c6a9.png"},4808:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/live_search_apps-d344482547f64a390b308f2e1272af31.png"},8114:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/live_search_results_oasis_install-b346253511375cf2643b524e3c0291ab.png"},7745:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/live_unlock_ledger-502e6c5d1ae4698f027cae7e166c59cd.png"},8021:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_account_address-0dd7d76aebb5f4ed5c078086328ccd9e.png"},7761:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_open_ledger-e51cb72a003a6182977c88ab17640e10.png"},8555:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_open_ledger_account-ed82b4ff6218c9048f1de817c86c59f5.png"},5023:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_received_rose_on_ledger_account-c4c156f34823a0295cb15ed58ba96c80.png"},4223:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_select_accounts_to_open-969db3be1effeaa820032d37798cb59a.png"},5349:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_select_ledger_device_connect-80a3396eca59a50b4df51f7b002604dd.png"},1473:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_send_confirm_tx-22c8e7574fb5cbc9edbfdfffae1c57de.png"},7587:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_send_confirm_tx_ledger-107bae9057a413cc91850ab7cceb910e.jpg"},8428:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_send_rose-be33ca81a26cbf7d896fa5fd60a883f8.png"},9491:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/wallet_web_send_verify_balance-49fdd9aa7169c2a34eb84bfdeee1e337.png"}}]); \ No newline at end of file diff --git a/assets/js/e6f41e1e.edfc34fa.js b/assets/js/e6f41e1e.edfc34fa.js new file mode 100644 index 0000000000..3847fc3b74 --- /dev/null +++ b/assets/js/e6f41e1e.edfc34fa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2469],{3905:(e,t,r)=>{r.d(t,{Zo:()=>i,kt:()=>f});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function o(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var p=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var s=a.createContext({}),d=function(e){var t=a.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},i=function(e){var t=d(e.components);return a.createElement(s.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,p=e.originalType,s=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),c=d(r),m=n,f=c["".concat(s,".").concat(m)]||c[m]||u[m]||p;return r?a.createElement(f,o(o({ref:t},i),{},{components:r})):a.createElement(f,o({ref:t},i))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var p=r.length,o=new Array(p);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[c]="string"==typeof e?e:n,o[1]=l;for(var d=2;d{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>p,metadata:()=>l,toc:()=>d});var a=r(7462),n=(r(7294),r(3905));const p={description:"List of Standard Contract Addresses"},o="Standard Contract Addresses",l={unversionedId:"dapp/sapphire/addresses",id:"dapp/sapphire/addresses",title:"Standard Contract Addresses",description:"List of Standard Contract Addresses",source:"@site/docs/dapp/sapphire/addresses.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/addresses",permalink:"/dapp/sapphire/addresses",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/addresses.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{description:"List of Standard Contract Addresses"},sidebar:"developers",previous:{title:"Precompiles",permalink:"/dapp/sapphire/precompiles"},next:{title:"Oasis Privacy Layer",permalink:"/dapp/opl/"}},s={},d=[],i={toc:d},c="wrapper";function u(e){let{components:t,...r}=e;return(0,n.kt)(c,(0,a.Z)({},i,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"standard-contract-addresses"},"Standard Contract Addresses"),(0,n.kt)("table",null,(0,n.kt)("thead",{parentName:"table"},(0,n.kt)("tr",{parentName:"thead"},(0,n.kt)("th",{parentName:"tr",align:null},"Name"),(0,n.kt)("th",{parentName:"tr",align:null},"Mainnet Address"),(0,n.kt)("th",{parentName:"tr",align:null},"Testnet Address"),(0,n.kt)("th",{parentName:"tr",align:null},"Verify"),(0,n.kt)("th",{parentName:"tr",align:null},"Source"))),(0,n.kt)("tbody",{parentName:"table"},(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://multicall3.com/"},"Multicall V3")),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("inlineCode",{parentName:"td"},"0xcA11bde05977b3631167028862bE2a173976CA11")),(0,n.kt)("td",{parentName:"tr",align:null},"-"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://sourcify.dev/#/lookup/0xcA11bde05977b3631167028862bE2a173976CA11"},"Mainnet")),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/mds1/multicall/blob/main/src/Multicall3.sol"},"Multicall3.sol"))),(0,n.kt)("tr",{parentName:"tbody"},(0,n.kt)("td",{parentName:"tr",align:null},"Wrapped ROSE"),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("inlineCode",{parentName:"td"},"0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3")),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("inlineCode",{parentName:"td"},"0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94")),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://sourcify.dev/#/lookup/0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3"},"Mainnet"),", ",(0,n.kt)("a",{parentName:"td",href:"https://sourcify.dev/#/lookup/0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94"},"Testnet")),(0,n.kt)("td",{parentName:"tr",align:null},(0,n.kt)("a",{parentName:"td",href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/WrappedROSE.sol"},"WrappedROSE.sol"))))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e6fdf0fb.b1e4c391.js b/assets/js/e6fdf0fb.b1e4c391.js new file mode 100644 index 0000000000..1980fc956b --- /dev/null +++ b/assets/js/e6fdf0fb.b1e4c391.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1794],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>g});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var d=o.createContext({}),l=function(e){var n=o.useContext(d),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},u=function(e){var n=l(e.components);return o.createElement(d.Provider,{value:n},e.children)},p="mdxType",c={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},m=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,d=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),p=l(t),m=r,g=p["".concat(d,".").concat(m)]||p[m]||c[m]||i;return t?o.createElement(g,a(a({ref:n},u),{},{components:t})):o.createElement(g,a({ref:n},u))}));function g(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,a=new Array(i);a[0]=m;var s={};for(var d in n)hasOwnProperty.call(n,d)&&(s[d]=n[d]);s.originalType=e,s[p]="string"==typeof e?e:r,a[1]=s;for(var l=2;l{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>c,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var o=t(7462),r=(t(7294),t(3905));const i={},a="Install Oasis Remote Signer Binary",s={unversionedId:"node/run-your-node/advanced/install-oasis-remote-signer-binary",id:"node/run-your-node/advanced/install-oasis-remote-signer-binary",title:"Install Oasis Remote Signer Binary",description:"You only need to install the Oasis Remote Signer binary if you intend to configure your Oasis node with a remote signer setup.",source:"@site/docs/node/run-your-node/advanced/install-oasis-remote-signer-binary.md",sourceDirName:"node/run-your-node/advanced",slug:"/node/run-your-node/advanced/install-oasis-remote-signer-binary",permalink:"/node/run-your-node/advanced/install-oasis-remote-signer-binary",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/advanced/install-oasis-remote-signer-binary.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Copy State from One Node to the Other",permalink:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other"},next:{title:"Using Ledger-backed Consensus Key with a Remote Signer",permalink:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer"}},d={},l=[{value:"Downloading a Binary Release",id:"downloading-a-binary-release",level:2},{value:"Building From Source",id:"building-from-source",level:2},{value:"Adding oasis-remote-signer Binary to PATH",id:"adding-oasis-remote-signer-binary-to-path",level:2}],u={toc:l},p="wrapper";function c(e){let{components:n,...t}=e;return(0,r.kt)(p,(0,o.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"install-oasis-remote-signer-binary"},"Install Oasis Remote Signer Binary"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"You only need to install the Oasis Remote Signer binary if you intend to configure your Oasis node with a remote signer setup."),(0,r.kt)("p",{parentName:"admonition"},"An example of such a setup is described in ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer"},"Using Ledger-backed Consensus Key with a Remote Signer"),".")),(0,r.kt)("p",null,"The Oasis Remote Signer is a binary that is created from the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," repository's ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-remote-signer"},(0,r.kt)("inlineCode",{parentName:"a"},"go/oasis-remote-signer")," path"),"."),(0,r.kt)("p",null,"It contains the logic for implementing various Oasis Core signers (i.e. Ledger-based signer, file-based signer or a combination of both via composite signer) and a gRPC service through which an Oasis node can connect to it and request signatures from it."),(0,r.kt)("admonition",{type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"The Oasis Remote Signer is currently only supported on x86_64 Linux systems.")),(0,r.kt)("h2",{id:"downloading-a-binary-release"},"Downloading a Binary Release"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"We suggest that you build Oasis Remote Signer from source yourself for a production deployment of an Oasis node with a remote signer setup.")),(0,r.kt)("p",null,"For convenience, we provide binaries that have been built by the Oasis Protocol Foundation. Links to the binaries are provided in the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters")," page."),(0,r.kt)("h2",{id:"building-from-source"},"Building From Source"),(0,r.kt)("p",null,"Although highly suggested, building from source is currently beyond the scope of this documentation."),(0,r.kt)("p",null,"See ",(0,r.kt)("a",{parentName:"p",href:"../../../core/development-setup/build-environment-setup-and-building"},"Oasis Core's Build Environment Setup and Building")," documentation for more details."),(0,r.kt)("admonition",{type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"The code in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/"},(0,r.kt)("inlineCode",{parentName:"a"},"master")," branch")," might be incompatible with the code used by other nodes in the Mainnet."),(0,r.kt)("p",{parentName:"admonition"},"Make sure to use the version specified in the ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),".")),(0,r.kt)("h2",{id:"adding-oasis-remote-signer-binary-to-path"},"Adding ",(0,r.kt)("inlineCode",{parentName:"h2"},"oasis-remote-signer")," Binary to ",(0,r.kt)("inlineCode",{parentName:"h2"},"PATH")),(0,r.kt)("p",null,"To install the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-remote-signer")," binary for the current user, copy/symlink it to ",(0,r.kt)("inlineCode",{parentName:"p"},"~/.local/bin"),"."),(0,r.kt)("p",null,"To install the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-remote-signer")," binary for all users of the system, copy it to ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/local/bin"),"."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e793830e.6c920105.js b/assets/js/e793830e.6c920105.js new file mode 100644 index 0000000000..836b6f0fd1 --- /dev/null +++ b/assets/js/e793830e.6c920105.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3573],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>f});var o=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=o.createContext({}),l=function(e){var n=o.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):a(a({},n),e)),t},u=function(e){var n=l(e.components);return o.createElement(s.Provider,{value:n},e.children)},c="mdxType",p={inlineCode:"code",wrapper:function(e){var n=e.children;return o.createElement(o.Fragment,{},n)}},m=o.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,u=d(e,["components","mdxType","originalType","parentName"]),c=l(t),m=r,f=c["".concat(s,".").concat(m)]||c[m]||p[m]||i;return t?o.createElement(f,a(a({ref:n},u),{},{components:t})):o.createElement(f,a({ref:n},u))}));function f(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,a=new Array(i);a[0]=m;var d={};for(var s in n)hasOwnProperty.call(n,s)&&(d[s]=n[s]);d.originalType=e,d[c]="string"==typeof e?e:r,a[1]=d;for(var l=2;l{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>d,toc:()=>l});var o=t(7462),r=(t(7294),t(3905));const i={},a="Seed Node",d={unversionedId:"node/run-your-node/seed-node",id:"node/run-your-node/seed-node",title:"Seed Node",description:"This guide will cover setting up a seed node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools.",source:"@site/docs/node/run-your-node/seed-node.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/seed-node",permalink:"/node/run-your-node/seed-node",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/seed-node.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Non-validator Node",permalink:"/node/run-your-node/non-validator-node"},next:{title:"Archive Node",permalink:"/node/run-your-node/archive-node"}},s={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Creating a Working Directory",id:"creating-a-working-directory",level:3},{value:"Copying the Genesis File",id:"copying-the-genesis-file",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Seed node address",id:"seed-node-address",level:3},{value:"Share seed node address",id:"share-seed-node-address",level:3}],u={toc:l},c="wrapper";function p(e){let{components:n,...t}=e;return(0,r.kt)(c,(0,o.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"seed-node"},"Seed Node"),(0,r.kt)("p",null,"This guide will cover setting up a seed node for the Oasis Network. This guide assumes some basic knowledge on the use of command line tools."),(0,r.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,r.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,r.kt)("a",{parentName:"p",href:"/node/run-your-node/prerequisites/oasis-node"},"Prerequisites Guide")," and understand how to use the ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary."),(0,r.kt)("h3",{id:"creating-a-working-directory"},"Creating a Working Directory"),(0,r.kt)("p",null,"We will be creating the following directory structure inside a chosen top-level ",(0,r.kt)("inlineCode",{parentName:"p"},"/node")," (feel free to name your directories however you wish) directory:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"etc"),": This will store the node configuration and genesis file.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("inlineCode",{parentName:"p"},"data"),": This will store the data directory needed by the running ",(0,r.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary, including the complete blockchain state."),(0,r.kt)("p",{parentName:"li"},"The directory permissions should be ",(0,r.kt)("inlineCode",{parentName:"p"},"rwx------"),"."))),(0,r.kt)("p",null,"To create the directory structure, use the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-text"},"mkdir -m700 -p /node/{etc,data}\n")),(0,r.kt)("h3",{id:"copying-the-genesis-file"},"Copying the Genesis File"),(0,r.kt)("p",null,"The latest genesis file can be found in ",(0,r.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Network Parameters"),". You should download the latest ",(0,r.kt)("inlineCode",{parentName:"p"},"genesis.json")," file and copy it to the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc")," directory we just created."),(0,r.kt)("h2",{id:"configuration"},"Configuration"),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"This will configure the given node to only act as a seed node.")),(0,r.kt)("p",null,"In order to configure the node create the ",(0,r.kt)("inlineCode",{parentName:"p"},"/node/etc/config.yml")," file with the following content:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"datadir: /node/data\n\nlog:\n level:\n default: info\n tendermint: info\n tendermint/context: error\n format: JSON\n\ngenesis:\n file: /node/etc/genesis.json\n\nconsensus:\n tendermint:\n mode: seed\n")),(0,r.kt)("h2",{id:"starting-the-oasis-node"},"Starting the Oasis Node"),(0,r.kt)("p",null,"You can start the node by running the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node --config /node/etc/config.yml\n")),(0,r.kt)("h3",{id:"seed-node-address"},"Seed node address"),(0,r.kt)("p",null,"To get the seed node Tendermint identity, run the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"oasis-node identity tendermint show-node-address --datadir /node/data/\n")),(0,r.kt)("h3",{id:"share-seed-node-address"},"Share seed node address"),(0,r.kt)("p",null,"Nodes can now use your seed node by specifying it via a configuration flag:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"--consensus.tendermint.p2p.seed @:26656\n")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e9951844.006194d9.js b/assets/js/e9951844.006194d9.js new file mode 100644 index 0000000000..df2b769368 --- /dev/null +++ b/assets/js/e9951844.006194d9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4015],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),h=r,m=u["".concat(l,".").concat(h)]||u[h]||d[h]||o;return n?a.createElement(m,i(i({ref:t},c),{},{components:n})):a.createElement(m,i({ref:t},c))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=h;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[u]="string"==typeof e?e:r,i[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const o={},i="Cryptography",s={unversionedId:"core/crypto",id:"core/crypto",title:"Cryptography",description:"Hash Functions",source:"@site/docs/core/crypto.md",sourceDirName:"core",slug:"/core/crypto",permalink:"/core/crypto",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/crypto.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Encoding",permalink:"/core/encoding"},next:{title:"Authenticated gRPC",permalink:"/core/authenticated-grpc"}},l={},p=[{value:"Hash Functions",id:"hash-functions",level:2},{value:"Signatures",id:"signatures",level:2},{value:"Domain Separation",id:"domain-separation",level:3},{value:"Contexts",id:"contexts",level:4},{value:"Chain Domain Separation",id:"chain-domain-separation",level:4},{value:"Envelopes",id:"envelopes",level:3},{value:"Standard Account Key Generation",id:"standard-account-key-generation",level:2}],c={toc:p},u="wrapper";function d(e){let{components:t,...n}=e;return(0,r.kt)(u,(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"cryptography"},"Cryptography"),(0,r.kt)("h2",{id:"hash-functions"},"Hash Functions"),(0,r.kt)("p",null,"In most places where cryptographic hashes are required, we use the SHA-512/256\nhash function as specified in ",(0,r.kt)("a",{parentName:"p",href:"https://csrc.nist.gov/publications/detail/fips/180/4/final"},"FIPS 180-4"),"."),(0,r.kt)("h2",{id:"signatures"},"Signatures"),(0,r.kt)("p",null,"All cryptographic signatures are made using the Ed25519 (pure) scheme specified\nin ",(0,r.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032"},"RFC 8032"),"."),(0,r.kt)("h3",{id:"domain-separation"},"Domain Separation"),(0,r.kt)("p",null,"When signing messages and verifying signatures we require the use of a domain\nseparation context in order to make sure the messages cannot be repurposed in\na different protocol."),(0,r.kt)("p",null,"The domain separation scheme adds a preprocessing step to any signing and\nverification operation. The step computes the value that is then signed/verified\nusing Ed25519 as usual."),(0,r.kt)("p",null,"The message to be signed is computed as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"M := H(Context || Message)\n")),(0,r.kt)("p",null,"Where:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"H")," is the SHA-512/256 cryptographic hash function."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Context")," is the domain separation context string."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"Message")," is the original message.")),(0,r.kt)("p",null,"The Ed25519 signature is then computed over ",(0,r.kt)("inlineCode",{parentName:"p"},"M"),"."),(0,r.kt)("p",null,(0,r.kt)("em",{parentName:"p"},"NOTE: While using something like Ed25519ph/ctx as specified by ",(0,r.kt)("a",{parentName:"em",href:"https://tools.ietf.org/html/rfc8032"},"RFC 8032")," would\nbe ideal, unfortunately these schemes are not supported in many hardware\nsecurity modules which is why we are using an ad-hoc scheme.")),(0,r.kt)("h4",{id:"contexts"},"Contexts"),(0,r.kt)("p",null,"All of the domain separation contexts used in Oasis Core use the following\nconvention:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"They start with the string ",(0,r.kt)("inlineCode",{parentName:"li"},"oasis-core/"),","),(0,r.kt)("li",{parentName:"ul"},"followed by the general module name,"),(0,r.kt)("li",{parentName:"ul"},"followed by the string ",(0,r.kt)("inlineCode",{parentName:"li"},": "),","),(0,r.kt)("li",{parentName:"ul"},"followed by a use case description.")),(0,r.kt)("p",null,"The maximum length of a domain separation context is 255 bytes to be compatible\nwith the length defined in ",(0,r.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc8032"},"RFC 8032"),"."),(0,r.kt)("p",null,"The Go implementation maintains a registry of all used contexts to make sure\nthey are not reused incorrectly."),(0,r.kt)("h4",{id:"chain-domain-separation"},"Chain Domain Separation"),(0,r.kt)("p",null,"For some signatures, we must ensure that the domain separation context is tied\nto the given network instance as defined by the genesis document. This ensures\nthat such messages cannot be replayed on a different network."),(0,r.kt)("p",null,"For all domain separation contexts where chain domain separation is required,\nwe use the following additional convention:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The context is as specified by the convention in the section above,"),(0,r.kt)("li",{parentName:"ul"},"followed by the string ",(0,r.kt)("inlineCode",{parentName:"li"},"for chain"),","),(0,r.kt)("li",{parentName:"ul"},"followed by the ",(0,r.kt)("a",{parentName:"li",href:"/core/consensus/genesis#genesis-documents-hash"},"genesis document's hash"),".")),(0,r.kt)("h3",{id:"envelopes"},"Envelopes"),(0,r.kt)("p",null,"There are currently two kinds of envelopes that are used when signing CBOR\nmessages:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/signature?tab=doc#Signed"},"Single signature envelope (",(0,r.kt)("inlineCode",{parentName:"a"},"Signed"),")")," contains the CBOR-serialized blob in\nthe ",(0,r.kt)("inlineCode",{parentName:"p"},"untrusted_raw_value")," field and a single ",(0,r.kt)("inlineCode",{parentName:"p"},"signature"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},(0,r.kt)("a",{parentName:"p",href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/signature?tab=doc#MultiSigned"},"Multiple signature envelope (",(0,r.kt)("inlineCode",{parentName:"a"},"MultiSigned"),")")," contains the CBOR-serialized\nblob in the ",(0,r.kt)("inlineCode",{parentName:"p"},"untrusted_raw_value")," field and multiple signatures in the\n",(0,r.kt)("inlineCode",{parentName:"p"},"signatures")," field."))),(0,r.kt)("p",null,"The envelopes are themselves CBOR-encoded. While no separate test vectors are\nprovided, ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/test-vectors"},"those used for transactions")," can be used as a reference."),(0,r.kt)("h2",{id:"standard-account-key-generation"},"Standard Account Key Generation"),(0,r.kt)("p",null,"When generating an ",(0,r.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#accounts"},"account"),"'s private/public key pair, follow ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/adrs/blob/master/0008-standard-account-key-generation.md"},"ADR 0008:\nStandard Account Key Generation"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ea8b28d2.1d85a6a6.js b/assets/js/ea8b28d2.1d85a6a6.js new file mode 100644 index 0000000000..8a5b0c6e25 --- /dev/null +++ b/assets/js/ea8b28d2.1d85a6a6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6561],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>k});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function s(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var i=a.createContext({}),d=function(e){var n=a.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},c=function(e){var n=d(e.components);return a.createElement(i.Provider,{value:n},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,o=e.originalType,i=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=d(t),m=r,k=p["".concat(i,".").concat(m)]||p[m]||u[m]||o;return t?a.createElement(k,s(s({ref:n},c),{},{components:t})):a.createElement(k,s({ref:n},c))}));function k(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=t.length,s=new Array(o);s[0]=m;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l[p]="string"==typeof e?e:r,s[1]=l;for(var d=2;d{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var a=t(7462),r=(t(7294),t(3905));const o={title:"Address book",description:"Storing your blockchain contacts for future use"},s="Address Book",l={unversionedId:"general/manage-tokens/cli/addressbook",id:"general/manage-tokens/cli/addressbook",title:"Address book",description:"Storing your blockchain contacts for future use",source:"@site/docs/general/manage-tokens/cli/addressbook.md",sourceDirName:"general/manage-tokens/cli",slug:"/general/manage-tokens/cli/addressbook",permalink:"/general/manage-tokens/cli/addressbook",draft:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/addressbook.md",tags:[],version:"current",lastUpdatedAt:1692174019,formattedLastUpdatedAt:"Aug 16, 2023",frontMatter:{title:"Address book",description:"Storing your blockchain contacts for future use"},sidebar:"general",previous:{title:"Transaction",permalink:"/general/manage-tokens/cli/transaction"},next:{title:"Frequently Asked Questions",permalink:"/general/manage-tokens/faq"}},i={},d=[{value:"Add a New Entry",id:"add",level:2},{value:"List Entries",id:"list",level:2},{value:"Show Entry Details",id:"show",level:2},{value:"Rename an Entry",id:"rename",level:2},{value:"Remove an Entry",id:"remove",level:2}],c={toc:d},p="wrapper";function u(e){let{components:n,...t}=e;return(0,r.kt)(p,(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"address-book"},"Address Book"),(0,r.kt)("p",null,"If you repeatedly transfer tokens to the same recipients or if you just want to\nstore an arbitrary address for future use, you can use the ",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook"),"\ncommand to ",(0,r.kt)("strong",{parentName:"p"},"name the address and store it in your address book"),". Entries\nin your address book are behaving similarly to the\n",(0,r.kt)("a",{parentName:"p",href:"/general/manage-tokens/cli/wallet"},"accounts stored in your wallet"),", for example when checking the balance\nof the account or sending tokens to. Of course, you cannot sign any\ntransactions with the address stored in your address book since you do not\npossess the private key of that account. Both the Oasis native and the\nEthereum-compatible addresses can be stored."),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"The name of the address book entry may not clash with any of the account names\nin your wallet. The Oasis CLI will prevent you from doing so.")),(0,r.kt)("h2",{id:"add"},"Add a New Entry"),(0,r.kt)("p",null,"Use ",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook add
")," to name the address and store it in your\naddress book."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook add mike oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook add meghan 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1\n")),(0,r.kt)("p",null,"Then, you can for example use the entry name in you address book to send the\ntokens to. In this case, we're sending ",(0,r.kt)("inlineCode",{parentName:"p"},"2.5 TEST")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"meghan")," on Sapphire\nTestnet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis account transfer 2.5 meghan\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"You are about to sign the following transaction:\nFormat: plain\nMethod: accounts.Transfer\nBody:\n To: meghan (oasis1qrjzcve7y6qp3nqs3n7ghavw68vkdh3epcv64ega)\n Amount: 2.5 ROSE\nAuthorized signer(s):\n 1. ArEjDxsPfDvfeLlity4mjGzy8E/nI4umiC8vYQh+eh/c (secp256k1eth)\n Nonce: 0\nFee:\n Amount: 0.0002316 ROSE\n Gas limit: 2316\n (gas price: 0.0000001 ROSE per gas unit)\n\nNetwork: mainnet\nParaTime: emerald\nAccount: eugene\n")),(0,r.kt)("h2",{id:"list"},"List Entries"),(0,r.kt)("p",null,"You can list all entries in your address book by invoking ",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook list"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NAME ADDRESS \nmeghan 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \nmike oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw \n")),(0,r.kt)("h2",{id:"show"},"Show Entry Details"),(0,r.kt)("p",null,"You can check the details such as the native Oasis address of the Ethereum\naccount or simply check, if an entry exists in the address book, by running\n",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook show "),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook show meghan\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Name: meghan\nEthereum address: 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1\nNative address: oasis1qrjzcve7y6qp3nqs3n7ghavw68vkdh3epcv64ega\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook show mike\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"Name: mike\nNative address: oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\n")),(0,r.kt)("h2",{id:"rename"},"Rename an Entry"),(0,r.kt)("p",null,"You can always rename the entry in your address book by using\n",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook rename "),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook rename mike mark\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NAME ADDRESS \nmark oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw \nmeghan 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \n")),(0,r.kt)("h2",{id:"remove"},"Remove an Entry"),(0,r.kt)("p",null,"To delete an entry from your address book invoke\n",(0,r.kt)("inlineCode",{parentName:"p"},"addressbook remove "),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook remove mike\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"oasis addressbook list\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"NAME ADDRESS \nmeghan 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \n")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/eb341911.5af714e6.js b/assets/js/eb341911.5af714e6.js new file mode 100644 index 0000000000..98382e01a0 --- /dev/null +++ b/assets/js/eb341911.5af714e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2699],{3905:(e,t,n)=>{n.d(t,{Zo:()=>m,kt:()=>k});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},m=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},c="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),c=p(n),d=a,k=c["".concat(s,".").concat(d)]||c[d]||u[d]||o;return n?r.createElement(k,i(i({ref:t},m),{},{components:n})):r.createElement(k,i({ref:t},m))}));function k(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[c]="string"==typeof e?e:a,i[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=n(7462),a=(n(7294),n(3905));const o={},i="Versioning",l={unversionedId:"core/versioning",id:"core/versioning",title:"Versioning",description:"Oasis Core",source:"@site/docs/core/versioning.md",sourceDirName:"core",slug:"/core/versioning",permalink:"/core/versioning",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/versioning.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Release Process",permalink:"/core/release-process"},next:{title:"Security",permalink:"/core/SECURITY"}},s={},p=[{value:"Oasis Core",id:"oasis-core",level:2},{value:"Protocols (Consensus, Runtime Host, Runtime Committee)",id:"protocols-consensus-runtime-host-runtime-committee",level:2},{value:"Version 1.0.0",id:"version-100",level:3}],m={toc:p},c="wrapper";function u(e){let{components:t,...n}=e;return(0,a.kt)(c,(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"versioning"},"Versioning"),(0,a.kt)("h2",{id:"oasis-core"},"Oasis Core"),(0,a.kt)("p",null,"Oasis Core (as a whole) uses a ",(0,a.kt)("a",{parentName:"p",href:"http://calver.org"},"CalVer")," (calendar versioning) scheme with the\nfollowing format:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-text"},"YY.MINOR[.MICRO][-MODIFIER]\n")),(0,a.kt)("p",null,"where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"YY")," represents short year (e.g. ",(0,a.kt)("inlineCode",{parentName:"p"},"19"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"20"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"21"),", ...),")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"MINOR")," represents the minor version starting with zero (e.g. ",(0,a.kt)("inlineCode",{parentName:"p"},"0"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"2"),",\n",(0,a.kt)("inlineCode",{parentName:"p"},"3"),", ...),")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"MICRO"),' represents (optional) final number in the version (sometimes referred\nto as the "patch" segment) (e.g. ',(0,a.kt)("inlineCode",{parentName:"p"},"0"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"1"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"2"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"3"),", ...)."),(0,a.kt)("p",{parentName:"li"},"If the ",(0,a.kt)("inlineCode",{parentName:"p"},"MICRO")," version is ",(0,a.kt)("inlineCode",{parentName:"p"},"0"),", it will be omitted.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("inlineCode",{parentName:"p"},"MODIFIER")," represents (optional) build metadata, e.g. ",(0,a.kt)("inlineCode",{parentName:"p"},"git8c01382"),"."))),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"YY")," version must be bumped after each new calendar year."),(0,a.kt)("p",null,"When a regularly scheduled release is made, the ",(0,a.kt)("inlineCode",{parentName:"p"},"MINOR")," version should be\nbumped."),(0,a.kt)("p",null,"If there is a major fix that we want to back-port from an upcoming next release\nand release it, then the ",(0,a.kt)("inlineCode",{parentName:"p"},"MICRO")," version should be bumped."),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"MODIFIER")," should be used to denote a build from an untagged (and\npotentially unclean) git source. It should be of the form:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-text"},"gitCOMMIT_SHA[+dirty]\n")),(0,a.kt)("p",null,"where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"COMMIT_SHA")," represents the current commit\u2019s abbreviated SHA.")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"+dirty")," part is optional and is only present if there are uncommitted\nchanges in the working directory."),(0,a.kt)("h2",{id:"protocols-consensus-runtime-host-runtime-committee"},"Protocols (Consensus, Runtime Host, Runtime Committee)"),(0,a.kt)("p",null,"Oasis Core\u2019s protocol versions use ",(0,a.kt)("a",{parentName:"p",href:"https://semver.org/"},"SemVer")," (semantic versioning) 2.0.0 with the\nfollowing format:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-text"},"MAJOR.MINOR.PATCH\n")),(0,a.kt)("p",null,"where:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MAJOR")," represents the major version,"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"MINOR")," represents the minor version,"),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("inlineCode",{parentName:"li"},"PATCH")," represents the patch version.")),(0,a.kt)("p",null,"Whenever a backward-incompatible change is made to a protocol, the ",(0,a.kt)("inlineCode",{parentName:"p"},"MAJOR"),"\nversion must be bumped."),(0,a.kt)("p",null,"If a new release adds a protocol functionality in a backwards compatible manner,\nthe ",(0,a.kt)("inlineCode",{parentName:"p"},"MINOR")," version must be bumped."),(0,a.kt)("p",null,"When only backwards compatible bug fixes are made to a protocol, the ",(0,a.kt)("inlineCode",{parentName:"p"},"PATCH"),"\nversion should be bumped."),(0,a.kt)("h3",{id:"version-100"},"Version 1.0.0"),(0,a.kt)("p",null,"With the release of ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/blob/v20.10/CHANGELOG.md"},"Oasis Core 20.10"),", we bumped the protocol versions to\nversion 1.0.0 which ",(0,a.kt)("a",{parentName:"p",href:"https://semver.org/#how-do-i-know-when-to-release-100"},"signified that they are ready for production use"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/eb677e7b.b0054f7d.js b/assets/js/eb677e7b.b0054f7d.js new file mode 100644 index 0000000000..33762c13e3 --- /dev/null +++ b/assets/js/eb677e7b.b0054f7d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3296],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>h});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function i(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),c=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):i(i({},t),e)),a},p=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(a),m=o,h=d["".concat(l,".").concat(m)]||d[m]||u[m]||r;return a?n.createElement(h,i(i({ref:t},p),{},{components:a})):n.createElement(h,i({ref:t},p))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:o,i[1]=s;for(var c=2;c{a.r(t),a.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>c});var n=a(7462),o=(a(7294),a(3905));const r={},i="Web",s={unversionedId:"general/manage-tokens/oasis-wallets/web",id:"general/manage-tokens/oasis-wallets/web",title:"Web",description:"Oasis Foundation-managed official non-custodial web wallet for the Oasis",source:"@site/docs/general/manage-tokens/oasis-wallets/web.md",sourceDirName:"general/manage-tokens/oasis-wallets",slug:"/general/manage-tokens/oasis-wallets/web",permalink:"/general/manage-tokens/oasis-wallets/web",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/oasis-wallets/web.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Oasis Wallets",permalink:"/general/manage-tokens/oasis-wallets/"},next:{title:"Browser Extension",permalink:"/general/manage-tokens/oasis-wallets/browser-extension"}},l={},c=[{value:"How to use the Oasis Wallet - Web",id:"how-to-use-the-oasis-wallet---web",level:2},{value:"Access the Oasis Wallet via your web browser",id:"access-the-oasis-wallet-via-your-web-browser",level:3},{value:"Create a New Wallet",id:"create-a-new-wallet",level:3},{value:"Access an Existing Wallet",id:"access-an-existing-wallet",level:3},{value:"Open Wallet via Mnemonic",id:"open-wallet-via-mnemonic",level:4},{value:"Open Wallet via Private Key",id:"open-wallet-via-private-key",level:4},{value:"Open wallet with Ledger",id:"open-wallet-with-ledger",level:4},{value:"Toggle between light mode and dark mode",id:"toggle-between-light-mode-and-dark-mode",level:3},{value:"Select a language for the web wallet interface",id:"select-a-language-for-the-web-wallet-interface",level:3},{value:"Share your feedback with us",id:"share-your-feedback-with-us",level:2}],p={toc:c},d="wrapper";function u(e){let{components:t,...r}=e;return(0,o.kt)(d,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"web"},"Web"),(0,o.kt)("p",null,"Oasis Foundation-managed official non-custodial web wallet for the Oasis\nNetwork."),(0,o.kt)("h2",{id:"how-to-use-the-oasis-wallet---web"},"How to use the Oasis Wallet - Web"),(0,o.kt)("h3",{id:"access-the-oasis-wallet-via-your-web-browser"},(0,o.kt)("strong",{parentName:"h3"},"Access the Oasis Wallet via your web browser")),(0,o.kt)("p",null,"You can access the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-web/"},"Oasis Wallet - Web")," by heading to ",(0,o.kt)("a",{parentName:"p",href:"https://wallet.oasis.io"},"https://wallet.oasis.io"),". For the best performance, we recommend using ",(0,o.kt)("a",{parentName:"p",href:"https://www.google.com/chrome/"},"Chrome")," or any other ",(0,o.kt)("a",{parentName:"p",href:"https://www.chromium.org/Home"},"Chromium"),"-based browser."),(0,o.kt)("h3",{id:"create-a-new-wallet"},(0,o.kt)("strong",{parentName:"h3"},"Create a New Wallet")),(0,o.kt)("p",null,"If you do not currently have an existing Oasis wallet address, you can create a new wallet address directly from the Oasis Wallet's home screen. Click on the \u201cCreate wallet\u201d button."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Home screen",src:a(8549).Z,width:"2048",height:"1616"})),(0,o.kt)("p",null,"The next page contains information about your mnemonic (an ordered list of words representing your keyphrase), which you will need in order to retrieve your wallet later. Review the information on this page very carefully. Save your mnemonic in the right order in a secure location."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Your mnemonic (i.e. keyphrase) is required to access your wallet. Be sure to store it in a secure location. If you lose or forget your mnemonic, you will lose access to your wallet and any token funds contained in it.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Never share your mnemonic (i.e. keyphrase). Anyone with your mnemonic can access your wallet and your tokens.")),(0,o.kt)("p",null,"After you\u2019ve saved your mnemonic, click the \u201cI saved my keyphrase\u201d checkbox and then click on the \u201cOpen my wallet\u201d button."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Create a New Wallet",src:a(4210).Z,width:"1970",height:"1676"})),(0,o.kt)("p",null,"Next, you will need to confirm your mnemonic by filling in some missing words. You can enter the missing word for each respective box, by clicking on the appropriate word from the list of words presented below. Be sure to enter all of the missing words in the right order."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Confirm your mnemonic",src:a(9251).Z,width:"982",height:"1622"})),(0,o.kt)("p",null,"After you correctly enter all of the missing words, you will be taken to your Oasis Wallet home screen, containing information about your account balance and more."),(0,o.kt)("h3",{id:"access-an-existing-wallet"},(0,o.kt)("strong",{parentName:"h3"},"Access an Existing Wallet")),(0,o.kt)("p",null,"If you already have an existing Oasis wallet address, you can open it in the web wallet by clicking the \u201cOpen wallet\u201d button on the home screen."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Home screen",src:a(8549).Z,width:"2048",height:"1616"})),(0,o.kt)("p",null,"Next, you should select whether you want to open your wallet via a mnemonic, a private key, or a Ledger hardware wallet. Select the respective button corresponding to the retrieval method you want to use."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Access an Existing Wallet",src:a(6627).Z,width:"1980",height:"1680"})),(0,o.kt)("h4",{id:"open-wallet-via-mnemonic"},"Open Wallet via Mnemonic"),(0,o.kt)("p",null,"In the ",(0,o.kt)("em",{parentName:"p"},"Enter your keyphrase"),' field, enter each word of your mnemonic separated by a space. Afterwards, hit the "Open my wallet" button.'),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Open Wallet via Mnemonic",src:a(6687).Z,width:"1219",height:"746"})),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"Oasis Wallet - Web uses English mnemonic phrase words as defined in ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki"},"BIP39"),". You can find a complete list of all valid phrase words ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt"},"here"),". If you misspelled a word, the wallet will warn you.")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Oasis Wallet mnemonics are incompatible with BitPie mnemonics. Check our ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/oasis-wallets/#frequently-asked-questions"},"FAQ")," for more information.")),(0,o.kt)("h4",{id:"open-wallet-via-private-key"},"Open Wallet via Private Key"),(0,o.kt)("p",null,"Paste your Base64-encoded Ed25519 private key in the ",(0,o.kt)("em",{parentName:"p"},"Enter your private key"),' field and then click on the "Open my wallet" button.'),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Open Wallet via Private Key",src:a(1841).Z,width:"1219",height:"746"})),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"The Ed25519 private key format that is used is 64 bytes long and consists of two 32-byte parts:"),(0,o.kt)("ol",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ol"},"First 32 bytes are the ",(0,o.kt)("strong",{parentName:"li"},"private key seed")," which is used to derive the private key that is then used for signing the transactions (i.e. sending tokens from your wallet)."),(0,o.kt)("li",{parentName:"ol"},"Last 32 bytes are the ",(0,o.kt)("strong",{parentName:"li"},"public key")," which is used to compute your account's address of the form ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis1..."),"."))),(0,o.kt)("admonition",{type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"If you typed in the private key manually, make sure you do not mix similar characters like the big O and 0 or big I and 1!"),(0,o.kt)("p",{parentName:"admonition"},"Currently, there is no error detection on the inputted private key, so the wallet cannot warn you of a mistyped character. ",(0,o.kt)("strong",{parentName:"p"},"It is imperative that you correctly input the private key, otherwise you will not be able to access your funds!")),(0,o.kt)("p",{parentName:"admonition"},"We suggest that you perform a test transaction the first time you import your wallet from the private key so you can rest assured the key is valid.")),(0,o.kt)("h4",{id:"open-wallet-with-ledger"},"Open wallet with Ledger"),(0,o.kt)("p",null,"To open your wallet via a Ledger hardware wallet, make sure you have your Ledger device readily available and have familiarized yourself with the ",(0,o.kt)("a",{parentName:"p",href:"/general/manage-tokens/holding-rose-tokens/ledger-wallet"},"Oasis-specific Ledger usage instructions"),"."),(0,o.kt)("p",null,"Follow the instructions on the screens that follow to open your existing wallet address."),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"To date, only Chromium-based browsers support WebUSB component which is required to access your Ledger device.")),(0,o.kt)("p",null,"After you complete the instructions, you will be taken to your Oasis Wallet home screen, containing information about your account balance and more."),(0,o.kt)("h3",{id:"toggle-between-light-mode-and-dark-mode"},(0,o.kt)("strong",{parentName:"h3"},"Toggle between light mode and dark mode")),(0,o.kt)("p",null,"If you are in night mode, you can click on the sun icon near the lower left corner of the screen to switch to light mode."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Toggle between light mode and dark mode",src:a(4023).Z,width:"2048",height:"1551"})),(0,o.kt)("p",null,"If you are in light mode, you can click on the moon icon near the lower left corner of the screen to switch to dark mode."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Light mode",src:a(5797).Z,width:"2048",height:"1552"})),(0,o.kt)("h3",{id:"select-a-language-for-the-web-wallet-interface"},(0,o.kt)("strong",{parentName:"h3"},"Select a language for the web wallet interface")),(0,o.kt)("p",null,"To select a language, you can click the globe icon near the lower left corner of the screen. Currently, you can select either English or French."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"Select a language",src:a(7457).Z,width:"2048",height:"1544"})),(0,o.kt)("h2",{id:"share-your-feedback-with-us"},(0,o.kt)("strong",{parentName:"h2"},"Share your feedback with us")),(0,o.kt)("p",null,"If you have any questions or issues using the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-web/"},"Oasis Wallet - Web"),", you can ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-web/issues"},"submit a GitHub issue")," and the dev team will take a look. You can also connect with us to share your feedback via ",(0,o.kt)("a",{parentName:"p",href:"https://oasis.io/discord"},"Discord")," or ",(0,o.kt)("a",{parentName:"p",href:"https://t.me/oasisprotocolcommunity"},"Telegram"),"."))}u.isMDXComponent=!0},8549:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/01_home-273aa8dd19d696a15d80a7ddb4775b03.png"},4210:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/02_this_is_your_mnemonic-f6b21a57650cd2882d4198b965225990.png"},9251:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/03_confirm_your_mnemonic-d8c76dc27f0eaabb82a0df2bcaadef60.png"},6627:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/04_how_to_open_your_wallet-207f16708a2033f2934b448cd6c7098f.png"},6687:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/05.1_open_with_mnemonics-5da80b206b09bfba004c0627b6a1ddf8.png"},1841:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/05.2_open_with_private_key-b8eb93b498f4e11035bc37a3d131b654.png"},4023:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/06_toogle_between_light_and_dark_mode-57dcfb63b072831a2665fc7326bba0f9.png"},5797:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/07_light_mode-6e042f5b062b159a9e6de55ca3f2fbee.png"},7457:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/08_select_language-36d406acc14d2ccb72103b323b774826.png"}}]); \ No newline at end of file diff --git a/assets/js/efcfca26.eb28d636.js b/assets/js/efcfca26.eb28d636.js new file mode 100644 index 0000000000..66c34138c7 --- /dev/null +++ b/assets/js/efcfca26.eb28d636.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[4736],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function s(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var l=a.createContext({}),c=function(e){var t=a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},g=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,o=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=c(r),g=n,m=u["".concat(l,".").concat(g)]||u[g]||d[g]||o;return r?a.createElement(m,s(s({ref:t},p),{},{components:r})):a.createElement(m,s({ref:t},p))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=r.length,s=new Array(o);s[0]=g;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[u]="string"==typeof e?e:n,s[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var a=r(7462),n=(r(7294),r(3905));const o={},s="Oasis Core Ledger Documentation",i={unversionedId:"oasis-core-ledger/README",id:"oasis-core-ledger/README",title:"Oasis Core Ledger Documentation",description:"This projects aims to provide support for using a [Ledger] hardware wallet with",source:"@site/docs/oasis-core-ledger/README.md",sourceDirName:"oasis-core-ledger",slug:"/oasis-core-ledger/",permalink:"/oasis-core-ledger/",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/README.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",next:{title:"Setup",permalink:"/oasis-core-ledger/usage/setup"}},l={},c=[{value:"Usage",id:"usage",level:2},{value:"Development",id:"development",level:2},{value:"Processes",id:"processes",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...r}=e;return(0,n.kt)(u,(0,a.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"oasis-core-ledger-documentation"},"Oasis Core Ledger Documentation"),(0,n.kt)("p",null,"This projects aims to provide support for using a ",(0,n.kt)("a",{parentName:"p",href:"https://www.ledger.com/"},"Ledger")," hardware wallet with\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core"),"."),(0,n.kt)("p",null,"It provides:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Oasis Core signer plugin for Ledger wallets."),(0,n.kt)("li",{parentName:"ul"},"CLI for running helper commands, e.g. showing an account address or listing\nLedger wallets.")),(0,n.kt)("h2",{id:"usage"},"Usage"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/setup"},"Setup")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/address"},"Obtaining Account Address")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/entity"},"Exporting Public Key to Entity")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/transactions"},"Generating and Signing Transactions")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/usage/wallets"},"Identifying Wallets"))),(0,n.kt)("h2",{id:"development"},"Development"),(0,n.kt)("p",null,(0,n.kt)("em",{parentName:"p"},"TODO.")),(0,n.kt)("h2",{id:"processes"},"Processes"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/versioning"},"Versioning")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/oasis-core-ledger/release-process"},"Release Process"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f0e2e4ae.92488908.js b/assets/js/f0e2e4ae.92488908.js new file mode 100644 index 0000000000..ba5de7c7d7 --- /dev/null +++ b/assets/js/f0e2e4ae.92488908.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2709],{3905:(e,t,a)=>{a.d(t,{Zo:()=>h,kt:()=>m});var r=a(7294);function n(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function s(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=r.createContext({}),p=function(e){var t=r.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},h=function(e){var t=p(e.components);return r.createElement(i.Provider,{value:t},e.children)},c="mdxType",g={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,i=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),c=p(a),u=n,m=c["".concat(i,".").concat(u)]||c[u]||g[u]||o;return a?r.createElement(m,s(s({ref:t},h),{},{components:a})):r.createElement(m,s({ref:t},h))}));function m(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,s=new Array(o);s[0]=u;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l[c]="string"==typeof e?e:n,s[1]=l;for(var p=2;p{a.r(t),a.d(t,{assets:()=>i,contentTitle:()=>s,default:()=>g,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=a(7462),n=(a(7294),a(3905));const o={},s="Release Process",l={unversionedId:"oasis-core-ledger/release-process",id:"oasis-core-ledger/release-process",title:"Release Process",description:"The following steps should be followed when preparing a release.",source:"@site/docs/oasis-core-ledger/release-process.md",sourceDirName:"oasis-core-ledger",slug:"/oasis-core-ledger/release-process",permalink:"/oasis-core-ledger/release-process",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core-ledger/edit/master/docs/release-process.md",tags:[],version:"current",lastUpdatedAt:1663062926,formattedLastUpdatedAt:"Sep 13, 2022",frontMatter:{},sidebar:"oasisSdk",previous:{title:"Versioning",permalink:"/oasis-core-ledger/versioning"}},i={},p=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Tooling",id:"tooling",level:2},{value:"Preparing a Regular Release",id:"preparing-a-regular-release",level:2},{value:"Prepare the Change Log",id:"prepare-the-change-log",level:3},{value:"Tag Next Release",id:"tag-next-release",level:3},{value:"Ensure GitHub Release Was Published",id:"ensure-github-release-was-published",level:3},{value:"Create stable/MAJOR.MINOR.x Branch",id:"create-stablemajorminorx-branch",level:3},{value:"Preparing a Bugfix/Stable Release",id:"preparing-a-bugfixstable-release",level:2},{value:"Back-port Changes",id:"back-port-changes",level:3},{value:"Prepare Change Log for Bugfix/Stable Release",id:"prepare-change-log-for-bugfixstable-release",level:3},{value:"Tag Bugfix/Stable Release",id:"tag-bugfixstable-release",level:3},{value:"Ensure GitHub Release for Bugfix/Stable Release Was Published",id:"ensure-github-release-for-bugfixstable-release-was-published",level:3}],h={toc:p},c="wrapper";function g(e){let{components:t,...a}=e;return(0,n.kt)(c,(0,r.Z)({},h,a,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"release-process"},"Release Process"),(0,n.kt)("p",null,"The following steps should be followed when preparing a release."),(0,n.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,n.kt)("p",null,"Our release process relies on some tooling that needs to be available on a\nmaintainer's system:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://www.python.org/"},"Python")," 3.6+."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/towncrier"},"Oasis' towncrier fork"),"."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://github.com/lgiordani/punch"},"Punch")," 2.0.x.")),(0,n.kt)("p",null,"Most systems should already have ",(0,n.kt)("a",{parentName:"p",href:"https://www.python.org/"},"Python")," pre-installed."),(0,n.kt)("p",null,"To install ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/towncrier"},"Oasis' towncrier fork")," and ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/lgiordani/punch"},"Punch"),", use ",(0,n.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/"},"pip"),":"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"pip3 install --upgrade \\\n https://github.com/oasisprotocol/towncrier/archive/oasis-master.tar.gz \\\n punch.py~=2.0.0\n")),(0,n.kt)("p",null,"You might want to install the packages to a ",(0,n.kt)("a",{parentName:"p",href:"https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments"},"Python virtual environment")," or\nvia so-called ",(0,n.kt)("a",{parentName:"p",href:"https://pip.pypa.io/en/stable/user_guide/#user-installs"},"User install")," (i.e. isolated to the current user)."),(0,n.kt)("h2",{id:"tooling"},"Tooling"),(0,n.kt)("p",null,"Our ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," tooling has some targets that automate parts of the release process\nand try to make it less error-prone:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"changelog"),": Bumps project's version with the ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/lgiordani/punch"},"Punch")," utility and assembles\nthe ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/CHANGELOG.md"},"Change Log")," from the ",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.changelog/README.md"},"Change Log Fragments")," using the\n",(0,n.kt)("a",{parentName:"li",href:"https://github.com/oasisprotocol/towncrier"},"towncrier")," utility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"release-tag"),": After performing a bunch of sanity checks, it tags the git\norigin remote's release branch's ",(0,n.kt)("inlineCode",{parentName:"li"},"HEAD")," with the ",(0,n.kt)("inlineCode",{parentName:"li"},"v")," tag and\npushes it to the remote."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"release-stable-branch"),": Creates and pushes a stable branch for the current\nrelease.")),(0,n.kt)("p",null,"Note that all above targets depend on the ",(0,n.kt)("inlineCode",{parentName:"p"},"fetch-git")," target which fetches the\nlatest changes (including tags) from the git origin remote to ensure the\ncomputed next version and other things are always up-to-date."),(0,n.kt)("p",null,"The version of the Oasis Core Ledger's release is computed automatically using\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/lgiordani/punch"},"Punch")," utility according to the project's ",(0,n.kt)("a",{parentName:"p",href:"/oasis-core-ledger/versioning"},"Versioning")," scheme."),(0,n.kt)("p",null,"The ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," Make target checks the name of the branch on which the release\nis being made and what types of ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.changelog/README.md"},"Change Log Fragments")," are present to know\nwhich part of the project's version to bump."),(0,n.kt)("p",null,"To customize the release process, one can set the following environment\nvariables:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"GIT_ORIGIN_REMOTE")," (default: ",(0,n.kt)("inlineCode",{parentName:"li"},"origin"),"): Name of the git remote pointing to\nthe canonical upstream git repository."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("inlineCode",{parentName:"li"},"RELEASE_BRANCH")," (default: ",(0,n.kt)("inlineCode",{parentName:"li"},"master"),"): Name of the branch where to tag the next\nrelease.")),(0,n.kt)("h2",{id:"preparing-a-regular-release"},"Preparing a Regular Release"),(0,n.kt)("h3",{id:"prepare-the-change-log"},"Prepare the Change Log"),(0,n.kt)("p",null,"Before a release, all ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.changelog/README.md"},"Change Log fragments")," should be assembled into a new\nsection of the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/CHANGELOG.md"},"Change Log")," using the ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," target."),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"/changelog"),", and then run ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make"),":"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b /changelog\nmake changelog\n")),(0,n.kt)("p",null,"Review the staged changes and make appropriate adjustment to the Change Log\n(e.g. re-order entries, make formatting/spelling fixes, ...)."),(0,n.kt)("p",null,"After you are content with the changes, commit them, push them to the origin\nand make a pull request."),(0,n.kt)("p",null,"Once the pull request had been reviewed and merged, proceed to the next step."),(0,n.kt)("h3",{id:"tag-next-release"},"Tag Next Release"),(0,n.kt)("p",null,"To create a signed git tag from the latest commit in origin remote's ",(0,n.kt)("inlineCode",{parentName:"p"},"master"),"\nbranch, use:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-tag\n")),(0,n.kt)("p",null,"This command will perform a bunch of sanity checks to prevent common errors\nwhile tagging the next release."),(0,n.kt)("p",null,"After those checks have passed, it will ask for confirmation before proceeding."),(0,n.kt)("h3",{id:"ensure-github-release-was-published"},"Ensure GitHub Release Was Published"),(0,n.kt)("p",null,"After the tag with the next release is pushed to the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger"},"canonical git repository"),",\nthe GitHub Actions ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.github/workflows/release.yml"},"Release manager workflow")," is triggered which uses the\n",(0,n.kt)("a",{parentName:"p",href:"https://goreleaser.com/"},"GoReleaser")," tool to automatically build the binaries, prepare archives and\nchecksums, and publish a GitHub Release that accompanies the versioned git tag."),(0,n.kt)("p",null,"Browse to ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/releases"},"Oasis Core Ledger's releases page")," and make sure the new release is\nproperly published."),(0,n.kt)("h3",{id:"create-stablemajorminorx-branch"},"Create ",(0,n.kt)("inlineCode",{parentName:"h3"},"stable/MAJOR.MINOR.x")," Branch"),(0,n.kt)("p",null,"To prepare a new stable branch from the new release tag and push it to the\norigin remote, use:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-stable-branch\n")),(0,n.kt)("p",null,"This command will perform sanity checks to prevent common errors."),(0,n.kt)("p",null,"After those checks have passed, it will ask for confirmation before proceeding."),(0,n.kt)("h2",{id:"preparing-a-bugfixstable-release"},"Preparing a Bugfix/Stable Release"),(0,n.kt)("p",null,"As mentioned in the ",(0,n.kt)("a",{parentName:"p",href:"/oasis-core-ledger/versioning"},"Versioning")," documentation, sometimes we will want to\nback-port some fixes (e.g. a security fix) and (backwards compatible) changes\nfrom an upcoming release and release them without also releasing all the other\n(potentially breaking) changes."),(0,n.kt)("p",null,"To make the following steps easier, set the ",(0,n.kt)("inlineCode",{parentName:"p"},"RELEASE_BRANCH")," environment\nvariable to the name of the stable branch of the ",(0,n.kt)("inlineCode",{parentName:"p"},"MAJOR.MINOR")," release you want\nto back-port the changes to, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"stable/1.5.x"),":"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},'RELEASE_BRANCH="stable/1.5.x"\n')),(0,n.kt)("h3",{id:"back-port-changes"},"Back-port Changes"),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"/${RELEASE_BRANCH}/backport-foo"),", from\nthe ",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b /${RELEASE_BRANCH}/backport-foo ${RELEASE_BRANCH}\n")),(0,n.kt)("p",null,"After back-porting all the desired changes, push it to the origin and make a\npull request against the ",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch."),(0,n.kt)("h3",{id:"prepare-change-log-for-bugfixstable-release"},"Prepare Change Log for Bugfix/Stable Release"),(0,n.kt)("p",null,"As with a regular release, the back-ported changes should include the\ncorresponding ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.changelog/README.md"},"Change Log Fragments")," that need to be assembled into a new\nsection of the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/CHANGELOG.md"},"Change Log")," using the ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make")," target."),(0,n.kt)("p",null,"Create a new branch, e.g. ",(0,n.kt)("inlineCode",{parentName:"p"},"/${RELEASE_BRANCH}/changelog"),", from the\n",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"git checkout -b /${RELEASE_BRANCH}/changelog ${RELEASE_BRANCH}\n")),(0,n.kt)("p",null,"Then run ",(0,n.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Make_(software)"},"Make"),"'s ",(0,n.kt)("inlineCode",{parentName:"p"},"changelog")," target:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make changelog\n")),(0,n.kt)("p",null,(0,n.kt)("em",{parentName:"p"},"NOTE: The ",(0,n.kt)("inlineCode",{parentName:"em"},"changelog")," Make target will bump the ",(0,n.kt)("inlineCode",{parentName:"em"},"PATCH")," part of the version\nautomatically.")),(0,n.kt)("p",null,"After reviewing the staged changes, commit them, push the changes to the origin\nand make a pull request against the ",(0,n.kt)("inlineCode",{parentName:"p"},"${RELEASE_BRANCH}")," branch."),(0,n.kt)("p",null,"Once the pull request had been reviewed and merged, proceed to the next step."),(0,n.kt)("h3",{id:"tag-bugfixstable-release"},"Tag Bugfix/Stable Release"),(0,n.kt)("p",null,"As with a regular release, create a signed git tag from the latest commit in\norigin remote's release branch by running the ",(0,n.kt)("inlineCode",{parentName:"p"},"release-tag")," Make target:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-bash"},"make release-tag\n")),(0,n.kt)("p",null,"After the sanity checks have passed, it will ask for confirmation before\nproceeding."),(0,n.kt)("h3",{id:"ensure-github-release-for-bugfixstable-release-was-published"},"Ensure GitHub Release for Bugfix/Stable Release Was Published"),(0,n.kt)("p",null,"Similar to a regular release, after the tag with the next release is pushed to\nthe ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger"},"canonical git repository"),", the GitHub Actions ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/tree/master/.github/workflows/release.yml"},"Release manager workflow")," is\ntriggered which uses the ",(0,n.kt)("a",{parentName:"p",href:"https://goreleaser.com/"},"GoReleaser")," tool to automatically build a new release."),(0,n.kt)("p",null,"Browse to ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core-ledger/releases"},"Oasis Core Ledger's releases page")," and make sure the new\nbugfix/stable release is properly published."))}g.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f33c2266.d48e87de.js b/assets/js/f33c2266.d48e87de.js new file mode 100644 index 0000000000..b8e053b8ec --- /dev/null +++ b/assets/js/f33c2266.d48e87de.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[8865],{3905:(e,t,o)=>{o.d(t,{Zo:()=>d,kt:()=>k});var n=o(7294);function a(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function r(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,n)}return o}function l(e){for(var t=1;t=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),o=t;return e&&(o="function"==typeof e?e(t):l(l({},t),e)),o},d=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var o=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=c(o),m=a,k=p["".concat(i,".").concat(m)]||p[m]||u[m]||r;return o?n.createElement(k,l(l({ref:t},d),{},{components:o})):n.createElement(k,l({ref:t},d))}));function k(e,t){var o=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=o.length,l=new Array(r);l[0]=m;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s[p]="string"==typeof e?e:a,l[1]=s;for(var c=2;c{o.r(t),o.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>s,toc:()=>c});var n=o(7462),a=(o(7294),o(3905));const r={},l="Browser Extension",s={unversionedId:"general/manage-tokens/oasis-wallets/browser-extension",id:"general/manage-tokens/oasis-wallets/browser-extension",title:"Browser Extension",description:"Oasis Foundation-managed official non-custodial browser extension wallet for the",source:"@site/docs/general/manage-tokens/oasis-wallets/browser-extension.md",sourceDirName:"general/manage-tokens/oasis-wallets",slug:"/general/manage-tokens/oasis-wallets/browser-extension",permalink:"/general/manage-tokens/oasis-wallets/browser-extension",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/oasis-wallets/browser-extension.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"general",previous:{title:"Web",permalink:"/general/manage-tokens/oasis-wallets/web"},next:{title:"3rd Party Custody & Wallets",permalink:"/general/manage-tokens/holding-rose-tokens"}},i={},c=[{value:"How to use the Oasis Wallet - Browser Extension",id:"how-to-use-the-oasis-wallet---browser-extension",level:2},{value:"Install the Oasis Wallet via Chrome Web Store",id:"install-the-oasis-wallet-via-chrome-web-store",level:3},{value:"Create a new wallet",id:"create-a-new-wallet",level:3},{value:"Access an existing wallet",id:"access-an-existing-wallet",level:3},{value:"Send tokens",id:"send-tokens",level:3},{value:"Receive tokens",id:"receive-tokens",level:3},{value:"Stake and delegate tokens",id:"stake-and-delegate-tokens",level:3},{value:"Use an Account on your Ledger Wallet",id:"use-an-account-on-your-ledger-wallet",level:3}],d={toc:c},p="wrapper";function u(e){let{components:t,...r}=e;return(0,a.kt)(p,(0,n.Z)({},d,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"browser-extension"},"Browser Extension"),(0,a.kt)("p",null,"Oasis Foundation-managed official non-custodial browser extension wallet for the\nOasis Network."),(0,a.kt)("h2",{id:"how-to-use-the-oasis-wallet---browser-extension"},(0,a.kt)("strong",{parentName:"h2"},"How to use the Oasis Wallet - Browser Extension")),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"Currently, ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-ext"},"Oasis Wallet - Browser Extension")," ",(0,a.kt)("strong",{parentName:"p"},"only supports")," ",(0,a.kt)("a",{parentName:"p",href:"https://www.google.com/chrome/"},(0,a.kt)("strong",{parentName:"a"},"Chrome"))," or other ",(0,a.kt)("a",{parentName:"p",href:"https://www.chromium.org/Home"},"Chromium"),"-based browsers.")),(0,a.kt)("h3",{id:"install-the-oasis-wallet-via-chrome-web-store"},"Install the Oasis Wallet via Chrome Web Store"),(0,a.kt)("p",null,"You can install the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-wallet-ext"},"Oasis Wallet - Browser Extension")," by heading to the ",(0,a.kt)("a",{parentName:"p",href:"https://chrome.google.com/webstore/detail/oasis-wallet/ppdadbejkmjnefldpcdjhnkpbjkikoip"},"Chrome Web Store"),"."),(0,a.kt)("h3",{id:"create-a-new-wallet"},"Create a new wallet"),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Your mnemonic phrase is required to access your wallet. Be sure to store it in a secure location. If you lose or forget your mnemonic phrase, you will lose access to your wallet and any token funds contained in it.")),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Never share your keyphrase. Anyone with your keyphrase can access your wallet and your tokens.")),(0,a.kt)("h3",{id:"access-an-existing-wallet"},(0,a.kt)("strong",{parentName:"h3"},"Access an existing wallet")),(0,a.kt)("h3",{id:"send-tokens"},"Send tokens"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Click the avatar on the top right corner"),(0,a.kt)("li",{parentName:"ol"},"Pick an account you want to transfer tokens out of"),(0,a.kt)("li",{parentName:"ol"},"Click \u2018Send\u2019"),(0,a.kt)("li",{parentName:"ol"},"Type in the token amount under \u2018Amount\u2019"),(0,a.kt)("li",{parentName:"ol"},"Type in the Receiver\u2019s wallet address"),(0,a.kt)("li",{parentName:"ol"},"Click \u2018Next\u2019"),(0,a.kt)("li",{parentName:"ol"},"Check the \u2018Send Details\u2019; if everything looks good to you, click \u2018Confirm\u2019"),(0,a.kt)("li",{parentName:"ol"},"Wait for a couple of seconds, and you\u2019ll get a status update of your transaction"),(0,a.kt)("li",{parentName:"ol"},"Go back to the Account page, and you\u2019ll see the transfer has gone through")),(0,a.kt)("h3",{id:"receive-tokens"},(0,a.kt)("strong",{parentName:"h3"},"Receive tokens")),(0,a.kt)("p",null,"Click \u2018Receive\u2019 on the Account page, and you\u2019ll get the QR code as well as the wallet address in text format"),(0,a.kt)("h3",{id:"stake-and-delegate-tokens"},(0,a.kt)("strong",{parentName:"h3"},"Stake and delegate tokens")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Click \u2018Staking\u2019 on the Account main page"),(0,a.kt)("li",{parentName:"ol"},"Go to \u2018Validator node\u2019, and select a node you want to delegate your tokens to."),(0,a.kt)("li",{parentName:"ol"},"Click into the node you want to delegate your tokens to, and click \u2018Add Escrow\u2019"),(0,a.kt)("li",{parentName:"ol"},"Fill in the amount you want to delegate under \u2018Amount\u2019 and click \u2018Next\u2019"),(0,a.kt)("li",{parentName:"ol"},"Check the \u2018Delegate info, if everything looks good to you, click \u2018Confirm\u2019"),(0,a.kt)("li",{parentName:"ol"},"Go to \u2018My delegate\u2019 and you will see which node you just delegated tokens to and by how much")),(0,a.kt)("h3",{id:"use-an-account-on-your-ledger-wallet"},(0,a.kt)("strong",{parentName:"h3"},"Use an Account on your Ledger Wallet")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Plug your Ledger device into your computer and log into the Oasis app on-device")),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Oasis App Ready on Ledger Nano S connected to your device",src:o(3493).Z,width:"640",height:"480"})),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"Open the Oasis Chrome Extension Wallet and click the account icon on the top right")),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Unlock your Oasis Wallet Extension",src:o(6777).Z,width:"746",height:"1196"})),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"Select Ledger on the bottom right of the app")),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Import Oasis Ledger Account",src:o(740).Z,width:"752",height:"1202"})),(0,a.kt)("ol",{start:4},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},'Follow user onboarding flow clicking "Next" as you move forward with set up.')),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},'You\'ll see a pop-up in your Chrome Browser asking you to select which device to connect. Click on your Ledger device. Then click "Connect". ',(0,a.kt)("em",{parentName:"p"},"NOTE: You may need to resize the pop up window to see all buttons.")))),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Confirm your Ledger device and Import",src:o(1888).Z,width:"747",height:"1200"})),(0,a.kt)("ol",{start:6},(0,a.kt)("li",{parentName:"ol"},'Follow the next onboarding steps to upload the correct Ledger account, clicking "Confirm" when complete.')),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"Confirm your account(s) from Ledger for Import",src:o(1902).Z,width:"748",height:"1200"})),(0,a.kt)("ol",{start:7},(0,a.kt)("li",{parentName:"ol"},"Use your Ledger to send, receive and stake on the Oasis Network!")))}u.isMDXComponent=!0},3493:(e,t,o)=>{o.d(t,{Z:()=>n});const n=o.p+"assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg"},740:(e,t,o)=>{o.d(t,{Z:()=>n});const n=o.p+"assets/images/wallet_ext_accounts_ledger-00e350e8cc5168c58d3dbd56d72f0357.png"},6777:(e,t,o)=>{o.d(t,{Z:()=>n});const n=o.p+"assets/images/wallet_ext_import1-695dd9713fb10621f4447840cdbbe9fd.png"},1888:(e,t,o)=>{o.d(t,{Z:()=>n});const n=o.p+"assets/images/wallet_ext_import2-ace8c17920abf877d4c68f40c1854eb3.png"},1902:(e,t,o)=>{o.d(t,{Z:()=>n});const n=o.p+"assets/images/wallet_ext_import3-bd9f503231d12dec0764340d7695cb5a.png"}}]); \ No newline at end of file diff --git a/assets/js/f57ebf67.c7259792.js b/assets/js/f57ebf67.c7259792.js new file mode 100644 index 0000000000..a940173779 --- /dev/null +++ b/assets/js/f57ebf67.c7259792.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[3671],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>k});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=p(n),m=o,k=d["".concat(l,".").concat(m)]||d[m]||c[m]||a;return n?r.createElement(k,i(i({ref:t},u),{},{components:n})):r.createElement(k,i({ref:t},u))}));function k(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:o,i[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var r=n(7462),o=(n(7294),n(3905));const a={},i="Troubleshooting",s={unversionedId:"node/run-your-node/troubleshooting",id:"node/run-your-node/troubleshooting",title:"Troubleshooting",description:"Before you begin troubleshooting we suggest you check all of the following:",source:"@site/docs/node/run-your-node/troubleshooting.md",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/troubleshooting",permalink:"/node/run-your-node/troubleshooting",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/troubleshooting.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Using Ledger-backed Consensus Key with a Remote Signer",permalink:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer"},next:{title:"Oasis Web3 Gateway for your EVM ParaTime",permalink:"/node/web3"}},l={},p=[{value:"Running a Node",id:"running-a-node",level:2},{value:"Invalid Permissions",id:"invalid-permissions",level:3},{value:"Permissions for node and entity",id:"permissions-for-node-and-entity",level:4},{value:"Permissions for .pem files",id:"permissions-for-pem-files",level:4},{value:"Serverdir Ownership",id:"serverdir-ownership",level:4},{value:"Cannot Find File",id:"cannot-find-file",level:3},{value:"Staking and Registering",id:"staking-and-registering",level:2},{value:"Transaction Out of Gas",id:"transaction-out-of-gas",level:3}],u={toc:p},d="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(d,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"troubleshooting"},"Troubleshooting"),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("mdxAdmonitionTitle",{parentName:"admonition"},(0,o.kt)("strong",{parentName:"mdxAdmonitionTitle"},"BEFORE YOU BEGIN TROUBLESHOOTING")),(0,o.kt)("p",{parentName:"admonition"},"Before you begin troubleshooting we suggest you check all of the following:"),(0,o.kt)("ul",{parentName:"admonition"},(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"Check that your current binary version is the latest listed on the ",(0,o.kt)("a",{parentName:"p",href:"/node/mainnet/"},"Current Network Parameters")),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Check the version on your localhost using ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node --version")),(0,o.kt)("li",{parentName:"ul"},"Check the version on your server using ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node --version")))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If upgrading, make sure that you've wiped state (unless that is explicitly not required)")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If you're doing anything with the entity:"),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Do you have the latest genesis?"),(0,o.kt)("li",{parentName:"ul"},"Do you have the correct private key (or Ledger device)."),(0,o.kt)("li",{parentName:"ul"},"If you're signing a transaction:",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Do you sufficient account balance to make the transaction?",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node stake account info")))),(0,o.kt)("li",{parentName:"ul"},"Are you using the correct nonce?",(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Run ",(0,o.kt)("inlineCode",{parentName:"li"},"oasis-node stake account info")))))))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If you're generating a transaction:"),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Do you have the latest genesis?"))),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("p",{parentName:"li"},"If you're submitting a transaction:"),(0,o.kt)("ul",{parentName:"li"},(0,o.kt)("li",{parentName:"ul"},"Do you have the latest genesis?"),(0,o.kt)("li",{parentName:"ul"},"Is your node synced? If not, the transaction will fail to run properly"))))),(0,o.kt)("h2",{id:"running-a-node"},"Running a Node"),(0,o.kt)("h3",{id:"invalid-permissions"},"Invalid Permissions"),(0,o.kt)("h4",{id:"permissions-for-node-and-entity"},"Permissions for node and entity"),(0,o.kt)("p",null,"Error Message:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"common/Mkdir: path '/serverdir/node' has invalid permissions: -rwxr-xr-x\n")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"entity")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"node")," directories both need to have permissions ",(0,o.kt)("inlineCode",{parentName:"p"},"rwx------"),". Make sure you initialize the directory with correct permissions or change them using ",(0,o.kt)("inlineCode",{parentName:"p"},"chmod"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"mkdir --mode 700 --parents {entity,node}\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"chmod 700 /serverdir/node\nchmod 700 /serverdir/entity\n")),(0,o.kt)("h4",{id:"permissions-for-pem-files"},"Permissions for .pem files"),(0,o.kt)("p",null,"Error Message example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"signature/signer/file: invalid PEM file permissions 700 on /serverdir/node/identity.pem\n")),(0,o.kt)("p",null,"All ",(0,o.kt)("inlineCode",{parentName:"p"},".pem")," files should have the permissions ",(0,o.kt)("inlineCode",{parentName:"p"},"600"),". You can set the permissions for all ",(0,o.kt)("inlineCode",{parentName:"p"},".pem")," files in a directory using the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"chmod -R 600 /path/*.pem\n")),(0,o.kt)("h4",{id:"serverdir-ownership"},"Serverdir Ownership"),(0,o.kt)("p",null,"Another possible cause of permission issues is not giving ownership of your ",(0,o.kt)("inlineCode",{parentName:"p"},"serverdir")," to the user running the node (e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"docker-host")," or replace with your user):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"chown -R docker-host:docker-host /serverdir\n")),(0,o.kt)("p",null,"In general, to avoid problems when running docker, specify the user when running ",(0,o.kt)("inlineCode",{parentName:"p"},"docker")," commands by adding the flag ",(0,o.kt)("inlineCode",{parentName:"p"},"--user $(id -u):$(id -g)"),"."),(0,o.kt)("h3",{id:"cannot-find-file"},"Cannot Find File"),(0,o.kt)("p",null,"Error Message examples:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"no such file or directory\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},"file does not exist\n")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},'ts=2019-11-17T03:42:09.778647033Z level=error module=cmd/registry/node caller=node.go:127 msg="failed to load entity" err="file does not exist"\n')),(0,o.kt)("p",null,"More often than you'd expect, this error is the result of setting the path incorrectly. You may have left something like ",(0,o.kt)("inlineCode",{parentName:"p"},"--genesis.file $GENESIS_FILE_PATH")," in the command without setting ",(0,o.kt)("inlineCode",{parentName:"p"},"$GENESIS_FILE_PATH")," first, or set the path incorrectly. Check that ",(0,o.kt)("inlineCode",{parentName:"p"},"echo $GENESIS_FILE_PATH")," matches your expectation or provide a path in the command."),(0,o.kt)("p",null,"Another possible cause: the files in your localhost directory cannot be read from the container. Make sure to run commands in the same session within the container."),(0,o.kt)("h2",{id:"staking-and-registering"},"Staking and Registering"),(0,o.kt)("h3",{id:"transaction-out-of-gas"},"Transaction Out of Gas"),(0,o.kt)("p",null,"Error message:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-text"},'module=cmd/stake caller=stake.go:70 msg="failed to submit transaction" err="rpc error: code = Unknown desc = staking: add escrow transaction failed: out of gas" attempt=1\n')),(0,o.kt)("p",null,"The docs are now updated to show that you need to add ",(0,o.kt)("inlineCode",{parentName:"p"},"--stake.transaction.fee.gas")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"--stake.transaction.fee.amount")," flags when generating your transaction. Note that if you're re-generating a transaction, you will need to increment the ",(0,o.kt)("inlineCode",{parentName:"p"},"--nonce")," flag."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f8012949.41e1690d.js b/assets/js/f8012949.41e1690d.js new file mode 100644 index 0000000000..9a079c8dda --- /dev/null +++ b/assets/js/f8012949.41e1690d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[2458],{3905:(e,t,a)=>{a.d(t,{Zo:()=>p,kt:()=>f});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var s=n.createContext({}),c=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=c(a),m=r,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||i;return a?n.createElement(f,o(o({ref:t},p),{},{components:a})):n.createElement(f,o({ref:t},p))}));function f(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:r,o[1]=l;for(var c=2;c{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=a(7462),r=(a(7294),a(3905));const i={},o="Security",l={unversionedId:"core/SECURITY",id:"core/SECURITY",title:"Security",description:"At [Oasis Foundation], we take security very seriously and we deeply appreciate",source:"@site/docs/core/SECURITY.md",sourceDirName:"core",slug:"/core/SECURITY",permalink:"/core/SECURITY",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/SECURITY.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Versioning",permalink:"/core/versioning"}},s={},c=[{value:"Specifications",id:"specifications",level:2},{value:"Contract Computational/Data Integrity",id:"contract-computationaldata-integrity",level:2},{value:"Tendermint",id:"tendermint",level:3},{value:"Discrepancy Detection",id:"discrepancy-detection",level:3},{value:"Storage",id:"storage",level:3},{value:"Contract Confidentiality",id:"contract-confidentiality",level:2},{value:"Availability",id:"availability",level:2}],p={toc:c},u="wrapper";function d(e){let{components:t,...a}=e;return(0,r.kt)(u,(0,n.Z)({},p,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"security"},"Security"),(0,r.kt)("p",null,"At ",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/"},"Oasis Foundation"),", we take security very seriously and we deeply appreciate\nany effort to discover and fix vulnerabilities in ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core"},"Oasis Core")," and other\nprojects powering the ",(0,r.kt)("a",{parentName:"p",href:"/general/oasis-network/"},"Oasis Network"),"."),(0,r.kt)("p",null,"We prefer that security reports be sent through our ",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/security"},"private bug bounty program\nlinked on our website"),"."),(0,r.kt)("p",null,"We sketch out the general classification of the kinds of errors\nbelow. This is not intended to be an exhaustive list."),(0,r.kt)("h2",{id:"specifications"},"Specifications"),(0,r.kt)("p",null,"Our ",(0,r.kt)("a",{parentName:"p",href:"https://oasisprotocol.org/papers"},"papers")," specify what we are building. Additional designs and\nspecifications may be made available later."),(0,r.kt)("p",null,"NB: Our designs/specifications describe what we are building toward,\nand do not necessarily reflect the state of the current iteration of\nthe system. Implementation/specification mismatches in such cases are\nexpected."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Conceptual errors.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Ambiguities, inconsistencies, or incorrect statements.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Mismatch between specifications and implementation of any subsystems\n/ modules, when the implementation is considered complete."))),(0,r.kt)("h2",{id:"contract-computationaldata-integrity"},"Contract Computational/Data Integrity"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Race conditions / non-determinism. These may introduce a denial of\nservice opportunity, or a way to force the system into slow path /\nrecovery mode.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Conditions under which compute nodes may cause a bogus transaction\nresult to be accepted (committed to the blockchain) by the system."))),(0,r.kt)("h3",{id:"tendermint"},"Tendermint"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Tendermint has its own vulnerability disclosure policy and bug\nbounty, so in general issues in the core tendermint code should be\nreported\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/tendermint/tendermint/blob/master/SECURITY.md"},"there"),".")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Oasis Labs code that misuses Tendermint code, i.e., in violation of\nAPI/contract, would definitely be in scope."))),(0,r.kt)("h3",{id:"discrepancy-detection"},"Discrepancy Detection"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Situations where a discrepant computation is not detected.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Situations where a discrepancy occurs but no receipts are\ngenerated/retained for blame assignment / slashing after slow-path\nrecovery."))),(0,r.kt)("h3",{id:"storage"},"Storage"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"We use immutable authenticated data structures."),(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Undetected mutations. E.g., situations where a conceptually\nimmutable data structure can be changed without updating hashes\n(and thus getting a new ID).")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Missing/incomplete ADS proof generation or verification.")))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Availability failures. Potential DoS, e.g., malformed requests that\ncause node panics, etc."))),(0,r.kt)("h2",{id:"contract-confidentiality"},"Contract Confidentiality"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Cryptography: information leak or integrity failure, e.g., due to a\npoor choice of signature algorithm, AEAD schemes, etc, or to\nimproper usage of the cryptographic schemes. NB: side channels are\nout of scope.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"TEE misuse, model failures."))),(0,r.kt)("h2",{id:"availability"},"Availability"),(0,r.kt)("p",null,"Bugs that create a potential for DOS or DDOS attack, e.g.:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Amplification attacks.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Failstop crashes / panics.")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Deadlocks / livelocks."))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f9140bb0.a827be12.js b/assets/js/f9140bb0.a827be12.js new file mode 100644 index 0000000000..5d8adaade4 --- /dev/null +++ b/assets/js/f9140bb0.a827be12.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[1889],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var d=r.createContext({}),l=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},c=function(e){var t=l(e.components);return r.createElement(d.Provider,{value:t},e.children)},m="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,d=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),m=l(n),u=i,g=m["".concat(d,".").concat(u)]||m[u]||p[u]||o;return n?r.createElement(g,s(s({ref:t},c),{},{components:n})):r.createElement(g,s({ref:t},c))}));function g(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,s=new Array(o);s[0]=u;var a={};for(var d in t)hasOwnProperty.call(t,d)&&(a[d]=t[d]);a.originalType=e,a[m]="string"==typeof e?e:i,s[1]=a;for(var l=2;l{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>p,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var r=n(7462),i=(n(7294),n(3905));const o={},s="Using Ledger-backed Consensus Key with a Remote Signer",a={unversionedId:"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer",id:"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer",title:"Using Ledger-backed Consensus Key with a Remote Signer",description:"This guide will describe how you can set up your validator node with a detached consensus key stored on a Ledger wallet connected via Oasis Core's Remote Signer.",source:"@site/docs/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer.md",sourceDirName:"node/run-your-node/advanced",slug:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer",permalink:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer.md",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Install Oasis Remote Signer Binary",permalink:"/node/run-your-node/advanced/install-oasis-remote-signer-binary"},next:{title:"Troubleshooting",permalink:"/node/run-your-node/troubleshooting"}},d={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Set Up Remote Signer System",id:"set-up-remote-signer-system",level:2},{value:"Initialize Remote Signer",id:"initialize-remote-signer",level:3},{value:"Run Remote Signer",id:"run-remote-signer",level:3},{value:"Copy Remote Signer Certificate and Client Key and Certificate",id:"copy-remote-signer-certificate-and-client-key-and-certificate",level:3},{value:"Set Up Oasis Node System",id:"set-up-oasis-node-system",level:2},{value:"Initialize Oasis Node",id:"initialize-oasis-node",level:3},{value:"Configure Oasis Node",id:"configure-oasis-node",level:3}],c={toc:l},m="wrapper";function p(e){let{components:t,...n}=e;return(0,i.kt)(m,(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"using-ledger-backed-consensus-key-with-a-remote-signer"},"Using Ledger-backed Consensus Key with a Remote Signer"),(0,i.kt)("p",null,"This guide will describe how you can set up your ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},(0,i.kt)("em",{parentName:"a"},"validator")," node")," with a detached consensus key stored on a ",(0,i.kt)("a",{parentName:"p",href:"https://www.ledger.com"},"Ledger")," wallet connected via ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-remote-signer"},"Oasis Core's Remote Signer"),"."),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"These instructions are still a work-in-progress draft."),(0,i.kt)("p",{parentName:"admonition"},"Your feedback is welcome. Please, reach out via the ",(0,i.kt)("a",{parentName:"p",href:"/get-involved/"},(0,i.kt)("strong",{parentName:"a"},"#node-operators")," channel at the Oasis Network Community server on Discord")," with your questions, comments, and feedback.")),(0,i.kt)("admonition",{type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"These are advanced instructions intended for node operators that want to increase their validator node security by having the consensus key be detached and stored on a Ledger wallet and connected via Oasis Core's remote signer instead of having consensus key simply be a file on the file system.")),(0,i.kt)("h2",{id:"prerequisites"},"Prerequisites"),(0,i.kt)("p",null,"Before following this guide, make sure you've followed the ",(0,i.kt)("a",{parentName:"p",href:"../prerequisites"},"Prerequisites")," section and have the Oasis Node binary installed on your Oasis node system."),(0,i.kt)("p",null,"Also make sure you've followed the ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/install-oasis-remote-signer-binary"},"Install Oasis Remote Signer Binary")," section and have the Oasis Remote Signer binary installed on your remote signer system where your Ledger wallet will be connected."),(0,i.kt)("p",null,"Finally, you need to do steps described in the ",(0,i.kt)("a",{parentName:"p",href:"/oasis-core-ledger/usage/setup"},"Setup")," section of our ",(0,i.kt)("a",{parentName:"p",href:"../../../oasis-core-ledger"},"Oasis Core Ledger docs"),". Make sure you also install the ",(0,i.kt)("em",{parentName:"p"},(0,i.kt)("strong",{parentName:"em"},"OasisVal")),(0,i.kt)("strong",{parentName:"p"}," app")," on your Ledger wallet."),(0,i.kt)("h2",{id:"set-up-remote-signer-system"},"Set Up Remote Signer System"),(0,i.kt)("h3",{id:"initialize-remote-signer"},"Initialize Remote Signer"),(0,i.kt)("p",null,"On your remote signer system, create a directory for the remote signer, e.g. ",(0,i.kt)("inlineCode",{parentName:"p"},"remote-signer"),", by running:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"mkdir --mode=700 remote-signer\n")),(0,i.kt)("p",null,"Then initialize remote signer's keys (consensus, entity, identity, ...) and server certificate by running:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-remote-signer init --datadir remote-signer/\n")),(0,i.kt)("p",null,"Also initialize remote signer's client certificate which will be used by the Oasis node system to connect to the remote signer system:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"oasis-remote-signer init_client --datadir remote-signer/\n")),(0,i.kt)("h3",{id:"run-remote-signer"},"Run Remote Signer"),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"Before following the instructions below, make sure your Ledger wallet is connected to your remote signer system, unlocked and the OasisVal App is open.")),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"While the OasisVal App is available in ",(0,i.kt)("em",{parentName:"p"},"Developer mode"),', opening the App brings up the "Pending Ledger review" screen. You need to press both buttons at once to close that screen and transition to the ',(0,i.kt)("em",{parentName:"p"},"ordinary"),' "Oasis Ready" screen where the OasisVal App is ready to be used.')),(0,i.kt)("p",null,"Choose the gRPC port on which the remote signer will listen for client requests and set the path to the ",(0,i.kt)("inlineCode",{parentName:"p"},"ledger-signer")," plugin in the appropriate environment variables and run:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"GRPC_PORT=\nLEDGER_SIGNER_PATH=\noasis-remote-signer \\\n--datadir remote-signer \\\n--signer.backend composite \\\n--signer.composite.backends entity:file,node:file,p2p:file,consensus:plugin \\\n--signer.plugin.name ledger \\\n--signer.plugin.path $LEDGER_SIGNER_PATH \\\n--client.certificate remote-signer/remote_signer_client_cert.pem \\\n--grpc.port $GRPC_PORT \\\n--log.level DEBUG\n")),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"If necessary, you can configure the Ledger-based signer by setting the ",(0,i.kt)("inlineCode",{parentName:"p"},"--signer.plugin.config")," flag appropriately, e.g.:"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre"},'--signer.plugin.config "wallet_id:1fc3be,index:5"\n')),(0,i.kt)("p",{parentName:"admonition"},"to configure the wallet with a specific ID and to use a non-zero account index.")),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"The Oasis Remote Signer is configured to run in the foreground by default."),(0,i.kt)("p",{parentName:"admonition"},"We recommend you configure and use it with a process manager like ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/systemd/systemd"},"systemd")," or ",(0,i.kt)("a",{parentName:"p",href:"http://supervisord.org"},"Supervisor"),".")),(0,i.kt)("h3",{id:"copy-remote-signer-certificate-and-client-key-and-certificate"},"Copy Remote Signer Certificate and Client Key and Certificate"),(0,i.kt)("p",null,"For the Oasis node system to be able to connect to the Oasis Remote Signer on the remote signer system and to be able to demonstrate its authenticity to it, you need to copy the following files from your remote signer system to your Oasis node system:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"remote-signer/remote_signer_server_cert.pem"),": The remote signer's certificate. This certificate ensures the Oasis node system is connecting to the trusted remote signer system."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"remote-signer/remote_signer_client_key.pem"),": The remote signer's client key. This key enables the Oasis node system to demonstrate its authenticity when it is requesting signatures from the remote signer system."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"remote-signer/remote_signer_client_cert.pem"),": The remote signer's client certificate. This certificate is the counterpart of the remote signer's client key.")),(0,i.kt)("h2",{id:"set-up-oasis-node-system"},"Set Up Oasis Node System"),(0,i.kt)("p",null,"For setting up your Oasis Node system, follow the ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node"},"Run a Validator Node")," docs."),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"Make sure you've copied the remote signer's certificate and remote signer's client key and certificate to your Oasis Node system as described in ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer#copy-remote-signer-certificate-and-client-key-and-certificate"},"Copy Remote Signer Certificate and Client Key and Certificate")," section.")),(0,i.kt)("h3",{id:"initialize-oasis-node"},"Initialize Oasis Node"),(0,i.kt)("p",null,"When ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#initializing-a-node"},"initializing your Oasis node"),", you need to pass appropriate ",(0,i.kt)("inlineCode",{parentName:"p"},"--signer.*")," flags to configure the composite and remote signers. For example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"ENTITY_DIR=\nSTATIC_IP=\nREMOTE_SIGNER_IP=\nREMOTE_SIGNER_PORT=\noasis-node registry node init \\\n--signer.backend composite \\\n--signer.composite.backends 1:file,2:file,3:file,4:remote \\\n--signer.dir $ENTITY_DIR \\\n--node.consensus_address $STATIC_IP:26656 \\\n--node.role validator \\\n--signer.remote.address $REMOTE_SIGNER_IP:$REMOTE_SIGNER_PORT \\\n--signer.remote.client.certificate remote-signer/remote_signer_client_cert.pem \\\n--signer.remote.client.key remote-signer/remote_signer_client_key.pem \\\n--signer.remote.server.certificate remote-signer/remote_signer_server_cert.pem \\\n--datadir node/\n")),(0,i.kt)("p",null,"This assumes you've copied the remote signer's certificate and remote signer's client key and certificate to the ",(0,i.kt)("inlineCode",{parentName:"p"},"remote-signer/")," directory."),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"The resulting directory only has ",(0,i.kt)("inlineCode",{parentName:"p"},"consensus_pub.pem")," and no ",(0,i.kt)("inlineCode",{parentName:"p"},"consensus.pem")," since the consensus key is Ledger-backed.")),(0,i.kt)("h3",{id:"configure-oasis-node"},"Configure Oasis Node"),(0,i.kt)("p",null,"When ",(0,i.kt)("a",{parentName:"p",href:"/node/run-your-node/validator-node#configuring-the-oasis-node"},"configuring your Oasis Node"),", you need to add the appropriate ",(0,i.kt)("inlineCode",{parentName:"p"},"signer")," section to configure the composite and remote signers. For example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-yaml"},"# Signer.\nsigner:\n backend: composite\n # Use file-based signer for entity, node and P2P keys and remote signer for the\n # consensus key.\n composite:\n backends: entity:file,node:file,p2p:file,consensus:remote\n # Configure how to connect to the Oasis Remote Signer.\n remote:\n address: :\n server:\n certificate: /srv/oasis/remote-signer/remote_signer_server_cert.pem\n client:\n key: /srv/oasis/remote-signer/remote_signer_client_key.pem\n certificate: /srv/oasis/remote-signer/remote_signer_client_cert.pem\n")),(0,i.kt)("p",null,"This assumes you've copied the remote signer's certificate and remote signer's client key and certificate to the ",(0,i.kt)("inlineCode",{parentName:"p"},"/srv/oasis/remote-signer/")," directory."),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"},"To ensure your Oasis Node will be able to sign consensus transactions, make sure your Ledger wallet is connected to your remote signer system, unlocked and the OasisVal App is open."),(0,i.kt)("p",{parentName:"admonition"},"Also make sure the Oasis Remote Signer is running on your remote signer system and accepting remote client connections via the designated port.")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/fb2e2efb.72724132.js b/assets/js/fb2e2efb.72724132.js new file mode 100644 index 0000000000..000f7b79b9 --- /dev/null +++ b/assets/js/fb2e2efb.72724132.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[7613],{8411:s=>{s.exports=JSON.parse('{"title":"Architectural Decision Records","description":"This page contains a list of accepted Oasis ADRs. To see the currently discussed ADRs or to open a new ADR, visit the official oasisprotocol/adrs repository on github.com.","slug":"/adrs","permalink":"/adrs","navigation":{"next":{"title":"ADR 0001: Multiple Roots Under the Tendermint Application Hash","permalink":"/adrs/0001-tm-multi-root-apphash"}}}')}}]); \ No newline at end of file diff --git a/assets/js/fdfc1f73.8a6346a9.js b/assets/js/fdfc1f73.8a6346a9.js new file mode 100644 index 0000000000..efbfc73853 --- /dev/null +++ b/assets/js/fdfc1f73.8a6346a9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[6228],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>f});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=r.createContext({}),u=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),p=u(n),m=a,f=p["".concat(l,".").concat(m)]||p[m]||d[m]||o;return n?r.createElement(f,i(i({ref:t},c),{},{components:n})):r.createElement(f,i({ref:t},c))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:a,i[1]=s;for(var u=2;u{n.d(t,{Z:()=>i});var r=n(7294),a=n(6010);const o={tabItem:"tabItem_Ymn6"};function i(e){let{children:t,hidden:n,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(o.tabItem,i),hidden:n},t)}},4866:(e,t,n)=>{n.d(t,{Z:()=>N});var r=n(7462),a=n(7294),o=n(6010),i=n(2466),s=n(6550),l=n(1980),u=n(7392),c=n(12);function p(e){return function(e){return a.Children.map(e,(e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:t}=e;return!!t&&"object"==typeof t&&"value"in t}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}function d(e){const{values:t,children:n}=e;return(0,a.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,u.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function m(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function f(e){let{queryString:t=!1,groupId:n}=e;const r=(0,s.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,l._X)(o),(0,a.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function h(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,o=d(e),[i,s]=(0,a.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!m({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[l,u]=f({queryString:n,groupId:r}),[p,h]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,c.Nk)(n);return[r,(0,a.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:r}),g=(()=>{const e=l??p;return m({value:e,tabValues:o})?e:null})();(0,a.useLayoutEffect)((()=>{g&&s(g)}),[g]);return{selectedValue:i,selectValue:(0,a.useCallback)((e=>{if(!m({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);s(e),u(e),h(e)}),[u,h,o]),tabValues:o}}var g=n(2389);const y={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function k(e){let{className:t,block:n,selectedValue:s,selectValue:l,tabValues:u}=e;const c=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),d=e=>{const t=e.currentTarget,n=c.indexOf(t),r=u[n].value;r!==s&&(p(t),l(r))},m=e=>{let t=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const n=c.indexOf(e.currentTarget)+1;t=c[n]??c[0];break}case"ArrowLeft":{const n=c.indexOf(e.currentTarget)-1;t=c[n]??c[c.length-1];break}}t?.focus()};return a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},u.map((e=>{let{value:t,label:n,attributes:i}=e;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:s===t?0:-1,"aria-selected":s===t,key:t,ref:e=>c.push(e),onKeyDown:m,onClick:d},i,{className:(0,o.Z)("tabs__item",y.tabItem,i?.className,{"tabs__item--active":s===t})}),n??t)})))}function b(e){let{lazy:t,children:n,selectedValue:r}=e;const o=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=o.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return a.createElement("div",{className:"margin-top--md"},o.map(((e,t)=>(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function v(e){const t=h(e);return a.createElement("div",{className:(0,o.Z)("tabs-container",y.tabList)},a.createElement(k,(0,r.Z)({},e,t)),a.createElement(b,(0,r.Z)({},e,t)))}function N(e){const t=(0,g.Z)();return a.createElement(v,(0,r.Z)({key:String(t)},e))}},201:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>s,metadata:()=>u,toc:()=>p});var r=n(7462),a=(n(7294),n(3905)),o=n(4866),i=n(5162);const s={},l="System Configuration",u={unversionedId:"node/run-your-node/prerequisites/system-configuration",id:"node/run-your-node/prerequisites/system-configuration",title:"System Configuration",description:"This page describes changes that should be made to the configuration of the",source:"@site/docs/node/run-your-node/prerequisites/system-configuration.mdx",sourceDirName:"node/run-your-node/prerequisites",slug:"/node/run-your-node/prerequisites/system-configuration",permalink:"/node/run-your-node/prerequisites/system-configuration",draft:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/system-configuration.mdx",tags:[],version:"current",lastUpdatedAt:1694782126,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{},sidebar:"operators",previous:{title:"Install Oasis Node Binary",permalink:"/node/run-your-node/prerequisites/oasis-node"},next:{title:"Set up Trusted Execution Environment (TEE)",permalink:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee"}},c={},p=[{value:"File Descriptor Limit",id:"file-descriptor-limit",level:2},{value:"System-wide Resource Limits Configuration File",id:"system-wide-resource-limits-configuration-file",level:3},{value:"Systemd Service Configuration",id:"systemd-service-configuration",level:3},{value:"Docker",id:"docker",level:3},{value:"Running Oasis Services with Non-root System User",id:"non-root",level:2},{value:"Changing Your Setup to Run Oasis Services with Non-root System User",id:"change-to-non-root",level:3}],d={toc:p},m="wrapper";function f(e){let{components:t,...n}=e;return(0,a.kt)(m,(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"system-configuration"},"System Configuration"),(0,a.kt)("p",null,"This page describes changes that should be made to the configuration of the\nsystem where you are running an Oasis Node instance."),(0,a.kt)("h2",{id:"file-descriptor-limit"},"File Descriptor Limit"),(0,a.kt)("p",null,"Make sure that the user under which you are running your Oasis Node has a high-enough file descriptor limit as the databases can have many files open and running out of file descriptors can lead to the node stopping unexpectedly."),(0,a.kt)("p",null,"You can check the file descriptor limit by running the following as the same user that will run Oasis Node:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"ulimit -n\n")),(0,a.kt)("p",null,"If this number is lower than 102400 you should consider increasing it by updating your system configuration. You can configure ",(0,a.kt)("em",{parentName:"p"},"temporary")," limits by running:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"ulimit -n 102400\n")),(0,a.kt)("p",null,"Note that this limit only applies to any processes started from the same shell after the command was executed. If you want to make the change permanent, you have the following options."),(0,a.kt)("h3",{id:"system-wide-resource-limits-configuration-file"},"System-wide Resource Limits Configuration File"),(0,a.kt)("p",null,"As ",(0,a.kt)("inlineCode",{parentName:"p"},"root"),", create a file in ",(0,a.kt)("inlineCode",{parentName:"p"},"/etc/security/limits.d/99-oasis-node.conf")," with content similar to the following example:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"* soft nofile 102400\n* hard nofile 1048576\n")),(0,a.kt)("p",null,"You can replace ",(0,a.kt)("inlineCode",{parentName:"p"},"*")," with the name of the user that is running the Oasis Node in case you only want to change the limits for that particular user."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"In order for the changes to take effect a system restart may be required.")),(0,a.kt)("h3",{id:"systemd-service-configuration"},"Systemd Service Configuration"),(0,a.kt)("p",null,"In case you are running your Oasis Node process via ",(0,a.kt)("a",{parentName:"p",href:"https://systemd.io/"},"systemd"),", you can add the following directive under the ",(0,a.kt)("inlineCode",{parentName:"p"},"[Service]")," section:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-text"},"LimitNOFILE=102400\n")),(0,a.kt)("h3",{id:"docker"},"Docker"),(0,a.kt)("p",null,"If you are running Oasis Node via ",(0,a.kt)("a",{parentName:"p",href:"https://www.docker.com/"},"Docker")," you can pass the following option to ",(0,a.kt)("inlineCode",{parentName:"p"},"docker run")," in order to increase the limit to desired values:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-text"},"--ulimit nofile=102400:1048576\n")),(0,a.kt)("h2",{id:"non-root"},"Running Oasis Services with Non-root System User"),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Beginning with ",(0,a.kt)("strong",{parentName:"p"},"Oasis Core 22.1.x release series")," it is\n",(0,a.kt)("strong",{parentName:"p"},"no longer allowed to run Oasis Node")," (i.e. the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-node")," binary)\n",(0,a.kt)("strong",{parentName:"p"},"as root")," (effective user ID of 0).")),(0,a.kt)("p",null,'Running network accessible services as the root user is extremely bad for\nsystem security as a general rule. While it would be "ok" if we could drop\nprivileges, ',(0,a.kt)("inlineCode",{parentName:"p"},"syscall.AllThreadsSyscall")," does not work if the binary uses ",(0,a.kt)("inlineCode",{parentName:"p"},"cgo"),"\nat all."),(0,a.kt)("p",null,"Nothing in Oasis Node will ever require elevated privileges.\nAttempting to run the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-node")," process as the root user will now terminate\nimmediately on startup."),(0,a.kt)("p",null,"While there may be specific circumstances where it is safe to run network\nservices with the effective user ID set to 0, the overwhelming majority of cases\nwhere this is done is a misconfiguration."),(0,a.kt)("h3",{id:"change-to-non-root"},"Changing Your Setup to Run Oasis Services with Non-root System User"),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"In these examples, we change the setup to run Oasis Services (e.g. Oasis Node)\nwith a non-root system user named ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis"),".\nThese instructions also assume that the node's datadir is ",(0,a.kt)("inlineCode",{parentName:"p"},"/serverdir/node"),"."),(0,a.kt)("p",{parentName:"admonition"},"Adjust these as appropriate to your setup.")),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Create the ",(0,a.kt)("inlineCode",{parentName:"li"},"oasis")," system user:")),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"Ubuntu",mdxType:"TabItem"},(0,a.kt)("p",null,"As root, run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"adduser --system oasis --shell /usr/sbin/nologin\n"))),(0,a.kt)(i.Z,{value:"Fedora",mdxType:"TabItem"},(0,a.kt)("p",null,"As root, run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"useradd -r -s /usr/sbin/nologin\n"))),(0,a.kt)(i.Z,{value:"Ansible",mdxType:"TabItem"},(0,a.kt)("p",null,"Add the following task to your playbook:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yml"},"- name: Create oasis user\n user:\n name: oasis\n comment: Oasis Services user\n system: yes\n shell: /usr/sbin/nologin\n")))),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Setting ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis")," user's Shell to ",(0,a.kt)("inlineCode",{parentName:"p"},"/usr/sbin/nologin")," prevents (accidentally)\nlogging-in as this user.")),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Stop your Oasis Node.")),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Transfer ownership of the datadir to the ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis")," user:"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"chown -R oasis /serverdir/node\n")),(0,a.kt)("p",null,"See ",(0,a.kt)("a",{parentName:"p",href:"/node/run-your-node/troubleshooting#invalid-permissions"},"Invalid Permissions")," troubleshooting guide for more information."),(0,a.kt)("ol",{start:4},(0,a.kt)("li",{parentName:"ol"},"Update how you run Oasis Node:")),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"systemd",mdxType:"TabItem"},(0,a.kt)("p",null,"Add a ",(0,a.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User="},(0,a.kt)("inlineCode",{parentName:"a"},"User")," directive")," to the Oasis service's systemd unit file:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-conf"},"...\nUser=oasis\n...\n")),(0,a.kt)("p",null,"Below can be found a simple systemd unit file for ",(0,a.kt)("inlineCode",{parentName:"p"},"oasis-node")," that can be used\nas a starting point."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-conf"},"[Unit]\nDescription=Oasis Node\nAfter=network.target\n\n[Service]\nType=simple\nUser=oasis\nWorkingDirectory=/serverdir/node\nExecStart=/serverdir/bin/oasis-node --config /serverdir/etc/config.yml\nRestart=on-failure\nRestartSec=3\nLimitNOFILE=1024000\n\n[Install]\nWantedBy=multi-user.target\n"))),(0,a.kt)(i.Z,{value:"Docker",mdxType:"TabItem"},(0,a.kt)("p",null,"Add ",(0,a.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/reference/builder/#user"},(0,a.kt)("inlineCode",{parentName:"a"},"USER")," instruction")," to your Oasis service's Dockerfile:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-conf"},"...\nUSER oasis\n...\n"))),(0,a.kt)(i.Z,{value:"runit",mdxType:"TabItem"},(0,a.kt)("p",null,"Wrap the invocation in a ",(0,a.kt)("a",{parentName:"p",href:"http://smarden.org/runit/chpst.8.html"},(0,a.kt)("inlineCode",{parentName:"a"},"chpst")," command"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"chpst -u oasis oasis-node ...\n")))),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},"Start your Oasis Node.")))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ffcff7f9.1f050029.js b/assets/js/ffcff7f9.1f050029.js new file mode 100644 index 0000000000..0e76daf1b5 --- /dev/null +++ b/assets/js/ffcff7f9.1f050029.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[5954],{3905:(e,n,t)=>{t.d(n,{Zo:()=>l,kt:()=>k});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=a.createContext({}),d=function(e){var n=a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},l=function(e){var n=d(e.components);return a.createElement(c.Provider,{value:n},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,s=e.originalType,c=e.parentName,l=r(e,["components","mdxType","originalType","parentName"]),p=d(t),m=o,k=p["".concat(c,".").concat(m)]||p[m]||u[m]||s;return t?a.createElement(k,i(i({ref:n},l),{},{components:t})):a.createElement(k,i({ref:n},l))}));function k(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var s=t.length,i=new Array(s);i[0]=m;var r={};for(var c in n)hasOwnProperty.call(n,c)&&(r[c]=n[c]);r.originalType=e,r[p]="string"==typeof e?e:o,i[1]=r;for(var d=2;d{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var a=t(7462),o=(t(7294),t(3905));const s={},i="oasis-node CLI",r={unversionedId:"core/oasis-node/cli",id:"core/oasis-node/cli",title:"oasis-node CLI",description:"control",source:"@site/docs/core/oasis-node/cli.md",sourceDirName:"core/oasis-node",slug:"/core/oasis-node/cli",permalink:"/core/oasis-node/cli",draft:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/cli.md",tags:[],version:"current",lastUpdatedAt:1692017182,formattedLastUpdatedAt:"Aug 14, 2023",frontMatter:{},sidebar:"oasisCore",previous:{title:"Metrics",permalink:"/core/oasis-node/metrics"},next:{title:"Common Functionality",permalink:"/core/common-functionality"}},c={},d=[{value:"control",id:"control",level:2},{value:"status",id:"status",level:3},{value:"genesis",id:"genesis",level:2},{value:"check",id:"check",level:3},{value:"dump",id:"dump",level:3},{value:"init",id:"init",level:3},{value:"stake",id:"stake",level:2},{value:"account",id:"account",level:3},{value:"info",id:"info",level:4},{value:"pubkey2address",id:"pubkey2address",level:3}],l={toc:d},p="wrapper";function u(e){let{components:n,...t}=e;return(0,o.kt)(p,(0,a.Z)({},l,t,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"oasis-node-cli"},(0,o.kt)("inlineCode",{parentName:"h1"},"oasis-node")," CLI"),(0,o.kt)("h2",{id:"control"},(0,o.kt)("inlineCode",{parentName:"h2"},"control")),(0,o.kt)("h3",{id:"status"},(0,o.kt)("inlineCode",{parentName:"h3"},"status")),(0,o.kt)("p",null,"Run"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node control status\n")),(0,o.kt)("p",null,"to get information like the following (example taken from a runtime compute\nnode):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{\n "software_version": "21.3",\n "identity": {\n "node": "iWq6Nft6dU2GWAr9U7ICbhXWwmAINIniKzMMblSo5Xs=",\n "p2p": "dGd+pGgIlkJb0dnkBQ7vI2EWWG81pF5M1G+jL2/6pyA=",\n "consensus": "QaMdKVwX1da0Uf82cp0DDukQQwrSjr8BwlIxc//ANE8=",\n "tls": [\n "Kj8ANHwfMzcWoA1vx0OMhn4oGv8Y0vc46xMOdQUIh5c=",\n "1C8rWqyuARkSxNXuPbDPh9XID/SiYAU3GxGk6nMwR0Q="\n ]\n },\n "consensus": {\n "version": {\n "major": 4\n },\n "backend": "tendermint",\n "features": 3,\n "node_peers": [\n "5ab8074ce3053ef9b72d664c73e39972241442e3@57.71.39.73:26658",\n "abb66e8780f3815d87bad488a2892b4d4b2221e3@108.15.34.59:50716"\n ],\n "latest_height": 5960191,\n "latest_hash": "091c29c3d588c52421a4f215268c6b4ab1a7762c429a98fec5de9251f8907add",\n "latest_time": "2021-09-24T21:42:29+02:00",\n "latest_epoch": 10489,\n "latest_state_root": {\n "ns": "0000000000000000000000000000000000000000000000000000000000000000",\n "version": 5960190,\n "root_type": 1,\n "hash": "c34581dcec59d80656d6082260d63f3206aef0a1b950c1f2c06d1eaa36a22ec3"\n },\n "genesis_height": 5891596,\n "genesis_hash": "e9d9fb99baefc3192a866581c35bf43d7f0499c64e1c150171e87b2d5dc35087",\n "last_retained_height": 5891596,\n "last_retained_hash": "e9d9fb99baefc3192a866581c35bf43d7f0499c64e1c150171e87b2d5dc35087",\n "chain_context": "9ee492b63e99eab58fd979a23dfc9b246e5fc151bfdecd48d3ba26a9d0712c2b",\n "is_validator": true\n },\n "runtimes": {\n "0000000000000000000000000000000000000000000000000000000000000001": {\n "descriptor": {\n "v": 2,\n "id": "0000000000000000000000000000000000000000000000000000000000000001",\n "entity_id": "Ldzg8aeLiUBrMYxidd5DqEzpamyV2cprmRH0pG8d/Jg=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "state": null,\n "storage_receipts": null,\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 0,\n "versions": {\n "version": {\n "minor": 2\n }\n },\n "executor": {\n "group_size": 3,\n "group_backup_size": 3,\n "allowed_stragglers": 1,\n "round_timeout": 5,\n "max_messages": 256\n },\n "txn_scheduler": {\n "algorithm": "simple",\n "batch_flush_timeout": 1000000000,\n "max_batch_size": 100,\n "max_batch_size_bytes": 1048576,\n "propose_batch_timeout": 2\n },\n "storage": {\n "group_size": 3,\n "min_write_replication": 2,\n "max_apply_write_log_entries": 10000,\n "max_apply_ops": 2,\n "checkpoint_interval": 100,\n "checkpoint_num_kept": 2,\n "checkpoint_chunk_size": 8388608\n },\n "admission_policy": {\n "any_node": {}\n },\n "constraints": {\n "executor": {\n "backup-worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 3\n }\n },\n "worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 3\n }\n }\n },\n "storage": {\n "worker": {\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 3\n }\n }\n }\n },\n "staking": {},\n "governance_model": "entity"\n },\n "latest_round": 1355,\n "latest_hash": "2a11820c0524a8a753f7f4a268ee2d0a4f4588a89121f92a43f4be9cc6acca7e",\n "latest_time": "2021-09-24T21:41:29+02:00",\n "latest_state_root": {\n "ns": "0000000000000000000000000000000000000000000000000000000000000000",\n "version": 1355,\n "root_type": 1,\n "hash": "45168e11548ac5322a9a206abff4368983b5cf676b1bcb2269f5dfbdf9df7be3"\n },\n "genesis_round": 0,\n "genesis_hash": "aed94c03ebd2d16dfb5f6434021abf69c8c15fc69b6b19554d23da8a5a053776",\n "committee": {\n "latest_round": 1355,\n "latest_height": 5960180,\n "last_committee_update_height": 5960174,\n "executor_roles": [\n "worker",\n "backup-worker"\n ],\n "storage_roles": [\n "worker"\n ],\n "is_txn_scheduler": false,\n "peers": [\n "/ip4/57.71.39.73/tcp/41002/p2p/12D3KooWJvL8mYzHbcLtj91bf5sHhtrB7C8CWND5sV6Kk24eUdpQ",\n "/ip4/108.67.32.45/tcp/26648/p2p/12D3KooWBKgcH7TGMSLuxzLxK41nTwk6DsxHRpb7HpWQXJzLurcv"\n ]\n },\n "storage": {\n "last_finalized_round": 1355\n }\n }\n },\n "registration": {\n "last_registration": "2021-09-24T21:41:08+02:00",\n "descriptor": {\n "v": 1,\n "id": "iWq6Nft6dU2GWAr9U7ICbhXWwmAINIniKzMMblSo5Xs=",\n "entity_id": "4G4ISI8hANvMRYTbxdXU+0r9m/6ZySHERR+2RDbNOU8=",\n "expiration": 10491,\n "tls": {\n "pub_key": "Kj8ANHwfMzcWoA1vx0OMhn4oGv8Y0vc46xMOdQUIh5c=",\n "next_pub_key": "1C8rWqyuARkSxNXuPbDPh9XID/SiYAU3GxGk6nMwR0Q=",\n "addresses": [\n "Kj8ANHwfMzcWoA1vx0OMhn4oGv8Y0vc46xMOdQUIh5c=@128.89.215.24:30001",\n "1C8rWqyuARkSxNXuPbDPh9XID/SiYAU3GxGk6nMwR0Q=@128.89.215.24:30001"\n ]\n },\n "p2p": {\n "id": "dGd+pGgIlkJb0dnkBQ7vI2EWWG81pF5M1G+jL2/6pyA=",\n "addresses": [\n "159.89.215.24:30002"\n ]\n },\n "consensus": {\n "id": "QaMdKVwX1da0Uf82cp0DDukQQwrSjr8BwlIxc//ANE8=",\n "addresses": [\n "dGd+pGgIlkJb0dnkBQ7vI2EWWG81pF5M1G+jL2/6pyA=@128.89.215.24:26656"\n ]\n },\n "beacon": {\n "point": "BHg8TOqKD4wV8UCu9nICvJt7rhXFd8CxXuYiHa6X/NnzlIndzGNEJyyTr00s5rgKwX25yPmv+r2xRFbcQK6hGLE="\n },\n "runtimes": [\n {\n "id": "0000000000000000000000000000000000000000000000000000000000000001",\n "version": {\n "minor": 2\n },\n "capabilities": {},\n "extra_info": null\n }\n ],\n "roles": "compute,storage,validator"\n },\n "node_status": {\n "expiration_processed": false,\n "freeze_end_time": 0,\n "election_eligible_after": 9810\n }\n },\n "pending_upgrades": []\n}\n')),(0,o.kt)("h2",{id:"genesis"},(0,o.kt)("inlineCode",{parentName:"h2"},"genesis")),(0,o.kt)("h3",{id:"check"},(0,o.kt)("inlineCode",{parentName:"h3"},"check")),(0,o.kt)("p",null,"To check if a given ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/genesis#genesis-file"},"genesis file")," is valid, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node genesis check --genesis.file /path/to/genesis.json\n")),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"This also checks if the genesis file is in the ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/genesis#canonical-form"},"canonical form"),".")),(0,o.kt)("h3",{id:"dump"},(0,o.kt)("inlineCode",{parentName:"h3"},"dump")),(0,o.kt)("p",null,"To dump the state of the network at a specific block height, e.g. 717600, to a\n",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/genesis#genesis-file"},"genesis file"),", run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node genesis dump \\\n --address unix:/path/to/node/internal.sock \\\n --genesis.file /path/to/genesis_dump.json \\\n --height 717600\n")),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"You must only run the following command after the given block height has been\nreached on the network.")),(0,o.kt)("h3",{id:"init"},(0,o.kt)("inlineCode",{parentName:"h3"},"init")),(0,o.kt)("p",null,"To initialize a new ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/genesis#genesis-file"},"genesis file")," with the given chain id and ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/services/staking#tokens-and-base-units"},"staking token\nsymbol"),", run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'oasis-node genesis init --genesis.file /path/to/genesis.json \\\n --chain.id "name-of-my-network" \\\n --staking.token_symbol TEST\n')),(0,o.kt)("admonition",{type:"info"},(0,o.kt)("p",{parentName:"admonition"},"You can set a lot of parameters for the various ",(0,o.kt)("a",{parentName:"p",href:"/core/consensus/"},"consensus layer services"),"."),(0,o.kt)("p",{parentName:"admonition"},"To see the full list, run:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node genesis init --help\n"))),(0,o.kt)("h2",{id:"stake"},(0,o.kt)("inlineCode",{parentName:"h2"},"stake")),(0,o.kt)("h3",{id:"account"},(0,o.kt)("inlineCode",{parentName:"h3"},"account")),(0,o.kt)("h4",{id:"info"},(0,o.kt)("inlineCode",{parentName:"h4"},"info")),(0,o.kt)("p",null,"Run"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node stake account info \\\n --stake.account.address \\\n --address unix:/path/to/node/internal.sock\n")),(0,o.kt)("p",null,"to get staking information for a specific account:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"General Account:\n Balance: TEST 0.0\n Nonce: 0\nEscrow Account:\n Active:\n Balance: TEST 0.0\n Total Shares: 0\n Debonding:\n Balance: TEST 0.0\n Total Shares: 0\n Commission Schedule:\n Rates: (none)\n Rate Bounds: (none)\n Stake Accumulator:\n Claims:\n - Name: registry.RegisterEntity\n Staking Thresholds:\n - Global: entity\n - Name: registry.RegisterNode.LQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH0=\n Staking Thresholds:\n - Global: node-validator\n")),(0,o.kt)("h3",{id:"pubkey2address"},(0,o.kt)("inlineCode",{parentName:"h3"},"pubkey2address")),(0,o.kt)("p",null,"Run"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"oasis-node stake pubkey2address --public_key \n")),(0,o.kt)("p",null,"to get staking account address from an entity or node public key. Example\nresponse:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre"},"oasis1qqncl383h8458mr9cytatygctzwsx02n4c5f8ed7\n")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/main.87007c19.js b/assets/js/main.87007c19.js new file mode 100644 index 0000000000..283a02723b --- /dev/null +++ b/assets/js/main.87007c19.js @@ -0,0 +1,2 @@ +/*! For license information please see main.87007c19.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_dev=self.webpackChunkdocs_oasis_dev||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),s=n(6887);const l={"00eda7cc":[()=>n.e(194).then(n.bind(n,474)),"@site/docs/core/development-setup/deploying-a-runtime.md",474],"03741c42":[()=>n.e(6525).then(n.bind(n,7846)),"@site/docs/core/README.md",7846],"041ef302":[()=>Promise.all([n.e(532),n.e(196)]).then(n.bind(n,2636)),"@site/docs/paratime/README.mdx",2636],"047b4156":[()=>n.e(5844).then(n.bind(n,7118)),"@site/docs/node/run-your-node/advanced/copy-state-from-one-node-to-the-other.md",7118],"049d1767":[()=>n.e(4073).then(n.bind(n,1458)),"@site/docs/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime.md",1458],"04a64f04":[()=>n.e(5921).then(n.bind(n,2465)),"@site/docs/dapp/opl/build.md",2465],"05c525ec":[()=>n.e(9392).then(n.bind(n,3882)),"@site/docs/core/consensus/services/roothash.md",3882],"06c96f46":[()=>n.e(9899).then(n.bind(n,5805)),"@site/docs/oasis-core-ledger/usage/transactions.md",5805],"086b3520":[()=>n.e(2930).then(n.bind(n,2642)),"@site/docs/general/manage-tokens/faq.md",2642],"0e099be9":[()=>n.e(7861).then(n.bind(n,1815)),"@site/docs/dapp/opl/host.md",1815],"0e9cd926":[()=>n.e(2072).then(n.bind(n,463)),"@site/docs/adrs/0020-governance-delegator-votes.md",463],"0f0ebacb":[()=>n.e(5776).then(n.bind(n,6504)),"@site/docs/paratime/reproducibility.md",6504],"0f921af1":[()=>n.e(2874).then(n.bind(n,3109)),"@site/docs/general/manage-tokens/cli/account.md",3109],"0f92291a":[()=>n.e(5293).then(n.bind(n,6296)),"@site/docs/get-involved/README.md",6296],"10bc4617":[()=>n.e(5944).then(n.bind(n,7380)),"@site/docs/core/consensus/services/epochtime.md",7380],"14eb3368":[()=>Promise.all([n.e(532),n.e(9817)]).then(n.bind(n,5541)),"@theme/DocCategoryGeneratedIndexPage",5541],"167edc4b":[()=>n.e(3019).then(n.t.bind(n,4526,19)),"~docs/default/category-operators-category-previous-upgrades-6e6.json",4526],17896441:[()=>Promise.all([n.e(532),n.e(7918)]).then(n.bind(n,620)),"@theme/DocItem",620],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,2027)),"@theme/SearchPage",2027],"1a50dc2d":[()=>n.e(7489).then(n.bind(n,6242)),"@site/docs/dapp/opl/setup.md",6242],"1a9d3710":[()=>n.e(3446).then(n.bind(n,7358)),"@site/docs/get-involved/token-delivery-and-kyc.md",7358],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1d621f19":[()=>n.e(9250).then(n.bind(n,605)),"@site/docs/node/genesis-doc.md",605],"1dbb95b6":[()=>Promise.all([n.e(859),n.e(4208)]).then(n.bind(n,3649)),"@site/docs/general/oasis-network/token-metrics-and-distribution.mdx",3649],"1df235ce":[()=>n.e(3600).then(n.bind(n,2582)),"@site/docs/dapp/cipher/confidential-smart-contract.md",2582],"1e60058c":[()=>n.e(28).then(n.bind(n,7595)),"@site/docs/core/consensus/README.md",7595],"1fa6bbb5":[()=>n.e(3845).then(n.bind(n,7998)),"@site/docs/core/consensus/services/beacon.md",7998],"20d2542b":[()=>n.e(8252).then(n.bind(n,4469)),"@site/docs/core/development-setup/prerequisites.md",4469],"210fedca":[()=>n.e(9839).then(n.bind(n,4396)),"@site/docs/node/run-your-node/maintenance/wiping-node-state.md",4396],"220011ce":[()=>n.e(3193).then(n.bind(n,5280)),"@site/docs/dapp/opl/enclave.md",5280],"2287f371":[()=>n.e(4988).then(n.bind(n,4324)),"@site/docs/adrs/0021-keymanager-ephemeral-secrets.md",4324],"24323d06":[()=>n.e(9160).then(n.bind(n,2474)),"@site/docs/core/authenticated-grpc.md",2474],"247783bb":[()=>n.e(9334).then(n.t.bind(n,3769,19)),"/home/runner/work/docs/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],26373622:[()=>Promise.all([n.e(532),n.e(1102)]).then(n.bind(n,396)),"@site/docs/dapp/sapphire/guide.mdx",396],"277e601e":[()=>n.e(3408).then(n.bind(n,1829)),"@site/docs/node/mainnet/previous-upgrades/cobalt-upgrade.md",1829],"27f9eba8":[()=>n.e(4440).then(n.bind(n,564)),"@site/docs/get-involved/delegation-policy.md",564],"2881b1cc":[()=>n.e(993).then(n.t.bind(n,5908,19)),"~docs/default/category-operators-category-advanced-e69.json",5908],"29c77900":[()=>n.e(8553).then(n.bind(n,711)),"@site/docs/node/run-your-node/prerequisites/stake-requirements.md",711],"2c58cae2":[()=>n.e(4077).then(n.bind(n,7119)),"@site/docs/dapp/cipher/prerequisites.md",7119],"2e8d1096":[()=>n.e(8038).then(n.bind(n,7256)),"@site/docs/adrs/0003-consensus-runtime-token-transfer.md",7256],"2ea67962":[()=>n.e(5603).then(n.bind(n,9210)),"@site/docs/node/run-your-node/prerequisites/oasis-node.md",9210],30129561:[()=>n.e(4072).then(n.bind(n,685)),"@site/docs/core/runtime/runtime-host-protocol.md",685],"30beaf32":[()=>Promise.all([n.e(532),n.e(6784)]).then(n.bind(n,6795)),"@site/docs/dapp/sapphire/quickstart.mdx",6795],"32b63699":[()=>n.e(7351).then(n.bind(n,9110)),"@site/docs/node/web3.md",9110],"34c89262":[()=>n.e(3487).then(n.bind(n,9716)),"@site/docs/adrs/0015-vrf-per-block-entropy.md",9716],"370b1912":[()=>n.e(245).then(n.bind(n,2948)),"@site/docs/adrs/0012-runtime-message-results.md",2948],"3812dde4":[()=>n.e(5060).then(n.t.bind(n,9980,19)),"~docs/default/category-oasiscore-category-oasis-node-93d.json",9980],"3ae86dfc":[()=>n.e(8990).then(n.bind(n,4365)),"@site/docs/core/encoding.md",4365],"3bc542c3":[()=>n.e(6536).then(n.bind(n,1139)),"@site/docs/general/manage-tokens/holding-rose-tokens/custody-providers.md",1139],"3c28ce58":[()=>n.e(3251).then(n.t.bind(n,8784,19)),"~docs/default/category-oasiscore-category-development-setup-865.json",8784],"3e5e0bf3":[()=>n.e(6990).then(n.bind(n,7141)),"@site/docs/adrs/0007-improved-random-beacon.md",7141],"3fb4947e":[()=>n.e(8203).then(n.bind(n,3509)),"@site/docs/core/oasis-node/metrics.md",3509],"4079c408":[()=>n.e(9439).then(n.bind(n,7685)),"@site/docs/adrs/0013-runtime-upgrades.md",7685],"409fc1d8":[()=>n.e(651).then(n.bind(n,9455)),"@site/docs/adrs/0011-incoming-runtime-messages.md",9455],"4129286c":[()=>n.e(5156).then(n.t.bind(n,2776,19)),"/home/runner/work/docs/docs/.docusaurus/@easyops-cn/docusaurus-search-local/default/plugin-route-context-module-100.json",2776],"414b6464":[()=>n.e(8905).then(n.bind(n,10)),"@site/docs/node/testnet/README.md",10],"433ff9f9":[()=>n.e(1266).then(n.bind(n,1802)),"@site/docs/general/manage-tokens/cli/network.md",1802],"4414cbb7":[()=>n.e(3267).then(n.bind(n,5071)),"@site/docs/node/mainnet/README.md",5071],"472a807d":[()=>n.e(9346).then(n.t.bind(n,8752,19)),"~docs/default/category-operators-category-maintenance-b7d.json",8752],"4740797d":[()=>n.e(4311).then(n.t.bind(n,5932,19)),"~docs/default/category-operators-category-run-your-node-710.json",5932],"4a27219a":[()=>n.e(6006).then(n.bind(n,1938)),"@site/docs/node/run-your-node/maintenance/refreshing-certificates.md",1938],"4adca928":[()=>n.e(1378).then(n.bind(n,9684)),"@site/docs/oasis-core-ledger/usage/wallets.md",9684],"4ae0b297":[()=>n.e(467).then(n.bind(n,6458)),"@site/docs/dapp/cipher/hello-world.md",6458],"4c52944b":[()=>n.e(3861).then(n.bind(n,4576)),"@site/docs/paratime/prerequisites.md",4576],"4daae886":[()=>n.e(450).then(n.bind(n,5809)),"@site/docs/adrs/0008-standard-account-key-generation.md",5809],"4fe2dd92":[()=>n.e(9561).then(n.bind(n,4754)),"@site/docs/oasis-core-ledger/SUMMARY.md",4754],"527e04fa":[()=>n.e(5657).then(n.bind(n,1817)),"@site/docs/core/runtime/identifiers.md",1817],"5334ec61":[()=>n.e(9200).then(n.bind(n,5022)),"@site/docs/core/development-setup/building.md",5022],"553dc0b4":[()=>n.e(8543).then(n.t.bind(n,5629,19)),"~docs/default/category-oasiscore-category-services-5de.json",5629],"5583c17b":[()=>n.e(8061).then(n.bind(n,1405)),"@site/docs/dapp/sapphire/browser.md",1405],"59b1a96c":[()=>Promise.all([n.e(532),n.e(67)]).then(n.bind(n,2075)),"@site/docs/README.mdx",2075],"59e83093":[()=>n.e(7206).then(n.bind(n,1396)),"@site/docs/node/mainnet/e-upgrade.md",1396],"5a14fd4c":[()=>n.e(5115).then(n.bind(n,8690)),"@site/docs/adrs/0010-vrf-elections.md",8690],"5da91464":[()=>n.e(108).then(n.bind(n,1757)),"@site/docs/node/run-your-node/archive-node.md",1757],"5ef859b9":[()=>n.e(7160).then(n.t.bind(n,8354,19)),"~docs/default/category-oasiscore-category-processes-7db.json",8354],"63d4daba":[()=>n.e(7683).then(n.bind(n,9186)),"@site/docs/oasis-core-ledger/usage/entity.md",9186],"6ac8b2ab":[()=>n.e(4239).then(n.bind(n,1162)),"@site/docs/adrs/0009-ed25519-semantics.md",1162],"6b19e4d7":[()=>Promise.all([n.e(532),n.e(8077)]).then(n.bind(n,7197)),"@site/docs/dapp/sapphire/README.mdx",7197],"6ca61699":[()=>n.e(8302).then(n.t.bind(n,4033,19)),"~docs/default/category-operators-category-prerequisites-18d.json",4033],"6d4312e8":[()=>Promise.all([n.e(532),n.e(6584)]).then(n.bind(n,8452)),"@site/docs/general/manage-tokens/oasis-wallets/README.mdx",8452],"6de7ad9b":[()=>n.e(6984).then(n.bind(n,7285)),"@site/docs/dapp/opl/frontend.md",7285],"6ea13540":[()=>n.e(1146).then(n.bind(n,2843)),"@site/docs/adrs/0001-tm-multi-root-apphash.md",2843],"70b0ec1b":[()=>Promise.all([n.e(532),n.e(4133)]).then(n.bind(n,9449)),"@site/docs/general/manage-tokens/how-to-transfer-rose-into-paratime.mdx",9449],"714fd338":[()=>n.e(743).then(n.bind(n,9444)),"@site/docs/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee.md",9444],"72e396cc":[()=>n.e(7592).then(n.bind(n,6693)),"@site/docs/node/run-your-node/sentry-node.md",6693],"72efe815":[()=>n.e(7954).then(n.bind(n,9950)),"@site/docs/node/run-your-node/ias-proxy.md",9950],"72f44a45":[()=>n.e(3724).then(n.bind(n,1984)),"@site/docs/general/oasis-network/faq.md",1984],"7327d54c":[()=>n.e(5524).then(n.bind(n,398)),"@site/docs/get-involved/network-governance.md",398],"736ce571":[()=>n.e(3336).then(n.bind(n,2505)),"@site/docs/node/run-your-node/prerequisites/hardware-recommendations.md",2505],"74cc02ce":[()=>Promise.all([n.e(532),n.e(3565)]).then(n.bind(n,4707)),"@site/docs/general/README.mdx",4707],"7671072d":[()=>n.e(594).then(n.bind(n,5194)),"@site/docs/node/run-your-node/non-validator-node.md",5194],"767aa429":[()=>n.e(8862).then(n.bind(n,2066)),"@site/docs/general/manage-tokens/cli/wallet.md",2066],"7687a514":[()=>Promise.all([n.e(532),n.e(6476)]).then(n.bind(n,7922)),"@site/docs/dapp/cipher/README.mdx",7922],"777245c5":[()=>n.e(5732).then(n.bind(n,9047)),"@site/docs/core/consensus/services/governance.md",9047],79102774:[()=>Promise.all([n.e(532),n.e(9541)]).then(n.bind(n,9890)),"@site/docs/node/run-your-node/validator-node.mdx",9890],"7b1f3817":[()=>n.e(8713).then(n.bind(n,3286)),"@site/docs/adrs/0002-go-modules-compatible-git-tags.md",3286],"7bee5ea1":[()=>n.e(3154).then(n.bind(n,8616)),"@site/docs/general/manage-tokens/terminology.md",8616],"7ca72da4":[()=>n.e(9634).then(n.bind(n,3652)),"@site/docs/core/bigint.md",3652],"7da689db":[()=>Promise.all([n.e(532),n.e(36)]).then(n.bind(n,9231)),"@site/docs/get-involved/run-node/paratime-node.mdx",9231],"7f0ce295":[()=>n.e(766).then(n.bind(n,6134)),"@site/docs/oasis-core-ledger/versioning.md",6134],"8199fa7c":[()=>n.e(5784).then(n.t.bind(n,4830,19)),"~docs/default/category-oasiscore-category-build-environment-setup-and-building-899.json",4830],85011861:[()=>n.e(8194).then(n.bind(n,9996)),"@site/docs/general/manage-tokens/cli/transaction.md",9996],"8786ced4":[()=>n.e(7487).then(n.bind(n,8341)),"@site/docs/adrs/0014-runtime-signing-tx-with-hardware-wallet.md",8341],"885a74d0":[()=>n.e(2597).then(n.bind(n,7999)),"@site/docs/core/development-setup/oasis-net-runner.md",7999],"886d3d06":[()=>n.e(1022).then(n.bind(n,5786)),"@site/docs/general/manage-tokens/cli/setup.md",5786],"8b083473":[()=>n.e(4540).then(n.bind(n,1233)),"@site/docs/core/oasis-node/rpc.md",1233],"8f21ad56":[()=>n.e(7050).then(n.bind(n,7829)),"@site/docs/node/testnet/upgrade-log.md",7829],"8fa03331":[()=>n.e(2459).then(n.bind(n,315)),"@site/docs/node/run-your-node/advanced/sync-node-using-state-sync.md",315],"904dacd1":[()=>n.e(9572).then(n.bind(n,3253)),"@site/docs/node/run-your-node/keymanager-node/signing-key-manager-policy.md",3253],"917d8c1f":[()=>n.e(8060).then(n.bind(n,6521)),"@site/docs/core/development-setup/single-validator-node-network.md",6521],"919a9404":[()=>n.e(1728).then(n.bind(n,4718)),"@site/docs/adrs/0005-runtime-compute-slashing.md",4718],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"94ed66ea":[()=>n.e(9008).then(n.bind(n,7242)),"@site/docs/core/consensus/services/scheduler.md",7242],"9645557e":[()=>n.e(6097).then(n.bind(n,6681)),"@site/docs/dapp/emerald/integrating-band-oracle-smart-contract.md",6681],"977c4838":[()=>Promise.all([n.e(532),n.e(817)]).then(n.bind(n,6548)),"@site/docs/node/README.mdx",6548],"9795c642":[()=>n.e(4913).then(n.bind(n,7180)),"@site/docs/get-involved/run-node/validator-node.md",7180],"994ee662":[()=>n.e(1932).then(n.bind(n,5619)),"@site/docs/general/manage-tokens/staking-and-delegating.md",5619],"9ba66431":[()=>n.e(910).then(n.bind(n,4097)),"@site/docs/core/consensus/services/staking.md",4097],"9fc93287":[()=>n.e(5851).then(n.t.bind(n,5488,19)),"~docs/default/category-oasiscore-category-high-level-components-6f7.json",5488],"9fda2e12":[()=>Promise.all([n.e(532),n.e(7907)]).then(n.bind(n,1074)),"@site/docs/dapp/README.mdx",1074],a02c83e6:[()=>n.e(3228).then(n.bind(n,1510)),"@site/docs/core/consensus/transactions.md",1510],a11d2c44:[()=>n.e(1581).then(n.bind(n,7488)),"@site/docs/node/run-your-node/keymanager-node/key-manager-upgrade.md",7488],a14fc975:[()=>n.e(9560).then(n.bind(n,7837)),"@site/docs/node/mainnet/upgrade-log.md",7837],a271df25:[()=>n.e(2916).then(n.bind(n,5371)),"@site/docs/oasis-core-ledger/usage/setup.md",5371],a71e7da1:[()=>n.e(8323).then(n.bind(n,317)),"@site/docs/node/run-your-node/maintenance/shutting-down-a-node.md",317],a7d941e7:[()=>n.e(6966).then(n.bind(n,504)),"@site/docs/general/manage-tokens/cli/paratime.md",504],a89bcaa3:[()=>n.e(2625).then(n.bind(n,6182)),"@site/docs/adrs/0016-consensus-parameters-change-proposal.md",6182],a9e87a2c:[()=>Promise.all([n.e(532),n.e(7771)]).then(n.bind(n,7632)),"@site/docs/general/oasis-network/README.mdx",7632],ab39d68c:[()=>n.e(8679).then(n.bind(n,6088)),"@site/docs/core/mkvs.md",6088],ab8e36ce:[()=>Promise.all([n.e(532),n.e(5585)]).then(n.bind(n,2375)),"@site/docs/general/manage-tokens/README.mdx",2375],acdeae29:[()=>Promise.all([n.e(532),n.e(9532)]).then(n.bind(n,8966)),"@site/docs/dapp/emerald/writing-dapps-on-emerald.mdx",8966],b230e4e5:[()=>n.e(5751).then(n.bind(n,3865)),"@site/docs/adrs/0004-runtime-governance.md",3865],b4883e93:[()=>n.e(7729).then(n.bind(n,6173)),"@site/docs/general/oasis-network/why-oasis.md",6173],b4c66254:[()=>n.e(5275).then(n.t.bind(n,6752,19)),"~docs/default/category-getinvolved-category-run-a-node-e2a.json",6752],b5f911d2:[()=>n.e(5414).then(n.t.bind(n,5426,19)),"~docs/default/category-oasiscore-category-running-tests-and-development-networks-9ba.json",5426],b622a7ea:[()=>n.e(9627).then(n.bind(n,7758)),"@site/docs/paratime/modules.md",7758],b66dccd5:[()=>n.e(2126).then(n.bind(n,8546)),"@site/docs/paratime/minimal-runtime.md",8546],b821a83b:[()=>n.e(1078).then(n.bind(n,5554)),"@site/docs/node/run-your-node/maintenance/adding-or-removing-nodes.md",5554],bb3e1595:[()=>n.e(4829).then(n.bind(n,873)),"@site/docs/get-involved/oasis-core.md",873],bcbc0322:[()=>Promise.all([n.e(532),n.e(1088)]).then(n.bind(n,5646)),"@site/docs/node/run-your-node/paratime-client-node.mdx",5646],bede16e2:[()=>Promise.all([n.e(532),n.e(7767)]).then(n.bind(n,2129)),"@site/docs/node/run-your-node/paratime-node.mdx",2129],c41a84e2:[()=>n.e(7990).then(n.bind(n,5526)),"@site/docs/core/runtime/README.md",5526],c74bdc2d:[()=>n.e(6684).then(n.bind(n,3759)),"@site/docs/oasis-core-ledger/usage/address.md",3759],c800e6d8:[()=>n.e(7383).then(n.bind(n,2239)),"@site/docs/adrs/0022-keymanager-master-secrets.md",2239],c9679863:[()=>Promise.all([n.e(532),n.e(8719)]).then(n.bind(n,2313)),"@site/docs/dapp/emerald/README.mdx",2313],cb5a5574:[()=>n.e(3049).then(n.bind(n,6914)),"@site/docs/general/manage-tokens/cli/README.md",6914],cd9af2e1:[()=>n.e(1045).then(n.bind(n,2520)),"@site/docs/core/consensus/test-vectors.md",2520],ce2c26b3:[()=>n.e(1862).then(n.bind(n,5227)),"@site/docs/adrs/0017-app-standards.md",5227],cef04ba6:[()=>n.e(355).then(n.bind(n,8728)),"@site/docs/adrs/0006-consensus-governance.md",8728],d089813a:[()=>n.e(6889).then(n.bind(n,3329)),"@site/docs/core/runtime/messages.md",3329],d0da959f:[()=>n.e(2337).then(n.bind(n,8924)),"@site/docs/node/mainnet/damask-upgrade.md",8924],d18a0ae3:[()=>n.e(8119).then(n.bind(n,3765)),"@site/docs/node/run-your-node/maintenance/handling-network-upgrades.md",3765],d31e1216:[()=>n.e(8080).then(n.t.bind(n,5980,19)),"~docs/default/category-oasiscore-category-common-functionality-f12.json",5980],d60ba3f8:[()=>n.e(97).then(n.bind(n,4561)),"@site/docs/dapp/sapphire/precompiles.md",4561],d632a858:[()=>n.e(4426).then(n.bind(n,9845)),"@site/docs/dapp/opl/introduction.md",9845],d940ecbe:[()=>n.e(198).then(n.t.bind(n,1094,19)),"~docs/default/category-general-category-3rd-party-custody-wallets-b52.json",1094],d941f4da:[()=>n.e(2978).then(n.bind(n,3301)),"@site/docs/core/release-process.md",3301],d95a60a6:[()=>n.e(6608).then(n.bind(n,1736)),"@site/docs/node/mainnet/previous-upgrades/mainnet-upgrade.md",1736],db582d92:[()=>n.e(6466).then(n.bind(n,2647)),"@site/docs/node/run-your-node/keymanager-node/README.md",2647],dcfcc267:[()=>n.e(3821).then(n.bind(n,3190)),"@site/docs/core/development-setup/running-tests.md",3190],de2ae66a:[()=>n.e(4139).then(n.bind(n,9503)),"@site/docs/core/consensus/genesis.md",9503],e27d89bb:[()=>n.e(974).then(n.bind(n,3179)),"@site/docs/core/consensus/services/registry.md",3179],e27f323d:[()=>n.e(1354).then(n.bind(n,9081)),"@site/docs/dapp/opl/README.md",9081],e2e2c701:[()=>n.e(9116).then(n.bind(n,4723)),"@site/docs/core/consensus/services/keymanager.md",4723],e607d64f:[()=>n.e(7581).then(n.bind(n,1749)),"@site/docs/dapp/sapphire/gasless.md",1749],e6c3daa2:[()=>n.e(3051).then(n.bind(n,247)),"@site/docs/general/manage-tokens/holding-rose-tokens/ledger-wallet.md",247],e6f41e1e:[()=>n.e(2469).then(n.bind(n,4984)),"@site/docs/dapp/sapphire/addresses.md",4984],e6fdf0fb:[()=>n.e(1794).then(n.bind(n,7560)),"@site/docs/node/run-your-node/advanced/install-oasis-remote-signer-binary.md",7560],e793830e:[()=>n.e(3573).then(n.bind(n,2872)),"@site/docs/node/run-your-node/seed-node.md",2872],e9951844:[()=>n.e(4015).then(n.bind(n,6910)),"@site/docs/core/crypto.md",6910],ea8b28d2:[()=>n.e(6561).then(n.bind(n,5192)),"@site/docs/general/manage-tokens/cli/addressbook.md",5192],eb341911:[()=>n.e(2699).then(n.bind(n,8358)),"@site/docs/core/versioning.md",8358],eb677e7b:[()=>n.e(3296).then(n.bind(n,8408)),"@site/docs/general/manage-tokens/oasis-wallets/web.md",8408],efcfca26:[()=>n.e(4736).then(n.bind(n,8857)),"@site/docs/oasis-core-ledger/README.md",8857],f0e2e4ae:[()=>n.e(2709).then(n.bind(n,2967)),"@site/docs/oasis-core-ledger/release-process.md",2967],f33c2266:[()=>n.e(8865).then(n.bind(n,9650)),"@site/docs/general/manage-tokens/oasis-wallets/browser-extension.md",9650],f57ebf67:[()=>n.e(3671).then(n.bind(n,2085)),"@site/docs/node/run-your-node/troubleshooting.md",2085],f8012949:[()=>n.e(2458).then(n.bind(n,7047)),"@site/docs/core/SECURITY.md",7047],f9140bb0:[()=>n.e(1889).then(n.bind(n,339)),"@site/docs/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer.md",339],fb2e2efb:[()=>n.e(7613).then(n.t.bind(n,8411,19)),"~docs/default/category-adrs-category-architectural-decision-records-a99.json",8411],fdfc1f73:[()=>Promise.all([n.e(532),n.e(6228)]).then(n.bind(n,201)),"@site/docs/node/run-your-node/prerequisites/system-configuration.mdx",201],ffcff7f9:[()=>n.e(5954).then(n.bind(n,9882)),"@site/docs/core/oasis-node/cli.md",9882]};function c(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function p(e,t){if("*"===e)return i()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=s[`${e}-${t}`],p={},f=[],m=[],h=(0,u.Z)(o);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=l[n];r&&(p[t]=r[0],f.push(r[1]),m.push(r[2]))})),i().Map({loading:c,loader:p,modules:f,webpack:()=>m,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=a}));const s=i.__comp;delete i.__comp;const l=i.__context;return delete i.__context,r.createElement(d.z,{value:l},r.createElement(s,(0,a.Z)({},i,n)))}})}const f=[{path:"/search",component:p("/search","ae7"),exact:!0},{path:"/",component:p("/","62b"),routes:[{path:"/",component:p("/","1d6"),exact:!0},{path:"/adrs",component:p("/adrs","56d"),exact:!0,sidebar:"adrs"},{path:"/adrs/0001-tm-multi-root-apphash",component:p("/adrs/0001-tm-multi-root-apphash","74f"),exact:!0,sidebar:"adrs"},{path:"/adrs/0002-go-modules-compatible-git-tags",component:p("/adrs/0002-go-modules-compatible-git-tags","09c"),exact:!0,sidebar:"adrs"},{path:"/adrs/0003-consensus-runtime-token-transfer",component:p("/adrs/0003-consensus-runtime-token-transfer","c9f"),exact:!0,sidebar:"adrs"},{path:"/adrs/0004-runtime-governance",component:p("/adrs/0004-runtime-governance","0c0"),exact:!0,sidebar:"adrs"},{path:"/adrs/0005-runtime-compute-slashing",component:p("/adrs/0005-runtime-compute-slashing","933"),exact:!0,sidebar:"adrs"},{path:"/adrs/0006-consensus-governance",component:p("/adrs/0006-consensus-governance","557"),exact:!0,sidebar:"adrs"},{path:"/adrs/0007-improved-random-beacon",component:p("/adrs/0007-improved-random-beacon","084"),exact:!0,sidebar:"adrs"},{path:"/adrs/0008-standard-account-key-generation",component:p("/adrs/0008-standard-account-key-generation","d15"),exact:!0,sidebar:"adrs"},{path:"/adrs/0009-ed25519-semantics",component:p("/adrs/0009-ed25519-semantics","c35"),exact:!0,sidebar:"adrs"},{path:"/adrs/0010-vrf-elections",component:p("/adrs/0010-vrf-elections","c5c"),exact:!0,sidebar:"adrs"},{path:"/adrs/0011-incoming-runtime-messages",component:p("/adrs/0011-incoming-runtime-messages","144"),exact:!0,sidebar:"adrs"},{path:"/adrs/0012-runtime-message-results",component:p("/adrs/0012-runtime-message-results","794"),exact:!0,sidebar:"adrs"},{path:"/adrs/0013-runtime-upgrades",component:p("/adrs/0013-runtime-upgrades","260"),exact:!0,sidebar:"adrs"},{path:"/adrs/0014-runtime-signing-tx-with-hardware-wallet",component:p("/adrs/0014-runtime-signing-tx-with-hardware-wallet","61a"),exact:!0,sidebar:"adrs"},{path:"/adrs/0015-vrf-per-block-entropy",component:p("/adrs/0015-vrf-per-block-entropy","b42"),exact:!0,sidebar:"adrs"},{path:"/adrs/0016-consensus-parameters-change-proposal",component:p("/adrs/0016-consensus-parameters-change-proposal","3cb"),exact:!0,sidebar:"adrs"},{path:"/adrs/0017-app-standards",component:p("/adrs/0017-app-standards","280"),exact:!0,sidebar:"adrs"},{path:"/adrs/0020-governance-delegator-votes",component:p("/adrs/0020-governance-delegator-votes","72f"),exact:!0,sidebar:"adrs"},{path:"/adrs/0021-keymanager-ephemeral-secrets",component:p("/adrs/0021-keymanager-ephemeral-secrets","a6e"),exact:!0,sidebar:"adrs"},{path:"/adrs/0022-keymanager-master-secrets",component:p("/adrs/0022-keymanager-master-secrets","994"),exact:!0,sidebar:"adrs"},{path:"/core/",component:p("/core/","682"),exact:!0,sidebar:"oasisCore"},{path:"/core/authenticated-grpc",component:p("/core/authenticated-grpc","2ba"),exact:!0,sidebar:"oasisCore"},{path:"/core/bigint",component:p("/core/bigint","c71"),exact:!0},{path:"/core/common-functionality",component:p("/core/common-functionality","47b"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/",component:p("/core/consensus/","da3"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/genesis",component:p("/core/consensus/genesis","e8f"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services",component:p("/core/consensus/services","1fd"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/beacon",component:p("/core/consensus/services/beacon","2be"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/epochtime",component:p("/core/consensus/services/epochtime","68a"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/governance",component:p("/core/consensus/services/governance","b23"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/keymanager",component:p("/core/consensus/services/keymanager","ecb"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/registry",component:p("/core/consensus/services/registry","a49"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/roothash",component:p("/core/consensus/services/roothash","b0d"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/scheduler",component:p("/core/consensus/services/scheduler","1f9"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/staking",component:p("/core/consensus/services/staking","ba7"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/test-vectors",component:p("/core/consensus/test-vectors","7e3"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/transactions",component:p("/core/consensus/transactions","abc"),exact:!0,sidebar:"oasisCore"},{path:"/core/crypto",component:p("/core/crypto","389"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup",component:p("/core/development-setup","e97"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/build-environment-setup-and-building",component:p("/core/development-setup/build-environment-setup-and-building","787"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/building",component:p("/core/development-setup/building","d53"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/deploying-a-runtime",component:p("/core/development-setup/deploying-a-runtime","e92"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/oasis-net-runner",component:p("/core/development-setup/oasis-net-runner","ca1"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/prerequisites",component:p("/core/development-setup/prerequisites","478"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/running-tests",component:p("/core/development-setup/running-tests","9b3"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/running-tests-and-development-networks",component:p("/core/development-setup/running-tests-and-development-networks","102"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/single-validator-node-network",component:p("/core/development-setup/single-validator-node-network","aa5"),exact:!0,sidebar:"oasisCore"},{path:"/core/encoding",component:p("/core/encoding","63c"),exact:!0,sidebar:"oasisCore"},{path:"/core/high-level-components",component:p("/core/high-level-components","b70"),exact:!0,sidebar:"oasisCore"},{path:"/core/mkvs",component:p("/core/mkvs","116"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node",component:p("/core/oasis-node","276"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/cli",component:p("/core/oasis-node/cli","60d"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/metrics",component:p("/core/oasis-node/metrics","ef4"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/rpc",component:p("/core/oasis-node/rpc","115"),exact:!0,sidebar:"oasisCore"},{path:"/core/processes",component:p("/core/processes","8e7"),exact:!0,sidebar:"oasisCore"},{path:"/core/release-process",component:p("/core/release-process","aa0"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/",component:p("/core/runtime/","8e4"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/identifiers",component:p("/core/runtime/identifiers","3ee"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/messages",component:p("/core/runtime/messages","4ea"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/runtime-host-protocol",component:p("/core/runtime/runtime-host-protocol","a0c"),exact:!0,sidebar:"oasisCore"},{path:"/core/SECURITY",component:p("/core/SECURITY","b00"),exact:!0,sidebar:"oasisCore"},{path:"/core/versioning",component:p("/core/versioning","cd9"),exact:!0,sidebar:"oasisCore"},{path:"/dapp/",component:p("/dapp/","51e"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/",component:p("/dapp/cipher/","cad"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/confidential-smart-contract",component:p("/dapp/cipher/confidential-smart-contract","738"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/hello-world",component:p("/dapp/cipher/hello-world","f43"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/prerequisites",component:p("/dapp/cipher/prerequisites","936"),exact:!0,sidebar:"developers"},{path:"/dapp/emerald/",component:p("/dapp/emerald/","c99"),exact:!0,sidebar:"developers"},{path:"/dapp/emerald/integrating-band-oracle-smart-contract",component:p("/dapp/emerald/integrating-band-oracle-smart-contract","d2c"),exact:!0,sidebar:"developers"},{path:"/dapp/emerald/writing-dapps-on-emerald",component:p("/dapp/emerald/writing-dapps-on-emerald","05d"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/",component:p("/dapp/opl/","0d8"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/build",component:p("/dapp/opl/build","43b"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/enclave",component:p("/dapp/opl/enclave","3da"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/frontend",component:p("/dapp/opl/frontend","4e4"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/host",component:p("/dapp/opl/host","8eb"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/introduction",component:p("/dapp/opl/introduction","727"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/setup",component:p("/dapp/opl/setup","e95"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/",component:p("/dapp/sapphire/","e08"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/addresses",component:p("/dapp/sapphire/addresses","0e3"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/browser",component:p("/dapp/sapphire/browser","833"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/gasless",component:p("/dapp/sapphire/gasless","69d"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/guide",component:p("/dapp/sapphire/guide","929"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/precompiles",component:p("/dapp/sapphire/precompiles","05e"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/quickstart",component:p("/dapp/sapphire/quickstart","ab1"),exact:!0,sidebar:"developers"},{path:"/general/",component:p("/general/","788"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/",component:p("/general/manage-tokens/","061"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/",component:p("/general/manage-tokens/cli/","9a9"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/account",component:p("/general/manage-tokens/cli/account","1ff"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/addressbook",component:p("/general/manage-tokens/cli/addressbook","79d"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/network",component:p("/general/manage-tokens/cli/network","351"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/paratime",component:p("/general/manage-tokens/cli/paratime","23e"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/setup",component:p("/general/manage-tokens/cli/setup","56c"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/transaction",component:p("/general/manage-tokens/cli/transaction","25e"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/wallet",component:p("/general/manage-tokens/cli/wallet","8fb"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/faq",component:p("/general/manage-tokens/faq","e31"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens",component:p("/general/manage-tokens/holding-rose-tokens","51e"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens/custody-providers",component:p("/general/manage-tokens/holding-rose-tokens/custody-providers","1e7"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",component:p("/general/manage-tokens/holding-rose-tokens/ledger-wallet","8ca"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",component:p("/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","bb7"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/how-to-transfer-rose-into-paratime",component:p("/general/manage-tokens/how-to-transfer-rose-into-paratime","2fb"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets/",component:p("/general/manage-tokens/oasis-wallets/","577"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets/browser-extension",component:p("/general/manage-tokens/oasis-wallets/browser-extension","172"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets/web",component:p("/general/manage-tokens/oasis-wallets/web","d9d"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/staking-and-delegating",component:p("/general/manage-tokens/staking-and-delegating","8da"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/terminology",component:p("/general/manage-tokens/terminology","145"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/",component:p("/general/oasis-network/","e52"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/faq",component:p("/general/oasis-network/faq","b27"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/token-metrics-and-distribution",component:p("/general/oasis-network/token-metrics-and-distribution","b88"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/why-oasis",component:p("/general/oasis-network/why-oasis","166"),exact:!0,sidebar:"general"},{path:"/get-involved/",component:p("/get-involved/","f5b"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/delegation-policy",component:p("/get-involved/delegation-policy","489"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/network-governance",component:p("/get-involved/network-governance","7f8"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/oasis-core",component:p("/get-involved/oasis-core","169"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node",component:p("/get-involved/run-node","a40"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node/paratime-node",component:p("/get-involved/run-node/paratime-node","b88"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node/validator-node",component:p("/get-involved/run-node/validator-node","926"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/token-delivery-and-kyc",component:p("/get-involved/token-delivery-and-kyc","731"),exact:!0,sidebar:"getInvolved"},{path:"/node/",component:p("/node/","036"),exact:!0,sidebar:"operators"},{path:"/node/genesis-doc",component:p("/node/genesis-doc","eb2"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/",component:p("/node/mainnet/","a3b"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/damask-upgrade",component:p("/node/mainnet/damask-upgrade","1ee"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/e-upgrade",component:p("/node/mainnet/e-upgrade","6b7"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades",component:p("/node/mainnet/previous-upgrades","e80"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades/cobalt-upgrade",component:p("/node/mainnet/previous-upgrades/cobalt-upgrade","a0a"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades/mainnet-upgrade",component:p("/node/mainnet/previous-upgrades/mainnet-upgrade","a18"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/upgrade-log",component:p("/node/mainnet/upgrade-log","e14"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node",component:p("/node/run-your-node","32a"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced",component:p("/node/run-your-node/advanced","2c9"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",component:p("/node/run-your-node/advanced/copy-state-from-one-node-to-the-other","d36"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/install-oasis-remote-signer-binary",component:p("/node/run-your-node/advanced/install-oasis-remote-signer-binary","d1a"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/sync-node-using-state-sync",component:p("/node/run-your-node/advanced/sync-node-using-state-sync","b33"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer",component:p("/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer","d57"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/archive-node",component:p("/node/run-your-node/archive-node","efd"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/ias-proxy",component:p("/node/run-your-node/ias-proxy","973"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/",component:p("/node/run-your-node/keymanager-node/","234"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/key-manager-upgrade",component:p("/node/run-your-node/keymanager-node/key-manager-upgrade","b24"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/signing-key-manager-policy",component:p("/node/run-your-node/keymanager-node/signing-key-manager-policy","642"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance",component:p("/node/run-your-node/maintenance","f56"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/adding-or-removing-nodes",component:p("/node/run-your-node/maintenance/adding-or-removing-nodes","1e4"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/handling-network-upgrades",component:p("/node/run-your-node/maintenance/handling-network-upgrades","6c1"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/refreshing-certificates",component:p("/node/run-your-node/maintenance/refreshing-certificates","b80"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/shutting-down-a-node",component:p("/node/run-your-node/maintenance/shutting-down-a-node","cab"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/wiping-node-state",component:p("/node/run-your-node/maintenance/wiping-node-state","2f8"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/non-validator-node",component:p("/node/run-your-node/non-validator-node","91b"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/paratime-client-node",component:p("/node/run-your-node/paratime-client-node","df4"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/paratime-node",component:p("/node/run-your-node/paratime-node","bc6"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites",component:p("/node/run-your-node/prerequisites","051"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/hardware-recommendations",component:p("/node/run-your-node/prerequisites/hardware-recommendations","ed3"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/oasis-node",component:p("/node/run-your-node/prerequisites/oasis-node","5c9"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",component:p("/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","e28"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/stake-requirements",component:p("/node/run-your-node/prerequisites/stake-requirements","964"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/system-configuration",component:p("/node/run-your-node/prerequisites/system-configuration","608"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/seed-node",component:p("/node/run-your-node/seed-node","004"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/sentry-node",component:p("/node/run-your-node/sentry-node","756"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/troubleshooting",component:p("/node/run-your-node/troubleshooting","a35"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/validator-node",component:p("/node/run-your-node/validator-node","ca2"),exact:!0,sidebar:"operators"},{path:"/node/testnet/",component:p("/node/testnet/","7f5"),exact:!0,sidebar:"operators"},{path:"/node/testnet/upgrade-log",component:p("/node/testnet/upgrade-log","c47"),exact:!0,sidebar:"operators"},{path:"/node/web3",component:p("/node/web3","c11"),exact:!0,sidebar:"operators"},{path:"/oasis-core-ledger/",component:p("/oasis-core-ledger/","259"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/release-process",component:p("/oasis-core-ledger/release-process","cc0"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/SUMMARY",component:p("/oasis-core-ledger/SUMMARY","30c"),exact:!0},{path:"/oasis-core-ledger/usage/address",component:p("/oasis-core-ledger/usage/address","c98"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/usage/entity",component:p("/oasis-core-ledger/usage/entity","2dd"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/usage/setup",component:p("/oasis-core-ledger/usage/setup","e1b"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/usage/transactions",component:p("/oasis-core-ledger/usage/transactions","3a1"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/usage/wallets",component:p("/oasis-core-ledger/usage/wallets","d50"),exact:!0,sidebar:"oasisSdk"},{path:"/oasis-core-ledger/versioning",component:p("/oasis-core-ledger/versioning","5e9"),exact:!0,sidebar:"oasisSdk"},{path:"/paratime/",component:p("/paratime/","c84"),exact:!0,sidebar:"paratime"},{path:"/paratime/minimal-runtime",component:p("/paratime/minimal-runtime","4d9"),exact:!0,sidebar:"paratime"},{path:"/paratime/modules",component:p("/paratime/modules","a7a"),exact:!0,sidebar:"paratime"},{path:"/paratime/prerequisites",component:p("/paratime/prerequisites","406"),exact:!0,sidebar:"paratime"},{path:"/paratime/reproducibility",component:p("/paratime/reproducibility","1b1"),exact:!0,sidebar:"paratime"}]},{path:"*",component:p("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),s=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790);function p(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var f=n(7462),m=n(5742),h=n(2263),g=n(4996),b=n(6668),v=n(1944),y=n(4711),k=n(9727),w=n(3320),E=n(197);function x(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,h.Z)(),n=(0,y.l)();return r.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function _(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),a=function(){const{siteConfig:{url:e}}=(0,h.Z)(),{pathname:t}=(0,u.TH)();return e+(0,g.Z)(t)}(),o=t?`${n}${t}`:a;return r.createElement(m.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function S(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,b.L)();return r.createElement(r.Fragment,null,r.createElement(m.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:k.h})),n&&r.createElement(v.d,{image:n}),r.createElement(_,null),r.createElement(x,null),r.createElement(E.Z,{tag:w.HX,locale:e}),r.createElement(m.Z,null,t.map(((e,t)=>r.createElement("meta",(0,f.Z)({key:t},e))))))}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var L=n(8934),A=n(8940);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const R=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:a}),P("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(R,{previousLocation:this.previousLocation,location:t},r.createElement(u.AW,{location:t,render:()=>e}))}}const N=I,M="__docusaurus-base-url-issue-banner-container",D="__docusaurus-base-url-issue-banner",F="__docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function $(e){return`\nwindow['${B}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${B}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${M}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{window[B]=!1}),[]),r.createElement(r.Fragment,null,!s.Z.canUseDOM&&r.createElement(m.Z,null,r.createElement("script",null,$(e))),r.createElement("div",{id:M}))}function z(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?r.createElement(j,null):null}function U(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,h.Z)(),i=(0,g.Z)(e),{htmlLang:s,direction:l}=o[a];return r.createElement(m.Z,null,r.createElement("html",{lang:s,dir:l}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var H=n(4763);function Z(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return r.createElement(H.Z,null,r.createElement(A.M,null,r.createElement(L.t,null,r.createElement(p,null,r.createElement(U,null),r.createElement(S,null),r.createElement(z,null),r.createElement(N,{location:T(t)},e)))))}var q=n(6887);const Q=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var V=n(9670);const W=new Set,G=new Set,Y=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,K={prefetch(e){if(!(e=>!Y()&&!G.has(e)&&!W.has(e))(e))return!1;W.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(q).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,V.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Q(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!Y()&&!G.has(e))(e)&&(G.add(e),O(e))},X=Object.freeze(K);if(s.Z.canUseDOM){window.docusaurus=X;const e=a.hydrate;O(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(Z,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/","mainDocId":"README","docs":[{"id":"adrs/0001-tm-multi-root-apphash","path":"/adrs/0001-tm-multi-root-apphash","sidebar":"adrs"},{"id":"adrs/0002-go-modules-compatible-git-tags","path":"/adrs/0002-go-modules-compatible-git-tags","sidebar":"adrs"},{"id":"adrs/0003-consensus-runtime-token-transfer","path":"/adrs/0003-consensus-runtime-token-transfer","sidebar":"adrs"},{"id":"adrs/0004-runtime-governance","path":"/adrs/0004-runtime-governance","sidebar":"adrs"},{"id":"adrs/0005-runtime-compute-slashing","path":"/adrs/0005-runtime-compute-slashing","sidebar":"adrs"},{"id":"adrs/0006-consensus-governance","path":"/adrs/0006-consensus-governance","sidebar":"adrs"},{"id":"adrs/0007-improved-random-beacon","path":"/adrs/0007-improved-random-beacon","sidebar":"adrs"},{"id":"adrs/0008-standard-account-key-generation","path":"/adrs/0008-standard-account-key-generation","sidebar":"adrs"},{"id":"adrs/0009-ed25519-semantics","path":"/adrs/0009-ed25519-semantics","sidebar":"adrs"},{"id":"adrs/0010-vrf-elections","path":"/adrs/0010-vrf-elections","sidebar":"adrs"},{"id":"adrs/0011-incoming-runtime-messages","path":"/adrs/0011-incoming-runtime-messages","sidebar":"adrs"},{"id":"adrs/0012-runtime-message-results","path":"/adrs/0012-runtime-message-results","sidebar":"adrs"},{"id":"adrs/0013-runtime-upgrades","path":"/adrs/0013-runtime-upgrades","sidebar":"adrs"},{"id":"adrs/0014-runtime-signing-tx-with-hardware-wallet","path":"/adrs/0014-runtime-signing-tx-with-hardware-wallet","sidebar":"adrs"},{"id":"adrs/0015-vrf-per-block-entropy","path":"/adrs/0015-vrf-per-block-entropy","sidebar":"adrs"},{"id":"adrs/0016-consensus-parameters-change-proposal","path":"/adrs/0016-consensus-parameters-change-proposal","sidebar":"adrs"},{"id":"adrs/0017-app-standards","path":"/adrs/0017-app-standards","sidebar":"adrs"},{"id":"adrs/0020-governance-delegator-votes","path":"/adrs/0020-governance-delegator-votes","sidebar":"adrs"},{"id":"adrs/0021-keymanager-ephemeral-secrets","path":"/adrs/0021-keymanager-ephemeral-secrets","sidebar":"adrs"},{"id":"adrs/0022-keymanager-master-secrets","path":"/adrs/0022-keymanager-master-secrets","sidebar":"adrs"},{"id":"core/authenticated-grpc","path":"/core/authenticated-grpc","sidebar":"oasisCore"},{"id":"core/bigint","path":"/core/bigint"},{"id":"core/consensus/genesis","path":"/core/consensus/genesis","sidebar":"oasisCore"},{"id":"core/consensus/README","path":"/core/consensus/","sidebar":"oasisCore"},{"id":"core/consensus/services/beacon","path":"/core/consensus/services/beacon","sidebar":"oasisCore"},{"id":"core/consensus/services/epochtime","path":"/core/consensus/services/epochtime","sidebar":"oasisCore"},{"id":"core/consensus/services/governance","path":"/core/consensus/services/governance","sidebar":"oasisCore"},{"id":"core/consensus/services/keymanager","path":"/core/consensus/services/keymanager","sidebar":"oasisCore"},{"id":"core/consensus/services/registry","path":"/core/consensus/services/registry","sidebar":"oasisCore"},{"id":"core/consensus/services/roothash","path":"/core/consensus/services/roothash","sidebar":"oasisCore"},{"id":"core/consensus/services/scheduler","path":"/core/consensus/services/scheduler","sidebar":"oasisCore"},{"id":"core/consensus/services/staking","path":"/core/consensus/services/staking","sidebar":"oasisCore"},{"id":"core/consensus/test-vectors","path":"/core/consensus/test-vectors","sidebar":"oasisCore"},{"id":"core/consensus/transactions","path":"/core/consensus/transactions","sidebar":"oasisCore"},{"id":"core/crypto","path":"/core/crypto","sidebar":"oasisCore"},{"id":"core/development-setup/building","path":"/core/development-setup/building","sidebar":"oasisCore"},{"id":"core/development-setup/deploying-a-runtime","path":"/core/development-setup/deploying-a-runtime","sidebar":"oasisCore"},{"id":"core/development-setup/oasis-net-runner","path":"/core/development-setup/oasis-net-runner","sidebar":"oasisCore"},{"id":"core/development-setup/prerequisites","path":"/core/development-setup/prerequisites","sidebar":"oasisCore"},{"id":"core/development-setup/running-tests","path":"/core/development-setup/running-tests","sidebar":"oasisCore"},{"id":"core/development-setup/single-validator-node-network","path":"/core/development-setup/single-validator-node-network","sidebar":"oasisCore"},{"id":"core/encoding","path":"/core/encoding","sidebar":"oasisCore"},{"id":"core/mkvs","path":"/core/mkvs","sidebar":"oasisCore"},{"id":"core/oasis-node/cli","path":"/core/oasis-node/cli","sidebar":"oasisCore"},{"id":"core/oasis-node/metrics","path":"/core/oasis-node/metrics","sidebar":"oasisCore"},{"id":"core/oasis-node/rpc","path":"/core/oasis-node/rpc","sidebar":"oasisCore"},{"id":"core/README","path":"/core/","sidebar":"oasisCore"},{"id":"core/release-process","path":"/core/release-process","sidebar":"oasisCore"},{"id":"core/runtime/identifiers","path":"/core/runtime/identifiers","sidebar":"oasisCore"},{"id":"core/runtime/messages","path":"/core/runtime/messages","sidebar":"oasisCore"},{"id":"core/runtime/README","path":"/core/runtime/","sidebar":"oasisCore"},{"id":"core/runtime/runtime-host-protocol","path":"/core/runtime/runtime-host-protocol","sidebar":"oasisCore"},{"id":"core/SECURITY","path":"/core/SECURITY","sidebar":"oasisCore"},{"id":"core/versioning","path":"/core/versioning","sidebar":"oasisCore"},{"id":"dapp/cipher/confidential-smart-contract","path":"/dapp/cipher/confidential-smart-contract","sidebar":"developers"},{"id":"dapp/cipher/hello-world","path":"/dapp/cipher/hello-world","sidebar":"developers"},{"id":"dapp/cipher/prerequisites","path":"/dapp/cipher/prerequisites","sidebar":"developers"},{"id":"dapp/cipher/README","path":"/dapp/cipher/","sidebar":"developers"},{"id":"dapp/emerald/integrating-band-oracle-smart-contract","path":"/dapp/emerald/integrating-band-oracle-smart-contract","sidebar":"developers"},{"id":"dapp/emerald/README","path":"/dapp/emerald/","sidebar":"developers"},{"id":"dapp/emerald/writing-dapps-on-emerald","path":"/dapp/emerald/writing-dapps-on-emerald","sidebar":"developers"},{"id":"dapp/opl/build","path":"/dapp/opl/build","sidebar":"developers"},{"id":"dapp/opl/enclave","path":"/dapp/opl/enclave","sidebar":"developers"},{"id":"dapp/opl/frontend","path":"/dapp/opl/frontend","sidebar":"developers"},{"id":"dapp/opl/host","path":"/dapp/opl/host","sidebar":"developers"},{"id":"dapp/opl/introduction","path":"/dapp/opl/introduction","sidebar":"developers"},{"id":"dapp/opl/README","path":"/dapp/opl/","sidebar":"developers"},{"id":"dapp/opl/setup","path":"/dapp/opl/setup","sidebar":"developers"},{"id":"dapp/README","path":"/dapp/","sidebar":"developers"},{"id":"dapp/sapphire/addresses","path":"/dapp/sapphire/addresses","sidebar":"developers"},{"id":"dapp/sapphire/browser","path":"/dapp/sapphire/browser","sidebar":"developers"},{"id":"dapp/sapphire/gasless","path":"/dapp/sapphire/gasless","sidebar":"developers"},{"id":"dapp/sapphire/guide","path":"/dapp/sapphire/guide","sidebar":"developers"},{"id":"dapp/sapphire/precompiles","path":"/dapp/sapphire/precompiles","sidebar":"developers"},{"id":"dapp/sapphire/quickstart","path":"/dapp/sapphire/quickstart","sidebar":"developers"},{"id":"dapp/sapphire/README","path":"/dapp/sapphire/","sidebar":"developers"},{"id":"general/manage-tokens/cli/account","path":"/general/manage-tokens/cli/account","sidebar":"general"},{"id":"general/manage-tokens/cli/addressbook","path":"/general/manage-tokens/cli/addressbook","sidebar":"general"},{"id":"general/manage-tokens/cli/network","path":"/general/manage-tokens/cli/network","sidebar":"general"},{"id":"general/manage-tokens/cli/paratime","path":"/general/manage-tokens/cli/paratime","sidebar":"general"},{"id":"general/manage-tokens/cli/README","path":"/general/manage-tokens/cli/","sidebar":"general"},{"id":"general/manage-tokens/cli/setup","path":"/general/manage-tokens/cli/setup","sidebar":"general"},{"id":"general/manage-tokens/cli/transaction","path":"/general/manage-tokens/cli/transaction","sidebar":"general"},{"id":"general/manage-tokens/cli/wallet","path":"/general/manage-tokens/cli/wallet","sidebar":"general"},{"id":"general/manage-tokens/faq","path":"/general/manage-tokens/faq","sidebar":"general"},{"id":"general/manage-tokens/holding-rose-tokens/custody-providers","path":"/general/manage-tokens/holding-rose-tokens/custody-providers","sidebar":"general"},{"id":"general/manage-tokens/holding-rose-tokens/ledger-wallet","path":"/general/manage-tokens/holding-rose-tokens/ledger-wallet","sidebar":"general"},{"id":"general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","path":"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","sidebar":"general"},{"id":"general/manage-tokens/how-to-transfer-rose-into-paratime","path":"/general/manage-tokens/how-to-transfer-rose-into-paratime","sidebar":"general"},{"id":"general/manage-tokens/oasis-wallets/browser-extension","path":"/general/manage-tokens/oasis-wallets/browser-extension","sidebar":"general"},{"id":"general/manage-tokens/oasis-wallets/README","path":"/general/manage-tokens/oasis-wallets/","sidebar":"general"},{"id":"general/manage-tokens/oasis-wallets/web","path":"/general/manage-tokens/oasis-wallets/web","sidebar":"general"},{"id":"general/manage-tokens/README","path":"/general/manage-tokens/","sidebar":"general"},{"id":"general/manage-tokens/staking-and-delegating","path":"/general/manage-tokens/staking-and-delegating","sidebar":"general"},{"id":"general/manage-tokens/terminology","path":"/general/manage-tokens/terminology","sidebar":"general"},{"id":"general/oasis-network/faq","path":"/general/oasis-network/faq","sidebar":"general"},{"id":"general/oasis-network/README","path":"/general/oasis-network/","sidebar":"general"},{"id":"general/oasis-network/token-metrics-and-distribution","path":"/general/oasis-network/token-metrics-and-distribution","sidebar":"general"},{"id":"general/oasis-network/why-oasis","path":"/general/oasis-network/why-oasis","sidebar":"general"},{"id":"general/README","path":"/general/","sidebar":"general"},{"id":"get-involved/delegation-policy","path":"/get-involved/delegation-policy","sidebar":"getInvolved"},{"id":"get-involved/network-governance","path":"/get-involved/network-governance","sidebar":"getInvolved"},{"id":"get-involved/oasis-core","path":"/get-involved/oasis-core","sidebar":"getInvolved"},{"id":"get-involved/README","path":"/get-involved/","sidebar":"getInvolved"},{"id":"get-involved/run-node/paratime-node","path":"/get-involved/run-node/paratime-node","sidebar":"getInvolved"},{"id":"get-involved/run-node/validator-node","path":"/get-involved/run-node/validator-node","sidebar":"getInvolved"},{"id":"get-involved/token-delivery-and-kyc","path":"/get-involved/token-delivery-and-kyc","sidebar":"getInvolved"},{"id":"node/genesis-doc","path":"/node/genesis-doc","sidebar":"operators"},{"id":"node/mainnet/damask-upgrade","path":"/node/mainnet/damask-upgrade","sidebar":"operators"},{"id":"node/mainnet/e-upgrade","path":"/node/mainnet/e-upgrade","sidebar":"operators"},{"id":"node/mainnet/previous-upgrades/cobalt-upgrade","path":"/node/mainnet/previous-upgrades/cobalt-upgrade","sidebar":"operators"},{"id":"node/mainnet/previous-upgrades/mainnet-upgrade","path":"/node/mainnet/previous-upgrades/mainnet-upgrade","sidebar":"operators"},{"id":"node/mainnet/README","path":"/node/mainnet/","sidebar":"operators"},{"id":"node/mainnet/upgrade-log","path":"/node/mainnet/upgrade-log","sidebar":"operators"},{"id":"node/README","path":"/node/","sidebar":"operators"},{"id":"node/run-your-node/advanced/copy-state-from-one-node-to-the-other","path":"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other","sidebar":"operators"},{"id":"node/run-your-node/advanced/install-oasis-remote-signer-binary","path":"/node/run-your-node/advanced/install-oasis-remote-signer-binary","sidebar":"operators"},{"id":"node/run-your-node/advanced/sync-node-using-state-sync","path":"/node/run-your-node/advanced/sync-node-using-state-sync","sidebar":"operators"},{"id":"node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer","path":"/node/run-your-node/advanced/using-ledger-backed-consensus-key-with-a-remote-signer","sidebar":"operators"},{"id":"node/run-your-node/archive-node","path":"/node/run-your-node/archive-node","sidebar":"operators"},{"id":"node/run-your-node/ias-proxy","path":"/node/run-your-node/ias-proxy","sidebar":"operators"},{"id":"node/run-your-node/keymanager-node/key-manager-upgrade","path":"/node/run-your-node/keymanager-node/key-manager-upgrade","sidebar":"operators"},{"id":"node/run-your-node/keymanager-node/README","path":"/node/run-your-node/keymanager-node/","sidebar":"operators"},{"id":"node/run-your-node/keymanager-node/signing-key-manager-policy","path":"/node/run-your-node/keymanager-node/signing-key-manager-policy","sidebar":"operators"},{"id":"node/run-your-node/maintenance/adding-or-removing-nodes","path":"/node/run-your-node/maintenance/adding-or-removing-nodes","sidebar":"operators"},{"id":"node/run-your-node/maintenance/handling-network-upgrades","path":"/node/run-your-node/maintenance/handling-network-upgrades","sidebar":"operators"},{"id":"node/run-your-node/maintenance/refreshing-certificates","path":"/node/run-your-node/maintenance/refreshing-certificates","sidebar":"operators"},{"id":"node/run-your-node/maintenance/shutting-down-a-node","path":"/node/run-your-node/maintenance/shutting-down-a-node","sidebar":"operators"},{"id":"node/run-your-node/maintenance/wiping-node-state","path":"/node/run-your-node/maintenance/wiping-node-state","sidebar":"operators"},{"id":"node/run-your-node/non-validator-node","path":"/node/run-your-node/non-validator-node","sidebar":"operators"},{"id":"node/run-your-node/paratime-client-node","path":"/node/run-your-node/paratime-client-node","sidebar":"operators"},{"id":"node/run-your-node/paratime-node","path":"/node/run-your-node/paratime-node","sidebar":"operators"},{"id":"node/run-your-node/prerequisites/hardware-recommendations","path":"/node/run-your-node/prerequisites/hardware-recommendations","sidebar":"operators"},{"id":"node/run-your-node/prerequisites/oasis-node","path":"/node/run-your-node/prerequisites/oasis-node","sidebar":"operators"},{"id":"node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","path":"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","sidebar":"operators"},{"id":"node/run-your-node/prerequisites/stake-requirements","path":"/node/run-your-node/prerequisites/stake-requirements","sidebar":"operators"},{"id":"node/run-your-node/prerequisites/system-configuration","path":"/node/run-your-node/prerequisites/system-configuration","sidebar":"operators"},{"id":"node/run-your-node/seed-node","path":"/node/run-your-node/seed-node","sidebar":"operators"},{"id":"node/run-your-node/sentry-node","path":"/node/run-your-node/sentry-node","sidebar":"operators"},{"id":"node/run-your-node/troubleshooting","path":"/node/run-your-node/troubleshooting","sidebar":"operators"},{"id":"node/run-your-node/validator-node","path":"/node/run-your-node/validator-node","sidebar":"operators"},{"id":"node/testnet/README","path":"/node/testnet/","sidebar":"operators"},{"id":"node/testnet/upgrade-log","path":"/node/testnet/upgrade-log","sidebar":"operators"},{"id":"node/web3","path":"/node/web3","sidebar":"operators"},{"id":"oasis-core-ledger/README","path":"/oasis-core-ledger/","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/release-process","path":"/oasis-core-ledger/release-process","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/SUMMARY","path":"/oasis-core-ledger/SUMMARY"},{"id":"oasis-core-ledger/usage/address","path":"/oasis-core-ledger/usage/address","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/usage/entity","path":"/oasis-core-ledger/usage/entity","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/usage/setup","path":"/oasis-core-ledger/usage/setup","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/usage/transactions","path":"/oasis-core-ledger/usage/transactions","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/usage/wallets","path":"/oasis-core-ledger/usage/wallets","sidebar":"oasisSdk"},{"id":"oasis-core-ledger/versioning","path":"/oasis-core-ledger/versioning","sidebar":"oasisSdk"},{"id":"paratime/minimal-runtime","path":"/paratime/minimal-runtime","sidebar":"paratime"},{"id":"paratime/modules","path":"/paratime/modules","sidebar":"paratime"},{"id":"paratime/prerequisites","path":"/paratime/prerequisites","sidebar":"paratime"},{"id":"paratime/README","path":"/paratime/","sidebar":"paratime"},{"id":"paratime/reproducibility","path":"/paratime/reproducibility","sidebar":"paratime"},{"id":"README","path":"/"},{"id":"general/manage-tokens/holding-rose-tokens","path":"/general/manage-tokens/holding-rose-tokens","sidebar":"general"},{"id":"node/mainnet/previous-upgrades","path":"/node/mainnet/previous-upgrades","sidebar":"operators"},{"id":"node/run-your-node","path":"/node/run-your-node","sidebar":"operators"},{"id":"node/run-your-node/prerequisites","path":"/node/run-your-node/prerequisites","sidebar":"operators"},{"id":"node/run-your-node/maintenance","path":"/node/run-your-node/maintenance","sidebar":"operators"},{"id":"node/run-your-node/advanced","path":"/node/run-your-node/advanced","sidebar":"operators"},{"id":"core/development-setup","path":"/core/development-setup","sidebar":"oasisCore"},{"id":"core/development-setup/build-environment-setup-and-building","path":"/core/development-setup/build-environment-setup-and-building","sidebar":"oasisCore"},{"id":"core/development-setup/running-tests-and-development-networks","path":"/core/development-setup/running-tests-and-development-networks","sidebar":"oasisCore"},{"id":"core/high-level-components","path":"/core/high-level-components","sidebar":"oasisCore"},{"id":"core/consensus/services","path":"/core/consensus/services","sidebar":"oasisCore"},{"id":"core/oasis-node","path":"/core/oasis-node","sidebar":"oasisCore"},{"id":"core/common-functionality","path":"/core/common-functionality","sidebar":"oasisCore"},{"id":"core/processes","path":"/core/processes","sidebar":"oasisCore"},{"id":"/adrs","path":"/adrs","sidebar":"adrs"},{"id":"get-involved/run-node","path":"/get-involved/run-node","sidebar":"getInvolved"}],"draftIds":[],"sidebars":{"general":{"link":{"path":"/general/","label":"Overview"}},"operators":{"link":{"path":"/node/","label":"Overview"}},"developers":{"link":{"path":"/dapp/","label":"Overview"}},"paratime":{"link":{"path":"/paratime/","label":"Overview"}},"oasisCore":{"link":{"path":"/core/","label":"Overview"}},"oasisSdk":{"link":{"path":"/oasis-core-ledger/","label":"Introduction to Oasis Core Ledger"}},"adrs":{"link":{"path":"/adrs","label":"Architectural Decision Records"}},"getInvolved":{"link":{"path":"/get-involved/","label":"get-involved/README"}}}}],"breadcrumbs":false}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.4.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.4.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.1"},"webpack-configuration-plugin":{"type":"local"},"docusaurus-plugin-client-redirects":{"type":"package","name":"@docusaurus/plugin-client-redirects","version":"2.4.1"},"@easyops-cn/docusaurus-search-local":{"type":"package","name":"@easyops-cn/docusaurus-search-local","version":"0.34.0"}}}'),c={siteConfig:a.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},u=r.createContext(c);function d(e){let{children:t}=e;return r.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7294),a=n(412),o=n(5742),i=n(8780),s=n(179);function l(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},r.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),r.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),r.createElement(c,{error:t}))}function c(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function u(e){let{error:t,tryAgain:n}=e;return r.createElement(p,{fallback:()=>r.createElement(l,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(s.Z,null,r.createElement(l,{error:t,tryAgain:n})))}const d=e=>r.createElement(u,e);class p extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??d)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),s=n(2263),l=n(3919),c=n(412);const u=a.createContext({collectLink:()=>{}});var d=n(4996);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":g,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:k}}=(0,s.Z)(),{withBaseUrl:w}=(0,d.C)(),E=(0,a.useContext)(u),x=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>x.current));const _=p||f;const S=(0,l.Z)(_),C=_?.replace("pathname://","");let T=void 0!==C?(L=C,b&&(e=>e.startsWith("/"))(L)?w(L):L):void 0;var L;T&&S&&(T=(0,i.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:k}));const A=(0,a.useRef)(!1),P=n?o.OL:o.rU,R=c.Z.canUseIntersectionObserver,O=(0,a.useRef)(),I=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,a.useEffect)((()=>(!R&&S&&null!=T&&window.docusaurus.prefetch(T),()=>{R&&O.current&&O.current.disconnect()})),[O,T,R,S]);const N=T?.startsWith("#")??!1,M=!T||!S||N;return M||g||E.collectLink(T),M?a.createElement("a",(0,r.Z)({ref:x,href:T},_&&!S&&{target:"_blank",rel:"noopener noreferrer"},v)):a.createElement(P,(0,r.Z)({},v,{onMouseEnter:I,onTouchStart:I,innerRef:e=>{x.current=e,R&&e&&S&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),O.current.observe(e))},to:T},n&&{isActive:h,activeClassName:m}))}const f=a.forwardRef(p)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>s});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const s=i({message:t,id:n});return r.createElement(r.Fragment,null,a(s,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){const t={};return function e(n,a){Object.entries(n).forEach((n=>{let[o,i]=n;const s=a?`${a}.${o}`:o;r(i)?e(i,s):t[s]=i}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>h,gA:()=>p,_r:()=>u,Jo:()=>g,zh:()=>d,yW:()=>m,gB:()=>f});var r=n(6550),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=function(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const c={},u=()=>i("docusaurus-plugin-content-docs")??c,d=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e),a=r?.[t];if(!a&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=u(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function f(e){return d(e).versions}function m(e){const t=d(e);return s(t)}function h(e){const t=d(e),{pathname:n}=(0,r.TH)();return l(t,n)}function g(e){const t=d(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(4891)(`./prism-${e}`)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a={iconExternalLink:"iconExternalLink_nPIU"};function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a.iconExternalLink},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},179:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Ot});var r=n(7294),a=n(6010),o=n(4763),i=n(1944),s=n(7462),l=n(6550),c=n(5999),u=n(5936);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,l.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,u.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:a}=f();return r.createElement("div",{ref:n,role:"region","aria-label":m},r.createElement("a",(0,s.Z)({},e,{href:`#${d}`,onClick:a}),t))}var g=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return r.createElement(h,{className:v.skipToContent})}var k=n(6668),w=n(9689);function E(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 15 15",width:t,height:n},l),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const x={closeButton:"closeButton_CVFx"};function _(e){return r.createElement("button",(0,s.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",x.closeButton,e.className)}),r.createElement(E,{width:14,height:14,strokeWidth:3.1}))}const S={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,k.L)(),{content:n}=t;return r.createElement("div",(0,s.Z)({},e,{className:(0,a.Z)(S.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function L(){const{announcementBar:e}=(0,k.L)(),{isActive:t,close:n}=(0,w.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T.announcementBar,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:T.announcementBarPlaceholder}),r.createElement(C,{className:T.announcementBarContent}),i&&r.createElement(_,{onClick:n,className:T.announcementBarClose}))}var A=n(3163),P=n(2466);var R=n(902),O=n(3102);const I=r.createContext(null);function N(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,O.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,R.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(I.Provider,{value:n},t)}function M(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function D(){const e=(0,r.useContext)(I);if(!e)throw new R.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,O.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:M(o)})),[a,o,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=D();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var B=n(2949),$=n(2389);function j(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function z(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:o,onChange:i}=e;const s=(0,$.Z)(),l=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)(U.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",U.toggleButton,!s&&U.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===o?"light":"dark"),disabled:!s,title:l,"aria-label":l,"aria-live":"polite"},r.createElement(j,{className:(0,a.Z)(U.toggleIcon,U.lightToggleIcon)}),r.createElement(z,{className:(0,a.Z)(U.toggleIcon,U.darkToggleIcon)})))}const Z=r.memo(H),q={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function Q(e){let{className:t}=e;const n=(0,k.L)().navbar.style,a=(0,k.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:i}=(0,B.I)();return a?null:r.createElement(Z,{className:t,buttonClassName:"dark"===n?q.darkNavbarColorModeToggle:void 0,value:o,onChange:i})}var V=n(1327);function W(){return r.createElement(V.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function G(){const e=(0,A.e)();return r.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(E,{color:"var(--ifm-color-emphasis-600)"}))}function Y(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(W,null),r.createElement(Q,{className:"margin-right--md"}),r.createElement(G,null))}var K=n(9960),X=n(4996),J=n(3919);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const p=(0,X.Z)(a),f=(0,X.Z)(t),m=(0,X.Z)(o,{forcePrependBaseUrl:!0}),h=i&&o&&!(0,J.Z)(o),g=l?{dangerouslySetInnerHTML:{__html:l}}:{children:r.createElement(r.Fragment,null,i,h&&r.createElement(te.Z,c&&{width:12,height:12}))};return o?r.createElement(K.Z,(0,s.Z)({href:u?m:o},d,g)):r.createElement(K.Z,(0,s.Z)({to:p,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(f)},d,g))}function re(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(ne,(0,s.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function ae(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(ne,(0,s.Z)({className:(0,a.Z)("menu__link",t)},o)))}function oe(e){let{mobile:t=!1,position:n,...a}=e;const o=t?ae:re;return r.createElement(o,(0,s.Z)({},a,{activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var ie=n(6043),se=n(8596),le=n(2263);function ce(e,t){return e.some((e=>function(e,t){return!!(0,se.Mg)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:i,...l}=e;const c=(0,r.useRef)(null),[u,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),r.createElement("div",{ref:c,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},r.createElement(ne,(0,s.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,a.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),r.createElement("ul",{className:"dropdown__menu"},t.map(((e,t)=>r.createElement(qe,(0,s.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function de(e){let{items:t,className:n,position:o,onClick:i,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=ce(t,u),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[u,d,m]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":p})},r.createElement(ne,(0,s.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),f()}}),c.children??c.label),r.createElement(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p},t.map(((e,t)=>r.createElement(qe,(0,s.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function pe(e){let{mobile:t=!1,...n}=e;const a=t?de:ue;return r.createElement(a,n)}var fe=n(4711);function me(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const he="iconLanguage_nlXk";var ge=n(1029),be=n(412),ve=n(373),ye=n(143),ke=n(22),we=n(8202),Ee=n(3926),xe=n(1073),_e=n(2539),Se=n(726);const Ce='',Te='',Le='',Ae='',Pe='',Re='',Oe='',Ie={searchBar:"searchBar_RVTs",dropdownMenu:"dropdownMenu_qbY6",searchBarLeft:"searchBarLeft_MXDe",suggestion:"suggestion_fB_2",cursor:"cursor_eG29",hitTree:"hitTree_kk6K",hitIcon:"hitIcon_a7Zy",hitPath:"hitPath_ieM4",noResultsIcon:"noResultsIcon_EBY5",hitFooter:"hitFooter_E9YW",hitWrapper:"hitWrapper_sAK8",hitTitle:"hitTitle_vyVt",hitAction:"hitAction_NqkB",hideAction:"hideAction_vcyE",noResults:"noResults_l6Q3",searchBarContainer:"searchBarContainer_NW3z",searchBarLoadingRing:"searchBarLoadingRing_YnHq",searchClearButton:"searchClearButton_qk4g",searchIndexLoading:"searchIndexLoading_EJ1f",searchHintContainer:"searchHintContainer_Pkmr",searchHint:"searchHint_iIMx",focused:"focused_OWtg",input:"input_FOTf",hint:"hint_URu1",suggestions:"suggestions_X8XU",dataset:"dataset_QiCy",empty:"empty_eITn"};function Ne(e){let{document:t,type:n,page:r,metadata:a,tokens:o,isInterOfTree:i,isLastOfTree:s}=e;const l=0===n,c=1===n,u=[];i?u.push(Re):s&&u.push(Oe);const d=u.map((e=>`${e}`)),p=`${l?Ce:c?Te:Le}`,f=[`${(0,Se.o)(t.t,(0,xe.m)(a,"t"),o)}`];if(!i&&!s&&ge.H6){const e=r?(r.b??[]).concat(r.t).concat(t.s&&t.s!==r.t?t.s:[]):t.b;f.push(`${(0,Ee.e)(e??[])}`)}else l||f.push(`${(0,_e.C)(r.t||(t.u.startsWith("/docs/api-reference/")?"API Reference":""),o)}`);const m=`${Ae}`;return[...d,p,``,...f,"",m].join("")}function Me(){return`${Pe}${(0,c.I)({id:"theme.SearchBar.noResultsText",message:"No results"})}`}var De=n(311);async function Fe(){const e=await Promise.all([n.e(8443),n.e(5525)]).then(n.t.bind(n,8443,23)),t=e.default;return t.noConflict?t.noConflict():e.noConflict&&e.noConflict(),t}const Be="_highlight";const $e=function(e){let{handleSearchBarToggle:t}=e;const{siteConfig:{baseUrl:n}}=(0,le.Z)(),o=(0,ye.gA)();let i=n;try{const{preferredVersion:e}=(0,ve.J)(o?.pluginId??ge.gQ);e&&!e.isLast&&(i=e.path+"/")}catch(M){if(ge.l9&&!(M instanceof R.i6))throw M}const s=(0,l.k6)(),u=(0,l.TH)(),d=(0,r.useRef)(null),p=(0,r.useRef)(new Map),f=(0,r.useRef)(!1),[m,h]=(0,r.useState)(!1),[g,b]=(0,r.useState)(!1),[v,y]=(0,r.useState)(""),k=(0,r.useRef)(null),w=(0,r.useRef)(""),[E,x]=(0,r.useState)("");(0,r.useEffect)((()=>{if(!Array.isArray(ge.Kc))return;let e="";if(u.pathname.startsWith(i)){const t=u.pathname.substring(i.length),n=ge.Kc.find((e=>t===e||t.startsWith(`${e}/`)));n&&(e=n)}w.current!==e&&(p.current.delete(e),w.current=e),x(e)}),[u.pathname,i]);const _=!!ge.hG&&Array.isArray(ge.Kc)&&""===E,S=(0,r.useCallback)((async()=>{if(_||p.current.get(E))return;p.current.set(E,"loading"),k.current?.autocomplete.destroy(),h(!0);const[{wrappedIndexes:e,zhDictionary:t},r]=await Promise.all([(0,ke.w)(i,E),Fe()]);if(k.current=r(d.current,{hint:!1,autoselect:!0,openOnFocus:!0,cssClasses:{root:(0,a.Z)(Ie.searchBar,{[Ie.searchBarLeft]:"left"===ge.pu}),noPrefix:!0,dropdownMenu:Ie.dropdownMenu,input:Ie.input,hint:Ie.hint,suggestions:Ie.suggestions,suggestion:Ie.suggestion,cursor:Ie.cursor,dataset:Ie.dataset,empty:Ie.empty}},[{source:(0,we.v)(e,t,ge.qo),templates:{suggestion:Ne,empty:Me,footer:e=>{let{query:t,isEmpty:r}=e;if(r)return;const a=document.createElement("a"),o=new URLSearchParams;if(o.set("q",t),Array.isArray(ge.Kc)&&o.set("ctx",E),i!==n){if(!i.startsWith(n))throw new Error(`Version url '${i}' does not start with base url '${n}', this is a bug of \`@easyops-cn/docusaurus-search-local\`, please report it.`);o.set("version",i.substring(n.length))}const l=`${n}search?${o.toString()}`;a.href=l,a.textContent=E?(0,c.I)({id:"theme.SearchBar.searchInContext",message:"See all results in {context}"},{context:E}):(0,c.I)({id:"theme.SearchBar.seeAll",message:"See all results"}),a.addEventListener("click",(e=>{e.ctrlKey||e.metaKey||(e.preventDefault(),k.current?.autocomplete.close(),s.push(l))}));const u=document.createElement("div");return u.className=Ie.hitFooter,u.appendChild(a),u}}}]).on("autocomplete:selected",(function(e,t){let{document:{u:n,h:r},tokens:a}=t;d.current?.blur();let o=n;if(ge.vc&&a.length>0){const e=new URLSearchParams;for(const t of a)e.append(Be,t);o+=`?${e.toString()}`}r&&(o+=r),s.push(o)})).on("autocomplete:closed",(()=>{d.current?.blur()})),p.current.set(E,"done"),h(!1),f.current){const e=d.current;e.value&&k.current?.autocomplete.open(),e.focus()}}),[_,E,i,n,s]);(0,r.useEffect)((()=>{if(!ge.vc)return;const e=be.Z.canUseDOM?new URLSearchParams(u.search).getAll(Be):[];setTimeout((()=>{const t=document.querySelector("article");if(!t)return;const n=new ge.vc(t);n.unmark(),0!==e.length&&n.mark(e),y(e.join(" ")),k.current?.autocomplete.setVal(e.join(" "))}))}),[u.search,u.pathname]);const[C,T]=(0,r.useState)(!1),L=(0,r.useCallback)((()=>{f.current=!0,S(),T(!0),t?.(!0)}),[t,S]),A=(0,r.useCallback)((()=>{T(!1),t?.(!1)}),[t]),P=(0,r.useCallback)((()=>{S()}),[S]),O=(0,r.useCallback)((e=>{y(e.target.value),e.target.value&&b(!0)}),[]),I=!!be.Z.canUseDOM&&/mac/i.test(navigator.userAgentData?.platform??navigator.platform);(0,r.useEffect)((()=>{if(!ge.AY)return;const e=e=>{!(I?e.metaKey:e.ctrlKey)||"k"!==e.key&&"K"!==e.key||(e.preventDefault(),d.current?.focus(),L())};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}}),[I,L]);const N=(0,r.useCallback)((()=>{const e=new URLSearchParams(u.search);e.delete(Be);const t=e.toString(),n=u.pathname+(""!=t?`?${t}`:"")+u.hash;n!=u.pathname+u.search+u.hash&&s.push(n),y(""),k.current?.autocomplete.setVal("")}),[u.pathname,u.search,u.hash,s]);return r.createElement("div",{className:(0,a.Z)("navbar__search",Ie.searchBarContainer,{[Ie.searchIndexLoading]:m&&g,[Ie.focused]:C}),hidden:_},r.createElement("input",{placeholder:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),"aria-label":"Search",className:"navbar__search-input",onMouseEnter:P,onFocus:L,onBlur:A,onChange:O,ref:d,value:v}),r.createElement(De.Z,{className:Ie.searchBarLoadingRing}),ge.AY&&ge.t_&&(""!==v?r.createElement("button",{className:Ie.searchClearButton,onClick:N},"\u2715"):be.Z.canUseDOM&&r.createElement("div",{className:Ie.searchHintContainer},r.createElement("kbd",{className:Ie.searchHint},I?"\u2318":"ctrl"),r.createElement("kbd",{className:Ie.searchHint},"K"))))},je={searchBox:"searchBox_ZlJk"};function ze(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,je.searchBox)},t)}var Ue=n(3438);const He=e=>e.docs.find((t=>t.id===e.mainDocId));const Ze={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:u,localeConfigs:d}}=(0,le.Z)(),p=(0,fe.l)(),{search:f,hash:m}=(0,l.TH)(),h=[...n,...u.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],g=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(pe,(0,s.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(me,{className:he}),g),items:h}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(ze,{className:n},r.createElement($e,null))},dropdown:pe,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return r.createElement(s,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ye.Iw)(a),l=(0,Ue.vY)(t,a);return null===l?null:r.createElement(oe,(0,s.Z)({exact:!0},o,{isActive:()=>i?.path===l.path||!!i?.sidebar&&i.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ye.Iw)(a),l=(0,Ue.oz)(t,a).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return r.createElement(oe,(0,s.Z)({exact:!0},o,{isActive:()=>i?.sidebar===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,Ue.lO)(a)[0],l=t??i.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(oe,(0,s.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...u}=e;const{search:d,hash:p}=(0,l.TH)(),f=(0,ye.Iw)(n),m=(0,ye.gB)(n),{savePreferredVersionName:h}=(0,ve.J)(n),g=[...o,...m.map((e=>{const t=f.alternateDocVersions[e.name]??He(e);return{label:e.label,to:`${t.path}${d}${p}`,isActive:()=>e===f.activeVersion,onClick:()=>h(e.name)}})),...i],b=(0,Ue.lO)(n)[0],v=t&&g.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&g.length>1?void 0:He(b).path;return g.length<=1?r.createElement(oe,(0,s.Z)({},u,{mobile:t,label:v,to:y,isActive:a?()=>!1:void 0})):r.createElement(pe,(0,s.Z)({},u,{mobile:t,label:v,to:y,items:g,isActive:a?()=>!1:void 0}))}};function qe(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ze[a];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(o,n)}function Qe(){const e=(0,A.e)(),t=(0,k.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(qe,(0,s.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ve(e){return r.createElement("button",(0,s.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function We(){const e=0===(0,k.L)().navbar.items.length,t=D();return r.createElement(r.Fragment,null,!e&&r.createElement(Ve,{onClick:()=>t.hide()}),t.content)}function Ge(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(F,{header:r.createElement(Y,null),primaryMenu:r.createElement(Qe,null),secondaryMenu:r.createElement(We,null)}):null}const Ye={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Ke(e){return r.createElement("div",(0,s.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function Xe(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,k.L)(),i=(0,A.e)(),{navbarRef:s,isNavbarVisible:l}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,P.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:s,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Ye.navbarHideable,!l&&Ye.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Ke,{onClick:i.toggle}),r.createElement(Ge,null))}var Je=n(8780);const et={errorBoundaryError:"errorBoundaryError_a6uf"};function tt(e){return r.createElement("button",(0,s.Z)({type:"button"},e),r.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function nt(e){let{error:t}=e;const n=(0,Je.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{className:et.errorBoundaryError},n)}class rt extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const at="right";function ot(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,s.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function it(){const{toggle:e,shown:t}=(0,A.e)();return r.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(ot,null))}const st={colorModeToggle:"colorModeToggle_DEke"};function lt(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(rt,{key:t,onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t})},r.createElement(qe,e)))))}function ct(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function ut(){const e=(0,A.e)(),t=(0,k.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??at)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(ct,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(it,null),r.createElement(W,null),r.createElement(lt,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(lt,{items:a}),r.createElement(Q,{className:st.colorModeToggle}),!o&&r.createElement(ze,null,r.createElement($e,null)))})}function dt(){return r.createElement(Xe,null,r.createElement(ut,null))}function pt(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...l}=t,c=(0,X.Z)(n),u=(0,X.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(K.Z,(0,s.Z)({className:"footer__link-item"},a?{href:i?u:a}:{to:c},l),o,a&&!(0,J.Z)(a)&&r.createElement(te.Z,null))}function ft(e){let{item:t}=e;return t.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement("li",{key:t.href??t.to,className:"footer__item"},r.createElement(pt,{item:t}))}function mt(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(ft,{key:t,item:e})))))}function ht(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(mt,{key:t,column:e}))))}function gt(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function bt(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(pt,{item:t})}function vt(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(bt,{item:e}),t.length!==n+1&&r.createElement(gt,null))))))}function yt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(ht,{columns:t}):r.createElement(vt,{links:t})}var kt=n(941);const wt={footerLogoLink:"footerLogoLink_BH7S"};function Et(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(kt.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function xt(e){let{logo:t}=e;return t.href?r.createElement(K.Z,{href:t.href,className:wt.footerLogoLink,target:t.target},r.createElement(Et,{logo:t})):r.createElement(Et,{logo:t})}function _t(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function St(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--center"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function Ct(){const{footer:e}=(0,k.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(St,{style:o,links:n&&n.length>0&&r.createElement(yt,{links:n}),logo:a&&r.createElement(xt,{logo:a}),copyright:t&&r.createElement(_t,{copyright:t})})}const Tt=r.memo(Ct),Lt=(0,R.Qc)([B.S,w.pl,P.OC,ve.L5,i.VC,function(e){let{children:t}=e;return r.createElement(O.n2,null,r.createElement(A.M,null,r.createElement(N,null,t)))}]);function At(e){let{children:t}=e;return r.createElement(Lt,null,t)}function Pt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("div",{className:"margin-vert--lg"},r.createElement(tt,{onClick:n,className:"button button--primary shadow--lw"})),r.createElement("hr",null),r.createElement("div",{className:"margin-vert--md"},r.createElement(nt,{error:t})))))}const Rt={mainWrapper:"mainWrapper_z2l0"};function Ot(e){const{children:t,noFooter:n,wrapperClassName:s,title:l,description:c}=e;return(0,b.t)(),r.createElement(At,null,r.createElement(i.d,{title:l,description:c}),r.createElement(y,null),r.createElement(L,null),r.createElement(dt,null),r.createElement("div",{id:d,className:(0,a.Z)(g.k.wrapper.main,Rt.mainWrapper,s)},r.createElement(o.Z,{fallback:e=>r.createElement(Pt,e)},t)),!n&&r.createElement(Tt,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),s=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},s=a.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},s):s}function d(e){const{siteConfig:{title:t}}=(0,s.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:p,...f}=e,m=(0,i.Z)(c?.href||"/"),h=n?"":t,g=c?.alt??h;return a.createElement(o.Z,(0,r.Z)({to:m},f,c?.target&&{target:c.target}),c&&a.createElement(u,{logo:c,alt:g,imageClassName:d}),null!=n&&a.createElement("b",{className:p},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7462),a=n(7294),o=n(6010),i=n(2389),s=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,i.Z)(),{colorMode:n}=(0,s.I)(),{sources:c,className:u,alt:d,...p}=e,f=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,f.map((e=>a.createElement("img",(0,r.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},p)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>l,z:()=>g});var r=n(7462),a=n(7294),o=n(412),i=n(1442);const s="ease-in-out";function l(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const c={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function d(e,t){const n=t?c:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function p(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=r?.duration??function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??s}`,height:`${t}px`}}function l(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return d(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=c.height,e.style.overflow=c.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function f(e){if(!o.Z.canUseDOM)return e?c:u}function m(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const c=(0,a.useRef)(null);return p({collapsibleRef:c,collapsed:n,animation:o}),a.createElement(t,{ref:c,style:l?void 0:f(n),onTransitionEnd:e=>{"height"===e.propertyName&&(d(c.current,n),i?.(n))},className:s},r)}function h(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[s,l]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?a.createElement(m,(0,r.Z)({},n,{collapsed:s})):null}function g(e){let{lazy:t,...n}=e;const r=t?h:m;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>f});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),p=r.createContext(null);function f(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&u()));(0,r.useEffect)((()=>{o(u())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;c.set(t),r&&d(!1),!r&&u()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(p.Provider,{value:n},t)}function m(){const e=(0,r.useContext)(p);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>g,S:()=>h});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668);const l=r.createContext(void 0),c="theme",u=(0,i.WA)(c),d={light:"light",dark:"dark"},p=e=>e===d.dark?d.dark:d.light,f=e=>a.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e),m=e=>{u.set(p(e))};function h(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[a,o]=(0,r.useState)(f(e));(0,r.useEffect)((()=>{t&&u.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(o(t),a&&m(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?d.dark:d.light:e),u.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(a))}),[a]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&i(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:a,setColorMode:i,get isDarkTheme(){return a===d.dark},setLightTheme(){i(d.light)},setDarkTheme(){i(d.dark)}})),[a,i])}();return r.createElement(l.Provider,{value:n},t)}function g(){const e=(0,r.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>g});var r=n(7294),a=n(143),o=n(9935),i=n(6668),s=n(3438),l=n(902),c=n(12);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()}},p=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const f=r.createContext(null);function m(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>p(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function h(e){let{children:t}=e;const n=m();return r.createElement(f.Provider,{value:n},t)}function g(e){let{children:t}=e;return s.cE?r.createElement(h,null,t):r.createElement(r.Fragment,null,t)}function b(){const e=(0,r.useContext)(f);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=b(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>s});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function s(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function l(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>s,q:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t,version:n}=e;return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(null===e)throw new a.i6("DocsVersionProvider");return e}},3163:(e,t,n)=>{"use strict";n.d(t,{M:()=>d,e:()=>p});var r=n(7294),a=n(3102),o=n(7524),i=n(1980),s=n(6668),l=n(902);const c=r.createContext(void 0);function u(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function d(e){let{children:t}=e;const n=u();return r.createElement(c.Provider,{value:n},t)}function p(){const e=r.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>s,Zo:()=>l,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=i,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var r=n(7294),a=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(){return a.Z.canUseDOM?window.innerWidth>i?o.desktop:o.mobile:o.ssr}const l=!1;function c(){const[e,t]=(0,r.useState)((()=>l?"ssr":s()));return(0,r.useEffect)((()=>{function e(){t(s())}const n=l?window.setTimeout(e,1e3):void 0;return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(n)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},1442:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},3438:(e,t,n)=>{"use strict";n.d(t,{MN:()=>S,Wl:()=>m,_F:()=>v,cE:()=>p,hI:()=>_,jA:()=>h,lO:()=>w,oz:()=>E,s1:()=>k,vY:()=>x,xz:()=>f});var r=n(7294),a=n(6550),o=n(8790),i=n(143),s=n(373),l=n(4477),c=n(1116),u=n(7392),d=n(8596);const p=!!i._r;function f(e){const t=(0,l.E)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function m(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=m(t);if(e)return e}}}function h(){const{pathname:e}=(0,a.TH)(),t=(0,c.V)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=y({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const g=(e,t)=>void 0!==e&&(0,d.Mg)(e,t),b=(e,t)=>e.some((e=>v(e,t)));function v(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||b(e.items,t))}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function k(){const e=(0,c.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>(0,u.j)([t,n,a].filter(Boolean))),[t,n,a])}function E(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function x(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,u.j)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function _(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,s=i.find((e=>(0,a.LX)(r.pathname,e)));if(!s)return null;const l=s.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(i),sidebarName:l,sidebarItems:c}}function S(e){return e.filter((e=>"category"!==e.type||!!m(e)))}},1980:(e,t,n)=>{"use strict";n.d(t,{Rb:()=>s,_X:()=>l});var r=n(7294),a=n(6550),o=n(1688),i=n(902);function s(e){!function(e){const t=(0,a.k6)(),n=(0,i.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function l(e){return function(e){const t=(0,a.k6)();return(0,o.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}},7392:(e,t,n)=>{"use strict";function r(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,r)=>e.findIndex((e=>t(e,n)))!==r))}function a(e){return Array.from(new Set(e))}n.d(t,{j:()=>a,l:()=>r})},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>p,d:()=>u,VC:()=>f});var r=n(7294),a=n(6010),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2263);function u(e){let{title:t,description:n,keywords:a,image:i,children:s}=e;const u=function(e){const{siteConfig:t}=(0,c.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,l.C)(),p=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,u),t&&r.createElement("meta",{property:"og:title",content:u}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),p&&r.createElement("meta",{property:"og:image",content:p}),p&&r.createElement("meta",{name:"twitter:image",content:p}),s)}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:s},r.createElement(o.Z,null,r.createElement("html",{className:s})),n)}function f(e){let{children:t}=e;const n=s(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(p,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>c,Ql:()=>l,i6:()=>s,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d,o5:()=>p});var r=n(7294),a=n(412),o=n(2389),i=n(902);const s=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(s.Provider,{value:n},t)}function c(){const e=(0,r.useContext)(s);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const u=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),a=(0,r.useRef)(u()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function p(){const e=c(),t=function(){const e=(0,r.useRef)({elem:null,top:0}),t=(0,r.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,r.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const r=t.getBoundingClientRect().top-n;return r&&window.scrollBy({left:0,top:r}),e.current={elem:null,top:0},{restored:0!==r}}),[]);return(0,r.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,r.useRef)(void 0),a=(0,r.useCallback)((r=>{t.save(r),e.disableScrollEvents(),n.current=()=>{const{restored:r}=t.restore();if(n.current=void 0,r){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,r.useLayoutEffect)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:a}}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&at&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>r,os:()=>a});n(2263);const r="default";function a(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{Nk:()=>d,WA:()=>u});var r=n(7294),a=n(1688);const o="localStorage";function i(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function s(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,l||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),l=!0),null}var t}let l=!1;const c={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function u(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=s(t?.persistence);return null===n?c:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),i({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),i({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}function d(e,t){const n=(0,r.useRef)((()=>null===e?c:u(e,t))).current(),o=(0,r.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,a.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var r=n(2263),a=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,r.Z)(),{pathname:i}=(0,a.TH)(),s=o===n?e:e.replace(`/${o}/`,"/"),l=i.replace(e,"");return{createUrl:function(e){let{locale:r,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===n?`${s}`:`${s}${e}/`}(r)}${l}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},311:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(7294),a=n(6010);const o={loadingRing:"loadingRing_RJI3","loading-ring":"loading-ring_FB5o"};function i(e){let{className:t}=e;return r.createElement("div",{className:(0,a.Z)(o.loadingRing,t)},r.createElement("div",null),r.createElement("div",null),r.createElement("div",null),r.createElement("div",null))}},22:(e,t,n)=>{"use strict";n.d(t,{w:()=>s});var r=n(1336),a=n.n(r),o=n(1029);const i=new Map;function s(e,t){const n=`${e}${t}`;let r=i.get(n);return r||(r=async function(e,t){{const n=`${e}${o.J.replace("{dir}",t?`-${t.replace(/\//g,"-")}`:"")}`;if(new URL(n,location.origin).origin!==location.origin)throw new Error("Unexpected version url");const r=await(await fetch(n)).json(),i=r.map(((e,t)=>{let{documents:n,index:r}=e;return{type:t,documents:n,index:a().Index.load(r)}})),s=r.reduce(((e,t)=>{for(const n of t.index.invertedIndex)/\p{Unified_Ideograph}/u.test(n[0][0])&&e.add(n[0]);return e}),new Set);return{wrappedIndexes:i,zhDictionary:Array.from(s)}}return{wrappedIndexes:[],zhDictionary:[]}}(e,t),i.set(n,r)),r}},8202:(e,t,n)=>{"use strict";n.d(t,{v:()=>l});var r=n(1336),a=n.n(r);var o=n(1029);function i(e){return s(e).concat(s(e.filter((e=>{const t=e[e.length-1];return!t.trailing&&t.maybeTyping})),!0))}function s(e,t){return e.map((e=>({tokens:e.map((e=>e.value)),term:e.map((e=>({value:e.value,presence:a().Query.presence.REQUIRED,wildcard:(t?e.trailing||e.maybeTyping:e.trailing)?a().Query.wildcard.TRAILING:a().Query.wildcard.NONE})))})))}function l(e,t,n){return function(r,s){const l=function(e,t){if(1===t.length&&["ja","jp","th"].includes(t[0]))return a()[t[0]].tokenizer(e).map((e=>e.toString()));let n=/[^-\s]+/g;return t.includes("zh")&&(n=/\w+|\p{Unified_Ideograph}+/gu),e.toLowerCase().match(n)||[]}(r,o.dK);if(0===l.length)return void s([]);const c=function(e,t){const n=function(e,t){const n=[];return function e(r,a){if(0===r.length)return void n.push(a);const o=r[0];if(/\p{Unified_Ideograph}/u.test(o)){const n=function(e,t){const n=[];return function e(r,a){let o=0,i=!1;for(const s of t)if(r.substr(0,s.length)===s){const t={missed:a.missed,term:a.term.concat({value:s})};r.length>s.length?e(r.substr(s.length),t):n.push(t),i=!0}else for(let t=s.length-1;t>o;t-=1){const l=s.substr(0,t);if(r.substr(0,t)===l){o=t;const s={missed:a.missed,term:a.term.concat({value:l,trailing:!0})};r.length>t?e(r.substr(t),s):n.push(s),i=!0;break}}i||(r.length>0?e(r.substr(1),{missed:a.missed+1,term:a.term}):a.term.length>0&&n.push(a))}(e,{missed:0,term:[]}),n.sort(((e,t)=>{const n=e.missed>0?1:0,r=t.missed>0?1:0;return n!==r?n-r:e.term.length-t.term.length})).map((e=>e.term))}(o,t);for(const t of n){const n=a.concat(...t);e(r.slice(1),n)}}else{const t=a.concat({value:o});e(r.slice(1),t)}}(e,[]),n}(e,t);if(0===n.length)return[{tokens:e,term:e.map((e=>({value:e,presence:a().Query.presence.REQUIRED,wildcard:a().Query.wildcard.LEADING|a().Query.wildcard.TRAILING})))}];for(const a of n)a[a.length-1].maybeTyping=!0;const r=[];for(const i of o.dK)if("en"===i)o._k||r.unshift(a().stopWordFilter);else{const e=a()[i];e.stopWordFilter&&r.unshift(e.stopWordFilter)}let s;if(r.length>0){const e=e=>r.reduce(((e,t)=>e.filter((e=>t(e.value)))),e);s=[];const t=[];for(const r of n){const n=e(r);s.push(n),n.length0&&t.push(n)}n.push(...t)}else s=n.slice();const l=[];for(const a of s)if(a.length>2)for(let e=a.length-1;e>=0;e-=1)l.push(a.slice(0,e).concat(a.slice(e+1)));return i(n).concat(i(l))}(l,t),u=[];e:for(const{term:t,tokens:a}of c)for(const{documents:r,index:o,type:i}of e)if(u.push(...o.query((e=>{for(const n of t)e.term(n.value,{wildcard:n.wildcard,presence:n.presence})})).slice(0,n).filter((e=>!u.some((t=>t.document.i.toString()===e.ref)))).slice(0,n-u.length).map((t=>{const n=r.find((e=>e.i.toString()===t.ref));return{document:n,type:i,page:0!==i&&e[0].documents.find((e=>e.i===n.p)),metadata:t.matchData.metadata,tokens:a,score:t.score}}))),u.length>=n)break e;!function(e){e.forEach(((e,t)=>{e.index=t})),e.sort(((t,n)=>{let r=t.type>0&&t.page?e.findIndex((e=>e.document===t.page)):t.index,a=n.type>0&&n.page?e.findIndex((e=>e.document===n.page)):n.index;return-1===r&&(r=t.index),-1===a&&(a=n.index),r===a?0===t.type?-1:0===n.type?1:t.index-n.index:r-a}))}(u),function(e){e.forEach(((t,n)=>{n>0&&t.page&&e.some((e=>e.document===t.page))&&(n{"use strict";function r(e){return e.join(" \u203a ")}n.d(t,{e:()=>r})},1690:(e,t,n)=>{"use strict";function r(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}n.d(t,{X:()=>r})},1073:(e,t,n)=>{"use strict";function r(e,t){const n=[];for(const r of Object.values(e))r[t]&&n.push(...r[t].position);return n.sort(((e,t)=>e[0]-t[0]||t[1]-e[1]))}n.d(t,{m:()=>r})},2539:(e,t,n)=>{"use strict";n.d(t,{C:()=>a});var r=n(1690);function a(e,t,n){const o=[];for(const i of t){const n=e.toLowerCase().indexOf(i);if(n>=0){n>0&&o.push(a(e.substr(0,n),t)),o.push(`${(0,r.X)(e.substr(n,i.length))}`);const s=n+i.length;s${(0,r.X)(e)}`:(0,r.X)(e):o.join("")}},726:(e,t,n)=>{"use strict";n.d(t,{o:()=>l});var r=n(1690),a=n(2539);const o=/\w+|\p{Unified_Ideograph}/u;function i(e){const t=[];let n=0,r=e;for(;r.length>0;){const a=r.match(o);if(!a){t.push(r);break}a.index>0&&t.push(r.substring(0,a.index)),t.push(a[0]),n+=a.index+a[0].length,r=e.substring(n)}return t}var s=n(1029);function l(e,t,n,o){void 0===o&&(o=s.Hk);const{chunkIndex:l,chunks:c}=function(e,t,n){const o=[];let s=0,l=0,c=-1;for(;sl){const t=i(e.substring(l,u)).map((e=>({html:(0,r.X)(e),textLength:e.length})));for(const e of t)o.push(e)}-1===c&&(c=o.length),l=u+d,o.push({html:(0,a.C)(e.substring(u,l),n,!0),textLength:d})}}if(l({html:(0,r.X)(e),textLength:e.length})));for(const e of t)o.push(e)}return{chunkIndex:c,chunks:o}}(e,t,n),u=c.slice(0,l),d=c[l],p=[d.html],f=c.slice(l+1);let m=d.textLength,h=0,g=0,b=!1,v=!1;for(;m0){const e=u.pop();m+e.textLength<=o?(p.unshift(e.html),h+=e.textLength,m+=e.textLength):(b=!0,u.length=0)}else{if(!(f.length>0))break;{const e=f.shift();m+e.textLength<=o?(p.push(e.html),g+=e.textLength,m+=e.textLength):(v=!0,f.length=0)}}return(b||u.length>0)&&p.unshift("\u2026"),(v||f.length>0)&&p.push("\u2026"),p.join("")}},1029:(e,t,n)=>{"use strict";n.d(t,{vc:()=>o,gQ:()=>f,H6:()=>c,hG:()=>g,l9:()=>m,dK:()=>r,_k:()=>a,pu:()=>p,AY:()=>u,t_:()=>d,Kc:()=>h,J:()=>i,Hk:()=>l,qo:()=>s,pQ:()=>b});n(1336);const r=["en"],a=!1,o=null,i="search-index{dir}.json",s=8,l=50,c=!1,u=!0,d=!0,p="right",f=void 0,m=!0,h=null,g=!1,b=!1},6010:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;ta});const a=function(){for(var e,t,n=0,a="";n{"use strict";n.d(t,{lX:()=>k,q_:()=>C,ob:()=>f,PP:()=>L,Ep:()=>p});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r=0;p--){var f=i[p];"."===f?o(i,p):".."===f?(o(i,p),d++):d&&(o(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=n(8776);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function f(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,h(),k.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(k.entries[k.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=k.index+e;return t>=0&&t{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=f(n);a&&a!==m&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),g=0;g{"use strict";e.exports=function(e,t,n,r,a,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,a,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},1336:(e,t,n)=>{var r,a;!function(){var o,i,s,l,c,u,d,p,f,m,h,g,b,v,y,k,w,E,x,_,S,C,T,L,A,P,R,O,I,N,M=function(e){var t=new M.Builder;return t.pipeline.add(M.trimmer,M.stopWordFilter,M.stemmer),t.searchPipeline.add(M.stemmer),e.call(t,t),t.build()};M.version="2.3.9",M.utils={},M.utils.warn=(o=this,function(e){o.console&&console.warn&&console.warn(e)}),M.utils.asString=function(e){return null==e?"":e.toString()},M.utils.clone=function(e){if(null==e)return e;for(var t=Object.create(null),n=Object.keys(e),r=0;r0){var l=M.utils.clone(t)||{};l.position=[i,s],l.index=a.length,a.push(new M.Token(n.slice(i,o),l))}i=o+1}}return a},M.tokenizer.separator=/[\s\-]+/,M.Pipeline=function(){this._stack=[]},M.Pipeline.registeredFunctions=Object.create(null),M.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&M.utils.warn("Overwriting existing registered function: "+t),e.label=t,M.Pipeline.registeredFunctions[e.label]=e},M.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||M.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},M.Pipeline.load=function(e){var t=new M.Pipeline;return e.forEach((function(e){var n=M.Pipeline.registeredFunctions[e];if(!n)throw new Error("Cannot load unregistered function: "+e);t.add(n)})),t},M.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach((function(e){M.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},M.Pipeline.prototype.after=function(e,t){M.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");n+=1,this._stack.splice(n,0,t)},M.Pipeline.prototype.before=function(e,t){M.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");this._stack.splice(n,0,t)},M.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},M.Pipeline.prototype.run=function(e){for(var t=this._stack.length,n=0;n1&&(oe&&(n=a),o!=e);)r=n-t,a=t+Math.floor(r/2),o=this.elements[2*a];return o==e||o>e?2*a:os?c+=2:i==s&&(t+=n[l+1]*r[c+1],l+=2,c+=2);return t},M.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},M.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,n=0;t0){var o,i=a.str.charAt(0);i in a.node.edges?o=a.node.edges[i]:(o=new M.TokenSet,a.node.edges[i]=o),1==a.str.length&&(o.final=!0),r.push({node:o,editsRemaining:a.editsRemaining,str:a.str.slice(1)})}if(0!=a.editsRemaining){if("*"in a.node.edges)var s=a.node.edges["*"];else{s=new M.TokenSet;a.node.edges["*"]=s}if(0==a.str.length&&(s.final=!0),r.push({node:s,editsRemaining:a.editsRemaining-1,str:a.str}),a.str.length>1&&r.push({node:a.node,editsRemaining:a.editsRemaining-1,str:a.str.slice(1)}),1==a.str.length&&(a.node.final=!0),a.str.length>=1){if("*"in a.node.edges)var l=a.node.edges["*"];else{l=new M.TokenSet;a.node.edges["*"]=l}1==a.str.length&&(l.final=!0),r.push({node:l,editsRemaining:a.editsRemaining-1,str:a.str.slice(1)})}if(a.str.length>1){var c,u=a.str.charAt(0),d=a.str.charAt(1);d in a.node.edges?c=a.node.edges[d]:(c=new M.TokenSet,a.node.edges[d]=c),1==a.str.length&&(c.final=!0),r.push({node:c,editsRemaining:a.editsRemaining-1,str:u+a.str.slice(2)})}}}return n},M.TokenSet.fromString=function(e){for(var t=new M.TokenSet,n=t,r=0,a=e.length;r=e;t--){var n=this.uncheckedNodes[t],r=n.child.toString();r in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[r]:(n.child._str=r,this.minimizedNodes[r]=n.child),this.uncheckedNodes.pop()}},M.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},M.Index.prototype.search=function(e){return this.query((function(t){new M.QueryParser(e,t).parse()}))},M.Index.prototype.query=function(e){for(var t=new M.Query(this.fields),n=Object.create(null),r=Object.create(null),a=Object.create(null),o=Object.create(null),i=Object.create(null),s=0;s1?1:e},M.Builder.prototype.k1=function(e){this._k1=e},M.Builder.prototype.add=function(e,t){var n=e[this._ref],r=Object.keys(this._fields);this._documents[n]=t||{},this.documentCount+=1;for(var a=0;a=this.length)return M.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},M.QueryLexer.prototype.width=function(){return this.pos-this.start},M.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},M.QueryLexer.prototype.backup=function(){this.pos-=1},M.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=M.QueryLexer.EOS&&this.backup()},M.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(M.QueryLexer.TERM)),e.ignore(),e.more())return M.QueryLexer.lexText},M.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(M.QueryLexer.EDIT_DISTANCE),M.QueryLexer.lexText},M.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(M.QueryLexer.BOOST),M.QueryLexer.lexText},M.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(M.QueryLexer.TERM)},M.QueryLexer.termSeparator=M.tokenizer.separator,M.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==M.QueryLexer.EOS)return M.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return M.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(M.QueryLexer.TERM),M.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(M.QueryLexer.TERM),M.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(M.QueryLexer.PRESENCE),M.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(M.QueryLexer.PRESENCE),M.QueryLexer.lexText;if(t.match(M.QueryLexer.termSeparator))return M.QueryLexer.lexTerm}else e.escapeCharacter()}},M.QueryParser=function(e,t){this.lexer=new M.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},M.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=M.QueryParser.parseClause;e;)e=e(this);return this.query},M.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},M.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},M.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},M.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case M.QueryLexer.PRESENCE:return M.QueryParser.parsePresence;case M.QueryLexer.FIELD:return M.QueryParser.parseField;case M.QueryLexer.TERM:return M.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(n+=" with value '"+t.str+"'"),new M.QueryParseError(n,t.start,t.end)}},M.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=M.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=M.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+t.str+"'";throw new M.QueryParseError(n,t.start,t.end)}var r=e.peekLexeme();if(null==r){n="expecting term or field, found nothing";throw new M.QueryParseError(n,t.start,t.end)}switch(r.type){case M.QueryLexer.FIELD:return M.QueryParser.parseField;case M.QueryLexer.TERM:return M.QueryParser.parseTerm;default:n="expecting term or field, found '"+r.type+"'";throw new M.QueryParseError(n,r.start,r.end)}}},M.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var n=e.query.allFields.map((function(e){return"'"+e+"'"})).join(", "),r="unrecognised field '"+t.str+"', possible fields: "+n;throw new M.QueryParseError(r,t.start,t.end)}e.currentClause.fields=[t.str];var a=e.peekLexeme();if(null==a){r="expecting term, found nothing";throw new M.QueryParseError(r,t.start,t.end)}if(a.type===M.QueryLexer.TERM)return M.QueryParser.parseTerm;r="expecting term, found '"+a.type+"'";throw new M.QueryParseError(r,a.start,a.end)}},M.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(null!=n)switch(n.type){case M.QueryLexer.TERM:return e.nextClause(),M.QueryParser.parseTerm;case M.QueryLexer.FIELD:return e.nextClause(),M.QueryParser.parseField;case M.QueryLexer.EDIT_DISTANCE:return M.QueryParser.parseEditDistance;case M.QueryLexer.BOOST:return M.QueryParser.parseBoost;case M.QueryLexer.PRESENCE:return e.nextClause(),M.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+n.type+"'";throw new M.QueryParseError(r,n.start,n.end)}else e.nextClause()}},M.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="edit distance must be numeric";throw new M.QueryParseError(r,t.start,t.end)}e.currentClause.editDistance=n;var a=e.peekLexeme();if(null!=a)switch(a.type){case M.QueryLexer.TERM:return e.nextClause(),M.QueryParser.parseTerm;case M.QueryLexer.FIELD:return e.nextClause(),M.QueryParser.parseField;case M.QueryLexer.EDIT_DISTANCE:return M.QueryParser.parseEditDistance;case M.QueryLexer.BOOST:return M.QueryParser.parseBoost;case M.QueryLexer.PRESENCE:return e.nextClause(),M.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+a.type+"'";throw new M.QueryParseError(r,a.start,a.end)}else e.nextClause()}},M.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var n=parseInt(t.str,10);if(isNaN(n)){var r="boost must be numeric";throw new M.QueryParseError(r,t.start,t.end)}e.currentClause.boost=n;var a=e.peekLexeme();if(null!=a)switch(a.type){case M.QueryLexer.TERM:return e.nextClause(),M.QueryParser.parseTerm;case M.QueryLexer.FIELD:return e.nextClause(),M.QueryParser.parseField;case M.QueryLexer.EDIT_DISTANCE:return M.QueryParser.parseEditDistance;case M.QueryLexer.BOOST:return M.QueryParser.parseBoost;case M.QueryLexer.PRESENCE:return e.nextClause(),M.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+a.type+"'";throw new M.QueryParseError(r,a.start,a.end)}else e.nextClause()}},void 0===(a="function"==typeof(r=function(){return M})?r.call(t,n,t,e):r)||(e.exports=a)}()},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&f(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,a){for(var o,i,s=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);x+=E.value.length,E=E.next){var _=E.value;if(t.length>e.length)return;if(!(_ instanceof a)){var S,C=1;if(v){if(!(S=o(w,x,e,b))||S.index>=e.length)break;var T=S.index,L=S.index+S[0].length,A=x;for(A+=E.value.length;T>=A;)A+=(E=E.next).value.length;if(x=A-=E.value.length,E.value instanceof a)continue;for(var P=E;P!==t.tail&&(Ad.reach&&(d.reach=N);var M=E.prev;if(O&&(M=l(t,M,O),x+=O.length),c(t,M,C),E=l(t,M,new a(p,g?r.tokenize(R,g):R,y,R)),I&&l(t,E,I),C>1){var D={cause:p+","+m,reach:N};i(e,t,n,E.prev,x,D),d&&D.reach>d.reach&&(d.reach=D.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function c(e,t,n){for(var r=t.next,a=0;a"+o.content+""},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(//g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n0)){var s=p(/^\{$/,/^\}$/);if(-1===s)continue;for(var l=n;l=0&&f(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function c(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function u(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,u={},d=l(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=s(i++,r)););return u[n]=a,n})).join(""),n,r),p=Object.keys(u);return i=0,function e(t){for(var n=0;n=p.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=p[i],o="string"==typeof r?r:r.content,s=o.indexOf(a);if(-1!==s){++i;var l=o.substring(0,s),d=c(u[a]),f=o.substring(s+a.length),m=[];if(l&&m.push(l),m.push(d),f){var h=[f];e(h),m.push.apply(m,h)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var g=r.content;Array.isArray(g)?e(g):e([g])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function p(e){return"string"==typeof e?e:Array.isArray(e)?e.map(p).join(""):p(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(//g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r*\.{3}(?:[^{}]|)*\})/.source;function o(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return r})).replace(//g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},s=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var l=i(a);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=i(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}a.content&&"string"!=typeof a.content&&s(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||s(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++a;var h=p.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(m+f.length),v=[];h&&v.push.apply(v,i([h])),v.push(g),b&&v.push.apply(v,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(v)):c.content=v}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},767:()=>{!function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|)*\*\//.source,n=0;n<2;n++)t=t.replace(//g,(function(){return t}));t=t.replace(//g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism)},893:()=>{Prism.languages.solidity=Prism.languages.extend("clike",{"class-name":{pattern:/(\b(?:contract|enum|interface|library|new|struct|using)\s+)(?!\d)[\w$]+/,lookbehind:!0},keyword:/\b(?:_|anonymous|as|assembly|assert|break|calldata|case|constant|constructor|continue|contract|default|delete|do|else|emit|enum|event|external|for|from|function|if|import|indexed|inherited|interface|internal|is|let|library|mapping|memory|modifier|new|payable|pragma|private|public|pure|require|returns?|revert|selfdestruct|solidity|storage|struct|suicide|switch|this|throw|using|var|view|while)\b/,operator:/=>|->|:=|=:|\*\*|\+\+|--|\|\||&&|<<=?|>>=?|[-+*/%^&|<>!=]=?|[~?]/}),Prism.languages.insertBefore("solidity","keyword",{builtin:/\b(?:address|bool|byte|u?int(?:8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?|string|bytes(?:[1-9]|[12]\d|3[0-2])?)\b/}),Prism.languages.insertBefore("solidity","number",{version:{pattern:/([<>]=?|\^)\d+\.\d+\.\d+\b/,lookbehind:!0,alias:"number"}}),Prism.languages.sol=Prism.languages.solidity},9930:()=>{!function(e){var t=/(?:[\w-]+|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*")/.source;function n(e){return e.replace(/__/g,(function(){return t}))}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n(/(^[\t ]*\[\s*(?:\[\s*)?)__(?:\s*\.\s*__)*(?=\s*\])/.source),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n(/(^[\t ]*|[{,]\s*)__(?:\s*\.\s*__)*(?=\s*=)/.source),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}}(Prism)},4891:(e,t,n)=>{var r={"./prism-rust":767,"./prism-solidity":893,"./prism-toml":9930};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=4891},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n