diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/404.html b/404.html new file mode 100644 index 0000000000..8b3e0b0fcc --- /dev/null +++ b/404.html @@ -0,0 +1,22 @@ + + + + + +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/745e13edde95dc87e78290c8e9752885.svg b/745e13edde95dc87e78290c8e9752885.svg new file mode 100644 index 0000000000..f1afac793b --- /dev/null +++ b/745e13edde95dc87e78290c8e9752885.svg @@ -0,0 +1,546 @@ + + + + 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/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..61133044a4 --- /dev/null +++ b/adrs/0001-tm-multi-root-apphash/index.html @@ -0,0 +1,93 @@ + + + + + +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..702f72e400 --- /dev/null +++ b/adrs/0002-go-modules-compatible-git-tags/index.html @@ -0,0 +1,135 @@ + + + + + +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..162fabe079 --- /dev/null +++ b/adrs/0003-consensus-runtime-token-transfer/index.html @@ -0,0 +1,432 @@ + + + + + +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..8d77edea9d --- /dev/null +++ b/adrs/0004-runtime-governance/index.html @@ -0,0 +1,217 @@ + + + + + +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..622c530a36 --- /dev/null +++ b/adrs/0005-runtime-compute-slashing/index.html @@ -0,0 +1,312 @@ + + + + + +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..8d4952c347 --- /dev/null +++ b/adrs/0006-consensus-governance/index.html @@ -0,0 +1,372 @@ + + + + + +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..1e1cc89771 --- /dev/null +++ b/adrs/0007-improved-random-beacon/index.html @@ -0,0 +1,307 @@ + + + + + +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..124d997700 --- /dev/null +++ b/adrs/0008-standard-account-key-generation/index.html @@ -0,0 +1,286 @@ + + + + + +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], [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 (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. +
  3. 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.
  4. +
+

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 and C implementation for their Speculos emulator (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 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..e7bf77bc11 --- /dev/null +++ b/adrs/0009-ed25519-semantics/index.html @@ -0,0 +1,117 @@ + + + + + +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..a75dd2e8d9 --- /dev/null +++ b/adrs/0010-vrf-elections/index.html @@ -0,0 +1,232 @@ + + + + + +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. +
  3. +

    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).

      +
    • +
    +
  4. +
  5. +

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

    +
  6. +
+

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. +
  3. +

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

    +
  4. +
+

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. +
  3. +

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

    +
  4. +
+

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:
  2. +
+

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. +
  3. +

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

    +
  4. +
+

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..3837e02bc7 --- /dev/null +++ b/adrs/0011-incoming-runtime-messages/index.html @@ -0,0 +1,262 @@ + + + + + +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..a27a9bfa16 --- /dev/null +++ b/adrs/0012-runtime-message-results/index.html @@ -0,0 +1,111 @@ + + + + + +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..a5d6393920 --- /dev/null +++ b/adrs/0013-runtime-upgrades/index.html @@ -0,0 +1,91 @@ + + + + + +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..9eae268ad6 --- /dev/null +++ b/adrs/0014-runtime-signing-tx-with-hardware-wallet/index.html @@ -0,0 +1,401 @@ + + + + + +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: +
      +
    • Fix Deoxys-II field description in Signing encrypted runtime +transactions section.
    • +
    • Rename SIGN_PT_ instructions in APDUSPEC to SIGN_RT_ for consistency +with oasis-core and oasis-sdk codebase.
    • +
    +
  • +
  • 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. +
  3. Changes to Allowance transaction
  4. +
  5. Signing general runtime transactions,
  6. +
  7. Signing smart contract runtime transactions,
  8. +
  9. Signing EVM runtime transactions.
  10. +
  11. Signing encrypted runtime transactions,
  12. +
+

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. +
  3. Render orig_to value in 0x format in place of MIXED_TO.
  4. +
+

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. +
  3. The number of decimals is 18, if runtime ID matches any Emerald or Sapphire +runtime on any network.
  4. +
  5. Otherwise, the number of decimals is 9.
  6. +
+

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..801cd1e533 --- /dev/null +++ b/adrs/0015-vrf-per-block-entropy/index.html @@ -0,0 +1,81 @@ + + + + + +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..5970b8edbe --- /dev/null +++ b/adrs/0016-consensus-parameters-change-proposal/index.html @@ -0,0 +1,131 @@ + + + + + +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..63e20f3c10 --- /dev/null +++ b/adrs/0017-app-standards/index.html @@ -0,0 +1,116 @@ + + + + + +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..2540239bc9 --- /dev/null +++ b/adrs/0020-governance-delegator-votes/index.html @@ -0,0 +1,161 @@ + + + + + +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..7fa7f03ea4 --- /dev/null +++ b/adrs/0021-keymanager-ephemeral-secrets/index.html @@ -0,0 +1,133 @@ + + + + + +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. +
  3. +

    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.

    +
  4. +
  5. +

    Publish SignedEncryptedEphemeralSecret to consensus via +a PublishEphemeralSecret transaction.

    +
  6. +
  7. +

    This key manager instance is DONE.

    +
  8. +
+

Replication

+

Each key manager will:

+
    +
  1. +

    Listen to the publications of new ephemeral secrets and forward them to +the enclave.

    +
  2. +
  3. +

    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.

    +
  4. +
  5. +

    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.

    +
  6. +
  7. +

    This key manager instance is DONE.

    +
  8. +
+

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..a8a6cfc422 --- /dev/null +++ b/adrs/0022-keymanager-master-secrets/index.html @@ -0,0 +1,342 @@ + + + + + +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. +
  3. +

    Check to see if another instance has published a proposal for the upcoming +epoch. If yes, go to step 5.

    +
  4. +
  5. +

    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.

    +
  6. +
  7. +

    Read SignedEncryptedMasterSecret from the response and publish it +in the consensus layer using PublishMasterSecret transaction.

    +
  8. +
  9. +

    This key manager instance is DONE.

    +
  10. +
+

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. +
  3. +

    Forward the proposal to the enclave.

    +
  4. +
  5. +

    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.

    +
  6. +
  7. +

    Request enclave to initialize again and use the response to register +with the forthcoming checksum and RSK key derived from the proposal.

    +
  8. +
  9. +

    This key manager instance is DONE.

    +
  10. +
+

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. +
  3. +

    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.
    • +
    +
  4. +
  5. +

    Count how many nodes have stored the proposal locally.

    +
      +
    • Compare the checksum of the proposal to the next_checksum field in +the init response.
    • +
    +
  6. +
  7. +

    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.

      +
    • +
    +
  8. +
  9. +

    Broadcast the new status.

    +
      +
    • If the master secret generation number has advanced, the enclaves will +try to apply the proposal they stored locally.
    • +
    +
  10. +
  11. +

    Key manager application is DONE.

    +
  12. +
+

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. +
  3. +

    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.

    +
  4. +
  5. +

    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.

    +
  6. +
  7. +

    This key manager instance is DONE.

    +
  8. +
+

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/0024-off-chain-runtime-logic/index.html b/adrs/0024-off-chain-runtime-logic/index.html new file mode 100644 index 0000000000..584cd565a8 --- /dev/null +++ b/adrs/0024-off-chain-runtime-logic/index.html @@ -0,0 +1,254 @@ + + + + + +ADR 0024: Runtime Off-chain Logic (ROFL) | Oasis Documentation + + + + +
Skip to main content

ADR 0024: Runtime Off-chain Logic (ROFL)

+

Component

+

Oasis Core, Oasis SDK

+

Changelog

+
    +
  • 2024-02-26: Notifications
  • +
  • 2023-11-27: Initial draft
  • +
+

Status

+

Proposed

+

Context

+

Sometimes we may want the runtime compute nodes to run additional off-chain +logic that communicates with the on-chain state securely (e.g. ensuring that the +off-chain logic is being run by the same node operator, is properly attested +when running in a TEE, etc.).

+

The off-chain logic may then perform non-deterministic and potentially expensive +things (like remote HTTPS requests or complex local computation) and securely +interact with the on-chain logic via transactions.

+

The main use case driving this proposal is support for running attested light +client committees that read and verify information from other chains, then make +this information available to Oasis runtimes with no additional trust +assumptions.

+

Decision

+

While similar functionality can be implemented entirely independently on the +application layer (and such solutions already exist), this proposal attempts to +reuse the same security and attestation infrastructure that is already available +for on-chain parts of the runtimes, specifically:

+
    +
  • +

    Compute nodes and runtime binary distribution and execution can stay the same +as it has been for existing node operators that run the runtimes. Handling of +the off-chain logic part should be done transparently if the runtime provides +it.

    +
  • +
  • +

    Existing attestation, consensus and freshness proof flows can be leveraged for +ensuring that the off-chain logic is running in a secure environment.

    +
  • +
+

One important consideration is also whether to have the off-chain logic part of +the same runtime binary or have it as a completely separate binary running in +its own process. This proposal decides on the latter to ensure that the +off-chain TCB is completely separate from the on-chain TCB. Given that the logic +running off-chain can be much more complex and can interact with untrusted +external services, ensuring this separation is important as a defense-in-depth +measure.

+

The proposed architecture extends the composition of the runtime so that it now +contains the following components:

+
    +
  • +

    Runtime On-chain Logic (RONL) is what has existed as the sole runtime +component before this proposal. It contains the logic (and TCB) that is +responsible for executing the deterministic on-chain logic of the runtime.

    +
  • +
  • +

    Runtime Off-chain Logic (ROFL) is an optional runtime component that may +run in parallel with RONL and is part of its own TCB. It also uses the same +general runtime framework and RHP, but instead of implementing the on-chain +batch scheduling, execution and query methods, it only implements specific +notification hooks that can trigger arbitrary actions.

    +
  • +
+

Both RONL and ROFL are managed as independent runtimes by the Oasis Node as +host, using the existing runtime host architecture. Failure of ROFL does not +affect RONL which can proceed to run as usual.

+

Attestation

+

An assumption made in this proposal is that both RONL and ROFL components are +developed and built together, by the same entity, and are part of the same +release. This means that we can simplify attestation by making RONL being able +to attest ROFL by being aware of its exact identity.

+

The idea is that during the release build process, ROFL is built first, its +signer-independent identity (e.g. MRENCLAVE) is measured and included during +compilation of RONL. The signer-dependent part of identity (e.g. MRSIGNER) is +assumed to be the same for both and can be read from trusted CPU state (since it +may not be available during the build process due to offline signing).

+

Alternatively, one can imagine a proposal where the ROFL identity is backed by +some sort of on-chain governance process defined in the RONL component. Defining +such a mechanism is outside the scope of this proposal.

+

The process for ROFL attestation proceeds as follows:

+
    +
  1. +

    Remote Attestation. The normal runtime attestation flow is initiated by +the host. As a result of this flow, the node.CapabilityTEE structure is +generated which includes the remote attestation quote and additional data.

    +
  2. +
  3. +

    Node Endorsement. The host verifies the node.CapabilityTEE structure +and if deemed correct, it signs it using the node's identity key and the +following domain separation context:

    +
    oasis-core/node: endorse TEE capability
    +

    The signature is stored in a new structure EndorsedCapabilityTEE which is +defined as follows:

    +
    type EndorsedCapabilityTEE struct {
    // CapabilityTEE is the TEE capability structure to be endorsed.
    CapabilityTEE CapabilityTEE `json:"capability_tee"`

    // NodeEndorsement is the node endorsement signature.
    NodeEndorsement signature.Signature `json:"node_endorsement"`
    }
    +
  4. +
  5. +

    Updating Node-Endorsed CapabilityTEE in ROFL. The EndorsedCapabilityTEE +is sent to ROFL to be stored and available for establishing secure EnclaveRPC +sessions.

    +
  6. +
  7. +

    RONL Verification. When establishing a new session with RONL, the +endorsed TEE capability is presented during session establishment. RONL +verifies the quote, ensures the enclave identity is one of the known +identities set at compile-time and verifies the node endorsement against the +locally known node identity (both RONL and ROFL must be from the same node).

    +

    If all the checks pass, a secure EnclaveRPC session is established.

    +
  8. +
+

This flow needs to be repeated whenever RAK changes for any reason and also +periodically to ensure freshness (consistent with the quote policy configured +for the runtime in the consensus layer).

+

Updates to the ORC Manifest

+

The ORC manifest is extended with a field that can specify extra components +which currently include ROFL binaries in a similar way as we already support +regular runtime binaries (e.g. specifying the executable and SGX metadata).

+

The manifest is updated as follows:

+
// Manifest is a deserialized runtime bundle manifest.
type Manifest struct {
// ... existing fields omitted ...

// Components are the additional runtime components.
Components []*Component `json:"components,omitempty"`
}

// ComponentKind is the kind of a component.
type ComponentKind string

const (
// ComponentInvalid is an invalid component.
ComponentInvalid ComponentKind = ""
// ComponentRONL is the on-chain logic component.
ComponentRONL ComponentKind = "ronl"
// ComponentROFL is the off-chain logic component.
ComponentROFL ComponentKind = "rofl"
)

// Component is a runtime component.
type Component struct {
// Kind is the component kind.
Kind ComponentKind `json:"kind"`

// Name is the name of the component that can be used to filter components
// when multiple are provided by a runtime.
Name string `json:"name,omitempty"`

// Executable is the name of the runtime ELF executable file.
Executable string `json:"executable"`

// SGX is the SGX specific manifest metadata if any.
SGX *SGXMetadata `json:"sgx,omitempty"`
}
+

The top-level executable and sgx fields are supported for backwards +compatibility and implicitly define a new Component of kind ComponentRONL.

+

Updates to the Runtime Host Protocol

+

This proposal includes some non-breaking updates to the Runtime Host Protocol in +order to support the ROFL component, as follows:

+
    +
  • +

    Consensus Block Notification. No updates are required to facilitate +notifications about consensus layer blocks as this is already handled as part +of the existing RHP flow. The only change is that for ROFL, these +notifications invoke a hook that can be implemented by the runtime.

    +
  • +
  • +

    Runtime Transaction Submission. A new method HostSubmitTx is introduced +which allows ROFL to submit transactions to the runtime. It works by queueing +the transaction in the transaction pool (local queue) for later scheduling.

    +
    type HostSubmitTxRequest struct {
    // RuntimeID is the identifier of the target runtime.
    RuntimeID common.Namespace `json:"runtime_id"`
    // Data is the raw transaction data.
    Data []byte `json:"data"`
    // Wait specifies whether the call should wait until the transaction is
    // included in a block.
    Wait bool `json:"wait,omitempty"`
    // Prove specifies whether the response should include a proof of
    // transaction being included in a block.
    Prove bool `json:"prove,omitempty"`
    }
    +
  • +
  • +

    Notify Registration. A new method HostRegisterNotify is introduced which +allows ROFL to register to be notified by the host when specific events occur. +Note that delivery of these notifications is best effort as a dishonest host +may withold notification delivery or generate spurious notifications.

    +

    Registering for notifications overwrites any previous configuration.

    +
    type HostRegisterNotifyRequest struct {
    // RuntimeBlock subscribes to runtime block notifications.
    RuntimeBlock bool `json:"runtime_block,omitempty"`
    // RuntimeEvent subscribes to runtime event emission notifications.
    RuntimeEvent *struct {
    // Tags specifies which event tags to subscribe to.
    Tags [][]byte `json:"tags,omitempty"`
    } `json:"runtime_event,omitempty"`
    }
    +
  • +
  • +

    Notification Delivery. A new method RuntimeNotify is introduced which +allows the host to deliver event notifications based on previously registered +notifiers.

    +
    type RuntimeNotifyRequest struct {
    // RuntimeBlock notifies about a new runtime block.
    RuntimeBlock *roothash.AnnotatedBlock `json:"runtime_block,omitempty"`
    // RuntimeEvent notifies about a specific runtime event being emitted.
    RuntimeEvent *struct {
    // Block is the block header of the block that emitted the event.
    Block *roothash.AnnotatedBlock `json:"block"`
    // Tags are the matching tags that were emitted.
    Tags [][]byte `json:"tags"`
    } `json:"runtime_event,omitempty"`
    }
    +
  • +
  • +

    RONL-ROFL Communication. The existing EnclaveRPC is reused to facilitate +the communication between the two components if/when needed. For this purpose +the endpoint identifier ronl is made available in the ROFL host method +handler to address the RONL component.

    +
  • +
  • +

    Updating Node-Endorsed CapabilityTEE in ROFL. A new method +RuntimeCapabilityTEEUpdateEndorsementRequest is introduced which allows the +node to refresh the EndorsedCapabilityTEE for ROFL.

    +
    type RuntimeCapabilityTEEUpdateEndorsementRequest struct {
    // EndorsedCapabilityTEE is an endorsed TEE capability.
    EndorsedCapabilityTEE node.EndorsedCapabilityTEE `json:"ect"`
    }
    +
  • +
+

Updates to EnclaveRPC RAK Binding

+

Version 2 of the RAKBinding structure is introduced for establishment of +EnclaveRPC sessions, as follows:

+
pub enum RAKBinding {
// ... previous versions omitted ...

/// V2 format which supports endorsed CapabilityTEE structures.
#[cbor(rename = 2)]
V2 {
ect: EndorsedCapabilityTEE,
binding: Signature,
},
}
+

Additionally, the relevant EnclaveRPC session implementation is updated to +facilitate thew new authentication mechanism via endorsed TEE capabilities and +the session demultiplexer is updated to support authentication policies on +incoming connections.

+

Updates to the Runtime Host Sandbox

+

This proposal updates the runtime host sandbox to support optionally allowing +external network requests. These are then allowed only for the ROFL component +(if any is available for a runtime).

+

The following modifications are required:

+
    +
  • +

    When setting up the Bubblewrap sandbox, --share-net is passed to share the +network namespace with the sandboxed runtime. All other namespaces are still +unshared.

    +
  • +
  • +

    The runtime loader is modified to accept an additional argument +--allow-network which then changes the usercall extension to pass through +any address passed in the connect_stream handler.

    +
  • +
+

Configuration

+

ROFL may require additional configuration which it may do through one of several +ways:

+
    +
  • +

    On-chain Configuration. Configuration for the ROFL component may be stored +in on-chain state. ROFL would then query the current configuration and apply +it locally.

    +
  • +
  • +

    Local Per-Node Configuration. In case some per-node configuration is +required (e.g. to allow the node operator to override a default), the existing +runtime local configuration mechanism can be used where configuration is +provided as part of the RHP handshake. All configuration for ROFL should be +contained under the rofl configuration key.

    +
  • +
+

Untrusted Local Storage

+

ROFL may utilize the existing untrusted node-local storage to store things like +sealed data local to the node. This store is shared between RONL and ROFL, but +all ROFL keys are transparently prefixed by rofl. on the host such that only +RONL can see (but not necessarily read) ROFL's keys but not vice versa.

+

Updates to the Oasis SDK

+

A convenient way to develop ROFL modules alongside the on-chain support +functionality should be implemented in the Oasis SDK, including a convenient way +for ROFL to submit runtime transactions in a way that can be verified on-chain +as coming from a specific node/runtime instance.

+

Consequences

+

Positive

+
    +
  • +

    Oasis runtimes can easily be extended with arbitrary off-chain logic that can +securely interact with on-chain functionality.

    +
  • +
  • +

    Node operators do not need to perform much additional configuration in order +to support the new off-chain logic.

    +
  • +
+

Negative

+
    +
  • Additional complexity is introduced to the Runtime Host Protocol and to the +node binary.
  • +
+

Neutral

+

References

+ + \ No newline at end of file diff --git a/adrs/index.html b/adrs/index.html new file mode 100644 index 0000000000..9222707a08 --- /dev/null +++ b/adrs/index.html @@ -0,0 +1,22 @@ + + + + + +Architectural Decision Records | Oasis Documentation + + + + +
Skip to main content

Architectural Decision Records

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.

+ + \ 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.7a5b674c.css b/assets/css/styles.7a5b674c.css new file mode 100644 index 0000000000..8faa4c20d5 --- /dev/null +++ b/assets/css/styles.7a5b674c.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}.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{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);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%}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_Gvgb,.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;--ifm-link-hover-color:inherit!important}.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_BuS1>:last-child,.cardContainer_fWXF :last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p: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}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;top:0;left:0;visibility:hidden}.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__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{appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;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);position:fixed;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;position:fixed;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{display:grid;grid-gap:var(--ifm-spacing-horizontal);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:#0ff;--ifm-color-primary-dark:#0ff;--ifm-color-primary-darker:#0ff;--ifm-color-primary-darkest:#0ff;--ifm-color-primary-light:#0ff;--ifm-color-primary-lighter:#0ff;--ifm-color-primary-lightest:#0ff;--docusaurus-highlighted-code-line-bg:#646464;--search-local-highlight-color:#3ec8ff}:root{--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#0500e2;--ifm-color-primary-dark:#0500e2;--ifm-color-primary-darker:#0500e2;--ifm-color-primary-darkest:#0500e2;--ifm-color-primary-light:#0500e2;--ifm-color-primary-lighter:#0500e2;--ifm-color-primary-lightest:#0500e2;--ifm-code-font-size:95%;--ifm-font-family-base:"Roboto",sans-serif;--ifm-font-family-monospace:"Roboto Mono",monospace;--ifm-global-radius:0;--ifm-alert-border-width:5px;--docusaurus-highlighted-code-line-bg:#dddfe1;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}#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}@font-face{font-family:Roboto;src:url(/assets/fonts/Roboto-Regular-fc2b5060f7accec5cf74437196c1b027.ttf) format("truetype")}@font-face{font-family:Roboto Medium;src:url(/assets/fonts/Roboto-Medium-7c8d04cd831df3033c8a96a2668d645e.ttf) format("truetype")}@font-face{font-family:Roboto Mono;src:url(/assets/fonts/RobotoMono-Regular-94ffabb10cbc81ee42ba565b8fce9542.ttf) format("truetype")}article strong,h1{font-family:Roboto Medium,sans-serif}.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 xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%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 xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%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 xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%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 xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%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}.navbar__search-input{border:1px solid #000;border-radius:0}.card,.pagination-nav__link{border:1px solid #000!important}[data-theme=dark] .card,[data-theme=dark] .pagination-nav__link{border:1px solid #fff!important}html[data-theme=dark] main img{background-color:#fff}.tabs-container>div{border-left:3px solid var(--ifm-tabs-color-active-border);margin-top:inherit!important;padding:1rem}.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}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.lastUpdated_JAkA{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}.cursor_eG29 .hideAction_vcyE>svg,.tocCollapsibleContent_vkbj a{display:block}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.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)}.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}.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)}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_YfHR,.hideAction_vcyE>svg,.navbarSearchContainer_Bca1:empty,.sidebarLogo_isFc,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.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] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.iconExternalLink_nPIU{margin-left:.3rem}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.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}.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}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.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}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}.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:"#"}.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}.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{left:0;position:absolute;top:0;fill:currentColor;height:inherit;opacity:inherit;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_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{display:inline-block;height:1.6em;width:1.6em;fill:var(--ifm-alert-foreground-color)}.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)}.searchContextInput_mXoe,.searchQueryInput_CFBF{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}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}.lastUpdated_JAkA{text-align:right}.tocMobile_ITEo{display:none}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.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_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG: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_TmdG{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_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);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_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.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}.docItemContainer_F8PC{padding:0 .3rem}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}}@media not (max-width:996px){.searchBar_RVTs.searchBarLeft_MXDe .dropdownMenu_qbY6{left:0!important;right:auto!important}}@media only screen and (max-width:996px){.searchQueryColumn_q7nx{max-width:60%!important}.searchContextColumn_oWAF{max-width:40%!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 screen and (max-width:576px){.searchQueryColumn_q7nx{max-width:100%!important}.searchContextColumn_oWAF{max-width:100%!important;padding-left:var(--ifm-spacing-horizontal)!important}}@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-096ee9f59abc938aa6c4f2fd8ae065e8.json b/assets/files/data-096ee9f59abc938aa6c4f2fd8ae065e8.json new file mode 100644 index 0000000000..96e1dda4f3 --- /dev/null +++ b/assets/files/data-096ee9f59abc938aa6c4f2fd8ae065e8.json @@ -0,0 +1,1410 @@ +[ + { + "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": 90000, + "scale": 283 + } +] 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-634123076dba9af3f2609c62957ba363.json b/assets/files/data-634123076dba9af3f2609c62957ba363.json new file mode 100644 index 0000000000..f46dc17d95 --- /dev/null +++ b/assets/files/data-634123076dba9af3f2609c62957ba363.json @@ -0,0 +1,39 @@ +{ + "months": [ + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, + 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, + 114, 117, 120 + ], + "strategicPartnersAndReserve": [ + 12500000, 0, 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, + 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, + 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, + 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, + 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, 12500000, + 12500000, 12500000, 12500000, 12500000, 12500000 + ], + "communityAndEcosystem": [ + 370000000, 0, 0, 0, 407000000, 0, 370000000, 37000000, 37000000, 37000000, + 37000000, 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, + 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, + 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, + 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, 18500000, + 18500000, 18500000, 18500000 + ], + "foundation": [ + 250000000, 0, 0, 0, 0, 0, 0, 0, 100000000, 0, 0, 0, 25000000, 0, 0, 0, + 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, + 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, + 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, 25000000, + 25000000, 25000000, 25000000, 25000000 + ], + "coreContributors": [ + 0, 0, 0, 0, 300000000, 150000000, 150000000, 150000000, 150000000, 150000000, + 150000000, 140000000, 140000000, 140000000, 140000000, 120000000, 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 + ], + "backers": [ + 759000000, 0, 0, 0, 759000000, 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 + ] +} diff --git a/assets/files/data-e5840a71c24b3bb058b0873d28e4ddd2.csv b/assets/files/data-e5840a71c24b3bb058b0873d28e4ddd2.csv new file mode 100644 index 0000000000..2e34c81d4f --- /dev/null +++ b/assets/files/data-e5840a71c24b3bb058b0873d28e4ddd2.csv @@ -0,0 +1,353 @@ +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-14T10:34:52.442Z,0.000920,8.6132 +18690,2022-11-15T09:59:28.153Z,0.000900,8.4183 +18714,2022-11-16T09:24:03.863Z,0.000879,8.2140 +18738,2022-11-17T08:48:39.573Z,0.000857,8.0004 +18762,2022-11-18T08:13:15.284Z,0.000837,7.8066 +18786,2022-11-19T07:37:50.994Z,0.000818,7.6228 +18810,2022-11-20T07:02:26.704Z,0.000800,7.4490 +18834,2022-11-21T06:27:02.415Z,0.000784,7.2947 +18858,2022-11-22T05:51:38.125Z,0.000770,7.1599 +18882,2022-11-23T05:16:13.835Z,0.000758,7.0445 +18906,2022-11-24T04:40:49.546Z,0.000747,6.9388 +18930,2022-11-25T04:05:25.256Z,0.000738,6.8524 +18954,2022-11-26T03:30:00.966Z,0.000730,6.7756 +18978,2022-11-27T02:54:36.677Z,0.000722,6.6990 +19002,2022-11-28T02:19:12.387Z,0.000716,6.6415 +19026,2022-11-29T01:43:48.098Z,0.000710,6.5840 +19050,2022-11-30T01:08:23.808Z,0.000705,6.5362 +19074,2022-12-01T00:32:59.518Z,0.000701,6.4979 +19098,2022-12-01T23:57:35.229Z,0.000697,6.4597 +19122,2022-12-02T23:22:10.939Z,0.000693,6.4214 +19146,2022-12-03T22:46:46.649Z,0.000689,6.3832 +19170,2022-12-04T22:11:22.360Z,0.000686,6.3545 +19194,2022-12-05T21:35:58.070Z,0.000684,6.3354 +19218,2022-12-06T21:00:33.780Z,0.000681,6.3068 +19242,2022-12-07T20:25:09.491Z,0.000679,6.2877 +19266,2022-12-08T19:49:45.201Z,0.000677,6.2686 +19290,2022-12-09T19:14:20.911Z,0.000675,6.2495 +19314,2022-12-10T18:38:56.622Z,0.000673,6.2305 +19338,2022-12-11T18:03:32.332Z,0.000671,6.2114 +19362,2022-12-12T17:28:08.042Z,0.000669,6.1923 +19386,2022-12-13T16:52:43.753Z,0.000668,6.1828 +19410,2022-12-14T16:17:19.463Z,0.000666,6.1637 +22386,2023-04-14T15:07:07.547Z,0.000665,6.1542 +22410,2023-04-15T14:31:43.257Z,0.000664,6.1446 +22434,2023-04-16T13:56:18.967Z,0.000663,6.1351 +22458,2023-04-17T13:20:54.678Z,0.000662,6.1256 +22482,2023-04-18T12:45:30.388Z,0.000661,6.1160 +22506,2023-04-19T12:10:06.098Z,0.000660,6.1065 +22530,2023-04-20T11:34:41.809Z,0.000659,6.0970 +22554,2023-04-21T10:59:17.519Z,0.000658,6.0874 +22578,2023-04-22T10:23:53.229Z,0.000657,6.0779 +22602,2023-04-23T09:48:28.940Z,0.000656,6.0684 +22626,2023-04-24T09:13:04.650Z,0.000655,6.0589 +22650,2023-04-25T08:37:40.360Z,0.000653,6.0398 +22674,2023-04-26T08:02:16.071Z,0.000651,6.0208 +22698,2023-04-27T07:26:51.781Z,0.000649,6.0017 +22722,2023-04-28T06:51:27.492Z,0.000647,5.9827 +22746,2023-04-29T06:16:03.202Z,0.000645,5.9637 +22770,2023-04-30T05:40:38.912Z,0.000643,5.9446 +22794,2023-05-01T05:05:14.623Z,0.000640,5.9161 +22818,2023-05-02T04:29:50.333Z,0.000636,5.8780 +22842,2023-05-03T03:54:26.043Z,0.000633,5.8495 +22866,2023-05-04T03:19:01.754Z,0.000629,5.8115 +22890,2023-05-05T02:43:37.464Z,0.000624,5.7640 +22914,2023-05-06T02:08:13.174Z,0.000618,5.7070 +22938,2023-05-07T01:32:48.885Z,0.000612,5.6501 +22962,2023-05-08T00:57:24.595Z,0.000605,5.5837 +22986,2023-05-09T00:22:00.305Z,0.000597,5.5079 +23010,2023-05-09T23:46:36.016Z,0.000588,5.4226 +23034,2023-05-10T23:11:11.726Z,0.000578,5.3280 +23058,2023-05-11T22:35:47.436Z,0.000568,5.2334 +23082,2023-05-12T22:00:23.147Z,0.000557,5.1295 +23106,2023-05-13T21:24:58.857Z,0.000546,5.0257 +23130,2023-05-14T20:49:34.567Z,0.000536,4.9314 +23154,2023-05-15T20:14:10.278Z,0.000526,4.8372 +23178,2023-05-16T19:38:45.988Z,0.000517,4.7525 +23202,2023-05-17T19:03:21.699Z,0.000509,4.6773 +23226,2023-05-18T18:27:57.409Z,0.000502,4.6115 +23250,2023-05-19T17:52:33.119Z,0.000495,4.5458 +23274,2023-05-20T17:17:08.830Z,0.000490,4.4988 +23298,2023-05-21T16:41:44.540Z,0.000485,4.4519 +23322,2023-05-22T16:06:20.250Z,0.000481,4.4144 +23346,2023-05-23T15:30:55.961Z,0.000477,4.3769 +23370,2023-05-24T14:55:31.671Z,0.000474,4.3488 +23394,2023-05-25T14:20:07.381Z,0.000471,4.3207 +23418,2023-05-26T13:44:43.092Z,0.000468,4.2926 +23442,2023-05-27T13:09:18.802Z,0.000466,4.2739 +23466,2023-05-28T12:33:54.512Z,0.000464,4.2551 +23490,2023-05-29T11:58:30.223Z,0.000462,4.2364 +23514,2023-05-30T11:23:05.933Z,0.000460,4.2177 +23538,2023-05-31T10:47:41.643Z,0.000459,4.2083 +23562,2023-06-01T10:12:17.354Z,0.000457,4.1896 +23586,2023-06-02T09:36:53.064Z,0.000456,4.1803 +23610,2023-06-03T09:01:28.774Z,0.000455,4.1709 +23634,2023-06-04T08:26:04.485Z,0.000454,4.1615 +23658,2023-06-05T07:50:40.195Z,0.000453,4.1522 +23682,2023-06-06T07:15:15.906Z,0.000452,4.1428 +23706,2023-06-07T06:39:51.616Z,0.000451,4.1335 +23730,2023-06-08T06:04:27.326Z,0.000450,4.1241 +23754,2023-06-09T05:29:03.037Z,0.000449,4.1148 +26754,2023-10-09T03:43:26.830Z,0.000448,4.1054 +26802,2023-10-11T02:32:38.251Z,0.000447,4.0961 +26826,2023-10-12T01:57:13.961Z,0.000446,4.0867 +26874,2023-10-14T00:46:25.382Z,0.000445,4.0774 +26898,2023-10-15T00:11:01.093Z,0.000444,4.0680 +26946,2023-10-16T23:00:12.513Z,0.000443,4.0587 +26970,2023-10-17T22:24:48.224Z,0.000442,4.0493 +26994,2023-10-18T21:49:23.934Z,0.000441,4.0400 +27018,2023-10-19T21:13:59.644Z,0.000440,4.0307 +27042,2023-10-20T20:38:35.355Z,0.000438,4.0120 +27066,2023-10-21T20:03:11.065Z,0.000437,4.0026 +27090,2023-10-22T19:27:46.775Z,0.000436,3.9933 +27114,2023-10-23T18:52:22.486Z,0.000434,3.9746 +27138,2023-10-24T18:16:58.196Z,0.000432,3.9559 +27162,2023-10-25T17:41:33.906Z,0.000430,3.9373 +27186,2023-10-26T17:06:09.617Z,0.000428,3.9186 +27210,2023-10-27T16:30:45.327Z,0.000426,3.8999 +27234,2023-10-28T15:55:21.037Z,0.000423,3.8720 +27258,2023-10-29T15:19:56.748Z,0.000420,3.8440 +27282,2023-10-30T14:44:32.458Z,0.000416,3.8067 +27306,2023-10-31T14:09:08.168Z,0.000412,3.7694 +27330,2023-11-01T13:33:43.879Z,0.000407,3.7228 +27354,2023-11-02T12:58:19.589Z,0.000402,3.6762 +27378,2023-11-03T12:22:55.300Z,0.000396,3.6204 +27402,2023-11-04T11:47:31.010Z,0.000389,3.5553 +27426,2023-11-05T11:12:06.720Z,0.000381,3.4809 +27450,2023-11-06T10:36:42.431Z,0.000373,3.4066 +27474,2023-11-07T10:01:18.141Z,0.000365,3.3323 +27498,2023-11-08T09:25:53.851Z,0.000357,3.2581 +27522,2023-11-09T08:50:29.562Z,0.000349,3.1839 +27546,2023-11-10T08:15:05.272Z,0.000341,3.1098 +27570,2023-11-11T07:39:40.982Z,0.000334,3.0450 +27594,2023-11-12T07:04:16.693Z,0.000328,2.9895 +27618,2023-11-13T06:28:52.403Z,0.000323,2.9433 +27642,2023-11-14T05:53:28.113Z,0.000318,2.8971 +27666,2023-11-15T05:18:03.824Z,0.000314,2.8601 +27690,2023-11-16T04:42:39.534Z,0.000310,2.8232 +27714,2023-11-17T04:07:15.244Z,0.000307,2.7955 +27738,2023-11-18T03:31:50.955Z,0.000304,2.7678 +27762,2023-11-19T02:56:26.665Z,0.000302,2.7493 +27786,2023-11-20T02:21:02.375Z,0.000299,2.7216 +27810,2023-11-21T01:45:38.086Z,0.000297,2.7032 +27834,2023-11-22T01:10:13.796Z,0.000296,2.6940 +27858,2023-11-23T00:34:49.507Z,0.000294,2.6755 +27882,2023-11-23T23:59:25.217Z,0.000293,2.6663 +27906,2023-11-24T23:24:00.927Z,0.000291,2.6479 +27930,2023-11-25T22:48:36.638Z,0.000290,2.6386 +27954,2023-11-26T22:13:12.348Z,0.000289,2.6294 +27978,2023-11-27T21:37:48.058Z,0.000288,2.6202 +28002,2023-11-28T21:02:23.769Z,0.000287,2.6110 +28050,2023-11-30T19:51:35.189Z,0.000286,2.6018 +28074,2023-12-01T19:16:10.900Z,0.000285,2.5926 +28122,2023-12-03T18:05:22.320Z,0.000284,2.5834 +28146,2023-12-04T17:29:58.031Z,0.000283,2.5741 +90000,2030-12-14T02:24:28Z,0.000283,2.5741 diff --git a/assets/fonts/Roboto-Medium-7c8d04cd831df3033c8a96a2668d645e.ttf b/assets/fonts/Roboto-Medium-7c8d04cd831df3033c8a96a2668d645e.ttf new file mode 100644 index 0000000000..ac0f908b9c Binary files /dev/null and b/assets/fonts/Roboto-Medium-7c8d04cd831df3033c8a96a2668d645e.ttf differ diff --git a/assets/fonts/Roboto-Regular-fc2b5060f7accec5cf74437196c1b027.ttf b/assets/fonts/Roboto-Regular-fc2b5060f7accec5cf74437196c1b027.ttf new file mode 100644 index 0000000000..ddf4bfacb3 Binary files /dev/null and b/assets/fonts/Roboto-Regular-fc2b5060f7accec5cf74437196c1b027.ttf differ diff --git a/assets/fonts/RobotoMono-Regular-94ffabb10cbc81ee42ba565b8fce9542.ttf b/assets/fonts/RobotoMono-Regular-94ffabb10cbc81ee42ba565b8fce9542.ttf new file mode 100644 index 0000000000..6df2b25360 Binary files /dev/null and b/assets/fonts/RobotoMono-Regular-94ffabb10cbc81ee42ba565b8fce9542.ttf differ 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/account-069b6ef007c33f2910379fbf63d87e8d.png b/assets/images/account-069b6ef007c33f2910379fbf63d87e8d.png new file mode 100644 index 0000000000..242dd0156a Binary files /dev/null and b/assets/images/account-069b6ef007c33f2910379fbf63d87e8d.png differ diff --git a/assets/images/account-popup-theme-dark-35de04ee7c5c16f57ad9cb3c31f7c5f4.png b/assets/images/account-popup-theme-dark-35de04ee7c5c16f57ad9cb3c31f7c5f4.png new file mode 100644 index 0000000000..c4fed74b75 Binary files /dev/null and b/assets/images/account-popup-theme-dark-35de04ee7c5c16f57ad9cb3c31f7c5f4.png differ diff --git a/assets/images/account_history-8cb60b00f32ab450bfa579f4e19a79a8.png b/assets/images/account_history-8cb60b00f32ab450bfa579f4e19a79a8.png new file mode 100644 index 0000000000..d12bd033d2 Binary files /dev/null and b/assets/images/account_history-8cb60b00f32ab450bfa579f4e19a79a8.png differ diff --git a/assets/images/accounts1-e6156dbb8ecdafc396eb0def137a062e.png b/assets/images/accounts1-e6156dbb8ecdafc396eb0def137a062e.png new file mode 100644 index 0000000000..12030aba61 Binary files /dev/null and b/assets/images/accounts1-e6156dbb8ecdafc396eb0def137a062e.png differ diff --git a/assets/images/accounts2-374ff3f5128e7f6683c4f5e5ef7cb7d0.png b/assets/images/accounts2-374ff3f5128e7f6683c4f5e5ef7cb7d0.png new file mode 100644 index 0000000000..9e3802ba94 Binary files /dev/null and b/assets/images/accounts2-374ff3f5128e7f6683c4f5e5ef7cb7d0.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/buy-731cdec1adebae502b372cf799dcfb1e.png b/assets/images/buy-731cdec1adebae502b372cf799dcfb1e.png new file mode 100644 index 0000000000..3f941924ed Binary files /dev/null and b/assets/images/buy-731cdec1adebae502b372cf799dcfb1e.png differ diff --git a/assets/images/c10l-smart-contract-call.mmd-bba499f12d79733189ed91fd919480b9.svg b/assets/images/c10l-smart-contract-call.mmd-bba499f12d79733189ed91fd919480b9.svg new file mode 100644 index 0000000000..030c019fcd --- /dev/null +++ b/assets/images/c10l-smart-contract-call.mmd-bba499f12d79733189ed91fd919480b9.svg @@ -0,0 +1 @@ +Oasis NodeKey Manager🔒Oasis NodeSapphire ParaTimeCompute 🔒Oasis NodeSapphireParaTime ClientOasis Web3GatewayClient(e.g. Node.js,MetaMask)Oasis NodeKey Manager🔒Oasis NodeSapphire ParaTimeCompute 🔒Oasis NodeSapphireParaTime ClientOasis Web3GatewayClient(e.g. Node.js,MetaMask)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'34 \ No newline at end of file diff --git a/assets/images/c10l-smart-contract-tx.mmd-1979dfebd7f16fb909380088da1c7be2.svg b/assets/images/c10l-smart-contract-tx.mmd-1979dfebd7f16fb909380088da1c7be2.svg new file mode 100644 index 0000000000..da9b8c787d --- /dev/null +++ b/assets/images/c10l-smart-contract-tx.mmd-1979dfebd7f16fb909380088da1c7be2.svg @@ -0,0 +1 @@ +Oasis NodeKey Manager🔒Oasis NodeSapphire ParaTimeCompute 🔒Oasis NodeSapphireParaTime ClientOasis Web3GatewayClient(e.g. Node.js,MetaMask)Oasis NodeKey Manager🔒Oasis NodeSapphire ParaTimeCompute 🔒Oasis NodeSapphireParaTime ClientOasis Web3GatewayClient(e.g. Node.js,MetaMask)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'34 \ No newline at end of file diff --git a/assets/images/chrome_web_store-567139994ac68a1da47074c041cbe959.png b/assets/images/chrome_web_store-567139994ac68a1da47074c041cbe959.png new file mode 100644 index 0000000000..bc1b3e5e89 Binary files /dev/null and b/assets/images/chrome_web_store-567139994ac68a1da47074c041cbe959.png differ diff --git a/assets/images/client-km-compute-e82d4c5748974134adbf78d76ca7bc03.svg b/assets/images/client-km-compute-e82d4c5748974134adbf78d76ca7bc03.svg new file mode 100644 index 0000000000..445fe55b7e --- /dev/null +++ b/assets/images/client-km-compute-e82d4c5748974134adbf78d76ca7bc03.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/create_new_wallet_mnemonic1-38b8681e7bfcb96e2f35c6ea81c66400.png b/assets/images/create_new_wallet_mnemonic1-38b8681e7bfcb96e2f35c6ea81c66400.png new file mode 100644 index 0000000000..dad1672a24 Binary files /dev/null and b/assets/images/create_new_wallet_mnemonic1-38b8681e7bfcb96e2f35c6ea81c66400.png differ diff --git a/assets/images/create_new_wallet_mnemonic2-451cacc316cbf85ce52d57e0e6ffa5ae.png b/assets/images/create_new_wallet_mnemonic2-451cacc316cbf85ce52d57e0e6ffa5ae.png new file mode 100644 index 0000000000..5adfce0d92 Binary files /dev/null and b/assets/images/create_new_wallet_mnemonic2-451cacc316cbf85ce52d57e0e6ffa5ae.png differ diff --git a/assets/images/create_new_wallet_select_accounts-a7c877683969a6d60d685e180fdcdf85.png b/assets/images/create_new_wallet_select_accounts-a7c877683969a6d60d685e180fdcdf85.png new file mode 100644 index 0000000000..a063865ca3 Binary files /dev/null and b/assets/images/create_new_wallet_select_accounts-a7c877683969a6d60d685e180fdcdf85.png differ diff --git a/assets/images/create_wallet-6f84ae326fa8da9fbeae3cb443992027.png b/assets/images/create_wallet-6f84ae326fa8da9fbeae3cb443992027.png new file mode 100644 index 0000000000..9e447bb14e Binary files /dev/null and b/assets/images/create_wallet-6f84ae326fa8da9fbeae3cb443992027.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/delegate1-5dc23231b5295a1105cdbc2fe05cb643.png b/assets/images/delegate1-5dc23231b5295a1105cdbc2fe05cb643.png new file mode 100644 index 0000000000..fe642116a1 Binary files /dev/null and b/assets/images/delegate1-5dc23231b5295a1105cdbc2fe05cb643.png differ diff --git a/assets/images/delegate2-0bcfa6e0aafaeeb26567ca27983c5b7b.png b/assets/images/delegate2-0bcfa6e0aafaeeb26567ca27983c5b7b.png new file mode 100644 index 0000000000..4e7d8cc26b Binary files /dev/null and b/assets/images/delegate2-0bcfa6e0aafaeeb26567ca27983c5b7b.png differ diff --git a/assets/images/delegate3-bb0733c0cb1ee723c180e19ad8cd7b82.png b/assets/images/delegate3-bb0733c0cb1ee723c180e19ad8cd7b82.png new file mode 100644 index 0000000000..c24cd1bfc1 Binary files /dev/null and b/assets/images/delegate3-bb0733c0cb1ee723c180e19ad8cd7b82.png differ diff --git a/assets/images/deposit-d0f6ca5b1c65739f54bbfa7867959334.png b/assets/images/deposit-d0f6ca5b1c65739f54bbfa7867959334.png new file mode 100644 index 0000000000..2b12f22e70 Binary files /dev/null and b/assets/images/deposit-d0f6ca5b1c65739f54bbfa7867959334.png differ diff --git a/assets/images/deposit1-ffc383d09d522d55905019dc23c625b9.png b/assets/images/deposit1-ffc383d09d522d55905019dc23c625b9.png new file mode 100644 index 0000000000..59f8970f7b Binary files /dev/null and b/assets/images/deposit1-ffc383d09d522d55905019dc23c625b9.png differ diff --git a/assets/images/deposit2-cb492dc855a1a94e4ec7f10f0f673c3d.png b/assets/images/deposit2-cb492dc855a1a94e4ec7f10f0f673c3d.png new file mode 100644 index 0000000000..edf44e77a7 Binary files /dev/null and b/assets/images/deposit2-cb492dc855a1a94e4ec7f10f0f673c3d.png differ diff --git a/assets/images/deposit3-d93d91d93b730749f94b32aeec0c736b.png b/assets/images/deposit3-d93d91d93b730749f94b32aeec0c736b.png new file mode 100644 index 0000000000..d5c1ba4ae8 Binary files /dev/null and b/assets/images/deposit3-d93d91d93b730749f94b32aeec0c736b.png differ diff --git a/assets/images/deposit4-b9134f051774cf4e3e54937c7bf7a35a.png b/assets/images/deposit4-b9134f051774cf4e3e54937c7bf7a35a.png new file mode 100644 index 0000000000..66aaa7ec6d Binary files /dev/null and b/assets/images/deposit4-b9134f051774cf4e3e54937c7bf7a35a.png differ diff --git a/assets/images/deposit5-f62af89e934740457be2f9ed9d7d6f25.png b/assets/images/deposit5-f62af89e934740457be2f9ed9d7d6f25.png new file mode 100644 index 0000000000..ef75373145 Binary files /dev/null and b/assets/images/deposit5-f62af89e934740457be2f9ed9d7d6f25.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/home-5ec3d62748626a64eb39984984d7008a.png b/assets/images/home-5ec3d62748626a64eb39984984d7008a.png new file mode 100644 index 0000000000..aeaee0e359 Binary files /dev/null and b/assets/images/home-5ec3d62748626a64eb39984984d7008a.png differ diff --git a/assets/images/import-8dc1af399466eba46658807f9d041223.png b/assets/images/import-8dc1af399466eba46658807f9d041223.png new file mode 100644 index 0000000000..07eb4093f1 Binary files /dev/null and b/assets/images/import-8dc1af399466eba46658807f9d041223.png differ diff --git a/assets/images/import2-6d7311fead222a1018d2cff955b43d6e.png b/assets/images/import2-6d7311fead222a1018d2cff955b43d6e.png new file mode 100644 index 0000000000..3c7fa6f671 Binary files /dev/null and b/assets/images/import2-6d7311fead222a1018d2cff955b43d6e.png differ diff --git a/assets/images/import3-33c28731c0ceaa30a8621945d48227eb.png b/assets/images/import3-33c28731c0ceaa30a8621945d48227eb.png new file mode 100644 index 0000000000..13875bff41 Binary files /dev/null and b/assets/images/import3-33c28731c0ceaa30a8621945d48227eb.png differ diff --git a/assets/images/import_wallet-498120a93d2f76cac5074fc9d70bc07d.png b/assets/images/import_wallet-498120a93d2f76cac5074fc9d70bc07d.png new file mode 100644 index 0000000000..e59591528b Binary files /dev/null and b/assets/images/import_wallet-498120a93d2f76cac5074fc9d70bc07d.png differ diff --git a/assets/images/import_wallet_ledger-b18f1448c7cdb73234c04c08df955b26.png b/assets/images/import_wallet_ledger-b18f1448c7cdb73234c04c08df955b26.png new file mode 100644 index 0000000000..df718ed18e Binary files /dev/null and b/assets/images/import_wallet_ledger-b18f1448c7cdb73234c04c08df955b26.png differ diff --git a/assets/images/import_wallet_mnemonic-6aa686a800639c41102700240187d2ad.png b/assets/images/import_wallet_mnemonic-6aa686a800639c41102700240187d2ad.png new file mode 100644 index 0000000000..e3798d2f17 Binary files /dev/null and b/assets/images/import_wallet_mnemonic-6aa686a800639c41102700240187d2ad.png differ diff --git a/assets/images/import_wallet_private_key-7e84a4df8e22b91eee2cb1073c9451d2.png b/assets/images/import_wallet_private_key-7e84a4df8e22b91eee2cb1073c9451d2.png new file mode 100644 index 0000000000..592558e530 Binary files /dev/null and b/assets/images/import_wallet_private_key-7e84a4df8e22b91eee2cb1073c9451d2.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/ledger1-00e350e8cc5168c58d3dbd56d72f0357.png b/assets/images/ledger1-00e350e8cc5168c58d3dbd56d72f0357.png new file mode 100644 index 0000000000..59a1deba85 Binary files /dev/null and b/assets/images/ledger1-00e350e8cc5168c58d3dbd56d72f0357.png differ diff --git a/assets/images/ledger2-ace8c17920abf877d4c68f40c1854eb3.png b/assets/images/ledger2-ace8c17920abf877d4c68f40c1854eb3.png new file mode 100644 index 0000000000..5cdb569153 Binary files /dev/null and b/assets/images/ledger2-ace8c17920abf877d4c68f40c1854eb3.png differ diff --git a/assets/images/ledger3-bd9f503231d12dec0764340d7695cb5a.png b/assets/images/ledger3-bd9f503231d12dec0764340d7695cb5a.png new file mode 100644 index 0000000000..53d105bef3 Binary files /dev/null and b/assets/images/ledger3-bd9f503231d12dec0764340d7695cb5a.png differ diff --git a/assets/images/ledger_oasis_approve-107bae9057a413cc91850ab7cceb910e.jpg b/assets/images/ledger_oasis_approve-107bae9057a413cc91850ab7cceb910e.jpg new file mode 100644 index 0000000000..2aa8d707dd Binary files /dev/null and b/assets/images/ledger_oasis_approve-107bae9057a413cc91850ab7cceb910e.jpg 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-0d550bcf5c975eaef183b78baa74b269.png b/assets/images/live_allow_ledger_manager-0d550bcf5c975eaef183b78baa74b269.png new file mode 100644 index 0000000000..2722486696 Binary files /dev/null and b/assets/images/live_allow_ledger_manager-0d550bcf5c975eaef183b78baa74b269.png differ diff --git a/assets/images/live_search_apps-0c74d0a0063a45242988e15770c01176.png b/assets/images/live_search_apps-0c74d0a0063a45242988e15770c01176.png new file mode 100644 index 0000000000..fb7dd76b29 Binary files /dev/null and b/assets/images/live_search_apps-0c74d0a0063a45242988e15770c01176.png differ diff --git a/assets/images/live_search_results_oasis_install-320e7861a97fc5b72575c82d0edbcde8.png b/assets/images/live_search_results_oasis_install-320e7861a97fc5b72575c82d0edbcde8.png new file mode 100644 index 0000000000..4d43675a39 Binary files /dev/null and b/assets/images/live_search_results_oasis_install-320e7861a97fc5b72575c82d0edbcde8.png differ diff --git a/assets/images/live_unlock_ledger-ef4071262dfbba6f5c0544a7efd15b5e.png b/assets/images/live_unlock_ledger-ef4071262dfbba6f5c0544a7efd15b5e.png new file mode 100644 index 0000000000..86ae2129a6 Binary files /dev/null and b/assets/images/live_unlock_ledger-ef4071262dfbba6f5c0544a7efd15b5e.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/no-profile-dark-theme-74306637e0c241922b8c7982372540af.png b/assets/images/no-profile-dark-theme-74306637e0c241922b8c7982372540af.png new file mode 100644 index 0000000000..3680646345 Binary files /dev/null and b/assets/images/no-profile-dark-theme-74306637e0c241922b8c7982372540af.png differ diff --git a/assets/images/oasis-core-consensus-cometbft-b8a8c686399e911605ee9c0bcfe687b5.svg b/assets/images/oasis-core-consensus-cometbft-b8a8c686399e911605ee9c0bcfe687b5.svg new file mode 100644 index 0000000000..3ca80a0abd --- /dev/null +++ b/assets/images/oasis-core-consensus-cometbft-b8a8c686399e911605ee9c0bcfe687b5.svg @@ -0,0 +1,3 @@ + + +
CometBFT Core
CometBFT 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
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/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/oasisscan_account_details-7d22b004206bda2502eee1ff799f731c.png b/assets/images/oasisscan_account_details-7d22b004206bda2502eee1ff799f731c.png new file mode 100644 index 0000000000..b6faa0744a Binary files /dev/null and b/assets/images/oasisscan_account_details-7d22b004206bda2502eee1ff799f731c.png differ diff --git a/assets/images/oasisscan_paratime_tx_details-9769c53959d64e58ffa4a387b78aede5.png b/assets/images/oasisscan_paratime_tx_details-9769c53959d64e58ffa4a387b78aede5.png new file mode 100644 index 0000000000..614aac940e Binary files /dev/null and b/assets/images/oasisscan_paratime_tx_details-9769c53959d64e58ffa4a387b78aede5.png differ diff --git a/assets/images/oasisscan_paratime_txes-e8560712be9b215cd6aca4ceb52c892f.png b/assets/images/oasisscan_paratime_txes-e8560712be9b215cd6aca4ceb52c892f.png new file mode 100644 index 0000000000..dc7e1e2ad8 Binary files /dev/null and b/assets/images/oasisscan_paratime_txes-e8560712be9b215cd6aca4ceb52c892f.png differ diff --git a/assets/images/oasisscan_validators-179f0f40e82465fad25d3d9fa6bd87c5.png b/assets/images/oasisscan_validators-179f0f40e82465fad25d3d9fa6bd87c5.png new file mode 100644 index 0000000000..8630d8c170 Binary files /dev/null and b/assets/images/oasisscan_validators-179f0f40e82465fad25d3d9fa6bd87c5.png differ diff --git a/assets/images/opl-contract-flow.mmd-a7b41e513987dc5c2d364b283a8147ec.svg b/assets/images/opl-contract-flow.mmd-a7b41e513987dc5c2d364b283a8147ec.svg new file mode 100644 index 0000000000..81940a489e --- /dev/null +++ b/assets/images/opl-contract-flow.mmd-a7b41e513987dc5c2d364b283a8147ec.svg @@ -0,0 +1 @@ +Sapphire ContractExecutorSGNHome ContractUserSapphire ContractExecutorSGNHome ContractUserTransactionSGN Watches EventsWaits for SGN ApprovalSubmit Proof Tx \ No newline at end of file diff --git a/assets/images/paratimes-ba19a88dd7d5bcb85ecce1a4ba286380.png b/assets/images/paratimes-ba19a88dd7d5bcb85ecce1a4ba286380.png new file mode 100644 index 0000000000..6b0bd69766 Binary files /dev/null and b/assets/images/paratimes-ba19a88dd7d5bcb85ecce1a4ba286380.png differ diff --git a/assets/images/paratimes-e69d45c9f116673d5250e2c5e2253a28.png b/assets/images/paratimes-e69d45c9f116673d5250e2c5e2253a28.png new file mode 100644 index 0000000000..4fb8541d78 Binary files /dev/null and b/assets/images/paratimes-e69d45c9f116673d5250e2c5e2253a28.png differ diff --git a/assets/images/paratimes2-718728090a646032557a7a9260a4c7fc.png b/assets/images/paratimes2-718728090a646032557a7a9260a4c7fc.png new file mode 100644 index 0000000000..0cd4280a9f Binary files /dev/null and b/assets/images/paratimes2-718728090a646032557a7a9260a4c7fc.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/rofl-6f0e9734207a8490d8a0cf83d21f10c1.svg b/assets/images/rofl-6f0e9734207a8490d8a0cf83d21f10c1.svg new file mode 100644 index 0000000000..92a0e1b5bf --- /dev/null +++ b/assets/images/rofl-6f0e9734207a8490d8a0cf83d21f10c1.svg @@ -0,0 +1,4 @@ + + + +
Oasis Node
TEE
ROFL App
Attestation
Light Client
TEE
ROFL App
Attestation
Light Client
TEE
ROFL App
Attestation
Light Client
Oasis Network
Consensus Layer
Sapphire
...
Outside
World
HTTPS etc.
\ No newline at end of file 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-939608ea8571e8881597cf3b86e09c98.png b/assets/images/settings-939608ea8571e8881597cf3b86e09c98.png new file mode 100644 index 0000000000..215404e1be Binary files /dev/null and b/assets/images/settings-939608ea8571e8881597cf3b86e09c98.png differ diff --git a/assets/images/settings-my-accounts-53f9c36b01d46ec195cc497ee62a65d3.png b/assets/images/settings-my-accounts-53f9c36b01d46ec195cc497ee62a65d3.png new file mode 100644 index 0000000000..3d17f30edd Binary files /dev/null and b/assets/images/settings-my-accounts-53f9c36b01d46ec195cc497ee62a65d3.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/stake-86196edcc331d1c43f8c237fc9f6798a.png b/assets/images/stake-86196edcc331d1c43f8c237fc9f6798a.png new file mode 100644 index 0000000000..185e2b4241 Binary files /dev/null and b/assets/images/stake-86196edcc331d1c43f8c237fc9f6798a.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/transfer-d8fb8e130893a73fc982b7fe4e3edf89.png b/assets/images/transfer-d8fb8e130893a73fc982b7fe4e3edf89.png new file mode 100644 index 0000000000..1186e07d48 Binary files /dev/null and b/assets/images/transfer-d8fb8e130893a73fc982b7fe4e3edf89.png differ diff --git a/assets/images/transfer_deposit_withdrawal-53746f908d877b4df255879762c41fa5.svg b/assets/images/transfer_deposit_withdrawal-53746f908d877b4df255879762c41fa5.svg new file mode 100644 index 0000000000..228d82d9b9 --- /dev/null +++ b/assets/images/transfer_deposit_withdrawal-53746f908d877b4df255879762c41fa5.svg @@ -0,0 +1,1486 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DepositWithdrawalTransferTransferoasis1qrydpazemvuwt...0x709EEbd979328A2... diff --git a/assets/images/undelegate1-84aee243b96036b49f330f15f786840a.png b/assets/images/undelegate1-84aee243b96036b49f330f15f786840a.png new file mode 100644 index 0000000000..e5a8488792 Binary files /dev/null and b/assets/images/undelegate1-84aee243b96036b49f330f15f786840a.png differ diff --git a/assets/images/undelegate2-2d8bc2659568544bc805950f74b1db8b.png b/assets/images/undelegate2-2d8bc2659568544bc805950f74b1db8b.png new file mode 100644 index 0000000000..4ecfe4923c Binary files /dev/null and b/assets/images/undelegate2-2d8bc2659568544bc805950f74b1db8b.png differ diff --git a/assets/images/undelegate3-8e001bea81c0d7acbec6bc7b0446251c.png b/assets/images/undelegate3-8e001bea81c0d7acbec6bc7b0446251c.png new file mode 100644 index 0000000000..72d9cfd704 Binary files /dev/null and b/assets/images/undelegate3-8e001bea81c0d7acbec6bc7b0446251c.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-b8c6aa32364d6e48a645937ed36caa31.png b/assets/images/wallet-b8c6aa32364d6e48a645937ed36caa31.png new file mode 100644 index 0000000000..44c5ee7808 Binary files /dev/null and b/assets/images/wallet-b8c6aa32364d6e48a645937ed36caa31.png differ diff --git a/assets/images/withdraw1-cab846888c907bfd23795853ca1af848.png b/assets/images/withdraw1-cab846888c907bfd23795853ca1af848.png new file mode 100644 index 0000000000..bb78e0c81a Binary files /dev/null and b/assets/images/withdraw1-cab846888c907bfd23795853ca1af848.png differ diff --git a/assets/images/withdraw2-857212a0823e3587a03b806112d7aee4.png b/assets/images/withdraw2-857212a0823e3587a03b806112d7aee4.png new file mode 100644 index 0000000000..970fb85ad9 Binary files /dev/null and b/assets/images/withdraw2-857212a0823e3587a03b806112d7aee4.png differ diff --git a/assets/images/withdraw3-81164f3b2c4f3cb1b590b87dba90a2f3.png b/assets/images/withdraw3-81164f3b2c4f3cb1b590b87dba90a2f3.png new file mode 100644 index 0000000000..b0ca7ef84f Binary files /dev/null and b/assets/images/withdraw3-81164f3b2c4f3cb1b590b87dba90a2f3.png differ diff --git a/assets/images/withdraw4-fa7a18227b15d6afe180c3301d44e805.png b/assets/images/withdraw4-fa7a18227b15d6afe180c3301d44e805.png new file mode 100644 index 0000000000..658cd72efd Binary files /dev/null and b/assets/images/withdraw4-fa7a18227b15d6afe180c3301d44e805.png differ diff --git a/assets/images/withdraw5-5c0d0aa06a45f88ffef0c34b380eb53d.png b/assets/images/withdraw5-5c0d0aa06a45f88ffef0c34b380eb53d.png new file mode 100644 index 0000000000..36c896636a Binary files /dev/null and b/assets/images/withdraw5-5c0d0aa06a45f88ffef0c34b380eb53d.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.fcdc000c.js b/assets/js/00eda7cc.fcdc000c.js new file mode 100644 index 0000000000..f648dfe443 --- /dev/null +++ b/assets/js/00eda7cc.fcdc000c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4754],{2268:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>s,metadata:()=>d,toc:()=>l});var i=t(4848),r=t(8453);const s={},o="Deploying a Runtime",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/deploying-a-runtime.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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"}},a={},l=[{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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"deploying-a-runtime",children:"Deploying a Runtime"}),"\n",(0,i.jsxs)(n.p,{children:["Before proceeding, make sure to look at the ",(0,i.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"prerequisites"})," required for running\nan Oasis Core environment followed by ",(0,i.jsx)(n.a,{href:"/core/development-setup/building",children:"build instructions"})," for the respective\nenvironment (non-SGX or SGX), using the ",(0,i.jsx)(n.a,{href:"/core/development-setup/oasis-net-runner",children:(0,i.jsx)(n.code,{children:"oasis-net-runner"})})," and see ",(0,i.jsx)(n.a,{href:"/core/runtime/",children:"runtime\ndocumentation"})," for a general documentation on runtimes."]}),"\n",(0,i.jsx)(n.p,{children:"These instructions will show how to register and deploy a runtime node on a\nlocal development network."}),"\n",(0,i.jsx)(n.h2,{id:"provision-a-single-validator-node-network",children:"Provision a Single Validator Node Network"}),"\n",(0,i.jsxs)(n.p,{children:["Use the ",(0,i.jsx)(n.a,{href:"/core/development-setup/oasis-net-runner",children:(0,i.jsx)(n.code,{children:"oasis-net-runner"})})," to provision a validator node network without any\nregistered runtimes."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsxs)(n.p,{children:["The following steps should be run in a separate terminal window. To simplify the\ninstructions set up an ",(0,i.jsx)(n.code,{children:"ADDR"})," environment variable pointing to the UNIX socket\nexposed by the started node:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"export ADDR=unix:/tmp/runtime-example/net-runner/network/validator-0/internal.sock\n"})}),"\n",(0,i.jsx)(n.p,{children:"Confirm the network is running by listing all registered entities:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node registry entity list -a $ADDR -v\n"})}),"\n",(0,i.jsx)(n.p,{children:"Should give output similar to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'{"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'})}),"\n",(0,i.jsxs)(n.p,{children:["In following steps we will register and run the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue",children:"simple-keyvalue"})," runtime on the\nnetwork."]}),"\n",(0,i.jsx)(n.h2,{id:"initializing-a-runtime",children:"Initializing a Runtime"}),"\n",(0,i.jsxs)(n.p,{children:["To generate and sign a runtime registration transaction that will initialize and\nregister the runtime we will use the ",(0,i.jsx)(n.code,{children:"registry runtime gen_register"})," command.\nWhen initializing a runtime we need to provide the runtime descriptor."]}),"\n",(0,i.jsxs)(n.p,{children:["For additional information about runtimes and parameters see the ",(0,i.jsx)(n.a,{href:"/core/runtime/",children:"runtime\ndocumentation"})," and ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime",children:"code reference"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Before generating the registration transaction, gather the following data and\nset up environment variables to simplify instructions."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"entity-2"})," entity (located\nin ",(0,i.jsx)(n.code,{children:"/tmp/runtime-example/net-runner/network/entity-2/"})," directory)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"ENTITY_ID"})," - ID of the entity that will be the owner of the runtime. You can\nget the entity ID from ",(0,i.jsx)(n.code,{children:"$ENTITY_DIR/entity.json"})," file."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"GENESIS_JSON"})," - Path to the genesis.json file used in the development\nnetwork. (defaults to:\n",(0,i.jsx)(n.code,{children:"/tmp/runtime-example/net-runner/network/genesis.json"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"RUNTIME_ID"})," - See ",(0,i.jsx)(n.a,{href:"/core/runtime/identifiers",children:"runtime identifiers"})," on how to choose a runtime\nidentifier. In this example we use\n",(0,i.jsx)(n.code,{children:"8000000000000000000000000000000000000000000000000000000001234567"})," which is a\ntest identifier that will not work outside local tests."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"RUNTIME_GENESIS_JSON"})," - Path to the runtime genesis state file. The runtime\nused in this example does not use a genesis file."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"NONCE"})," - Entity account nonce. If you followed the guide, nonce ",(0,i.jsx)(n.code,{children:"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,i.jsx)(n.a,{href:"/core/oasis-node/cli#info",children:"stake account info"})," CLI."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsx)(n.p,{children:"Prepare a runtime descriptor:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'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'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsxs)(n.p,{children:["After confirmation, this command outputs a signed transaction in the\n",(0,i.jsx)(n.code,{children:"/tmp/runtime-example/register_runtime.tx"})," file. In the next step we will submit\nthe transaction to complete the runtime registration."]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["When registering a runtime on a ",(0,i.jsx)(n.em,{children:"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,i.jsx)(n.code,{children:"debug.dont_blame_oasis"})," and\n",(0,i.jsx)(n.code,{children:"debug.allow_test_keys"})," flags."]})}),"\n",(0,i.jsx)(n.h2,{id:"submitting-the-runtime-register-transaction",children:"Submitting the Runtime Register Transaction"}),"\n",(0,i.jsx)(n.p,{children:"To register the runtime, submit the generated transaction."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node consensus submit_tx \\\n --transaction.file /tmp/runtime-example/register_runtime.tx \\\n --address $ADDR\n"})}),"\n",(0,i.jsx)(n.h2,{id:"confirm-runtime-is-registered",children:"Confirm Runtime is Registered"}),"\n",(0,i.jsxs)(n.p,{children:["To confirm the runtime is registered use the ",(0,i.jsx)(n.code,{children:"registry runtime list"})," command."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node registry runtime list \\\n --verbose \\\n --include_suspended \\\n --address $ADDR\n"})}),"\n",(0,i.jsx)(n.p,{children:"Should give output similar to"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'{\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'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Since we did not setup any runtime nodes, the runtime\nwill get ",(0,i.jsx)(n.a,{href:"/core/runtime/#suspending-runtimes",children:"suspended"})," until nodes for the runtime register."]})}),"\n",(0,i.jsx)(n.p,{children:"In the next step we will setup and run a runtime node."}),"\n",(0,i.jsx)(n.h2,{id:"running-a-runtime-node",children:"Running a Runtime Node"}),"\n",(0,i.jsx)(n.p,{children:"We will now run a node that will act as a compute, storage and client node for\nthe runtime."}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"In a real word scenario there would be multiple nodes\nrunning the runtime, each likely serving as a single type only."})}),"\n",(0,i.jsx)(n.p,{children:"Before running the node, gather the following data parameters and set up\nenvironment variables to simplify instructions."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"RUNTIME_BINARY"})," - Path to the runtime binary that will be run on the node. We\nwill use the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue",children:"simple-keyvalue"})," runtime. If you followed the ",(0,i.jsx)(n.a,{href:"/core/development-setup/building",children:"build\ninstructions"})," the built binary is available at\n",(0,i.jsx)(n.code,{children:"./target/default/release/simple-keyvalue"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"SEED_NODE_ADDRESS"})," - Address of the seed node in the development network.\nSeed node address can be seen in the ",(0,i.jsx)(n.code,{children:"oasis-net-runner"})," logs, when the network\nis initially provisioned."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"export RUNTIME_BINARY=/workdir/target/default/release/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.cometbft.debug.addr_book_lenient \\\n --consensus.cometbft.debug.allow_duplicate_ip \\\n --consensus.cometbft.p2p.seed $SEED_NODE_ADDRESS \\\n --debug.dont_blame_oasis \\\n --debug.allow_test_keys\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsx)(n.p,{children:"This also enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise."})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["When running a runtime node in a production setting, the ",(0,i.jsx)(n.code,{children:"p2p.addresses"})," flag\nneeds to be configured as well."]})}),"\n",(0,i.jsx)(n.p,{children:"Following steps should be run in a new terminal window."}),"\n",(0,i.jsx)(n.h2,{id:"updating-entity-nodes",children:"Updating Entity Nodes"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"/tmp/runtime-example/runtime-node/identity_pub.pem"})," (or using the ",(0,i.jsx)(n.a,{href:"/core/oasis-node/cli#status",children:"node control\nstatus command"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"Update the entity and generate a transaction that will update the registry\nstate."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"# 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"})}),"\n",(0,i.jsx)(n.p,{children:"Submit the generated transaction:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node consensus submit_tx \\\n --transaction.file /tmp/runtime-example/update_entity.tx \\\n --address $ADDR\n"})}),"\n",(0,i.jsx)(n.p,{children:"Confirm the entity in the registry has been updated by querying the registry\nstate:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"Node is now able to register and the runtime should get resumed, make sure this\nhappens by querying the registry for runtimes:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'# 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'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"You might need to wait few seconds for an epoch\ntransition so that the node is registered and runtime gets resumed."})})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>d});var i=t(6540);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/03741c42.6176a22d.js b/assets/js/03741c42.6176a22d.js new file mode 100644 index 0000000000..a9b12cbfd5 --- /dev/null +++ b/assets/js/03741c42.6176a22d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[367],{2296:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var i=s(4848),r=s(8453);const o={},t="Oasis Core Developer Documentation",c={id:"core/README",title:"Oasis Core Developer Documentation",description:"Architecture",source:"@site/docs/core/README.md",sourceDirName:"core",slug:"/core/",permalink:"/core/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/README.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",next:{title:"Development Setup",permalink:"/core/development-setup"}},l={},d=[{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}];function a(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"oasis-core-developer-documentation",children:"Oasis Core Developer Documentation"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Architecture",src:s(5405).A+""})}),"\n",(0,i.jsx)(n.h2,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Build Environment Setup and Building","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"Prerequisites"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/building",children:"Building"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Running Tests and Development Networks","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/running-tests",children:"Running Tests"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/oasis-net-runner",children:"Local Network Runner With a Simple Runtime"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/single-validator-node-network",children:"Single Validator Node Network"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/development-setup/deploying-a-runtime",children:"Deploying a Runtime"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"high-level-components",children:"High-Level Components"}),"\n",(0,i.jsxs)(n.p,{children:["At the highest level, Oasis Core is divided into two major layers: the\n",(0,i.jsx)(n.em,{children:"consensus layer"})," and the ",(0,i.jsx)(n.em,{children:"runtime layer"})," as shown on the figure above."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Epoch-based time keeping and a random beacon."}),"\n",(0,i.jsx)(n.li,{children:"Basic staking operations required to operate a PoS blockchain."}),"\n",(0,i.jsx)(n.li,{children:"An entity, node and runtime registry that distributes public keys and\nmetadata."}),"\n",(0,i.jsx)(n.li,{children:"Runtime committee scheduling, commitment processing and minimal state keeping."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"See the following chapters for more details on specific components and their\nimplementations."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/core/consensus/",children:"Consensus Layer"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/transactions",children:"Transactions"})}),"\n",(0,i.jsxs)(n.li,{children:["Services","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/epochtime",children:"Epoch Time"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/beacon",children:"Random Beacon"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/staking",children:"Staking"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/registry",children:"Registry"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/scheduler",children:"Committee Scheduler"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/governance",children:"Governance"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"Root Hash"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/services/keymanager",children:"Key Manager"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/genesis",children:"Genesis Document"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/consensus/test-vectors",children:"Transaction Test Vectors"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/core/runtime/",children:"Runtime Layer"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/runtime/#operation-model",children:"Operation Model"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/runtime/runtime-host-protocol",children:"Runtime Host Protocol"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/runtime/identifiers",children:"Identifiers"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"Messages"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Oasis Node (",(0,i.jsx)(n.code,{children:"oasis-node"}),")","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/oasis-node/rpc",children:"RPC"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/oasis-node/metrics",children:"Metrics"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/oasis-node/cli",children:"CLI"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"common-functionality",children:"Common Functionality"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/encoding",children:"Serialization"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/crypto",children:"Cryptography"})}),"\n",(0,i.jsxs)(n.li,{children:["Protocols","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/authenticated-grpc",children:"Authenticated gRPC"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/mkvs",children:"Merklized Key-Value Store (MKVS)"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"processes",children:"Processes"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/adrs",children:"Architectural Decision Records"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/release-process",children:"Release Process"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/versioning",children:"Versioning"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/core/SECURITY",children:"Security"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},5405:(e,n,s)=>{s.d(n,{A:()=>i});const i=s.p+"assets/images/oasis-core-high-level-4dd19f00411531fadd7a32ea1d596e6f.svg"},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var i=s(6540);const r={},o=i.createContext(r);function t(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:t(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/041ef302.42bccadd.js b/assets/js/041ef302.42bccadd.js new file mode 100644 index 0000000000..48c381f97f --- /dev/null +++ b/assets/js/041ef302.42bccadd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3722],{8076:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>u,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>d});var i=r(4848),n=r(8453),s=r(2550),o=r(6116);const a={description:"Build your own ParaTime using Oasis Runtime SDK"},c="Build ParaTime",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/paratime/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Build your own ParaTime using Oasis Runtime SDK"},sidebar:"paratime",next:{title:"Prerequisites",permalink:"/paratime/prerequisites"}},u={},d=[];function m(e){const t={a:"a",h1:"h1",p:"p",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"build-paratime",children:"Build ParaTime"}),"\n",(0,i.jsxs)(t.p,{children:["This chapter will teach you how to build your own ParaTime with ",(0,i.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk",children:"Oasis Runtime\nSDK"}),"."]}),"\n",(0,i.jsx)(s.A,{items:[(0,o.$)("/paratime/prerequisites"),(0,o.$)("/paratime/minimal-runtime"),(0,o.$)("/paratime/modules"),(0,o.$)("/paratime/reproducibility"),(0,o.$)("https://api.docs.oasis.io/rust/oasis_runtime_sdk")]})]})}function p(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(m,{...e})}):m(e)}},5965:(e,t,r)=>{r.d(t,{A:()=>g});r(6540);var i=r(4164),n=r(8774),s=r(4142),o=r(5846),a=r(6654),c=r(1312),l=r(1107);const u={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var d=r(4848);function m(e){let{href:t,children:r}=e;return(0,d.jsx)(n.A,{href:t,className:(0,i.A)("card padding--lg",u.cardContainer),children:r})}function p(e){let{href:t,icon:r,title:n,description:s}=e;return(0,d.jsxs)(m,{href:t,children:[(0,d.jsxs)(l.A,{as:"h2",className:(0,i.A)("text--truncate",u.cardTitle),title:n,children:[r," ",n]}),s&&(0,d.jsx)("p",{className:(0,i.A)("text--truncate",u.cardDescription),title:s,children:s})]})}function h(e){let{item:t}=e;const r=(0,s.Nr)(t),i=function(){const{selectMessage:e}=(0,o.W)();return t=>e(t,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return r?(0,d.jsx)(p,{href:r,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??i(t.items.length)}):null}function f(e){let{item:t}=e;const r=(0,a.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",i=(0,s.cC)(t.docId??void 0);return(0,d.jsx)(p,{href:t.href,icon:r,title:t.label,description:t.description??i?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,d.jsx)(f,{item:t});case"category":return(0,d.jsx)(h,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,r)=>{r.d(t,{A:()=>c});r(6540);var i=r(4164),n=r(4142),s=r(5965),o=r(4848);function a(e){let{className:t}=e;const r=(0,n.$S)();return(0,o.jsx)(c,{items:r.items,className:t})}function c(e){const{items:t,className:r}=e;if(!t)return(0,o.jsx)(a,{...e});const c=(0,n.d1)(t);return(0,o.jsx)("section",{className:(0,i.A)("row",r),children:c.map(((e,t)=>(0,o.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,o.jsx)(s.A,{item:e})},t)))})}},5846:(e,t,r)=>{r.d(t,{W:()=>l});var i=r(6540),n=r(4586);const s=["zero","one","two","few","many","other"];function o(e){return s.filter((t=>e.includes(t)))}const a={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,n.A)();return(0,i.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:o(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`),a}}),[e])}function l(){const e=c();return{selectMessage:(t,r)=>function(e,t,r){const i=e.split("|");if(1===i.length)return i[0];i.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${i.length}: ${e}`);const n=r.select(t),s=r.pluralForms.indexOf(n);return i[Math.min(s,i.length-1)]}(r,t,e)}}},6116:(e,t,r)=>{r.d(t,{$:()=>s});var i=r(2252);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 s(e){const t=(0,i.r)();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]}},8453:(e,t,r)=>{r.d(t,{R:()=>o,x:()=>a});var i=r(6540);const n={},s=i.createContext(n);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/047b4156.bbb77b59.js b/assets/js/047b4156.bbb77b59.js new file mode 100644 index 0000000000..96285452c4 --- /dev/null +++ b/assets/js/047b4156.bbb77b59.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5296],{450:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>i,default:()=>l,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var t=o(4848),s=o(8453);const r={},i="Copy State from One Node to the Other",d={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",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,unlisted:!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:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Using State Sync for Quick Bootstraping",permalink:"/node/run-your-node/advanced/sync-node-using-state-sync"},next:{title:"Remote Signer for Oasis Node Keys",permalink:"/node/run-your-node/advanced/remote-signer"}},a={},c=[];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"copy-state-from-one-node-to-the-other",children:"Copy State from One Node to the Other"}),"\n",(0,t.jsx)(n.p,{children:"A network that's been running for some time can accrue significant amount of\nstate. This means bootstraping a new Oasis node would take quite some time and\nresources (bandwidth, CPU) since it would need to fetch (download) and validate\n(replay) all the blocks from the genesis height onwards."}),"\n",(0,t.jsx)(n.p,{children:"If one has access to an Oasis node that is synced with the latest height, he\ncould just copy Oasis node's state from the synced node to an unsynced node."}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["Another way to speed up bootstrapping an Oasis node is to sync the node using\nthe ",(0,t.jsx)(n.a,{href:"/node/run-your-node/advanced/sync-node-using-state-sync",children:"State Sync"}),"."]})}),"\n",(0,t.jsxs)(n.p,{children:["To bootstrap a new Oasis node by copying state from a synced Oasis node, first\nset up your new Oasis node as a ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"Validator Node"}),", a\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Non-validator Node"})," or a\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"ParaTime Node"}),"."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Make sure you use the ",(0,t.jsx)(n.strong,{children:"exact same version of Oasis Core"})," on both the synced\nOasis node and your new Oasis node to prevent ",(0,t.jsx)(n.strong,{children:"issues or state corruption"})," if\nan Oasis node's state is opened ",(0,t.jsx)(n.strong,{children:"with an incompatible version"})," of Oasis\nCore."]})}),"\n",(0,t.jsx)(n.p,{children:"Before starting your new Oasis node, do the following:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Stop the synced Oasis node."}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsxs)(n.p,{children:["If an Oasis node is ",(0,t.jsx)(n.strong,{children:"not stopped"})," before its state is copied, its on-disk\nstate might not be consistent and up-to-date. This can lead to ",(0,t.jsx)(n.strong,{children:"state\ncorruption"})," and inability to use the state with your new Oasis node."]})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Copy the following directories from your synced Oasis node's ",(0,t.jsx)(n.strong,{children:"data\ndirectory"})," (e.g. ",(0,t.jsx)(n.code,{children:"/node/data"}),") to your new Oasis node's data directory:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"consensus/state"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"consensus/data"})}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsxs)(n.p,{children:["You could also copy the whole ",(0,t.jsx)(n.code,{children:"consensus"})," directory from your synced Oasis\nnode's working directory. In that case, you must ",(0,t.jsx)(n.strong,{children:"omit"})," the\n",(0,t.jsxs)(n.strong,{children:[(0,t.jsx)(n.code,{children:"oasis_priv_validator.json"})," file"]}),", otherwise starting your new Oasis node\nwith fail with something like:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{"caller":"node.go:541","err":"cometbft/crypto: public key mismatch, state corruption?: %!w()","level":"error","module":"oasis-node","msg":"failed to initialize cometbft service","ts":"2023-11-25T14:13:17.919296668Z"}\n'})})]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["If you are copying data from a node that is running ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",children:"TEE-enabled ParaTimes"}),",\nyou must make sure to ",(0,t.jsx)(n.strong,{children:"remove"})," the ",(0,t.jsx)(n.code,{children:"runtimes/*/worker-local-storage.badger.db"}),"\nas otherwise the ParaTime binary may fail to start on a different node since\nit contains data sealed to the source CPU."]})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Start back the synced Oasis node."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Finally, you can start your new Oasis node for the first time."})]})}function l(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>i,x:()=>d});var t=o(6540);const s={},r=t.createContext(s);function i(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/049d1767.8ae879c8.js b/assets/js/049d1767.8ae879c8.js new file mode 100644 index 0000000000..3cd0f0d634 --- /dev/null +++ b/assets/js/049d1767.8ae879c8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2005],{9738:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var s=n(4848),r=n(8453);const o={},a="How to Transfer ETH/ERC20 to Emerald ParaTime",i={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,unlisted:!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:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Ledger Hardware Wallet",permalink:"/general/manage-tokens/holding-rose-tokens/ledger-wallet"},next:{title:"Oasis CLI",permalink:"/general/manage-tokens/cli/"}},d={},l=[{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}];function c(e){const t={a:"a",admonition:"admonition",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"how-to-transfer-etherc20-to-emerald-paratime",children:"How to Transfer ETH/ERC20 to Emerald ParaTime"}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h2,{id:"about",children:"About"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.a,{href:"/dapp/emerald/",children:"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."]}),"\n",(0,s.jsxs)(t.p,{children:["To transfer your ROSE tokens into Emerald, read the ",(0,s.jsx)(t.a,{href:"/",children:"Manage tokens"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["To transfer (i.e. bridge and wrap) your ETH and ERC20 tokens, follow this guide. It will show you how to use ",(0,s.jsx)(t.a,{href:"https://wormholebridge.com",children:"Wormhole Bridge"})," to seamlessly transfer your tokens from Ethereum, Solana, Avalanche, BSC, Terra or Polygon to the Oasis Network."]}),"\n",(0,s.jsx)(t.h2,{id:"using-wormhole-bridge",children:"Using Wormhole Bridge"}),"\n",(0,s.jsx)(t.h3,{id:"open-wormhole-bridge-and-connect-your-account",children:"Open Wormhole Bridge and Connect your Account"}),"\n",(0,s.jsxs)(t.p,{children:["First, get your assets ready in your MetaMask to be transferred over to Oasis. Then navigate to the ",(0,s.jsx)(t.a,{href:"https://wormholebridge.com",children:"Wormhole Bridge"}),"'s website and click on ",(0,s.jsx)(t.em,{children:"Transfer Tokens"})," to open the ",(0,s.jsx)(t.a,{href:"https://wormholebridge.com/#/transfer",children:"Wormhole Bridge Transfer"})," application."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Wormhole Bridge",src:n(7611).A+"",width:"2616",height:"2612"})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Step 1 (Source)"})," is to point ",(0,s.jsx)(t.em,{children:"Source"})," to the network from where you want to transfer your tokens to ",(0,s.jsx)(t.strong,{children:"Ethereum"})," and set the ",(0,s.jsx)(t.em,{children:"Target"})," to ",(0,s.jsx)(t.strong,{children:"Oasis"}),". Then click ",(0,s.jsx)(t.em,{children:"Connect"})," to connect your wallet with the Wormhole Bridge."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Connect your wallet",src:n(2469).A+"",width:"3004",height:"1732"})}),"\n",(0,s.jsx)(t.h3,{id:"transfer-assets-to-oasis",children:"Transfer Assets to Oasis"}),"\n",(0,s.jsx)(t.p,{children:"Now you can select an asset from all available assets in your wallet, e.g. ETH, to be transferred to Oasis."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Select the asset to be transferred",src:n(2953).A+"",width:"3008",height:"1516"})}),"\n",(0,s.jsx)(t.admonition,{type:"caution",children:(0,s.jsx)(t.p,{children:"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."})}),"\n",(0,s.jsxs)(t.p,{children:["Choose the ",(0,s.jsx)(t.em,{children:"Amount"})," of tokens you want to transfer and click ",(0,s.jsx)(t.em,{children:"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)."]}),"\n",(0,s.jsxs)(t.p,{children:["You will then proceed to ",(0,s.jsx)(t.strong,{children:"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."]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsxs)(t.p,{children:["Next, confirm the recipient address and the amount of WETH tokens to be transferred (i.e. bridged) and click ",(0,s.jsx)(t.em,{children:"Next"}),"."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Confirm your recipient address",src:n(5266).A+"",width:"3004",height:"1728"})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"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,s.jsx)(t.em,{children:"Transfer"}),"."]}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsx)(t.p,{children:"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."})}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Send tokens to Wormhole",src:n(4080).A+"",width:"3004",height:"1730"})}),"\n",(0,s.jsxs)(t.p,{children:["Confirm the Transfer of ETH from Ethereum to wETH on Oasis Emerald by clicking ",(0,s.jsx)(t.em,{children:"Confirm"}),"."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Confirm the transfer ETH->WETH",src:n(3915).A+"",width:"3010",height:"1728"})}),"\n",(0,s.jsx)(t.admonition,{type:"caution",children:(0,s.jsx)(t.p,{children:'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.'})}),"\n",(0,s.jsx)(t.p,{children:"You will have to wait for the confirmations on Ethereum before redeeming your new wETH tokens in Oasis Emerald."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Wait for Ethereum confirmations",src:n(8772).A+"",width:"3006",height:"1732"})}),"\n",(0,s.jsx)(t.p,{children:"Now you are ready to redeem your tokens on the Oasis Emerald. Confirm the wallet approval in your MetaMask."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Confirm Redeeming your wETH",src:n(8570).A+"",width:"3006",height:"1730"})}),"\n",(0,s.jsx)(t.p,{children:"Congratulations! You just bridged your first ETH (your chosen asset) to wETH on Oasis Emerald."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"ETH to wETH bridging completed",src:n(5506).A+"",width:"3006",height:"1734"})}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsx)(t.p,{children:"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."})}),"\n",(0,s.jsx)(t.h2,{id:"using-wrapped-assets-on-oasis",children:"Using Wrapped Assets on Oasis"}),"\n",(0,s.jsxs)(t.p,{children:["Now you can start using that wrapped assets across new Oasis dApps like the first DEX build on Emerald - ",(0,s.jsx)(t.a,{href:"https://yuzu-swap.com",children:"YuzuSwap"}),", where you can swap, provide liquidity and farm YUZU rewards."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Start using wrapped assets on Oasis",src:n(3047).A+"",width:"2990",height:"1732"})}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsxs)(t.p,{children:["Make sure that your MetaMask is connected to the Emerald Mainnet chain. You\ncan find the network parameters ",(0,s.jsx)(t.a,{href:"/dapp/emerald/#rpc-endpoints",children:"here"}),"."]})})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},3915:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/confirm_transaction_ETH_WETH-9fb853c57c97ac65fe40ca29178ad684.png"},2469:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/connect_wallet-6c13918efbcc33da6004a1306f8a1b0e.png"},7611:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/index-45df31c8f3f67661a8d6c4944be35956.png"},8570:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/redeem_tokens-f1082c546b479f813a98c3969e4257ba.png"},5506:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/redeem_tokens2-738d656761667f29cfbd85388866ea49.png"},2953:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/select_source_dest_amount-6be16ab5449bce3d7d1fe651cef4876f.png"},8772:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/send_tokens-0e219f5c38fda30ea6ec094e6dabec62.png"},4080:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/send_tokens_to_wormhole-a7154abd51883a7b0b9b10659830e7a1.png"},5266:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/switch_to_emerald-64787a9ffef61c7bc90fe1437e97d21d.png"},3047:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/yuzuswap-ea0c9c9a22e563c5b43b9ea538b5faac.png"},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>i});var s=n(6540);const r={},o=s.createContext(r);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/04a64f04.7abdf204.js b/assets/js/04a64f04.7abdf204.js new file mode 100644 index 0000000000..b0f37b6c19 --- /dev/null +++ b/assets/js/04a64f04.7abdf204.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5616],{6142:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>p,frontMatter:()=>s,metadata:()=>c,toc:()=>h});var a=t(4848),o=t(8453),r=t(1470),l=t(9365);const s={},i="Build",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/build.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Ballot Contract",permalink:"/dapp/opl/enclave"},next:{title:"Frontend Application",permalink:"/dapp/opl/frontend"}},d={},h=[{value:"Compiling",id:"compiling",level:3},{value:"Deploying",id:"deploying",level:3},{value:"Localhost",id:"localhost",level:4},{value:"Testnet",id:"testnet",level:4}];function u(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"build",children:"Build"}),"\n",(0,a.jsx)(n.p,{children:"Now that we have written our two smart contracts, let's compile and deploy them!"}),"\n",(0,a.jsx)(n.h3,{id:"compiling",children:"Compiling"}),"\n",(0,a.jsx)(n.p,{children:"Compile both the host and enclave smart contracts by invoking:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npx hardhat compile\n"})}),"\n",(0,a.jsx)(n.h3,{id:"deploying",children:"Deploying"}),"\n",(0,a.jsxs)(n.p,{children:["We can make deployments easier by using ",(0,a.jsx)(n.a,{href:"https://github.com/wighawag/hardhat-deploy",children:"Hardhat deploy"}),"."]}),"\n",(0,a.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,a.jsx)(l.A,{value:"npm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npm install -D hardhat-deploy\n"})})}),(0,a.jsx)(l.A,{value:"pnpm",label:"pnpm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"pnpm add -D hardhat-deploy\n"})})}),(0,a.jsx)(l.A,{value:"yarn",label:"Yarn",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"yarn add --dev hardhat-deploy\n"})})})]}),"\n",(0,a.jsxs)(n.p,{children:["Add the following configuration changes to your ",(0,a.jsx)(n.code,{children:"hardhat.config.ts"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-diff",children:"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.io',\n+ chainId: 0x5aff,\n+ accounts,\n+ },\n+ }\n };\n \n export default config;\n"})}),"\n",(0,a.jsx)(n.h4,{id:"localhost",children:"Localhost"}),"\n",(0,a.jsx)(n.p,{children:"We can start local Hardhat node again:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npx hardhat node\n"})}),"\n",(0,a.jsx)(n.p,{children:"Our deploy should succeed locally."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"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"})}),"\n",(0,a.jsx)(n.p,{children:"We will use these addresses in our frontend application."}),"\n",(0,a.jsx)(n.h4,{id:"testnet",children:"Testnet"}),"\n",(0,a.jsxs)(n.p,{children:["We can likewise deploy to ",(0,a.jsx)(n.a,{href:"../../dapp/sapphire/guide#testnet-and-mainnet",children:"Testnet"}),"\nwith Sapphire."]}),"\n",(0,a.jsxs)(n.p,{children:["In this case, we should prepare a wallet with Testnet tokens on both BNB Smart\nChain ",(0,a.jsx)(n.a,{href:"https://testnet.bnbchain.org/faucet-smart",children:"Faucet"})," and Sapphire ",(0,a.jsx)(n.a,{href:"https://faucet.testnet.oasis.io",children:"faucet"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"We will use a common private key for both the host and enclave smart contracts."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"export PRIVATE_KEY=\n"})}),"\n",(0,a.jsx)(n.p,{children:"Deploy the enclave smart contract using Testnet parameters."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"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"})}),"\n",(0,a.jsxs)(n.p,{children:["Next, use the obtained ",(0,a.jsx)(n.code,{children:"BallotBox"})," address below to deploy the host smart\ncontract:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"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"})}),"\n",(0,a.jsx)(n.admonition,{title:"Example",type:"info",children:(0,a.jsxs)(n.p,{children:["You can try out and download a complete backend example with both host and\nenclave smart contracts from the\n",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/demo-opl-secret-ballot/tree/main/backend",children:"Oasis Playground repository"}),"."]})})]})}function p(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>l});t(6540);var a=t(4164);const o={tabItem:"tabItem_Ymn6"};var r=t(4848);function l(e){let{children:n,hidden:t,className:l}=e;return(0,r.jsx)("div",{role:"tabpanel",className:(0,a.A)(o.tabItem,l),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>j});var a=t(6540),o=t(4164),r=t(3104),l=t(6347),s=t(205),i=t(7485),c=t(1682),d=t(9466);function h(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function u(e){const{values:n,children:t}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:t,attributes:a,default:o}}=e;return{value:n,label:t,attributes:a,default:o}}))}(t);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function p(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,l.W6)(),r=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,i.aZ)(r),(0,a.useCallback)((e=>{if(!r)return;const n=new URLSearchParams(o.location.search);n.set(r,e),o.replace({...o.location,search:n.toString()})}),[r,o])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,r=u(e),[l,i]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=t.find((e=>e.default))??t[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:r}))),[c,h]=m({queryString:t,groupId:o}),[g,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,r]=(0,d.Dv)(t);return[o,(0,a.useCallback)((e=>{t&&r.set(e)}),[t,r])]}({groupId:o}),f=(()=>{const e=c??g;return p({value:e,tabValues:r})?e:null})();(0,s.A)((()=>{f&&i(f)}),[f]);return{selectedValue:l,selectValue:(0,a.useCallback)((e=>{if(!p({value:e,tabValues:r}))throw new Error(`Can't select invalid tab value=${e}`);i(e),h(e),b(e)}),[h,b,r]),tabValues:r}}var b=t(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(4848);function y(e){let{className:n,block:t,selectedValue:a,selectValue:l,tabValues:s}=e;const i=[],{blockElementScrollPositionUntilNextRender:c}=(0,r.a_)(),d=e=>{const n=e.currentTarget,t=i.indexOf(n),o=s[t].value;o!==a&&(c(n),l(o))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=i.indexOf(e.currentTarget)+1;n=i[t]??i[0];break}case"ArrowLeft":{const t=i.indexOf(e.currentTarget)-1;n=i[t]??i[i.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.A)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:r}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>i.push(e),onKeyDown:h,onClick:d,...r,className:(0,o.A)("tabs__item",f.tabItem,r?.className,{"tabs__item--active":a===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:o}=e;const r=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=r.find((e=>e.props.value===o));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:r.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function w(e){const n=g(e);return(0,x.jsxs)("div",{className:(0,o.A)("tabs-container",f.tabList),children:[(0,x.jsx)(y,{...n,...e}),(0,x.jsx)(v,{...n,...e})]})}function j(e){const n=(0,b.A)();return(0,x.jsx)(w,{...e,children:h(e.children)},String(n))}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>s});var a=t(6540);const o={},r=a.createContext(o);function l(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/05c525ec.ab7d7129.js b/assets/js/05c525ec.ab7d7129.js new file mode 100644 index 0000000000..06628f6fea --- /dev/null +++ b/assets/js/05c525ec.ab7d7129.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7329],{7897:(e,s,o)=>{o.r(s),o.d(s,{assets:()=>a,contentTitle:()=>i,default:()=>d,frontMatter:()=>r,metadata:()=>c,toc:()=>h});var n=o(4848),t=o(8453);const r={},i="Root Hash",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/roothash.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Governance",permalink:"/core/consensus/services/governance"},next:{title:"Key Manager",permalink:"/core/consensus/services/keymanager"}},a={},h=[{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}];function m(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"root-hash",children:"Root Hash"}),"\n",(0,n.jsx)(s.p,{children:"The roothash service is responsible for runtime commitment processing and\nminimal runtime state keeping."}),"\n",(0,n.jsxs)(s.p,{children:["The service interface definition lives in ",(0,n.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/api/api.go",children:(0,n.jsx)(s.code,{children:"go/roothash/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,n.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc",children:"consensus service API documentation"}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"methods",children:"Methods"}),"\n",(0,n.jsx)(s.h3,{id:"executor-commit",children:"Executor Commit"}),"\n",(0,n.jsxs)(s.p,{children:["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.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc#NewExecutorCommitTx",children:(0,n.jsx)(s.code,{children:"NewExecutorCommitTx"})}),"."]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"Method name:"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{children:"roothash.ExecutorCommit\n"})}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"Body:"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-golang",children:'type ExecutorCommit struct {\n ID common.Namespace `json:"id"`\n Commits []commitment.ExecutorCommitment `json:"commits"`\n}\n'})}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"Fields:"})}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"id"})," specifies the ",(0,n.jsx)(s.a,{href:"/core/runtime/identifiers",children:"runtime identifier"})," of a runtime this commit is for."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"commits"})," are the ",(0,n.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api/commitment?tab=doc#ExecutorCommitment",children:"executor commitments"}),"."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"events",children:"Events"}),"\n",(0,n.jsx)(s.h2,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"max_runtime_messages"})," (uint32) specifies the global limit on the number of\n",(0,n.jsx)(s.a,{href:"/core/runtime/messages",children:"messages"})," that can be emitted in each round by the runtime. The default value\nof ",(0,n.jsx)(s.code,{children:"0"})," disables the use of runtime messages."]}),"\n"]})]})}function d(e={}){const{wrapper:s}={...(0,t.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},8453:(e,s,o)=>{o.d(s,{R:()=>i,x:()=>c});var n=o(6540);const t={},r=n.createContext(t);function i(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/06ddcc68.8bcbd78b.js b/assets/js/06ddcc68.8bcbd78b.js new file mode 100644 index 0000000000..a1e10c7cfd --- /dev/null +++ b/assets/js/06ddcc68.8bcbd78b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7205],{8640:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"operators","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/06f6e027.bbf49a86.js b/assets/js/06f6e027.bbf49a86.js new file mode 100644 index 0000000000..7419b77cba --- /dev/null +++ b/assets/js/06f6e027.bbf49a86.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9267],{1788:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Processes","slug":"core/processes","permalink":"/core/processes","sidebar":"oasisCore","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/07b8cc2d.4dc3cf30.js b/assets/js/07b8cc2d.4dc3cf30.js new file mode 100644 index 0000000000..ab933eff34 --- /dev/null +++ b/assets/js/07b8cc2d.4dc3cf30.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9874],{6074:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>d,default:()=>m,frontMatter:()=>a,metadata:()=>c,toc:()=>h});var i=r(4848),s=r(8453),t=r(5965),o=r(6116);const a={},d="Remote Signer for Oasis Node Keys",c={id:"node/run-your-node/advanced/remote-signer",title:"Remote Signer for Oasis Node Keys",description:"The Oasis remote signer is an application that",source:"@site/docs/node/run-your-node/advanced/remote-signer.mdx",sourceDirName:"node/run-your-node/advanced",slug:"/node/run-your-node/advanced/remote-signer",permalink:"/node/run-your-node/advanced/remote-signer",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/advanced/remote-signer.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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:"Troubleshooting",permalink:"/node/run-your-node/troubleshooting"}},l={},h=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Install Oasis Remote Signer Binary",id:"install-oasis-remote-signer-binary",level:2},{value:"Downloading a Binary Release",id:"downloading-a-binary-release",level:3},{value:"Building From Source",id:"building-from-source",level:3},{value:"Adding oasis-remote-signer Binary to PATH",id:"adding-oasis-remote-signer-binary-to-path",level:3},{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, Client Key and Certificate",id:"copy-remote-signer-certificate-client-key-and-certificate",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis node",id:"starting-the-oasis-node",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"remote-signer-for-oasis-node-keys",children:"Remote Signer for Oasis Node Keys"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-remote-signer",children:"Oasis remote signer"})," is an application that\ncontains logic for various Oasis Core signers. Currently, only the file-based\nsigner is implemented, but support for hardware signers is in the works. Access\nto the remote signer is provided via a gRPC service through which the Oasis node\ncan connect to it and request signatures."]}),"\n",(0,i.jsx)(n.p,{children:"This chapter will describe how to install the Oasis remote signer and then\nconfigure your Oasis node to use it. We will use two separate physical machines\nfor deployment:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["a ",(0,i.jsx)(n.code,{children:"server"})," which will function as a system running the Oasis node,"]}),"\n",(0,i.jsxs)(n.li,{children:["a ",(0,i.jsx)(n.code,{children:"signer-server"})," which will run the Oasis remote signer and store the node\nkeys."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"These are advanced instructions intended for node operators that want to\nincrease the security of their validator nodes."})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["This chapter describes a tool to remotely access the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#node-keys",children:"node keys"})," (i.e.\n",(0,i.jsx)(n.code,{children:"beacon.pem"}),", ",(0,i.jsx)(n.code,{children:"consensus.pem"}),", ",(0,i.jsx)(n.code,{children:"identity.pem"}),", ",(0,i.jsx)(n.code,{children:"p2p.pem"}),"...). There is another\n",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#remote-signer",children:(0,i.jsx)(n.code,{children:"oasis wallet remote-signer"})})," Oasis CLI command which enables remote access to\nyour ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#initialize-entity",children:"entity key"})," and should not be confused with."]})}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsxs)(n.p,{children:["Before we continue, make sure you've followed the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Install Oasis Node Binary"}),"\nchapter and have the Oasis node binary installed on your system."]}),"\n",(0,i.jsx)(n.h2,{id:"install-oasis-remote-signer-binary",children:"Install Oasis Remote Signer Binary"}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis remote signer is part of the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-remote-signer",children:"Oasis Core"}),".\nYou can either download the binary or compile it from source and then copy it\nover to your ",(0,i.jsx)(n.code,{children:"signer-server"})," system."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Oasis remote signer is currently only supported on x86_64 Linux systems."})}),"\n",(0,i.jsx)(n.h3,{id:"downloading-a-binary-release",children:"Downloading a Binary Release"}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis remote signer binary is part of the ",(0,i.jsx)(n.strong,{children:"Oasis Core release bundle"}),".\nLinks to the latest releases are on the Network Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),",\n",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),"). The Oasis remote signer binary inside the release bundle is called\n",(0,i.jsx)(n.code,{children:"oasis-remote-signer"}),". You should always use the version of the remote signer\nmatching the version of your Oasis node."]}),"\n",(0,i.jsx)(n.h3,{id:"building-from-source",children:"Building From Source"}),"\n",(0,i.jsxs)(n.p,{children:["Follow the ",(0,i.jsx)(n.a,{href:"../../../core/development-setup/build-environment-setup-and-building",children:"Oasis Core's Build Environment Setup and Building"}),"\nchapter. After the Oasis Core is compiled, the ",(0,i.jsx)(n.code,{children:"oasis-remote-signer"})," binary\nshould be located in the ",(0,i.jsx)(n.code,{children:"go/oasis-remote-signer"})," subdirectory."]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["The code in the current ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/",children:(0,i.jsx)(n.code,{children:"master"})})," branch may be incompatible with the code used\nby other nodes on the network. Make sure to use the version specified on the\nNetwork Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]})}),"\n",(0,i.jsxs)(n.h3,{id:"adding-oasis-remote-signer-binary-to-path",children:["Adding ",(0,i.jsx)(n.code,{children:"oasis-remote-signer"})," Binary to ",(0,i.jsx)(n.code,{children:"PATH"})]}),"\n",(0,i.jsxs)(n.p,{children:["To install the ",(0,i.jsx)(n.code,{children:"oasis-remote-signer"})," binary for the current user, copy/symlink\nit to ",(0,i.jsx)(n.code,{children:"~/.local/bin"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["To install the ",(0,i.jsx)(n.code,{children:"oasis-remote-signer"})," binary for all users of the system, copy\nit to ",(0,i.jsx)(n.code,{children:"/usr/local/bin"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"set-up-remote-signer-system",children:"Set Up Remote Signer System"}),"\n",(0,i.jsx)(n.h3,{id:"initialize-remote-signer",children:"Initialize Remote Signer"}),"\n",(0,i.jsxs)(n.p,{children:["On ",(0,i.jsx)(n.code,{children:"signer-server"}),", create a directory for the remote signer, e.g.\n",(0,i.jsx)(n.code,{children:"remote-signer"}),", by running:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"mkdir --mode=700 remote-signer\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Then, generate the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#node-keys",children:"node keys"})," and the server certificate by running:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-remote-signer init --datadir remote-signer/\n"})}),"\n",(0,i.jsx)(n.p,{children:"Also, generate the remote signer's client certificate which will be used by\nthe Oasis node to connect to the remote signer:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-remote-signer init_client --datadir remote-signer/\n"})}),"\n",(0,i.jsx)(n.h3,{id:"run-remote-signer",children:"Run Remote Signer"}),"\n",(0,i.jsx)(n.p,{children:"Choose the gRPC port on which the remote signer will listen for client requests\nand run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-remote-signer \\\n--datadir remote-signer \\\n--client.certificate remote-signer/remote_signer_client_cert.pem \\\n--grpc.port \\\n--log.level DEBUG\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"The Oasis Remote Signer is configured to run in the foreground by default."}),(0,i.jsxs)(n.p,{children:["We recommend you configure and use it with a process manager like ",(0,i.jsx)(n.a,{href:"https://github.com/systemd/systemd",children:"systemd"})," or\n",(0,i.jsx)(n.a,{href:"http://supervisord.org",children:"Supervisor"}),". Check out the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#create-a-user",children:"System Configuration"})," page for examples."]})]}),"\n",(0,i.jsx)(n.h3,{id:"copy-remote-signer-certificate-client-key-and-certificate",children:"Copy Remote Signer Certificate, Client Key and Certificate"}),"\n",(0,i.jsxs)(n.p,{children:["In order for the Oasis node to securely connect to the Oasis remote signer and\nbe able to demonstrate its authenticity, you need to copy the following files\nfrom ",(0,i.jsx)(n.code,{children:"signer-server"})," to ",(0,i.jsx)(n.code,{children:"server"})," inside the ",(0,i.jsx)(n.code,{children:"/node/data/remote-signer"}),"\ndirectory:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"remote-signer/remote_signer_server_cert.pem"}),": The remote signer's\ncertificate. This certificate ensures the Oasis node system is connecting to\nthe trusted remote signer system."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"remote-signer/remote_signer_client_key.pem"}),": The remote signer's client key.\nThis key enables the Oasis node system to demonstrate its authenticity when it\nis requesting signatures from the remote signer system."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"remote-signer/remote_signer_client_cert.pem"}),": The remote signer's client\ncertificate. This certificate is the counterpart of the remote signer's client\nkey."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsxs)(n.p,{children:["When ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#configuration",children:"configuring your Oasis Node"}),"\non ",(0,i.jsx)(n.code,{children:"server"}),", you need to add the appropriate ",(0,i.jsx)(n.code,{children:"signer"})," section to configure the\n",(0,i.jsx)(n.strong,{children:"composite"})," and ",(0,i.jsx)(n.strong,{children:"remote"})," signers. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"# 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: /node/data/remote-signer/remote_signer_server_cert.pem\n client:\n key: /node/data/remote-signer/remote_signer_client_key.pem\n certificate: /node/data/remote-signer/remote_signer_client_cert.pem\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This assumes you've copied the remote signer's certificate and remote signer's\nclient key and certificate to the ",(0,i.jsx)(n.code,{children:"/node/data/remote-signer/"})," directory."]}),"\n",(0,i.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis node"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#starting-the-oasis-node",children:"Start the Oasis node"})," using the modified config above. To ensure that your\nOasis node will be able to sign consensus transactions, check that the Oasis\nremote signer is running and accepting remote client connections via the\ndesignated port."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"/node/data"})," directory on ",(0,i.jsx)(n.code,{children:"server"})," will only have ",(0,i.jsx)(n.code,{children:"consensus_pub.pem"})," and no\n",(0,i.jsx)(n.code,{children:"consensus.pem"})," since the consensus key is backed by the Oasis remote signer."]})}),"\n",(0,i.jsx)(n.h1,{id:"see-also",children:"See also"}),"\n",(0,i.jsx)(t.A,{item:(0,o.$)("/node/run-your-node/validator-node")}),"\n",(0,i.jsx)(t.A,{item:(0,o.$)("/general/manage-tokens/cli/wallet")})]})}function m(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},5965:(e,n,r)=>{r.d(n,{A:()=>f});r(6540);var i=r(4164),s=r(8774),t=r(4142),o=r(5846),a=r(6654),d=r(1312),c=r(1107);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=r(4848);function u(e){let{href:n,children:r}=e;return(0,h.jsx)(s.A,{href:n,className:(0,i.A)("card padding--lg",l.cardContainer),children:r})}function m(e){let{href:n,icon:r,title:s,description:t}=e;return(0,h.jsxs)(u,{href:n,children:[(0,h.jsxs)(c.A,{as:"h2",className:(0,i.A)("text--truncate",l.cardTitle),title:s,children:[r," ",s]}),t&&(0,h.jsx)("p",{className:(0,i.A)("text--truncate",l.cardDescription),title:t,children:t})]})}function g(e){let{item:n}=e;const r=(0,t.Nr)(n),i=function(){const{selectMessage:e}=(0,o.W)();return n=>e(n,(0,d.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return r?(0,h.jsx)(m,{href:r,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??i(n.items.length)}):null}function p(e){let{item:n}=e;const r=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",i=(0,t.cC)(n.docId??void 0);return(0,h.jsx)(m,{href:n.href,icon:r,title:n.label,description:n.description??i?.description})}function f(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(p,{item:n});case"category":return(0,h.jsx)(g,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},5846:(e,n,r)=>{r.d(n,{W:()=>c});var i=r(6540),s=r(4586);const t=["zero","one","two","few","many","other"];function o(e){return t.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function d(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,i.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:o(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function c(){const e=d();return{selectMessage:(n,r)=>function(e,n,r){const i=e.split("|");if(1===i.length)return i[0];i.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${i.length}: ${e}`);const s=r.select(n),t=r.pluralForms.indexOf(s);return i[Math.min(t,i.length-1)]}(r,n,e)}}},6116:(e,n,r)=>{r.d(n,{$:()=>t});var i=r(2252);function s(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&s(n.items)}}function t(e){const n=(0,i.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)s(n.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]}},8453:(e,n,r)=>{r.d(n,{R:()=>o,x:()=>a});var i=r(6540);const s={},t=i.createContext(s);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0da7eee9.242b6a3f.js b/assets/js/0da7eee9.242b6a3f.js new file mode 100644 index 0000000000..eeb4043b9a --- /dev/null +++ b/assets/js/0da7eee9.242b6a3f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5567],{8449:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>c,frontMatter:()=>o,metadata:()=>l,toc:()=>h});var s=n(4848),i=n(8453);const o={description:"How to build your first ROFL app"},r="Prerequisites",l={id:"rofl/prerequisites",title:"Prerequisites",description:"How to build your first ROFL app",source:"@site/docs/rofl/prerequisites.md",sourceDirName:"rofl",slug:"/rofl/prerequisites",permalink:"/rofl/prerequisites",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/rofl/prerequisites.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"How to build your first ROFL app"},sidebar:"rofl",previous:{title:"Overview",permalink:"/rofl/"},next:{title:"Application",permalink:"/rofl/app"}},a={},h=[{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:"SGXS Utilities",id:"sgxs-utilities",level:2},{value:"Oasis CLI Installation",id:"oasis-cli-installation",level:2},{value:"TEE-enabled Hardware for Deployment",id:"tee-enabled-hardware-for-deployment",level:2}];function u(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsx)(t.p,{children:"This chapter will show you how to install the software required for developing\na ROFL app using the Oasis SDK. After successfully completing all the described\nsteps you will be able to start building your first ROFL app!"}),"\n",(0,s.jsxs)(t.p,{children:["If you already have everything set up, feel free to skip to the ",(0,s.jsx)(t.a,{href:"/rofl/app",children:"next chapter"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"environment-setup",children:"Environment Setup"}),"\n",(0,s.jsx)(t.p,{children:"The following is a list of prerequisites required to start developing using the\nOasis SDK:"}),"\n",(0,s.jsx)(t.h3,{id:"rust",children:(0,s.jsx)(t.a,{href:"https://www.rust-lang.org/",children:"Rust"})}),"\n",(0,s.jsxs)(t.p,{children:["We follow ",(0,s.jsx)(t.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust upstream's recommendation"})," on using\n",(0,s.jsx)(t.a,{href:"https://rustup.rs/",children:"rustup"})," to install and manage Rust versions."]}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsx)(t.p,{children:"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."})}),"\n",(0,s.jsx)(t.p,{children:"Install it by running:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n"})}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsxs)(t.p,{children:["If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,s.jsxs)(t.a,{href:"https://rust-lang.github.io/rustup/installation/other.html",children:["download ",(0,s.jsx)(t.code,{children:"rustup-init"})," executable for your platform"]}),"\nand run it manually."]})}),"\n",(0,s.jsxs)(t.p,{children:["This will run ",(0,s.jsx)(t.code,{children:"rustup-init"})," which will download and install the latest stable\nversion of Rust on your system."]}),"\n",(0,s.jsx)(t.h4,{id:"rust-toolchain-version",children:"Rust Toolchain Version"}),"\n",(0,s.jsxs)(t.p,{children:["The version of the Rust toolchain we use in the Oasis SDK is specified in the\n",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,s.jsx)(t.code,{children:"rust-toolchain.toml"})})," file."]}),"\n",(0,s.jsxs)(t.p,{children:["The rustup-installed versions of ",(0,s.jsx)(t.code,{children:"cargo"}),", ",(0,s.jsx)(t.code,{children:"rustc"})," and other tools will\n",(0,s.jsx)(t.a,{href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence",children:"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,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,s.jsx)(t.code,{children:"rust-toolchain.toml"})}),"\nfile to your project's top-level directory as well."]}),"\n",(0,s.jsx)(t.p,{children:"To install the appropriate version of the Rust toolchain, make sure you are\nin the project directory and run:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"rustup show\n"})}),"\n",(0,s.jsx)(t.p,{children:"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"...\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"})}),"\n",(0,s.jsx)(t.h2,{id:"sgxs-utilities",children:"SGXS Utilities"}),"\n",(0,s.jsx)(t.p,{children:"In order to generate binaries suitable for use with Intel SGX, you also need to\ninstall the relevant utilities. You can do so as follows:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"cargo install fortanix-sgx-tools\ncargo install sgxs-tools\n"})}),"\n",(0,s.jsx)(t.h2,{id:"oasis-cli-installation",children:"Oasis CLI Installation"}),"\n",(0,s.jsxs)(t.p,{children:["The rest of the guide uses the Oasis CLI as an easy way to interact with the\nParaTimes. You can use ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/cli/releases",children:"one of the binary releases"})," or ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/cli/blob/master/README.md",children:"compile it yourself"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"tee-enabled-hardware-for-deployment",children:"TEE-enabled Hardware for Deployment"}),"\n",(0,s.jsx)(t.p,{children:"While ROFL app development and testing can be performed on any machine that has\nthe appropriate tools, for actually running the apps, at least one machine with\nappropriate TEE-enabled hardware is required."}),"\n",(0,s.jsxs)(t.p,{children:["Please look at the ",(0,s.jsx)(t.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",children:"Set up Trusted Execution Environment (TEE)"})," chapter for\ninstructions. The deployment part of the guide assumes you have an appropriate\nmachine ready to use."]})]})}function c(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>l});var s=n(6540);const i={},o=s.createContext(i);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0e099be9.155ab32a.js b/assets/js/0e099be9.155ab32a.js new file mode 100644 index 0000000000..9fd70cd20a --- /dev/null +++ b/assets/js/0e099be9.155ab32a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[192],{802:(e,o,s)=>{s.r(o),s.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>c});var n=s(4848),t=s(8453);const a={},r="DAO Contract",i={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/host.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Setup",permalink:"/dapp/opl/setup"},next:{title:"Ballot Contract",permalink:"/dapp/opl/enclave"}},l={},c=[{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}];function p(e){const o={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.h1,{id:"dao-contract",children:"DAO Contract"}),"\n",(0,n.jsxs)(o.p,{children:["Let's start with a smart contract that describes a basic DAO, ",(0,n.jsx)(o.code,{children:"DAOV1.sol"}),", with a\nmapping of proposals before we consider the OPL differences."]}),"\n",(0,n.jsx)(o.h2,{id:"base-contract",children:"Base Contract"}),"\n",(0,n.jsxs)(o.p,{children:["Inside your ",(0,n.jsx)(o.code,{children:"contracts/"})," directory, create a ",(0,n.jsx)(o.code,{children:"DAOV1.sol"})," file. You may have\nalready deployed a similar contract to your home network such as BNB or\nPolygon."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:'// 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'})}),"\n",(0,n.jsxs)(o.p,{children:["Instead of storing complete ballot proposals on the network, we will use\n",(0,n.jsx)(o.a,{href:"https://ipfs.tech",children:"IPFS"}),". Our smart contract will refer to a pinned\n",(0,n.jsx)(o.a,{href:"https://docs.ipfs.tech/concepts/lifecycle/#_1-content-addressable-representation",children:"IPFS file"})," by its ",(0,n.jsx)(o.a,{href:"https://docs.ipfs.tech/concepts/hashing/",children:"hash"}),"."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:"struct ProposalParams {\n string ipfsHash;\n uint16 numChoices;\n bool publishVotes;\n}\n"})}),"\n",(0,n.jsxs)(o.p,{children:["Our very simple DAO contract creates proposals and manages them, allowing\nboth active and past proposals to be queried externally through methods\n",(0,n.jsx)(o.code,{children:"getActiveProposals"})," and ",(0,n.jsx)(o.code,{children:"getPastProposals"}),". This would be sufficient on a\nsingle chain, and it is possible to develop confidential applications without\nbridges, relying solely on ",(0,n.jsx)(o.a,{href:"/dapp/sapphire/",children:"Sapphire"}),". However, we will proceed\nto demonstrate the cross-chain capabilities of OPL."]}),"\n",(0,n.jsx)(o.h2,{id:"what-is-different-with-opl",children:"What is different with OPL?"}),"\n",(0,n.jsxs)(o.p,{children:["OPL leverages ",(0,n.jsx)(o.a,{href:"https://celer.network",children:"Celer"}),"'s inter-chain ",(0,n.jsx)(o.a,{href:"https://im-docs.celer.network/developer/celer-im-overview",children:"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."]}),"\n",(0,n.jsxs)(o.p,{children:["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,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L35-L45",children:"Endpoint"}),":"]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:"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"})}),"\n",(0,n.jsxs)(o.p,{children:["which allows us to use this bridge ",(0,n.jsx)(o.a,{href:"https://im-docs.celer.network/developer/development-guide/contract-framework#send-message",children:"function"}),":"]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:"function sendMessage(\n address _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n uint256 _fee\n) internal\n"})}),"\n",(0,n.jsxs)(o.p,{children:["In production, you can see the deployed ",(0,n.jsx)(o.a,{href:"https://explorer.sapphire.oasis.io/address/0x9B36f165baB9ebe611d491180418d8De4b8f3a1f/transactions",children:"cBridge contract"})," and\n",(0,n.jsx)(o.a,{href:"https://explorer.sapphire.oasis.io/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D/transactions",children:"MessageBus contract"}),"."]}),"\n",(0,n.jsx)(o.h3,{id:"how-does-opl-do-this",children:"How does OPL do this?"}),"\n",(0,n.jsxs)(o.p,{children:["We can ",(0,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L76-L84",children:"register"})," functions with endpoints in order to simplify our code.\nEndpoints are effectively callbacks which listen to messages from the enclaved\nsmart contract."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:"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"})}),"\n",(0,n.jsxs)(o.p,{children:["Under the hood, a ",(0,n.jsx)(o.code,{children:"postMessage"})," function ",(0,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/9a74e57e72b06ba86ec8454062b8c0a5281edb97/contracts/contracts/opl/Endpoint.sol#L91-L119",children:"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."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:" ICelerMessageBus(messageBus).sendMessage{value: fee}(\n remote,\n remoteChainId,\n envelope\n );\n"})}),"\n",(0,n.jsx)(o.h3,{id:"endpoints-why-not-solidity-events",children:"Endpoints? Why not Solidity events?"}),"\n",(0,n.jsxs)(o.p,{children:["Events in Solidity are non-confidential and do not allow cross-chain\ncommunication. For this reason, OPL uses ",(0,n.jsx)(o.em,{children:"endpoints"})," for passing messages\ncross-chain. For example, this function below will listen to such a message and\nclose the proposal."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:" 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,n.jsx)(o.h3,{id:"lets-see-the-code",children:"Let's see the code"}),"\n",(0,n.jsxs)(o.p,{children:["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,n.jsx)(o.code,{children:"DAOV1.sol"}),"."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-diff",children:'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'})}),"\n",(0,n.jsx)(o.h4,{id:"host",children:"Host"}),"\n",(0,n.jsxs)(o.p,{children:["A ",(0,n.jsx)(o.em,{children:"host"})," contract in our terminology is just a smart contract that extends the\n",(0,n.jsx)(o.code,{children:"Host"})," contract ",(0,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/opl/Host.sol",children:"provided"})," and deployed on a home network such as BNB or\nPolygon with a reference to the Sapphire network where our ",(0,n.jsx)(o.em,{children:"enclave"}),"\n(privacy-preserving) smart contract will reside."]}),"\n",(0,n.jsx)(o.h4,{id:"constructor",children:"Constructor"}),"\n",(0,n.jsxs)(o.p,{children:["We provide the address of the confidential (also known as ",(0,n.jsx)(o.em,{children:"enclave"}),") smart\ncontract deployed on the Oasis Sapphire as a constructor parameter to the\n",(0,n.jsx)(o.em,{children:"host"})," smart contract."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:' constructor(address _ballotBox) Host(_ballotBox) {\n registerEndpoint("ballotClosed", _oplBallotClosed);\n }\n'})})]})}function d(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(p,{...e})}):p(e)}},8453:(e,o,s)=>{s.d(o,{R:()=>r,x:()=>i});var n=s(6540);const t={},a=n.createContext(t);function r(e){const o=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(a.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0e9cd926.bca7dbcd.js b/assets/js/0e9cd926.bca7dbcd.js new file mode 100644 index 0000000000..2e716e3071 --- /dev/null +++ b/assets/js/0e9cd926.bca7dbcd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7943],{6176:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>d});var s=n(4848),o=n(8453);const i={},a="ADR 0020: Governance Support for Delegator Votes",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0020-governance-delegator-votes.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"adr-0020-governance-support-for-delegator-votes",children:"ADR 0020: Governance Support for Delegator Votes"}),"\n",(0,s.jsx)(t.h2,{id:"component",children:"Component"}),"\n",(0,s.jsx)(t.p,{children:"Oasis Core"}),"\n",(0,s.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"2022-11-07: Minor updates. Added Cosmos-SDK implementation note."}),"\n",(0,s.jsx)(t.li,{children:"2022-11-03: Added benchmarks, minor updates."}),"\n",(0,s.jsx)(t.li,{children:"2022-11-02: Initial draft."}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(t.p,{children:"Accepted"}),"\n",(0,s.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(t.p,{children:["With the current governance voting mechanism (",(0,s.jsx)(t.a,{href:"/adrs/0004-runtime-governance",children:"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."]}),"\n",(0,s.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(t.h3,{id:"casting-votes",children:"Casting Votes"}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsxs)(t.p,{children:["This change requires an efficient ",(0,s.jsx)(t.code,{children:"staking.DelegationsFor"})," query to obtain a\nlist of accounts the submitter is delegating to. Staking state is updated with:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:"// 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"})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"state.SetDelegation"})," function is updated to store both ",(0,s.jsx)(t.code,{children:"delegationKeyFmt"})," and\nthe reverse ",(0,s.jsx)(t.code,{children:"delegationKeyReverseFmt"}),". ",(0,s.jsx)(t.code,{children:"DelegationsFor"})," query function is\nupdated to use the added reverse mapping."]}),"\n",(0,s.jsx)(t.p,{children:"For completeness the same can be done for debonding delegations, although not\nnecessary for the governance changes proposed in this ADR."}),"\n",(0,s.jsx)(t.h4,{id:"alternative-solutions",children:"Alternative solutions"}),"\n",(0,s.jsx)(t.p,{children:"Possible alternatives that would avoid adding the reverse mapping are:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Querying ",(0,s.jsx)(t.code,{children:"DelegationsTo"})," for each validator. This results in ",(0,s.jsx)(t.code,{children:"num_validators"}),"\nqueries per cast vote transaction which is still too much."]}),"\n",(0,s.jsx)(t.li,{children:"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."}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"vote-tallying",children:"Vote tallying"}),"\n",(0,s.jsx)(t.p,{children:"When a proposal closes, the vote tallying procedure changes to:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"# 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"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Possbile variant: instead of using ",(0,s.jsx)(t.code,{children:"DelegationsFor"})," query in step 3), a map of\nall validator delegators could be prebuild, by using ",(0,s.jsx)(t.code,{children:"DelegationTo"})," for each\nof the validators. Even with the efficient ",(0,s.jsx)(t.code,{children:"DelegationsFor"})," query, this can be\nbeneficial IF the number of voters is large."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h4,{id:"alternative-vote-tallying-procedures",children:"Alternative Vote Tallying procedures"}),"\n",(0,s.jsx)(t.p,{children:"A possible alternative would be to iterate over the delegators-validator sets:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"# 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"})}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h4,{id:"implementations-in-other-chains",children:"Implementations in other chains"}),"\n",(0,s.jsxs)(t.p,{children:["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,s.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/dc004c85f2e8b8fb4f66caac2703228c5bf544cf/x/gov/keeper/tally.go#L37-L90",children:"Cosmos-SDK Vote Tallying Code"}),". The voting itself is\nlimited to delegators (similar as proposed in this document)."]}),"\n",(0,s.jsx)(t.h4,{id:"benchmarks",children:"Benchmarks"}),"\n",(0,s.jsx)(t.p,{children:"The Vote Tallying procedure variants were benchmarked on mainnet data."}),"\n",(0,s.jsx)(t.p,{children:"Some basic stats from mainnet:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"120 validators"}),"\n",(0,s.jsx)(t.li,{children:"~49500 eligible voters (unique delegators to validators)"}),"\n",(0,s.jsx)(t.li,{children:"average number of delegations-to per account is 1"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"The three tested variants were:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:['"Two pass over voters (optimized DelegationsFor)" - as described in the\nproposed Vote tallying solution. Reverse mapping key is used for the\n',(0,s.jsx)(t.code,{children:"DelegationsFor"})," queries (described in Casting Votes section)."]}),"\n",(0,s.jsx)(t.li,{children:'"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).'}),"\n",(0,s.jsx)(t.li,{children:'"Validator-delegators" - as described in the alternatives section.'}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.img,{alt:"Two pass over voters (optimized DelegationsFor)",src:n(8543).A+"",width:"720",height:"576"}),"\n",(0,s.jsx)(t.img,{alt:"Two pass over voters (pre-build validators escrow)",src:n(3892).A+"",width:"720",height:"576"}),"\n",(0,s.jsx)(t.img,{alt:"Validator-delegators",src:n(3837).A+"",width:"720",height:"576"})]}),"\n",(0,s.jsx)(t.p,{children:"The above results show that:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Two-pass approach (querying ",(0,s.jsx)(t.code,{children:"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."]}),"\n",(0,s.jsx)(t.li,{children:'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.'}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["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,s.jsx)(t.code,{children:"DelegationsFor"}),"\nfor every voter) seems to make the most sense."]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h3,{id:"pruning",children:"Pruning"}),"\n",(0,s.jsxs)(t.p,{children:["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,s.jsx)(t.code,{children:"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."]}),"\n",(0,s.jsx)(t.h3,{id:"voting-via-messages",children:"Voting via messages"}),"\n",(0,s.jsx)(t.p,{children:"Delegator can also be a runtime. For enabling runtimes to vote, casting votes\nshould also be supported via runtime messages."}),"\n",(0,s.jsx)(t.p,{children:"Roothash message type is updated to include governance message field:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-go",children:'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'})}),"\n",(0,s.jsx)(t.p,{children:"Governance backend is updated to handle the cast vote message."}),"\n",(0,s.jsx)(t.p,{children:"For completeness, support for submitting proposals via runtime messages can also\nbe implemented."}),"\n",(0,s.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Delegators are able to override validators vote. In the case of unresponsive\nvalidators this increases the voting participation."}),"\n",(0,s.jsx)(t.li,{children:"Delegators are able to vote with their own stake."}),"\n",(0,s.jsxs)(t.li,{children:["(if implemented) Staking ",(0,s.jsx)(t.code,{children:"DelegationsFor"})," queries are now efficient and don't\nrequire scanning the full delegations state."]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"This increases the complexity of the vote tallying procedure."}),"\n",(0,s.jsx)(t.li,{children:"This increases the size of the governance votes state."}),"\n",(0,s.jsxs)(t.li,{children:["This increases the complexity and size of the consensus staking state if the\n",(0,s.jsx)(t.code,{children:"DelegationsFor"})," reverse mapping is implemented."]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"neutral",children:"Neutral"})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8543:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/0020-bench1-b406915bd71a67020495939d2c89075b.png"},3892:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/0020-bench2-1cc7812d2c015e4a03288cc6f165bb4e.png"},3837:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/0020-bench3-8741906103d267c9119ac66826d39bd1.png"},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var s=n(6540);const o={},i=s.createContext(o);function a(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0f0ebacb.58c91d72.js b/assets/js/0f0ebacb.58c91d72.js new file mode 100644 index 0000000000..a451ce8f62 --- /dev/null +++ b/assets/js/0f0ebacb.58c91d72.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7556],{1738:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var s=i(4848),t=i(8453);const a={},r="Reproducibility",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/reproducibility.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"paratime",previous:{title:"Modules",permalink:"/paratime/modules"}},l={},d=[{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}];function c(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"reproducibility",children:"Reproducibility"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsxs)(n.p,{children:["The steps below show how to build the test runtimes provided in the\n",(0,s.jsx)(n.code,{children:"oasis-sdk"})," sources; steps for other paratimes should be similar."]}),"\n",(0,s.jsx)(n.h2,{id:"environment-setup",children:"Environment Setup"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.p,{children:"The runtime sources need to be mounted into the container so prepare a\ndirectory first, such as:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone https://github.com/oasisprotocol/oasis-sdk.git\n"})}),"\n",(0,s.jsx)(n.h2,{id:"running-the-image",children:"Running the Image"}),"\n",(0,s.jsxs)(n.p,{children:["The images are available in the ",(0,s.jsx)(n.code,{children:"ghcr.io/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:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -t -i -v /home/user/oasis-sdk:/src ghcr.io/oasisprotocol/runtime-builder:main /bin/bash\n"})}),"\n",(0,s.jsx)(n.p,{children:"where:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"/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"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"main"})," is a release of the SDK - the documentation of the paratime\nyou're trying to build should mention the version required."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["This gives you a root shell in the container. Rust and Cargo are\ninstalled in ",(0,s.jsx)(n.code,{children:"/cargo"}),", Go in ",(0,s.jsx)(n.code,{children:"/go"}),", and the sources to your paratime are\navailable in ",(0,s.jsx)(n.code,{children:"/src"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"building",children:"Building"}),"\n",(0,s.jsx)(n.h3,{id:"elf",children:"ELF"}),"\n",(0,s.jsx)(n.p,{children:"Simply build the paratime in release mode using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cargo build --release\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The resulting binaries will be in ",(0,s.jsx)(n.code,{children:"/src/target/release/"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"intel-sgx",children:"Intel SGX"}),"\n",(0,s.jsx)(n.p,{children:"Follow the normal build procedure for your paratime. For the testing\nruntimes in the SDK, e.g.:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cd /src\ncargo build --release --target x86_64-fortanix-unknown-sgx\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After this step is complete, the binaries will be in\n",(0,s.jsx)(n.code,{children:"/src/target/x86_64-fortanix-unknown-sgx/release/"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To produce the sgxs format needed on the Oasis network, change directory\nto where a particular runtime's ",(0,s.jsx)(n.code,{children:"Cargo.toml"})," file is and run the\nfollowing command:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"cargo elf2sgxs --release\n"})}),"\n",(0,s.jsx)(n.p,{children:"It is necessary to change directories first because the tool does not\ncurrently support cargo workspaces."}),"\n",(0,s.jsxs)(n.p,{children:["The resulting binaries will have the ",(0,s.jsx)(n.code,{children:".sgxs"})," extension."]}),"\n",(0,s.jsx)(n.h2,{id:"generating-bundles",children:"Generating Bundles"}),"\n",(0,s.jsxs)(n.p,{children:["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,s.jsx)(n.code,{children:"orc"})," tool provided by\nthe SDK."]}),"\n",(0,s.jsxs)(n.admonition,{type:"info",children:[(0,s.jsxs)(n.p,{children:["You can install the ",(0,s.jsx)(n.code,{children:"orc"})," utility by running:"]}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"go install github.com/oasisprotocol/oasis-sdk/tools/orc@latest\n"})})]}),"\n",(0,s.jsx)(n.p,{children:"The same bundle can contain both ELF and Intel SGX artifacts. To create a bundle\nuse the following command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc init path/to/elf-binary\n"})}),"\n",(0,s.jsx)(n.p,{children:"When including Intel SGX artifacts you may additionally specify:"}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"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."})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc init path/to/elf-binary --sgx-executable path/to/binary.sgxs --sgx-signature path/to/binary.sig\n"})}),"\n",(0,s.jsx)(n.p,{children:"You can omit the signature initially and add it later by using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc sgx-set-sig bundle.orc path/to/binary.sig\n"})}),"\n",(0,s.jsx)(n.h3,{id:"multi-step-sgx-signing-example",children:"Multi-step SGX Signing Example"}),"\n",(0,s.jsxs)(n.p,{children:["Multi-step signing allows enclave signing keys to be kept offline, preferrably\nin some HSM. The following example uses ",(0,s.jsx)(n.code,{children:"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."]}),"\n",(0,s.jsx)(n.h4,{id:"generate-a-key",children:"Generate a key"}),"\n",(0,s.jsx)(n.p,{children:"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:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openssl genrsa -3 3072 > private.pem\n"})}),"\n",(0,s.jsx)(n.p,{children:"We will also need the public key in a later step so let's also generate this\nnow."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openssl rsa -in private.pem -pubout > public.pem\n"})}),"\n",(0,s.jsx)(n.h4,{id:"generate-signing-data-for-your-enclave",children:"Generate signing data for your enclave"}),"\n",(0,s.jsxs)(n.p,{children:["Generating signing data is done with the ",(0,s.jsx)(n.code,{children:"orc sgx-gen-sign-data"})," subcommand,\nlike so:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc sgx-gen-sign-data [options] bundle.orc\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.code,{children:"orc sgx-gen-sign-data --help"})," for details on available options."]})}),"\n",(0,s.jsxs)(n.p,{children:["For purposes of this example, let's assume your bundle is named ",(0,s.jsx)(n.code,{children:"bundle.orc"}),".\nYou would generate data to sign like so:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc sgx-gen-sign-data bundle.orc > sigstruct.sha256.bin\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The output file ",(0,s.jsx)(n.code,{children:"sigstruct.sha256.bin"})," contains the sha256 hash of the\nSIGSTRUCT fields to be signed."]}),"\n",(0,s.jsx)(n.h5,{id:"sign-the-sigstruct-hash",children:"Sign the SIGSTRUCT hash"}),"\n",(0,s.jsxs)(n.p,{children:["To sign the SIGSTRUCT you must create a signature using the ",(0,s.jsx)(n.code,{children:"RSASSA-PKCS1-v1_5"}),"\nscheme. The following command will do so with ",(0,s.jsx)(n.code,{children:"openssl"}),". If you're using an HSM,\nyour device may have a different process for generating a signature of this\ntype."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"openssl pkeyutl -sign \\\n -in sigstruct.sha256.bin \\\n -inkey private.pem \\\n -out sigstruct.sha256.sig \\\n -pkeyopt digest:sha256\n"})}),"\n",(0,s.jsx)(n.h5,{id:"attach-the-singed-sigstruct-to-the-bundle",children:"Attach the singed SIGSTRUCT to the bundle"}),"\n",(0,s.jsxs)(n.p,{children:["With the signature in ",(0,s.jsx)(n.code,{children:"sigstruct.sha256.sig"})," we can now generate a valid\nSIGSTRUCT and attach it into the bundle."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc sgx-set-sig bundle.orc sigstruct.sha256.sig public.pem\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If there are no errors, ",(0,s.jsx)(n.code,{children:"bundle.orc"})," will now contain a valid SGX SIGSTRUCT\nthat was signed by ",(0,s.jsx)(n.code,{children:"private.pem"}),". To verify you can use ",(0,s.jsx)(n.code,{children:"orc show"})," as follows."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"orc show bundle.orc\n"})}),"\n",(0,s.jsx)(n.p,{children:"It should return something like the following, showing the bundle content\nincluding the signed SGX SIGSTRUCT (the signature is also verified):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"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"})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>o});var s=i(6540);const t={},a=s.createContext(t);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0f921af1.5c776a7d.js b/assets/js/0f921af1.5c776a7d.js new file mode 100644 index 0000000000..f1ab649c69 --- /dev/null +++ b/assets/js/0f921af1.5c776a7d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9861],{8432:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var a=s(4848),t=s(8453);const o={title:"Account",description:"Using CLI for performing account-related tasks"},i="Account-related Tasks",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/account.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,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"}},c={},l=[{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:"Output format",id:"format",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:"Initialize Entity",id:"entity-init",level:4},{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},{value:"Pools and Reserved Addresses",id:"reserved-addresses",level:3},{value:"Consensus layer",id:"consensus-layer",level:4},{value:"ParaTime layer",id:"paratime-layer",level:4}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"account-related-tasks",children:"Account-related Tasks"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"account"})," command is the home for most consensus and ParaTime-layer\non-chain transactions that are signed with one of your accounts such as:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"getting the account balance including delegated assets,"}),"\n",(0,a.jsx)(n.li,{children:"sending tokens,"}),"\n",(0,a.jsxs)(n.li,{children:["delegating or undelegating tokens to or from validators (",(0,a.jsx)(n.em,{children:"staking"}),"),"]}),"\n",(0,a.jsx)(n.li,{children:"depositing and withdrawing tokens to or from a ParaTime,"}),"\n",(0,a.jsx)(n.li,{children:"managing withdrawal beneficiaries of your accounts,"}),"\n",(0,a.jsx)(n.li,{children:"validator utils such as entity registration, setting the commission schedule,\nunfreezing your node and similar."}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"npa",children:"Network, ParaTime and Account Selectors"}),"\n",(0,a.jsxs)(n.p,{children:["Before we dig into ",(0,a.jsx)(n.code,{children:"account"})," subcommands, let's look at the three most common\nselectors."]}),"\n",(0,a.jsx)(n.h3,{id:"network",children:"Network"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"--network "})," parameter specifies the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/network",children:"network"})," which the\nOasis CLI should connect to."]}),"\n",(0,a.jsx)(n.p,{children:"For example:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000 --network testnet\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 1.0 TEST\n Available: 1.0 TEST\n\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000 --network mainnet\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\n\n=== CONSENSUS LAYER (mainnet) ===\n Nonce: 0\n\n Total: 0.0 ROSE\n Available: 0.0 ROSE\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"paratime",children:"ParaTime"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"--paratime "})," sets which ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/paratime",children:"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,a.jsx)(n.code,{children:"--no-paratime"})," flag explicitly."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show eric --no-paratime\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qzplmfaeywvtc2qnylyhk0uzcxr4y5s3euhaug7q\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n"})}),"\n",(0,a.jsx)(n.h3,{id:"account",children:"Account"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"--account "})," specifies which account in your wallet the\nOasis CLI should use to sign the transaction with."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 1.5 0xDce075E1C39b1ae0b75D554558b6451A226ffe00 --account orlando\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 1.5 0xDce075E1C39b1ae0b75D554558b6451A226ffe00 --account eric\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["You can also set ",(0,a.jsxs)(n.strong,{children:["the default ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/network#set-default",children:"network"}),",\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/paratime#set-default",children:"ParaTime"})," or ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#set-default",children:"account"})," to use"]}),", if\nno network, ParaTime or account selectors are provided."]})}),"\n",(0,a.jsx)(n.h2,{id:"show",children:"Show the Balance of an Account"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"account show [address]"})," command prints the balance, delegated assets\nand other validator information corresponding to:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"a given address,"}),"\n",(0,a.jsxs)(n.li,{children:["the name of the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/addressbook",children:"address book entry"})," or"]}),"\n",(0,a.jsx)(n.li,{children:"the name of one of the accounts in your wallet."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"The address is looked up both on the consensus layer and the ParaTime, if\nselected."}),"\n",(0,a.jsx)(n.p,{children:"Running the command without arguments will show you the balance\nof your default account on the default network and ParaTime:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 2\n\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n"})}),"\n",(0,a.jsxs)(n.p,{children:["You can also pass the name of the account in your wallet or address book, or one\nof the ",(0,a.jsx)(n.a,{href:"#reserved-addresses",children:"built-in named addresses"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show orlando\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qq84sc4q0shp5c5klwklqu59evz2mg59hveg7dqx\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 10.0 TEST\n Available: 10.0 TEST\n\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis acc show pool:consensus:fee-accumulator\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qqnv3peudzvekhulf8v3ht29z4cthkhy7gkxmph5\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n"})}),"\n",(0,a.jsx)(n.p,{children:"Or, you can check the balance of an arbitrary account address by passing the\nnative or Ethereum-compatible addresses."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 1.0 TEST\n Available: 1.0 TEST\n\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show 0xA3243B310CfA8D4b008780BC87E0bb9f6d4FDA06\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Address: oasis1qzplmfaeywvtc2qnylyhk0uzcxr4y5s3euhaug7q\n\n=== CONSENSUS LAYER (testnet) ===\n Nonce: 0\n\n Total: 0.0 TEST\n Available: 0.0 TEST\n\n=== sapphire PARATIME ===\n Nonce: 0\n\n Balances for all denominations:\n - Amount: 10.0\n Symbol: TEST\n\n"})}),"\n",(0,a.jsxs)(n.p,{children:["To also include any staked assets in the balance, pass the ",(0,a.jsx)(n.code,{children:"--show-delegations"}),"\nflag. For example:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve --show-delegations\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsxs)(n.p,{children:["Let's look more closely at the figures above. The account's ",(0,a.jsx)(n.strong,{children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["We can see that the total account's ",(0,a.jsx)(n.strong,{children:"balance"})," on the consensus layer is ~973\ntokens:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"~951 tokens can immediately be transferred."}),"\n",(0,a.jsx)(n.li,{children:"~16.3 tokens (15,000,000,0000 shares) are staked (delegated)."}),"\n",(0,a.jsx)(n.li,{children:"~5.4 tokens are debonding and will be available for spending in the epoch\n26558."}),"\n",(0,a.jsxs)(n.li,{children:["up to ~270 tokens are ",(0,a.jsx)(n.a,{href:"#allow",children:"allowed"})," to be transferred to accounts\n",(0,a.jsx)(n.code,{children:"oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd"})," and\n",(0,a.jsx)(n.code,{children:"oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx"})," without the signature of the\naccount above."]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["Separately, you can notice there are ~7 tokens currently ",(0,a.jsx)(n.a,{href:"#deposit",children:"deposited"}),"\nin Sapphire."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"--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."]})}),"\n",(0,a.jsx)(n.p,{children:"Next, let's look at how the account of a validator typically looks like. For\nexample:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4 --show-delegations\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.em,{children:"escrow accounts"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Next, we can see a ",(0,a.jsx)(n.em,{children:"commission schedule"}),". A validator can charge commission for\ntokens that are delegated to it in form of the commission schedule ",(0,a.jsx)(n.strong,{children:"rate\nsteps"})," (7%, 11%, 14% and 18% activated on epochs 15883, 15994, 16000 and 16134\nrespectively) and the commission schedule ",(0,a.jsx)(n.strong,{children:"rate bound steps"})," (0-10% on\nepoch 15883 and then 0-20% activated on epoch 15993). For more details, see the\n",(0,a.jsx)(n.a,{href:"./account#amend-commission-schedule",children:"account amend-commission-schedule"}),"\ncommand."]}),"\n",(0,a.jsxs)(n.p,{children:["An escrow account may also accumulate one or more ",(0,a.jsx)(n.strong,{children:"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,a.jsx)(n.strong,{children:"all of the existing claims plus the\nnew claim can be satisfied"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"We can observe that the stake accumulator currently has the following claims:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"registry.RegisterEntity"})," claim is for registering an entity. It needs to\nsatisfy the global threshold for\n",(0,a.jsxs)(n.a,{href:"./network#show-native-token",children:["registering the ",(0,a.jsx)(n.code,{children:"entity"})]}),"."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"registry.RegisterNode.LAdHWnCkjFR5NUkFHVpfGuKFfZW1Cqjzu6wTFY6v2JI="}),"\nclaim is for registering the validator node with the public key\n",(0,a.jsx)(n.code,{children:"LAdHWnCkjFR5NUkFHVpfGuKFfZW1Cqjzu6wTFY6v2JI="}),". The claim needs to satisfy the\n",(0,a.jsx)(n.a,{href:"./network#show-native-token",children:(0,a.jsx)(n.code,{children:"node-validator"})})," global staking threshold parameter."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"registry.RegisterNode.xk58fx5ys6CSO33ngMQkgOL5UUHSgOSt0QbqWGGuEF8="}),"\nclaim is for registering the three compute nodes with the public key\n",(0,a.jsx)(n.code,{children:"xk58fx5ys6CSO33ngMQkgOL5UUHSgOSt0QbqWGGuEF8=="}),". The claim needs to satisfy\nthree ",(0,a.jsx)(n.a,{href:"./network#show-native-token",children:(0,a.jsx)(n.code,{children:"node-compute"})})," global staking threshold parameters."]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["For more details on registering entities, nodes and ParaTimes, see the\n",(0,a.jsx)(n.a,{href:"/core/consensus/services/registry#entities-and-nodes",children:"Oasis Core Registry service"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and ParaTime"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account show"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"transfer",children:"Transfer"}),"\n",(0,a.jsxs)(n.p,{children:["Use ",(0,a.jsx)(n.code,{children:"account transfer "})," command to transfer funds between two\naccounts on the consensus layer or between two accounts inside the same\nParaTime."]}),"\n",(0,a.jsx)(n.p,{children:"The following command will perform a token transfer inside default ParaTime:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 2.5 oscar --account orlando\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.p,{children:"Consensus layer token transfers:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 2.5 oscar --account orlando --no-paratime\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network, ParaTime and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account transfer"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"allow",children:"Allowance"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"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,a.jsx)(n.strong,{children:"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."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account allow logan 10\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.Allow\nBody:\n Beneficiary: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\n Amount change: +10.0 TEST\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.p,{children:"The allowance command uses relative amount. For example, if your run the\nabove command 3 times, Logan will be allowed to withdraw 30 ROSE."}),"\n",(0,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsxs)(n.p,{children:["To reduce the allowed amount or completely ",(0,a.jsx)(n.strong,{children:"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,a.jsx)(n.code,{children:"--"})," to mark the end of options, and finally append the negative amount."]}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account allow logan -- -10\n"})}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})})]}),"\n",(0,a.jsxs)(n.p,{children:["The allowance transaction is also required if you want to deposit funds from\nyour consensus account to a ParaTime. The ParaTime will ",(0,a.jsx)(n.strong,{children:"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,a.jsx)(n.code,{children:"paratime:"})," as the beneficiary\naddress."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account allow paratime:sapphire 10\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.Allow\nBody:\n Beneficiary: oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd\n Amount change: +10.0 TEST\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the ",(0,a.jsx)(n.code,{children:"account allow"}),"\ncommand."]})}),"\n",(0,a.jsx)(n.h2,{id:"deposit",children:"Deposit Tokens to a ParaTime"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"account deposit [address]"})," will deposit funds from your consensus\naccount to the target address inside the selected ParaTime."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis accounts deposit 10 eugene --gas-price 0\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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: 61310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.p,{children:"If no address is provided, the deposit will be made to the address\ncorresponding to your consensus account inside the ParaTime."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis accounts deposit 10 --gas-price 0\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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: 61285\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Currently, deposit transactions are free of charge, hence the ",(0,a.jsx)(n.code,{children:"--gas-price 0"}),"\nparameter to avoid spending unnecessary gas fees. Also, keep in\nmind that ",(0,a.jsx)(n.strong,{children:"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."]}),"\n",(0,a.jsx)(n.p,{children:"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:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account deposit 10 oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6 --gas-price 0\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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: 61310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.p,{children:"Or to some address in the Ethereum format:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis accounts deposit 10 0x90adE3B7065fa715c7a150313877dF1d33e777D5 --gas-price 0\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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: 61310\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network, ParaTime and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account deposit"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"withdraw",children:"Withdraw Tokens from the ParaTime"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"account withdraw [to]"})," will withdraw funds from your ParaTime account\nto a consensus address:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account withdraw 10 orlando\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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.0061311 TEST\n Gas limit: 61311\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.p,{children:"If the address is not provided, the address of the account inside ParaTime will\nbe used as a consensus address:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account withdraw 10\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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.0061286 TEST\n Gas limit: 61286\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"caution",children:(0,a.jsxs)(n.p,{children:["Withdrawal transactions are not free of charge and the fee will be deducted\n",(0,a.jsx)(n.strong,{children:"from your ParaTime balance"}),"."]})}),"\n",(0,a.jsxs)(n.p,{children:["Similar to the ",(0,a.jsx)(n.a,{href:"#deposit",children:(0,a.jsx)(n.code,{children:"account deposit"})})," command, you can also specify an\narbitrary Oasis address which you want to withdraw your tokens to."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis accounts withdraw 10 oasis1qpxhsf7xnm007csw2acaa7mta2krzpwex5c90qu6\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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.0061311 TEST\n Gas limit: 61311\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"caution",children:(0,a.jsxs)(n.p,{children:["You cannot use the destination address of your ",(0,a.jsx)(n.code,{children:"secp256k1"})," account or any other\nEthereum-formatted address for the withdrawal, because this signature scheme is\nnot supported on the consensus layer!"]})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network, ParaTime and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account withdraw"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"delegate",children:"Delegate Tokens to a Validator"}),"\n",(0,a.jsxs)(n.p,{children:["To stake your tokens on the consensus layer, run\n",(0,a.jsx)(n.code,{children:"account delegate "}),". This will delegate the specified amount of\ntokens to a validator."]}),"\n",(0,a.jsx)(n.p,{children:"You can either delegate directly on the consensus layer:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account delegate 20 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk --no-paratime\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.AddEscrow\nBody:\n To: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Amount: 20.0 TEST\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.p,{children:"Or you can delegate from inside a ParaTime that supports delegations:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account delegate 20 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Delegate\nBody:\n To: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Amount: 20.0 TEST\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.0061312 TEST\n Gas limit: 61312\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Once your tokens are staked, they are converted into ",(0,a.jsx)(n.em,{children:"shares"})," since the number\nof tokens may change over time based on the\n",(0,a.jsx)(n.a,{href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives",children:"staking reward schedule"})," or if your validator is subject to\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/terminology#slashing",children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["To find out how many shares did you delegate, run ",(0,a.jsx)(n.a,{href:"#show",children:(0,a.jsx)(n.code,{children:"account show"})})," and\nlook for the ",(0,a.jsx)(n.code,{children:"shares"})," under the active delegations section."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network, ParaTime and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account delegate"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"undelegate",children:"Undelegate Tokens from the Validator"}),"\n",(0,a.jsxs)(n.p,{children:["To reclaim your delegated assets, use ",(0,a.jsx)(n.code,{children:"account undelegate "}),". You\nwill need to specify the ",(0,a.jsx)(n.strong,{children:"number of shares instead of tokens"})," and the\nvalidator address you want to reclaim your assets from."]}),"\n",(0,a.jsx)(n.p,{children:"Depending on where the tokens have been delegated from, you can either reclaim\ndelegated tokens directly on the consensus layer:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account undelegate 20000000000 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk --no-paratime\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.ReclaimEscrow\nBody:\n From: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Shares: 20000000000\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.p,{children:"Or you can reclaim from inside a ParaTime that supports delegations:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account undelegate 20000000000 oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nFormat: plain\nMethod: consensus.Undelegate\nBody:\n From: oasis1qpkl3vykn9mf4xcq9eevmey4ffrzf0ajtcpvd7sk\n Shares: 20000000000\nAuthorized signer(s):\n 1. Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8= (ed25519)\n Nonce: 0\nFee:\n Amount: 0.012131 TEST\n Gas limit: 121310\n (gas price: 0.0000001 TEST per gas unit)\n\nNetwork: testnet\nParaTime: sapphire\nAccount: oscar\n"})}),"\n",(0,a.jsxs)(n.p,{children:["After submitting the transaction, a ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show",children:"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,a.jsx)(n.a,{href:"/general/manage-tokens/terminology#slashing",children:"slashed"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network, ParaTime and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account undelegate"})," command."]})}),"\n",(0,a.jsx)(n.h2,{id:"advanced",children:"Advanced"}),"\n",(0,a.jsx)(n.h3,{id:"from-public-key",children:"Public Key to Address"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"account from-public-key "})," converts the Base64-encoded public key\nto the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/terminology#address",children:"Oasis native address"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account from-public-key NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve\n"})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.code,{children:"id"})," field of the ",(0,a.jsx)(n.code,{children:"entity.json"})," file."]}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["Oasis consensus transactions hold the public key of the signer instead of their\n",(0,a.jsx)(n.em,{children:"from"})," address. This command can be used for debugging to determine the\nsigner's staking address on the network."]})}),"\n",(0,a.jsx)(n.h3,{id:"y",children:"Non-Interactive Mode"}),"\n",(0,a.jsxs)(n.p,{children:["Add ",(0,a.jsx)(n.code,{children:"-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.']}),"\n",(0,a.jsx)(n.h3,{id:"output-file",children:"Output Transaction to File"}),"\n",(0,a.jsxs)(n.p,{children:["Use ",(0,a.jsx)(n.code,{children:"--output-file "})," parameter to save the resulting transaction to a\nfile instead of broadcasting it to the network. You can then use the\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/transaction",children:(0,a.jsx)(n.code,{children:"transaction"})})," command to verify and submit it."]}),"\n",(0,a.jsxs)(n.p,{children:["Check out the ",(0,a.jsx)(n.a,{href:"#unsigned",children:(0,a.jsx)(n.code,{children:"--unsigned"})})," flag, if you wish to store the unsigned version of\nthe transaction and the ",(0,a.jsx)(n.a,{href:"#format",children:(0,a.jsx)(n.code,{children:"--format"})})," parameter for a different transaction\nencoding."]}),"\n",(0,a.jsx)(n.h3,{id:"unsigned",children:"Do Not Sign the Transaction"}),"\n",(0,a.jsxs)(n.p,{children:["If you wish to ",(0,a.jsx)(n.em,{children:"prepare"})," a transaction to be signed by a specific account in\nthe future, use the ",(0,a.jsx)(n.code,{children:"--unsigned"})," flag. This will cause Oasis CLI to skip the\nsigning and broadcasting steps. The transaction will be printed to the\nstandard output instead."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also use ",(0,a.jsx)(n.a,{href:"#output-file",children:(0,a.jsx)(n.code,{children:"--output-file"})})," to store the transaction to a file. This\nsetup is ideal when you want to sign a transaction with the\n",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Air_gap_(networking)",children:"offline/air-gapped machine"})," machine:"]}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"First, generate an unsigned transaction on a networked machine,"}),"\n",(0,a.jsx)(n.li,{children:"copy it over to an air-gapped machine,"}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/transaction#sign",children:"sign it"})," on the air-gapped machine,"]}),"\n",(0,a.jsx)(n.li,{children:"copy it over to the networked machine,"}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/transaction#submit",children:"broadcast the transaction"})," on the networked machine."]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["Use the CBOR format, if you are using a 3rd party tool in step 3 to sign the\ntransaction content directly. Check out the ",(0,a.jsx)(n.a,{href:"#format",children:(0,a.jsx)(n.code,{children:"--format"})})," parameter to learn\nmore."]}),"\n",(0,a.jsx)(n.h3,{id:"format",children:"Output format"}),"\n",(0,a.jsxs)(n.p,{children:["Use ",(0,a.jsx)(n.code,{children:"--format json"})," or ",(0,a.jsx)(n.code,{children:"--format cbor"})," to select the output file\nformat. By default the JSON encoding is selected so that the file is\nhuman-readable and that 3rd party applications can easily manage it. If you want\nto output the transaction in the same format that will be stored on-chain or you\nare using a 3rd party tool for signing the content of the transaction file\ndirectly use the CBOR encoding."]}),"\n",(0,a.jsxs)(n.p,{children:["This parameter only works together with ",(0,a.jsx)(n.a,{href:"#unsigned",children:(0,a.jsx)(n.code,{children:"--unsigned"})})," and/or\n",(0,a.jsx)(n.a,{href:"#output-file",children:(0,a.jsx)(n.code,{children:"--output-file"})})," parameters."]}),"\n",(0,a.jsx)(n.h3,{id:"offline",children:"Offline Mode"}),"\n",(0,a.jsxs)(n.p,{children:["To generate a transaction without accessing the network and also without\nbroadcasting it, add ",(0,a.jsx)(n.code,{children:"--offline"})," flag. In this case Oasis CLI will require that\nyou provide all necessary transaction details (e.g. ",(0,a.jsx)(n.a,{href:"#nonce",children:"account nonce"}),",\n",(0,a.jsx)(n.a,{href:"#gas-limit",children:"gas limit"}),", ",(0,a.jsx)(n.a,{href:"#gas-price",children:"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,a.jsx)(n.a,{href:"#output-file",children:(0,a.jsx)(n.code,{children:"--output-file"})}),", if\nyou wish to save the transaction to the file and submit it to the network\nafterwards by using the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/transaction#submit",children:(0,a.jsx)(n.code,{children:"transaction submit"})})," command."]}),"\n",(0,a.jsx)(n.h3,{id:"nonce",children:"Account's Nonce"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"--nonce "})," will override the detection of the account's nonce used\nto sign the transaction with the specified one."]}),"\n",(0,a.jsx)(n.h3,{id:"gas-price",children:"Gas Price"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"--gas-price "})," sets the transaction's price per gas unit in\nbase units."]}),"\n",(0,a.jsx)(n.h3,{id:"gas-limit",children:"Gas Limit"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"--gas-limit "})," sets the maximum amount of gas that can be spend by the\ntransaction."]}),"\n",(0,a.jsx)(n.h3,{id:"entity",children:"Entity Management"}),"\n",(0,a.jsx)(n.h4,{id:"entity-init",children:"Initialize Entity"}),"\n",(0,a.jsxs)(n.p,{children:["When setting up a validator node for the first time, you will need to provide\nthe path to the file containing your entity descriptor as well as register it in\nthe network registry. Use ",(0,a.jsx)(n.code,{children:"account entity init"})," to generate the entity\ndescriptor file containing the public key of the selected account."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account entity init\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "id": "Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=",\n "nodes": [],\n "v": 2\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["By default, the file content will be printed to the standard output. You can use\n",(0,a.jsx)(n.code,{children:"-o"})," parameter to store it to a file, for example:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account entity init -o entity.json\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#account",children:"Account"})," selector is available for the\n",(0,a.jsx)(n.code,{children:"account entity init"})," command."]})}),"\n",(0,a.jsx)(n.h4,{id:"entity-register",children:"Register your Entity"}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.code,{children:"account entity register "})," command to register\nyour entity and provide a JSON file with the Entity descriptor. You can use the\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show",children:(0,a.jsx)(n.code,{children:"network show"})})," command to see existing entities and\nthen examine specific ones to see how entity descriptors of the currently\nregistered entities look like."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account entity register entity.json\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'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: 2\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'})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account entity register"})," command."]})}),"\n",(0,a.jsx)(n.h4,{id:"entity-deregister",children:"Deregister Your Entity"}),"\n",(0,a.jsxs)(n.p,{children:["To remove an entity from the network's registry, invoke\n",(0,a.jsx)(n.code,{children:"account entity deregister"}),". No additional arguments are required since each\naccount can only deregister their own entity, if one exists in the registry."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account entity deregister\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: registry.DeregisterEntity\nBody:\n {}\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account entity deregister"})," command."]})}),"\n",(0,a.jsx)(n.h3,{id:"amend-commission-schedule",children:"Change Your Commission Schedule"}),"\n",(0,a.jsxs)(n.p,{children:["Validators can use ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.code,{children:"--bounds //"})," parameter.\nActual rates which can be subject to change every epoch can be defined with the\n",(0,a.jsx)(n.code,{children:"--rates /"})," parameter. Rates are specified in milipercents\n(100% = 100000m%). The new commission schedule will replace any previous\nschedules."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account amend-commission-schedule --bounds 329000/1000/2000,335000/900/1900 --rates 329000/1500\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.AmendCommissionSchedule\nBody:\n Amendment:\n Rates:\n (1) start: epoch 329000\n rate: 1.5%\n Rate Bounds:\n (1) start: epoch 329000\n minimum rate: 1.0%\n maximum rate: 2.0%\n (2) start: epoch 335000\n minimum rate: 0.9%\n maximum rate: 1.9%\nNonce: 2\nFee:\n Amount: 0.0 TEST\n Gas limit: 1361\n (gas price: 0.0 TEST per gas unit)\n\nNetwork: testnet\nParaTime: none (consensus layer)\nAccount: oscar\n"})}),"\n",(0,a.jsxs)(n.p,{children:["To learn more on commission rates read the section inside the Oasis Core\n",(0,a.jsx)(n.a,{href:"/core/consensus/services/staking#amend-commission-schedule",children:"Staking service"})," chapter."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account amend-commission-schedule"})," command."]})}),"\n",(0,a.jsx)(n.h3,{id:"node-unfreeze",children:"Unfreeze Your Node"}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"/node/run-your-node/maintenance/shutting-down-a-node",children:"Shutting Down a Node"})," instructions. Nevertheless, if the network froze your\nnode, the only way to unfreeze it is to execute the ",(0,a.jsx)(n.code,{children:"account node-unfreeze"})]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account node-unfreeze fasTG3pMOwLfFA7JX3R8Kxw1zFflqeY6NP/cpjcFu5I=\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'You are about to sign the following transaction:\nMethod: registry.UnfreezeNode\nBody:\n {\n "node_id": "fasTG3pMOwLfFA7JX3R8Kxw1zFflqeY6NP/cpjcFu5I="\n }\nNonce: 2\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'})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the\n",(0,a.jsx)(n.code,{children:"account node-unfreeze"})," command."]})}),"\n",(0,a.jsx)(n.h3,{id:"burn",children:"Burn Tokens"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account burn 2.5\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"You are about to sign the following transaction:\nMethod: staking.Burn\nBody:\n Amount: 2.5 TEST\nNonce: 2\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"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"#npa",children:"Network and account"})," selectors are available for the ",(0,a.jsx)(n.code,{children:"account burn"}),"\ncommand."]})}),"\n",(0,a.jsx)(n.h3,{id:"reserved-addresses",children:"Pools and Reserved Addresses"}),"\n",(0,a.jsx)(n.p,{children:"The following literals are used in the Oasis CLI to denote special reserved\naddresses which cannot be directly used in the ledger:"}),"\n",(0,a.jsx)(n.h4,{id:"consensus-layer",children:"Consensus layer"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:consensus:burn"}),": The token burn address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:consensus:common"}),": The common pool address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:consensus:fee-accumulator"}),": The per-block fee accumulator address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:consensus:governance-deposits"}),": The governance deposits address."]}),"\n"]}),"\n",(0,a.jsx)(n.h4,{id:"paratime-layer",children:"ParaTime layer"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:paratime:common"}),": The common pool address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:paratime:fee-accumulator"}),": The per-block fee accumulator address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:paratime:pending-withdrawal"}),": The internal pending withdrawal address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:paratime:pending-delegation"}),": The internal pending delegation address."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"pool:paratime:rewards"}),": The reward pool address."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>r});var a=s(6540);const t={},o=a.createContext(t);function i(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0f92291a.ea9eed1e.js b/assets/js/0f92291a.ea9eed1e.js new file mode 100644 index 0000000000..e3d820e157 --- /dev/null +++ b/assets/js/0f92291a.ea9eed1e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8593],{3917:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>m,contentTitle:()=>r,default:()=>c,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var s=i(4848),n=i(8453);const o={},r="Join our Community",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"getInvolved",next:{title:"Run a Node",permalink:"/get-involved/run-node"}},m={},h=[{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}];function l(e){const t={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"join-our-community",children:"Join our Community"}),"\n",(0,s.jsx)(t.h2,{id:"welcome-to-the-oasis-community",children:"Welcome to the Oasis Community"}),"\n",(0,s.jsx)(t.p,{children:"Whether you're a blockchain enthusiast, a software developer, or someone who is\njust starting to 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."}),"\n",(0,s.jsx)(t.h2,{id:"social-media-channels",children:"Social Media Channels"}),"\n",(0,s.jsx)(t.p,{children:"To stay up-to-date on the latest Oasis Network news, events, and programs, be\nsure to join our social media channels:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"https://oasis.io/discord",children:"Discord"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"https://twitter.com/OasisProtocol",children:"Twitter"})}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"https://t.me/oasisprotocolcommunity",children:"Public Telegram channel"})," (for community discussions open to everyone)"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"https://t.me/oasisprotocolfoundation",children:"Telegram Announcement channel"})," (for one-way updates from the Oasis Foundation)"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"regional-communities",children:"Regional Communities"}),"\n",(0,s.jsx)(t.p,{children:"To connect with Oasis community members who live in your home region or speak\nyour native language, check out our region-based community channels:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Arabic Speaking Countries: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Arabic",children:"https://t.me/OasisNetworkCommunity_Arabic"})]}),"\n",(0,s.jsxs)(t.li,{children:["Austria: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Austria",children:"https://t.me/OasisNetworkCommunity_Austria"})]}),"\n",(0,s.jsxs)(t.li,{children:["Bangladesh: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Bangladesh",children:"https://t.me/OasisNetworkCommunity_Bangladesh"})]}),"\n",(0,s.jsxs)(t.li,{children:["Brazil: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Brazil",children:"https://t.me/OasisNetworkCommunity_Brazil"})]}),"\n",(0,s.jsxs)(t.li,{children:["China WeChat: ",(0,s.jsx)(t.a,{href:"https://t.me/oasisprotocolcommunity/27378",children:"https://t.me/oasisprotocolcommunity/27378"})]}),"\n",(0,s.jsxs)(t.li,{children:["France: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_France",children:"https://t.me/OasisNetworkCommunity_France"})]}),"\n",(0,s.jsxs)(t.li,{children:["Germany: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Germany",children:"https://t.me/OasisNetworkCommunity_Germany"})]}),"\n",(0,s.jsxs)(t.li,{children:["India: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_India",children:"https://t.me/OasisNetworkCommunity_India"})]}),"\n",(0,s.jsxs)(t.li,{children:["Indonesia: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Indonesia",children:"https://t.me/OasisNetworkCommunity_Indonesia"})]}),"\n",(0,s.jsxs)(t.li,{children:["Japan: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_japan8",children:"https://t.me/OasisNetworkCommunity_japan8"})]}),"\n",(0,s.jsxs)(t.li,{children:["Korea: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Korea",children:"https://t.me/OasisNetworkCommunity_Korea"})]}),"\n",(0,s.jsxs)(t.li,{children:["Nigeria: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Nigeria",children:"https://t.me/OasisNetworkCommunity_Nigeria"})]}),"\n",(0,s.jsxs)(t.li,{children:["Philippines: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Philippine",children:"https://t.me/OasisNetworkCommunity_Philippine"})]}),"\n",(0,s.jsxs)(t.li,{children:["Russia: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Russia",children:"https://t.me/OasisNetworkCommunity_Russia"})]}),"\n",(0,s.jsxs)(t.li,{children:["Singapore: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Singapore8",children:"https://t.me/OasisNetworkCommunity_Singapore8"})]}),"\n",(0,s.jsxs)(t.li,{children:["Spanish Speaking Countries: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Spanish",children:"https://t.me/OasisNetworkCommunity_Spanish"})]}),"\n",(0,s.jsxs)(t.li,{children:["Sri Lanka: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_SriLanka",children:"https://t.me/OasisNetworkCommunity_SriLanka"})]}),"\n",(0,s.jsxs)(t.li,{children:["Sweden: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Sweden8",children:"https://t.me/OasisNetworkCommunity_Sweden8"})]}),"\n",(0,s.jsxs)(t.li,{children:["Switzerland: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunitySwitzerland",children:"https://t.me/OasisNetworkCommunitySwitzerland"})]}),"\n",(0,s.jsxs)(t.li,{children:["Turkey: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Turkey",children:"https://t.me/OasisNetworkCommunity_Turkey"})]}),"\n",(0,s.jsxs)(t.li,{children:["Ukraine: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Ukraine",children:"https://t.me/OasisNetworkCommunity_Ukraine"})]}),"\n",(0,s.jsxs)(t.li,{children:["Uzbekistan: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Uzbekistan",children:"https://t.me/OasisNetworkCommunity_Uzbekistan"})]}),"\n",(0,s.jsxs)(t.li,{children:["Vietnam: ",(0,s.jsx)(t.a,{href:"https://t.me/OasisNetworkCommunity_Vietnam",children:"https://t.me/OasisNetworkCommunity_Vietnam"})]}),"\n"]})]})}function c(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>r,x:()=>a});var s=i(6540);const n={},o=s.createContext(n);function r(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/10244602.e46a9577.js b/assets/js/10244602.e46a9577.js new file mode 100644 index 0000000000..54230791fb --- /dev/null +++ b/assets/js/10244602.e46a9577.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4518],{7446:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>d,toc:()=>h});var r=t(4848),o=t(8453),a=t(1470),i=t(9365);const s={},l="Frequently Asked Questions",d={id:"general/manage-tokens/faq",title:"Frequently Asked Questions",description:"This documents answers frequently asked questions about the official Oasis and",source:"@site/docs/general/manage-tokens/faq.mdx",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/faq",permalink:"/general/manage-tokens/faq",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/faq.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Address book",permalink:"/general/manage-tokens/cli/addressbook"}},c={},h=[{value:"How can I transfer ROSE tokens from my BitPie wallet to my ROSE Wallet?",id:"how-can-i-transfer-rose-tokens-from-my-bitpie-wallet-to-my-rose-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 ROSE Wallet that different? I can use the same mnemonics with both, right?",id:"are-ethereum-and-rose-wallet-that-different-i-can-use-the-same-mnemonics-with-both-right",level:3},{value:"Which derivation path should I use on Ledger? ADR-8 or Legacy?",id:"ledger-derivation-paths",level:3},{value:"I lost my Ledger or my Ledger is broken. I urgently need to access my assets. Can I import Ledger mnemonic into ROSE Wallet?",id:"i-lost-my-ledger-or-my-ledger-is-broken-i-urgently-need-to-access-my-assets-can-i-import-ledger-mnemonic-into-rose-wallet",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}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"}),"\n",(0,r.jsx)(n.p,{children:"This documents answers frequently asked questions about the official Oasis and\n3rd party wallets & custody providers supporting ROSE."}),"\n",(0,r.jsx)(n.h3,{id:"how-can-i-transfer-rose-tokens-from-my-bitpie-wallet-to-my-rose-wallet",children:"How can I transfer ROSE tokens from my BitPie wallet to my ROSE Wallet?"}),"\n",(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsxs)(n.p,{children:["BitPie wallet doesn't use the ",(0,r.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"standardized Oasis mnemonic derivation (ADR-8)"}),".\nConsequently, your ",(0,r.jsx)(n.strong,{children:"Bitpie wallet's mnemonic phrase will not open the same\naccount in the ROSE Wallet"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["In May 2023, the BitPie team ",(0,r.jsx)(n.a,{href:"https://medium.com/bitpie/announcement-on-suspension-of-support-for-algo-and-rose-fc35cb322617",children:"removed support for the Oasis\nnetwork"}),". Thus, the only way to access your tokens stored\non your BitPie wallet is to obtain the private key of your BitPie's wallet in\none of the two ways:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet",children:"Export private key from a working BitPie wallet"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#how-can-i-export-oasis-private-key-if-bitpie-doesnt-show-my-rose-account-anymore",children:"Convert BitPie mnemonic to Oasis private key offline"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Once you obtained the private key, you can\n",(0,r.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#import-an-existing-account",children:"import it to the ROSE Wallet"})," and access\nyour assets."]}),"\n",(0,r.jsx)(n.h3,{id:"how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet",children:"How can I export Oasis private key from a working BitPie wallet?"}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["Chinese users can follow the ",(0,r.jsx)(n.a,{href:"https://bitpie.zendesk.com/hc/zh-cn/articles/6796209839503",children:"official BitPie support article"})," on how to export\nthe Oasis private key from your BitPie wallet."]})}),"\n",(0,r.jsx)(n.p,{children:"If you have an existing ROSE account in your BitPie wallet, you can obtain the\nwallet's private key by following the steps below."}),"\n",(0,r.jsx)(n.p,{children:'On the main BitPie wallet screen, click on the "Receive" button.'}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"BitPie main screen",src:t(9151).A+"",width:"720",height:"1520"})}),"\n",(0,r.jsxs)(n.p,{children:['The QR code with your ROSE address will appear. Then, in the top right corner,\ntap on the kebab menu "\u22ee" and select "Display Private Key"',(0,r.jsx)(n.em,{children:"."})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"BitPie show private key",src:t(4684).A+"",width:"720",height:"1520"})}),"\n",(0,r.jsx)(n.p,{children:"BitPie wallet will now ask you to enter your PIN to access the private key."}),"\n",(0,r.jsxs)(n.p,{children:["Finally, your account's private key will be shown to you encoded in Base64\nformat (e.g.\n",(0,r.jsx)(n.code,{children:"YgwGOfrHG1TVWSZBs8WM4w0BUjLmsbk7Gqgd7IGeHfSqdbeQokEhFEJxtc3kVQ4KqkdZTuD0bY7LOlhdEKevaQ=="}),")\nwhich you can\n",(0,r.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#import-an-existing-account",children:"import into ROSE Wallet"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"how-can-i-export-oasis-private-key-if-bitpie-doesnt-show-my-rose-account-anymore",children:"How can I export Oasis private key, if BitPie doesn't show my ROSE account anymore?"}),"\n",(0,r.jsxs)(n.p,{children:["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,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/tree/main/unmnemonic",children:"Oasis\nunmnemonic tool"})," (64-bit binaries available for ",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_linux_amd64",children:"Linux"}),",\n",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_darwin_all",children:"MacOS"})," and ",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_windows_amd64.exe",children:"Windows"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["Open a terminal (on Windows run ",(0,r.jsx)(n.code,{children:"cmd"}),"), move to the corresponding folder and\ninvoke the unmnemonic executable:"]}),"\n",(0,r.jsxs)(a.A,{children:[(0,r.jsx)(i.A,{value:"Linux",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"./unmnemonic_linux_amd64\n"})})}),(0,r.jsx)(i.A,{value:"MacOS",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"./unmnemonic_darwin_all\n"})})}),(0,r.jsx)(i.A,{value:"Windows",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"unmnemonic_windows_amd64\n"})})})]}),"\n",(0,r.jsx)(n.p,{children:"An interactive prompt will be shown to you:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["select the ",(0,r.jsx)(n.strong,{children:"Bitpie"})," algorithm,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the number of words in the mnemonic (typically ",(0,r.jsx)(n.strong,{children:"12"}),") and carefully\ntype them in one by line,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the private key index (start with ",(0,r.jsx)(n.strong,{children:"0"})," and gradually increase it by 1,\nif the resulting account does not contain any tokens),"]}),"\n",(0,r.jsxs)(n.li,{children:["answer ",(0,r.jsx)(n.strong,{children:"Yes"})," for writing the keys to disk,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the name of the ",(0,r.jsx)(n.strong,{children:"output directory"})," to store the Oasis private key\ninto (by default the folder name starts with ",(0,r.jsx)(n.code,{children:"wallet-export-"}),")"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" 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"})}),"\n",(0,r.jsxs)(n.p,{children:["Finally, look into the output directory. There you should find a ",(0,r.jsx)(n.code,{children:".private.pem"}),"\nfile containing the private key and named after the address it belongs to. You\ncan either:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Open it with a text editor, copy the Base64-encoded key between the\n",(0,r.jsx)(n.code,{children:"-----BEGIN ED25519 PRIVATE KEY-----"})," and ",(0,r.jsx)(n.code,{children:"-----END ED25519 PRIVATE KEY-----"}),",\nand ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#import-an-existing-account",children:"paste it into the ROSE Wallet"}),", or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["if you use the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," simply execute the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import-file",children:(0,r.jsx)(n.code,{children:"oasis wallet import-file"})}),"\ncommand to add the exported account to your CLI wallet, for example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"oasis wallet import-file my_unmnemonic_account oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl.private.pem\n"})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"chromium-under-ubuntu-does-not-recognize-my-ledger-device-what-is-the-problem",children:"Chromium under Ubuntu does not recognize my Ledger device. What is the problem?"}),"\n",(0,r.jsxs)(n.p,{children:["First check that you added the Ledger udev device descriptors as mentioned in\nthe ",(0,r.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/4404389606417-Download-and-install-Ledger-Live",children:"Linux installation guide"}),". Next, check that your Ledger wallet is\nrecognized by the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"}),". You should be able to add your Ledger account to\nthe Oasis CLI wallet by running:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"oasis wallet create oscar\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If all of the above works, then the issue is most likely that Chromium does not\nhave the permission to access your Ledger device. Starting with Ubuntu 20.04 the\nChromium browser is installed via snap package by default. Snap is more\nconvenient for upstream developers to deploy their software and it also adds\nadditional layer of security by using apparmor. In our case however, it prevents\nChromium to access arbitrary USB devices with WebUSB API including your Ledger\ndevice. A workaround for this issue is to install Chromium natively using the\nofficial ",(0,r.jsx)(n.a,{href:"https://launchpad.net/~saiarcot895/+archive/ubuntu/chromium-beta",children:"Chormium beta PPA"})," or the official ",(0,r.jsx)(n.a,{href:"https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb",children:"Google Chrome .deb package"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"are-ethereum-and-rose-wallet-that-different-i-can-use-the-same-mnemonics-with-both-right",children:"Are Ethereum and ROSE Wallet that different? I can use the same mnemonics with both, right?"}),"\n",(0,r.jsxs)(n.p,{children:["Yes, both ROSE and Ethereum wallets make use of the mnemonics as defined in ",(0,r.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",children:"BIP39"})," and they even use the same wordlist to derive the keypairs for your wallet. However, they use a different ",(0,r.jsx)(n.strong,{children:"signature scheme and a derivation path"}),", so the addresses and the private keys are incompatible."]}),"\n",(0,r.jsx)(n.p,{children:"Here's a task for you:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["Visit ",(0,r.jsx)(n.a,{href:"https://iancoleman.io/bip39/",children:"https://iancoleman.io/bip39/"})," to generate a BIP39 mnemonic."]}),"\n",(0,r.jsxs)(n.li,{children:["Select ETH token and copy the hex-encoded private key of the first derived account, for example ",(0,r.jsx)(n.code,{children:"0xab2c4f3bc70d40f12f6030750fe452448b5464114cbfc46704edeef2cd06da74"}),"."]}),"\n",(0,r.jsx)(n.li,{children:"Import the Ethereum-compatible account with the private key obtained above to your ROSE Wallet."}),"\n",(0,r.jsxs)(n.li,{children:["Notice the Ethereum address of the account, for example ",(0,r.jsx)(n.code,{children:"0x58c72Eb040Dd0DF10882aA87a39851c21Ae5F331"}),"."]}),"\n",(0,r.jsx)(n.li,{children:'Now in the Account management screen, select this account and click on the "Export private key" button. Confirm the risk warning.'}),"\n",(0,r.jsxs)(n.li,{children:["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,r.jsx)(n.code,{children:"oasis1qpaj6hznytpvyvalmsdg8vw5fzlpftpw7g7ku0h0"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Now let's use the private key from step 2 to import the account. First, convert the hex-encoded key to base64 format, for example by using ",(0,r.jsx)(n.a,{href:"https://base64.guru/converter/encode/hex",children:"this service"}),". In our example, that would be ",(0,r.jsx)(n.code,{children:"qyxPO8cNQPEvYDB1D+RSRItUZBFMv8RnBO3u8s0G2nQ="}),"."]}),"\n",(0,r.jsx)(n.li,{children:"Next, import this base64-encoded private key to the ROSE Wallet Browser Extension."}),"\n",(0,r.jsxs)(n.li,{children:["You should see your newly imported account and the Oasis address. In our case ",(0,r.jsx)(n.code,{children:"oasis1qzaf9zd8rlmchywmkkqmy00wrczstugfxu9q09ng"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["Observe that this account address ",(0,r.jsx)(n.strong,{children:"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,r.jsx)(n.em,{children:"signature scheme"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["As an additional exercise, you can also create an Oasis account 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,r.jsx)(n.em,{children:"derivation path"})," than Ethereum."]}),"\n",(0,r.jsx)(n.h3,{id:"ledger-derivation-paths",children:"Which derivation path should I use on Ledger? ADR-8 or Legacy?"}),"\n",(0,r.jsxs)(n.p,{children:["To convert your mnemonic phrase into a private key for signing trasactions,\neach wallet (hardware or software) performs a ",(0,r.jsx)(n.em,{children:"key derivation"}),". The Oasis\nProtocol Foundation standardized the key derivation for the official ROSE Wallet\nin a document called ",(0,r.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8"})," back in January 2021. However, the Ledger\nhardware wallet already supported signing transactions at that time using a\ncustom (we now call it ",(0,r.jsx)(n.em,{children:"legacy"}),") derivation path which is incompatible with\nthe one defined in ADR-8. Later, in Oasis app for Ledger v2.3.1 support for\nADR-8 was added so the wallet can request either derivation from the Ledger\ndevice."]}),"\n",(0,r.jsx)(n.p,{children:"The key derivation path defined in ADR-8 has the following advantages\ncompared to the legacy one:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Derivation path is shorter which results in approximately twice as fast\nkey derivation (and transaction signing) without compromising security."}),"\n",(0,r.jsx)(n.li,{children:"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 a ROSE Wallet which implements ADR-8."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"For reasons above, we recommend the usage of ADR-8. However, since there are\nno security considerations at stake, the ROSE Wallet will support legacy\nderivation on Ledger for the foreseeable future."}),"\n",(0,r.jsx)(n.h3,{id:"i-lost-my-ledger-or-my-ledger-is-broken-i-urgently-need-to-access-my-assets-can-i-import-ledger-mnemonic-into-rose-wallet",children:"I lost my Ledger or my Ledger is broken. I urgently need to access my assets. Can I import Ledger mnemonic into ROSE Wallet?"}),"\n",(0,r.jsx)(n.admonition,{type:"danger",children:(0,r.jsxs)(n.p,{children:["When you import your Ledger mnemonic to a software wallet, consider\nthat mnemonic ",(0,r.jsx)(n.em,{children:"potentially exposed/compromised"}),", i.e. not appropriate for a\nhardware wallet mnemonic anymore. If you use a new hardware wallet in the\nfuture, ",(0,r.jsx)(n.strong,{children:"never restore it from the mnemonic that was previously used by any\nsoftware wallet!"})]})}),"\n",(0,r.jsxs)(n.p,{children:["Ledger supports ",(0,r.jsx)(n.a,{href:"#ledger-derivation-paths",children:"two derivation paths"})," on the Oasis\nnetwork."]}),"\n",(0,r.jsxs)(n.p,{children:["If you used your Ledger with the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," and the ",(0,r.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8"})," derivation path,\nyou can import the mnemonic directly into the CLI wallet by invoking\n",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import",children:(0,r.jsx)(n.code,{children:"oasis wallet import"})})," and selecting the ",(0,r.jsx)(n.code,{children:"ed25519-adr8"})," algorithm."]}),"\n",(0,r.jsxs)(n.p,{children:["If you used your Ledger with the ROSE Wallet Web, the browser extension, the\nOasis CLI with the ",(0,r.jsx)(n.code,{children:"ed25519-legacy"})," derivation path or the Oasis Core, then you\nwill need to use the ",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/tree/main/unmnemonic",children:"Oasis unmnemonic tool"})," (64-bit binaries available for\n",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_linux_amd64",children:"Linux"}),", ",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_darwin_all",children:"MacOS"})," and\n",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases/download/unmnemonic-tool-0.1.0/unmnemonic_windows_amd64.exe",children:"Windows"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["Open a terminal (on Windows run ",(0,r.jsx)(n.code,{children:"cmd"}),"), move to the corresponding folder and\ninvoke the unmnemonic executable:"]}),"\n",(0,r.jsxs)(a.A,{children:[(0,r.jsx)(i.A,{value:"Linux",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"./unmnemonic_linux_amd64\n"})})}),(0,r.jsx)(i.A,{value:"MacOS",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"./unmnemonic_darwin_all\n"})})}),(0,r.jsx)(i.A,{value:"Windows",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"unmnemonic_windows_amd64\n"})})})]}),"\n",(0,r.jsx)(n.p,{children:"An interactive prompt will be shown to you:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["select the ",(0,r.jsx)(n.strong,{children:"Ledger"})," algorithm,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the number of words in the mnemonic (typically ",(0,r.jsx)(n.strong,{children:"24"}),") and carefully\ntype them in one by line,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the private key index (start with ",(0,r.jsx)(n.strong,{children:"0"})," and gradually increase it by 1,\nif the resulting account does not contain any tokens),"]}),"\n",(0,r.jsxs)(n.li,{children:["answer ",(0,r.jsx)(n.strong,{children:"Yes"})," for writing the keys to disk,"]}),"\n",(0,r.jsxs)(n.li,{children:["enter the name of the ",(0,r.jsx)(n.strong,{children:"output directory"})," to store the Oasis private key\ninto (by default the folder name starts with ",(0,r.jsx)(n.code,{children:"wallet-export-"}),")"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" unmnemonic - Recover Oasis Network signing keys from mnemonics\n\n? Which algorithm does your wallet use Ledger\n WARNING:\n\n Entering your Ledger device mnemonic into any non-Leger device\n can COMPROMISE THE SECURITY OF ALL ACCOUNTS TIED TO THE MNEMONIC.\n Use of this tool is STRONGLY DISCOURAGED.\n\n? Have you read and understand the warning Yes\n? How many words is your mnemonic 24\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? Enter word 13 *****\n? Enter word 14 ****\n? Enter word 15 ****\n? Enter word 16 ******\n? Enter word 17 ****\n? Enter word 18 *****\n? Enter word 19 ****\n? Enter word 20 *******\n? Enter word 21 ******\n? Enter word 22 *****\n? Enter word 23 ***\n? Enter word 24 *****\n? Wallet index(es) (comma separated) 4\n Index[4]: oasis1qqwkm23pyg638xvl2nu00frxhapusjjv8qhh3p77\n? Write the keys to disk Yes\n? Output directory /home/oa/tmp/wallet-export-2023-11-28\n Index[4]: oasis1qqwkm23pyg638xvl2nu00frxhapusjjv8qhh3p77.private.pem - done\nDone writing wallet keys to disk, goodbye.\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Finally, look into the output directory. There you should find a ",(0,r.jsx)(n.code,{children:".private.pem"}),"\nfile containing the private key and named after the address it belongs to. You\ncan either:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Open it with a text editor, copy the Base64-encoded key between the\n",(0,r.jsx)(n.code,{children:"-----BEGIN ED25519 PRIVATE KEY-----"})," and ",(0,r.jsx)(n.code,{children:"-----END ED25519 PRIVATE KEY-----"}),",\nand ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#import-an-existing-account",children:"paste it into the ROSE Wallet"}),", or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["if you use the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," simply execute the ",(0,r.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import-file",children:(0,r.jsx)(n.code,{children:"oasis wallet import-file"})}),"\ncommand to add the exported account to your CLI wallet, for example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"oasis wallet import-file my_unmnemonic_account oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl.private.pem\n"})}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.h3,{id:"the-wallet-gives-me-invalid-keyphrase-error-when-importing-my-wallet-from-mnemonics-how-do-i-solve-it",children:["The wallet gives me ",(0,r.jsx)(n.em,{children:"Invalid keyphrase"})," error when importing my wallet from mnemonics. How do I solve it?"]}),"\n",(0,r.jsx)(n.p,{children:"Please check that:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["All mnemonics were spelled correctly. The ROSE Wallet uses English mnemonic phrase words as defined in BIP39. You can find a complete list of valid phrase words ",(0,r.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt",children:"here"}),"."]}),"\n",(0,r.jsx)(n.li,{children:"The mnemonics were input in correct order."}),"\n",(0,r.jsx)(n.li,{children:"All mnemonics were provided. The keyphrase should be either 12, 15, 18, 21, or 24 words long."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"If you checked all of the above and the keyphrase still cannot be imported, please contact Oasis support."}),"\n",(0,r.jsx)(n.h3,{id:"i-imported-my-wallet-with-mnemonics-the-wallet-should-contain-funds-but-the-balance-is-empty-what-can-i-do",children:"I imported my wallet with mnemonics. The wallet should contain funds, but the balance is empty. What can I do?"}),"\n",(0,r.jsxs)(n.p,{children:["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,r.jsx)(n.a,{href:"https://oasisscan.com",children:"Oasis Monitor service"})," itself which observes the network\nand indexes transactions. The ROSE Wallet relies on that service and once it is\nback up and running, you should be able to see the correct balance."]}),"\n",(0,r.jsxs)(n.p,{children:["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 ",(0,r.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"standardized key\nderivation path"}),". If you were using the BitPie wallet see\n",(0,r.jsx)(n.a,{href:"#how-can-i-export-oasis-private-key-from-a-working-bitpie-wallet",children:"this question"}),".\nLedger hardware wallet users should refer to\n",(0,r.jsx)(n.a,{href:"#ledger-derivation-paths",children:"this question"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["If you still cannot access your funds, please contact Oasis support on ",(0,r.jsx)(n.a,{href:"https://oasis.io/discord",children:"#wallets\nDiscord channel"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"i-sent-my-rose-to-binancestaking-address--are-they-staked-are-they-lost-what-can-i-do",children:"I sent my ROSE to BinanceStaking address. Are they staked? Are they lost? What can I do?"}),"\n",(0,r.jsxs)(n.p,{children:["If you just make a ",(0,r.jsx)(n.strong,{children:"Send"})," transaction to BinanceStaking address ",(0,r.jsx)(n.code,{children:"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,r.jsx)(n.a,{href:"https://www.binance.com/en/support",children:"Support Center"})," or ",(0,r.jsx)(n.a,{href:"https://www.binance.com/en/chat",children:"Submit a request"}),"."]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Sending ROSE is different than staking it! With the staking transaction you ",(0,r.jsx)(n.strong,{children:"lend"})," your ROSE to the chosen validator and you are rewarded for that. ",(0,r.jsx)(n.strong,{children:"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,r.jsx)(n.a,{href:"/general/manage-tokens/staking-and-delegating",children:"Staking and Delegating chapter"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"i-withdrew-rose-from-emerald-to-an-exchange-binance-kucoin-but-my-deposit-is-not-there-what-should-i-do",children:"I withdrew ROSE from Emerald to an exchange (Binance, KuCoin), but my deposit is not there. What should I do?"}),"\n",(0,r.jsxs)(n.p,{children:["Withdrawals from Emerald are slightly different from regular ",(0,r.jsx)(n.code,{children:"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,r.jsx)(n.a,{href:"https://www.oasisscan.com",children:"Oasis Scan"})," where they can verify all transactions. To learn more about this issue, read the ",(0,r.jsx)(n.a,{href:"/",children:"Manage tokens"})," chapter."]})]})}function m(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>i});t(6540);var r=t(4164);const o={tabItem:"tabItem_Ymn6"};var a=t(4848);function i(e){let{children:n,hidden:t,className:i}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,r.A)(o.tabItem,i),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>j});var r=t(6540),o=t(4164),a=t(3104),i=t(6347),s=t(205),l=t(7485),d=t(1682),c=t(9466);function h(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function u(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,d.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.W6)(),a=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,l.aZ)(a),(0,r.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(o.location.search);n.set(a,e),o.replace({...o.location,search:n.toString()})}),[a,o])]}function w(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,a=u(e),[i,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:a}))),[d,h]=p({queryString:t,groupId:o}),[w,y]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,a]=(0,c.Dv)(t);return[o,(0,r.useCallback)((e=>{t&&a.set(e)}),[t,a])]}({groupId:o}),g=(()=>{const e=d??w;return m({value:e,tabValues:a})?e:null})();(0,s.A)((()=>{g&&l(g)}),[g]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!m({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),h(e),y(e)}),[h,y,a]),tabValues:a}}var y=t(2303);const g={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(4848);function x(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:d}=(0,a.a_)(),c=e=>{const n=e.currentTarget,t=l.indexOf(n),o=s[t].value;o!==r&&(d(n),i(o))},h=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.A)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:h,onClick:c,...a,className:(0,o.A)("tabs__item",g.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function b(e){let{lazy:n,children:t,selectedValue:o}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function v(e){const n=w(e);return(0,f.jsxs)("div",{className:(0,o.A)("tabs-container",g.tabList),children:[(0,f.jsx)(x,{...n,...e}),(0,f.jsx)(b,{...n,...e})]})}function j(e){const n=(0,y.A)();return(0,f.jsx)(v,{...e,children:h(e.children)},String(n))}},9151:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/mainscreen-444c4a14f5bcc45a74a9697a0a1e9b80.png"},4684:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/show_private_key-bf6f89e80fb50ffa6728980e19d7d96b.png"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>s});var r=t(6540);const o={},a=r.createContext(o);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/10bc4617.1bd9a524.js b/assets/js/10bc4617.1bd9a524.js new file mode 100644 index 0000000000..6d613cf93e --- /dev/null +++ b/assets/js/10bc4617.1bd9a524.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3095],{5309:(e,s,o)=>{o.r(s),o.d(s,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>u});var t=o(4848),n=o(8453);const c={},r="Epoch Time",i={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/epochtime.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Services",permalink:"/core/consensus/services"},next:{title:"Random Beacon",permalink:"/core/consensus/services/beacon"}},a={},u=[];function p(e){const s={h1:"h1",...(0,n.R)(),...e.components};return(0,t.jsx)(s.h1,{id:"epoch-time",children:"Epoch Time"})}function d(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},8453:(e,s,o)=>{o.d(s,{R:()=>r,x:()=>i});var t=o(6540);const n={},c=t.createContext(n);function r(e){const s=t.useContext(c);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),t.createElement(c.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/138e0e15.3fafd732.js b/assets/js/138e0e15.3fafd732.js new file mode 100644 index 0000000000..9caeaed754 --- /dev/null +++ b/assets/js/138e0e15.3fafd732.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4921],{1597:s=>{s.exports=JSON.parse('{"name":"@easyops-cn/docusaurus-search-local","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/14eb3368.ae7b0835.js b/assets/js/14eb3368.ae7b0835.js new file mode 100644 index 0000000000..08267cb9b0 --- /dev/null +++ b/assets/js/14eb3368.ae7b0835.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6969],{1243:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var s=n(4164),r=n(7559),i=n(4142),a=n(9169),l=n(8774),o=n(1312),c=n(6025),d=n(4848);function u(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,d.jsx)("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 m={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function h(){const e=(0,c.A)("/");return(0,d.jsx)("li",{className:"breadcrumbs__item",children:(0,d.jsx)(l.A,{"aria-label":(0,o.T)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,d.jsx)(u,{className:m.breadcrumbHomeIcon})})})}const b={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function x(e){let{children:t,href:n,isLast:s}=e;const r="breadcrumbs__link";return s?(0,d.jsx)("span",{className:r,itemProp:"name",children:t}):n?(0,d.jsx)(l.A,{className:r,href:n,itemProp:"item",children:(0,d.jsx)("span",{itemProp:"name",children:t})}):(0,d.jsx)("span",{className:r,children:t})}function p(e){let{children:t,active:n,index:r,addMicrodata:i}=e;return(0,d.jsxs)("li",{...i&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,s.A)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,d.jsx)("meta",{itemProp:"position",content:String(r+1)})]})}function g(){const e=(0,i.OF)(),t=(0,a.Dt)();return e?(0,d.jsx)("nav",{className:(0,s.A)(r.G.docs.docBreadcrumbs,b.breadcrumbsContainer),"aria-label":(0,o.T)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,d.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,d.jsx)(h,{}),e.map(((t,n)=>{const s=n===e.length-1,r="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,d.jsx)(p,{active:s,index:n,addMicrodata:!!r,children:(0,d.jsx)(x,{href:r,isLast:s,children:t.label})},n)}))]})}):null}},5965:(e,t,n)=>{n.d(t,{A:()=>p});n(6540);var s=n(4164),r=n(8774),i=n(4142),a=n(5846),l=n(6654),o=n(1312),c=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=n(4848);function m(e){let{href:t,children:n}=e;return(0,u.jsx)(r.A,{href:t,className:(0,s.A)("card padding--lg",d.cardContainer),children:n})}function h(e){let{href:t,icon:n,title:r,description:i}=e;return(0,u.jsxs)(m,{href:t,children:[(0,u.jsxs)(c.A,{as:"h2",className:(0,s.A)("text--truncate",d.cardTitle),title:r,children:[n," ",r]}),i&&(0,u.jsx)("p",{className:(0,s.A)("text--truncate",d.cardDescription),title:i,children:i})]})}function b(e){let{item:t}=e;const n=(0,i.Nr)(t),s=function(){const{selectMessage:e}=(0,a.W)();return t=>e(t,(0,o.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,u.jsx)(h,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??s(t.items.length)}):null}function x(e){let{item:t}=e;const n=(0,l.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",s=(0,i.cC)(t.docId??void 0);return(0,u.jsx)(h,{href:t.href,icon:n,title:t.label,description:t.description??s?.description})}function p(e){let{item:t}=e;switch(t.type){case"link":return(0,u.jsx)(x,{item:t});case"category":return(0,u.jsx)(b,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,n)=>{n.d(t,{A:()=>o});n(6540);var s=n(4164),r=n(4142),i=n(5965),a=n(4848);function l(e){let{className:t}=e;const n=(0,r.$S)();return(0,a.jsx)(o,{items:n.items,className:t})}function o(e){const{items:t,className:n}=e;if(!t)return(0,a.jsx)(l,{...e});const o=(0,r.d1)(t);return(0,a.jsx)("section",{className:(0,s.A)("row",n),children:o.map(((e,t)=>(0,a.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,a.jsx)(i.A,{item:e})},t)))})}},5847:(e,t,n)=>{n.r(t),n.d(t,{default:()=>p});n(6540);var s=n(1003),r=n(4142),i=n(6025),a=n(2550),l=n(6929),o=n(1878),c=n(4267),d=n(1243),u=n(1107);const m={generatedIndexPage:"generatedIndexPage_vN6x",list:"list_eTzJ",title:"title_kItE"};var h=n(4848);function b(e){let{categoryGeneratedIndex:t}=e;return(0,h.jsx)(s.be,{title:t.title,description:t.description,keywords:t.keywords,image:(0,i.A)(t.image)})}function x(e){let{categoryGeneratedIndex:t}=e;const n=(0,r.$S)();return(0,h.jsxs)("div",{className:m.generatedIndexPage,children:[(0,h.jsx)(o.A,{}),(0,h.jsx)(d.A,{}),(0,h.jsx)(c.A,{}),(0,h.jsxs)("header",{children:[(0,h.jsx)(u.A,{as:"h1",className:m.title,children:t.title}),t.description&&(0,h.jsx)("p",{children:t.description})]}),(0,h.jsx)("article",{className:"margin-top--lg",children:(0,h.jsx)(a.A,{items:n.items,className:m.list})}),(0,h.jsx)("footer",{className:"margin-top--lg",children:(0,h.jsx)(l.A,{previous:t.navigation.previous,next:t.navigation.next})})]})}function p(e){return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(b,{...e}),(0,h.jsx)(x,{...e})]})}},6929:(e,t,n)=>{n.d(t,{A:()=>o});n(6540);var s=n(1312),r=n(4164),i=n(8774),a=n(4848);function l(e){const{permalink:t,title:n,subLabel:s,isNext:l}=e;return(0,a.jsxs)(i.A,{className:(0,r.A)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,a.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,a.jsx)("div",{className:"pagination-nav__label",children:n})]})}function o(e){const{previous:t,next:n}=e;return(0,a.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,s.T)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,a.jsx)(l,{...t,subLabel:(0,a.jsx)(s.A,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,a.jsx)(l,{...n,subLabel:(0,a.jsx)(s.A,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}},4267:(e,t,n)=>{n.d(t,{A:()=>o});n(6540);var s=n(4164),r=n(1312),i=n(7559),a=n(2252),l=n(4848);function o(e){let{className:t}=e;const n=(0,a.r)();return n.badge?(0,l.jsx)("span",{className:(0,s.A)(t,i.G.docs.docVersionBadge,"badge badge--secondary"),children:(0,l.jsx)(r.A,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}},1878:(e,t,n)=>{n.d(t,{A:()=>p});n(6540);var s=n(4164),r=n(4586),i=n(8774),a=n(1312),l=n(4070),o=n(7559),c=n(5597),d=n(2252),u=n(4848);const m={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(a.A,{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:(0,u.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(a.A,{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:(0,u.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function h(e){const t=m[e.versionMetadata.banner];return(0,u.jsx)(t,{...e})}function b(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,u.jsx)(a.A,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,u.jsx)("b",{children:(0,u.jsx)(i.A,{to:n,onClick:s,children:(0,u.jsx)(a.A,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function x(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:i}}=(0,r.A)(),{pluginId:a}=(0,l.vT)({failfast:!0}),{savePreferredVersionName:d}=(0,c.g1)(a),{latestDocSuggestion:m,latestVersionSuggestion:x}=(0,l.HW)(a),p=m??(g=x).docs.find((e=>e.id===g.mainDocId));var g;return(0,u.jsxs)("div",{className:(0,s.A)(t,o.G.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,u.jsx)("div",{children:(0,u.jsx)(h,{siteTitle:i,versionMetadata:n})}),(0,u.jsx)("div",{className:"margin-top--md",children:(0,u.jsx)(b,{versionLabel:x.label,to:p.path,onClick:()=>d(x.name)})})]})}function p(e){let{className:t}=e;const n=(0,d.r)();return n.banner?(0,u.jsx)(x,{className:t,versionMetadata:n}):null}},5846:(e,t,n)=>{n.d(t,{W:()=>c});var s=n(6540),r=n(4586);const i=["zero","one","two","few","many","other"];function a(e){return i.filter((t=>e.includes(t)))}const l={locale:"en",pluralForms:a(["one","other"]),select:e=>1===e?"one":"other"};function o(){const{i18n:{currentLocale:e}}=(0,r.A)();return(0,s.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:a(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`),l}}),[e])}function c(){const e=o();return{selectMessage:(t,n)=>function(e,t,n){const s=e.split("|");if(1===s.length)return s[0];s.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${s.length}: ${e}`);const r=n.select(t),i=n.pluralForms.indexOf(r);return s[Math.min(i,s.length-1)]}(n,t,e)}}}}]); \ No newline at end of file diff --git a/assets/js/17896441.1297eba9.js b/assets/js/17896441.1297eba9.js new file mode 100644 index 0000000000..39f90adfae --- /dev/null +++ b/assets/js/17896441.1297eba9.js @@ -0,0 +1 @@ +(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8401],{1243:(e,t,n)=>{"use strict";n.d(t,{A:()=>b});n(6540);var s=n(4164),a=n(7559),o=n(4142),i=n(9169),l=n(8774),c=n(1312),r=n(6025),d=n(4848);function u(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,d.jsx)("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 m={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function h(){const e=(0,r.A)("/");return(0,d.jsx)("li",{className:"breadcrumbs__item",children:(0,d.jsx)(l.A,{"aria-label":(0,c.T)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,d.jsx)(u,{className:m.breadcrumbHomeIcon})})})}const p={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function f(e){let{children:t,href:n,isLast:s}=e;const a="breadcrumbs__link";return s?(0,d.jsx)("span",{className:a,itemProp:"name",children:t}):n?(0,d.jsx)(l.A,{className:a,href:n,itemProp:"item",children:(0,d.jsx)("span",{itemProp:"name",children:t})}):(0,d.jsx)("span",{className:a,children:t})}function x(e){let{children:t,active:n,index:a,addMicrodata:o}=e;return(0,d.jsxs)("li",{...o&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,s.A)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,d.jsx)("meta",{itemProp:"position",content:String(a+1)})]})}function b(){const e=(0,o.OF)(),t=(0,i.Dt)();return e?(0,d.jsx)("nav",{className:(0,s.A)(a.G.docs.docBreadcrumbs,p.breadcrumbsContainer),"aria-label":(0,c.T)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,d.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,d.jsx)(h,{}),e.map(((t,n)=>{const s=n===e.length-1,a="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,d.jsx)(x,{active:s,index:n,addMicrodata:!!a,children:(0,d.jsx)(f,{href:a,isLast:s,children:t.label})},n)}))]})}):null}},5113:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>wt});var s=n(6540),a=n(1003),o=n(9532),i=n(4848);const l=s.createContext(null);function c(e){let{children:t,content:n}=e;const a=function(e){return(0,s.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return(0,i.jsx)(l.Provider,{value:a,children:t})}function r(){const e=(0,s.useContext)(l);if(null===e)throw new o.dV("DocProvider");return e}function d(){const{metadata:e,frontMatter:t,assets:n}=r();return(0,i.jsx)(a.be,{title:e.title,description:e.description,keywords:t.keywords,image:n.image??t.image})}var u=n(4164),m=n(4581),h=n(6929);function p(){const{metadata:e}=r();return(0,i.jsx)(h.A,{previous:e.previous,next:e.next})}var f=n(1878),x=n(4267),b=n(7559),g=n(1312),v=n(8774);const j={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function N(e){let{permalink:t,label:n,count:s}=e;return(0,i.jsxs)(v.A,{href:t,className:(0,u.A)(j.tag,s?j.tagWithCount:j.tagRegular),children:[n,s&&(0,i.jsx)("span",{children:s})]})}const A={tags:"tags_jXut",tag:"tag_QGVx"};function C(e){let{tags:t}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("b",{children:(0,i.jsx)(g.A,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list",children:"Tags:"})}),(0,i.jsx)("ul",{className:(0,u.A)(A.tags,"padding--none","margin-left--sm"),children:t.map((e=>{let{label:t,permalink:n}=e;return(0,i.jsx)("li",{className:A.tag,children:(0,i.jsx)(N,{label:t,permalink:n})},n)}))})]})}const k={iconEdit:"iconEdit_Z9Sw"};function y(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,u.A)(k.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("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(0,i.jsxs)(v.A,{to:t,className:b.G.common.editThisPage,children:[(0,i.jsx)(y,{}),(0,i.jsx)(g.A,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}var _=n(4586);function B(e){void 0===e&&(e={});const{i18n:{currentLocale:t}}=(0,_.A)(),n=function(){const{i18n:{currentLocale:e,localeConfigs:t}}=(0,_.A)();return t[e].calendar}();return new Intl.DateTimeFormat(t,{calendar:n,...e})}function w(e){let{lastUpdatedAt:t}=e;const n=new Date(t),s=B({day:"numeric",month:"short",year:"numeric",timeZone:"UTC"}).format(n);return(0,i.jsx)(g.A,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:n.toISOString(),itemProp:"dateModified",children:s})})},children:" on {date}"})}function T(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(g.A,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function E(e){let{lastUpdatedAt:t,lastUpdatedBy:n}=e;return(0,i.jsxs)("span",{className:b.G.common.lastUpdated,children:[(0,i.jsx)(g.A,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t?(0,i.jsx)(w,{lastUpdatedAt:t}):"",byUser:n?(0,i.jsx)(T,{lastUpdatedBy:n}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const H={lastUpdated:"lastUpdated_JAkA"};function M(e){let{className:t,editUrl:n,lastUpdatedAt:s,lastUpdatedBy:a}=e;return(0,i.jsxs)("div",{className:(0,u.A)("row",t),children:[(0,i.jsx)("div",{className:"col",children:n&&(0,i.jsx)(L,{editUrl:n})}),(0,i.jsx)("div",{className:(0,u.A)("col",H.lastUpdated),children:(s||a)&&(0,i.jsx)(E,{lastUpdatedAt:s,lastUpdatedBy:a})})]})}function I(){const{metadata:e}=r(),{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s,tags:a}=e,o=a.length>0,l=!!(t||n||s);return o||l?(0,i.jsxs)("footer",{className:(0,u.A)(b.G.docs.docFooter,"docusaurus-mt-lg"),children:[o&&(0,i.jsx)("div",{className:(0,u.A)("row margin-top--sm",b.G.docs.docFooterTagsRow),children:(0,i.jsx)("div",{className:"col",children:(0,i.jsx)(C,{tags:a})})}),l&&(0,i.jsx)(M,{className:(0,u.A)("margin-top--sm",b.G.docs.docFooterEditMetaRow),editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s})]}):null}var S=n(1422),U=n(6342);function V(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const s=n.slice(2,e.level);e.parentIndex=Math.max(...s),n[e.level]=t}));const s=[];return t.forEach((e=>{const{parentIndex:n,...a}=e;n>=0?t[n].children.push(a):s.push(a)})),s}function R(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:s}=e;return t.flatMap((e=>{const t=R({toc:e.children,minHeadingLevel:n,maxHeadingLevel:s});return function(e){return e.level>=n&&e.level<=s}(e)?[{...e,children:t}]:t}))}function z(e){const t=e.getBoundingClientRect();return t.top===t.bottom?z(e.parentNode):t}function O(e,t){let{anchorTopOffset:n}=t;const s=e.find((e=>z(e).top>=n));if(s){return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function G(e){const t=(0,s.useRef)(void 0),n=P();(0,s.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:s,linkActiveClassName:a,minHeadingLevel:o,maxHeadingLevel:i}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(s),l=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const s=[];for(let a=t;a<=n;a+=1)s.push(`h${a}.anchor`);return Array.from(document.querySelectorAll(s.join()))}({minHeadingLevel:o,maxHeadingLevel:i}),c=O(l,{anchorTopOffset:n.current}),r=e.find((e=>c&&c.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(a),e.classList.add(a),t.current=e):e.classList.remove(a)}(e,e===r)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,n])}function D(e){let{toc:t,className:n,linkClassName:s,isChild:a}=e;return t.length?(0,i.jsx)("ul",{className:a?void 0:n,children:t.map((e=>(0,i.jsxs)("li",{children:[(0,i.jsx)(v.A,{to:`#${e.id}`,className:s??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,i.jsx)(D,{isChild:!0,toc:e.children,className:n,linkClassName:s})]},e.id)))}):null}const W=s.memo(D);function $(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:a="table-of-contents__link",linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:c,...r}=e;const d=(0,U.p)(),u=l??d.tableOfContents.minHeadingLevel,m=c??d.tableOfContents.maxHeadingLevel,h=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,s.useMemo)((()=>R({toc:V(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:u,maxHeadingLevel:m});return G((0,s.useMemo)((()=>{if(a&&o)return{linkClassName:a,linkActiveClassName:o,minHeadingLevel:u,maxHeadingLevel:m}}),[a,o,u,m])),(0,i.jsx)(W,{toc:h,className:n,linkClassName:a,...r})}const F={tocCollapsibleButton:"tocCollapsibleButton_TO0P",tocCollapsibleButtonExpanded:"tocCollapsibleButtonExpanded_MG3E"};function q(e){let{collapsed:t,...n}=e;return(0,i.jsx)("button",{type:"button",...n,className:(0,u.A)("clean-btn",F.tocCollapsibleButton,!t&&F.tocCollapsibleButtonExpanded,n.className),children:(0,i.jsx)(g.A,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component",children:"On this page"})})}const Z={tocCollapsible:"tocCollapsible_ETCw",tocCollapsibleContent:"tocCollapsibleContent_vkbj",tocCollapsibleExpanded:"tocCollapsibleExpanded_sAul"};function J(e){let{toc:t,className:n,minHeadingLevel:s,maxHeadingLevel:a}=e;const{collapsed:o,toggleCollapsed:l}=(0,S.u)({initialState:!0});return(0,i.jsxs)("div",{className:(0,u.A)(Z.tocCollapsible,!o&&Z.tocCollapsibleExpanded,n),children:[(0,i.jsx)(q,{collapsed:o,onClick:l}),(0,i.jsx)(S.N,{lazy:!0,className:Z.tocCollapsibleContent,collapsed:o,children:(0,i.jsx)($,{toc:t,minHeadingLevel:s,maxHeadingLevel:a})})]})}const Y={tocMobile:"tocMobile_ITEo"};function K(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(J,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,u.A)(b.G.docs.docTocMobile,Y.tocMobile)})}const Q={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"},X="table-of-contents__link toc-highlight",ee="table-of-contents__link--active";function te(e){let{className:t,...n}=e;return(0,i.jsx)("div",{className:(0,u.A)(Q.tableOfContents,"thin-scrollbar",t),children:(0,i.jsx)($,{...n,linkClassName:X,linkActiveClassName:ee})})}function ne(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(te,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:b.G.docs.docTocDesktop})}var se=n(1107),ae=n(8453),oe=n(5260),ie=n(2303),le=n(5293);function ce(){const{prism:e}=(0,U.p)(),{colorMode:t}=(0,le.G)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var re=n(8426),de=n.n(re);const ue=/title=(?["'])(?.*?)\1/,me=/\{(?<range>[\d,-]+)\}/,he={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},pe={...he,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},fe=Object.keys(he);function xe(e,t){const n=e.map((e=>{const{start:n,end:s}=pe[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function be(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:a,metastring:o}=t;if(o&&me.test(o)){const e=o.match(me).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${o}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,s=de()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const i=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return xe(["js","jsBlock"],t);case"jsx":case"tsx":return xe(["js","jsBlock","jsx"],t);case"html":return xe(["js","jsBlock","html"],t);case"python":case"py":case"bash":return xe(["bash"],t);case"markdown":case"md":return xe(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return xe(["tex"],t);case"lua":case"haskell":case"sql":return xe(["lua"],t);case"wasm":return xe(["wasm"],t);case"vb":case"vba":case"visual-basic":return xe(["vb","rem"],t);case"vbnet":return xe(["vbnet","rem"],t);case"batch":return xe(["rem"],t);case"basic":return xe(["rem","f90"],t);case"fsharp":return xe(["js","ml"],t);case"ocaml":case"sml":return xe(["ml"],t);case"fortran":return xe(["f90"],t);case"cobol":return xe(["cobol"],t);default:return xe(fe,t)}}(s,a),l=n.split("\n"),c=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),r=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;h<l.length;){const e=l[h].match(i);if(!e){h+=1;continue}const t=e.slice(1).find((e=>void 0!==e));r[t]?c[r[t]].range+=`${h},`:d[t]?c[d[t]].start=h:u[t]&&(c[u[t]].range+=`${c[u[t]].start}-${h-1},`),l.splice(h,1)}n=l.join("\n");const m={};return Object.entries(c).forEach((e=>{let[t,{range:n}]=e;de()(n).forEach((e=>{m[e]??=[],m[e].push(t)}))})),{lineClassNames:m,code:n}}const ge={codeBlockContainer:"codeBlockContainer_Ckt0"};function ve(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,a]=e;const o=t[s];o&&"string"==typeof a&&(n[o]=a)})),n}(ce());return(0,i.jsx)(t,{...n,style:s,className:(0,u.A)(n.className,ge.codeBlockContainer,b.G.common.codeBlock)})}const je={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function Ne(e){let{children:t,className:n}=e;return(0,i.jsx)(ve,{as:"pre",tabIndex:0,className:(0,u.A)(je.codeBlockStandalone,"thin-scrollbar",n),children:(0,i.jsx)("code",{className:je.codeBlockLines,children:t})})}const Ae={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Ce(e,t){const[n,a]=(0,s.useState)(),i=(0,s.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,s.useEffect)((()=>{i()}),[i]),function(e,t,n){void 0===n&&(n=Ae);const a=(0,o._q)(t),i=(0,o.Be)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,i),()=>t.disconnect()}),[e,a,i])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),i())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var ke=n(1765);const ye={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function Le(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:a,getTokenProps:o}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const l=a({line:t,className:(0,u.A)(n,s&&ye.codeLine)}),c=t.map(((e,t)=>(0,i.jsx)("span",{...o({token:e})},t)));return(0,i.jsxs)("span",{...l,children:[s?(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("span",{className:ye.codeLineNumber}),(0,i.jsx)("span",{className:ye.codeLineContent,children:c})]}):c,(0,i.jsx)("br",{})]})}function _e(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("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 Be(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const we={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function Te(e){let{code:t,className:n}=e;const[a,o]=(0,s.useState)(!1),l=(0,s.useRef)(void 0),c=(0,s.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 s=document.createElement("textarea"),a=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const o=document.getSelection(),i=o.rangeCount>0&&o.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}s.remove(),i&&(o.removeAllRanges(),o.addRange(i)),a&&a.focus()}(t),o(!0),l.current=window.setTimeout((()=>{o(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),(0,i.jsx)("button",{type:"button","aria-label":a?(0,g.T)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,g.T)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,g.T)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,u.A)("clean-btn",n,we.copyButton,a&&we.copyButtonCopied),onClick:c,children:(0,i.jsxs)("span",{className:we.copyButtonIcons,"aria-hidden":"true",children:[(0,i.jsx)(_e,{className:we.copyButtonIcon}),(0,i.jsx)(Be,{className:we.copyButtonSuccessIcon})]})})}function Ee(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("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 He={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function Me(e){let{className:t,onClick:n,isEnabled:s}=e;const a=(0,g.T)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,i.jsx)("button",{type:"button",onClick:n,className:(0,u.A)("clean-btn",t,s&&He.wordWrapButtonEnabled),"aria-label":a,title:a,children:(0,i.jsx)(Ee,{className:He.wordWrapButtonIcon,"aria-hidden":"true"})})}function Ie(e){let{children:t,className:n="",metastring:a,title:o,showLineNumbers:l,language:c}=e;const{prism:{defaultLanguage:r,magicComments:d}}=(0,U.p)(),m=function(e){return e?.toLowerCase()}(c??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??r),h=ce(),p=function(){const[e,t]=(0,s.useState)(!1),[n,a]=(0,s.useState)(!1),o=(0,s.useRef)(null),i=(0,s.useCallback)((()=>{const n=o.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[o,e]),l=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=o.current,n=e>t||o.current.querySelector("code").hasAttribute("style");a(n)}),[o]);return Ce(o,l),(0,s.useEffect)((()=>{l()}),[e,l]),(0,s.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:o,isEnabled:e,isCodeScrollable:n,toggle:i}}(),f=function(e){return e?.match(ue)?.groups.title??""}(a)||o,{lineClassNames:x,code:b}=be(t,{metastring:a,language:m,magicComments:d}),g=l??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return(0,i.jsxs)(ve,{as:"div",className:(0,u.A)(n,m&&!n.includes(`language-${m}`)&&`language-${m}`),children:[f&&(0,i.jsx)("div",{className:je.codeBlockTitle,children:f}),(0,i.jsxs)("div",{className:je.codeBlockContent,children:[(0,i.jsx)(ke.f4,{theme:h,code:b,language:m??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:a,getTokenProps:o}=e;return(0,i.jsx)("pre",{tabIndex:0,ref:p.codeBlockRef,className:(0,u.A)(t,je.codeBlock,"thin-scrollbar"),style:n,children:(0,i.jsx)("code",{className:(0,u.A)(je.codeBlockLines,g&&je.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,i.jsx)(Le,{line:e,getLineProps:a,getTokenProps:o,classNames:x[t],showLineNumbers:g},t)))})})}}),(0,i.jsxs)("div",{className:je.buttonGroup,children:[(p.isEnabled||p.isCodeScrollable)&&(0,i.jsx)(Me,{className:je.codeButton,onClick:()=>p.toggle(),isEnabled:p.isEnabled}),(0,i.jsx)(Te,{className:je.codeButton,code:b})]})]})]})}function Se(e){let{children:t,...n}=e;const a=(0,ie.A)(),o=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),l="string"==typeof o?Ie:Ne;return(0,i.jsx)(l,{...n,children:o},String(a))}function Ue(e){return(0,i.jsx)("code",{...e})}var Ve=n(3427);const Re={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function ze(e){return!!e&&("SUMMARY"===e.tagName||ze(e.parentElement))}function Oe(e,t){return!!e&&(e===t||Oe(e.parentElement,t))}function Pe(e){let{summary:t,children:n,...a}=e;(0,Ve.A)().collectAnchor(a.id);const o=(0,ie.A)(),l=(0,s.useRef)(null),{collapsed:c,setCollapsed:r}=(0,S.u)({initialState:!a.open}),[d,m]=(0,s.useState)(a.open),h=s.isValidElement(t)?t:(0,i.jsx)("summary",{children:t??"Details"});return(0,i.jsxs)("details",{...a,ref:l,open:d,"data-collapsed":c,className:(0,u.A)(Re.details,o&&Re.isBrowser,a.className),onMouseDown:e=>{ze(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;ze(t)&&Oe(t,l.current)&&(e.preventDefault(),c?(r(!1),m(!0)):r(!0))},children:[h,(0,i.jsx)(S.N,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{r(e),m(!e)},children:(0,i.jsx)("div",{className:Re.collapsibleContent,children:n})})]})}const Ge={details:"details_b_Ee"},De="alert alert--info";function We(e){let{...t}=e;return(0,i.jsx)(Pe,{...t,className:(0,u.A)(De,Ge.details,t.className)})}function $e(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),a=(0,i.jsx)(i.Fragment,{children:t.filter((e=>e!==n))});return(0,i.jsx)(We,{...e,summary:n,children:a})}function Fe(e){return(0,i.jsx)(se.A,{...e})}const qe={containsTaskList:"containsTaskList_mC6p"};function Ze(e){if(void 0!==e)return(0,u.A)(e,e?.includes("contains-task-list")&&qe.containsTaskList)}const Je={img:"img_ev3q"};function Ye(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n)),o=n?.props.children;return{mdxAdmonitionTitle:o,rest:a.length>0?(0,i.jsx)(i.Fragment,{children:a}):null}}(e.children),a=e.title??t;return{...e,...a&&{title:a},children:n}}const Ke={admonition:"admonition_xJq3",admonitionHeading:"admonitionHeading_Gvgb",admonitionIcon:"admonitionIcon_Rf37",admonitionContent:"admonitionContent_BuS1"};function Qe(e){let{type:t,className:n,children:s}=e;return(0,i.jsx)("div",{className:(0,u.A)(b.G.common.admonition,b.G.common.admonitionType(t),Ke.admonition,n),children:s})}function Xe(e){let{icon:t,title:n}=e;return(0,i.jsxs)("div",{className:Ke.admonitionHeading,children:[(0,i.jsx)("span",{className:Ke.admonitionIcon,children:t}),n]})}function et(e){let{children:t}=e;return t?(0,i.jsx)("div",{className:Ke.admonitionContent,children:t}):null}function tt(e){const{type:t,icon:n,title:s,children:a,className:o}=e;return(0,i.jsxs)(Qe,{type:t,className:o,children:[s||n?(0,i.jsx)(Xe,{title:s,icon:n}):null,(0,i.jsx)(et,{children:a})]})}function nt(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("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"})})}const st={icon:(0,i.jsx)(nt,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function at(e){return(0,i.jsx)(tt,{...st,...e,className:(0,u.A)("alert alert--secondary",e.className),children:e.children})}function ot(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("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"})})}const it={icon:(0,i.jsx)(ot,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function lt(e){return(0,i.jsx)(tt,{...it,...e,className:(0,u.A)("alert alert--success",e.className),children:e.children})}function ct(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("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"})})}const rt={icon:(0,i.jsx)(ct,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function dt(e){return(0,i.jsx)(tt,{...rt,...e,className:(0,u.A)("alert alert--info",e.className),children:e.children})}function ut(e){return(0,i.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,i.jsx)("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"})})}const mt={icon:(0,i.jsx)(ut,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function ht(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("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"})})}const pt={icon:(0,i.jsx)(ht,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const ft={icon:(0,i.jsx)(ut,{}),title:(0,i.jsx)(g.A,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const xt={...{note:at,tip:lt,info:dt,warning:function(e){return(0,i.jsx)(tt,{...mt,...e,className:(0,u.A)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,i.jsx)(tt,{...pt,...e,className:(0,u.A)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,i.jsx)(at,{title:"secondary",...e}),important:e=>(0,i.jsx)(dt,{title:"important",...e}),success:e=>(0,i.jsx)(lt,{title:"success",...e}),caution:function(e){return(0,i.jsx)(tt,{...ft,...e,className:(0,u.A)("alert alert--warning",e.className),children:e.children})}}};function bt(e){const t=Ye(e),n=(s=t.type,xt[s]||(console.warn(`No admonition component found for admonition type "${s}". Using Info as fallback.`),xt.info));var s;return(0,i.jsx)(n,{...t})}const gt={Head:oe.A,details:$e,Details:$e,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,i.jsx)(Ue,{...e}):(0,i.jsx)(Se,{...e})},a:function(e){return(0,i.jsx)(v.A,{...e})},pre:function(e){return(0,i.jsx)(i.Fragment,{children:e.children})},ul:function(e){return(0,i.jsx)("ul",{...e,className:Ze(e.className)})},li:function(e){return(0,Ve.A)().collectAnchor(e.id),(0,i.jsx)("li",{...e})},img:function(e){return(0,i.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,u.A)(t,Je.img))});var t},h1:e=>(0,i.jsx)(Fe,{as:"h1",...e}),h2:e=>(0,i.jsx)(Fe,{as:"h2",...e}),h3:e=>(0,i.jsx)(Fe,{as:"h3",...e}),h4:e=>(0,i.jsx)(Fe,{as:"h4",...e}),h5:e=>(0,i.jsx)(Fe,{as:"h5",...e}),h6:e=>(0,i.jsx)(Fe,{as:"h6",...e}),admonition:bt,mermaid:()=>null};function vt(e){let{children:t}=e;return(0,i.jsx)(ae.x,{components:gt,children:t})}function jt(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=r();return t.hide_title||void 0!==n?null:e.title}();return(0,i.jsxs)("div",{className:(0,u.A)(b.G.docs.docMarkdown,"markdown"),children:[n&&(0,i.jsx)("header",{children:(0,i.jsx)(se.A,{as:"h1",children:n})}),(0,i.jsx)(vt,{children:t})]})}var Nt=n(1243);function At(){return(0,i.jsx)(g.A,{id:"theme.unlistedContent.title",description:"The unlisted content banner title",children:"Unlisted page"})}function Ct(){return(0,i.jsx)(g.A,{id:"theme.unlistedContent.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function kt(){return(0,i.jsx)(oe.A,{children:(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}function yt(e){let{className:t}=e;return(0,i.jsx)(bt,{type:"caution",title:(0,i.jsx)(At,{}),className:(0,u.A)(t,b.G.common.unlistedBanner),children:(0,i.jsx)(Ct,{})})}function Lt(e){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(kt,{}),(0,i.jsx)(yt,{...e})]})}const _t={docItemContainer:"docItemContainer_Djhp",docItemCol:"docItemCol_VOVn"};function Bt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=r(),n=(0,m.l)(),s=e.hide_table_of_contents,a=!s&&t.length>0;return{hidden:s,mobile:a?(0,i.jsx)(K,{}):void 0,desktop:!a||"desktop"!==n&&"ssr"!==n?void 0:(0,i.jsx)(ne,{})}}(),{metadata:{unlisted:s}}=r();return(0,i.jsxs)("div",{className:"row",children:[(0,i.jsxs)("div",{className:(0,u.A)("col",!n.hidden&&_t.docItemCol),children:[s&&(0,i.jsx)(Lt,{}),(0,i.jsx)(f.A,{}),(0,i.jsxs)("div",{className:_t.docItemContainer,children:[(0,i.jsxs)("article",{children:[(0,i.jsx)(Nt.A,{}),(0,i.jsx)(x.A,{}),n.mobile,(0,i.jsx)(jt,{children:t}),(0,i.jsx)(I,{})]}),(0,i.jsx)(p,{})]})]}),n.desktop&&(0,i.jsx)("div",{className:"col col--3",children:n.desktop})]})}function wt(e){const t=`docs-doc-id-${e.content.metadata.id}`,n=e.content;return(0,i.jsx)(c,{content:e.content,children:(0,i.jsxs)(a.e3,{className:t,children:[(0,i.jsx)(d,{}),(0,i.jsx)(Bt,{children:(0,i.jsx)(n,{})})]})})}},6929:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});n(6540);var s=n(1312),a=n(4164),o=n(8774),i=n(4848);function l(e){const{permalink:t,title:n,subLabel:s,isNext:l}=e;return(0,i.jsxs)(o.A,{className:(0,a.A)("pagination-nav__link",l?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,i.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,i.jsx)("div",{className:"pagination-nav__label",children:n})]})}function c(e){const{previous:t,next:n}=e;return(0,i.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,s.T)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,i.jsx)(l,{...t,subLabel:(0,i.jsx)(s.A,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,i.jsx)(l,{...n,subLabel:(0,i.jsx)(s.A,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}},4267:(e,t,n)=>{"use strict";n.d(t,{A:()=>c});n(6540);var s=n(4164),a=n(1312),o=n(7559),i=n(2252),l=n(4848);function c(e){let{className:t}=e;const n=(0,i.r)();return n.badge?(0,l.jsx)("span",{className:(0,s.A)(t,o.G.docs.docVersionBadge,"badge badge--secondary"),children:(0,l.jsx)(a.A,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}},1878:(e,t,n)=>{"use strict";n.d(t,{A:()=>x});n(6540);var s=n(4164),a=n(4586),o=n(8774),i=n(1312),l=n(4070),c=n(7559),r=n(5597),d=n(2252),u=n(4848);const m={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(i.A,{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:(0,u.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,u.jsx)(i.A,{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:(0,u.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function h(e){const t=m[e.versionMetadata.banner];return(0,u.jsx)(t,{...e})}function p(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,u.jsx)(i.A,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,u.jsx)("b",{children:(0,u.jsx)(o.A,{to:n,onClick:s,children:(0,u.jsx)(i.A,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function f(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:o}}=(0,a.A)(),{pluginId:i}=(0,l.vT)({failfast:!0}),{savePreferredVersionName:d}=(0,r.g1)(i),{latestDocSuggestion:m,latestVersionSuggestion:f}=(0,l.HW)(i),x=m??(b=f).docs.find((e=>e.id===b.mainDocId));var b;return(0,u.jsxs)("div",{className:(0,s.A)(t,c.G.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,u.jsx)("div",{children:(0,u.jsx)(h,{siteTitle:o,versionMetadata:n})}),(0,u.jsx)("div",{className:"margin-top--md",children:(0,u.jsx)(p,{versionLabel:f.label,to:x.path,onClick:()=>d(f.name)})})]})}function x(e){let{className:t}=e;const n=(0,d.r)();return n.banner?(0,u.jsx)(f,{className:t,versionMetadata:n}):null}},8426:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,a,o]=t;if(s&&o){s=parseInt(s),o=parseInt(o);const e=s<o?1:-1;"-"!==a&&".."!==a&&"\u2025"!==a||(o+=e);for(let t=s;t!==o;t+=e)n.push(t)}}return n}t.default=n,e.exports=n},8453:(e,t,n)=>{"use strict";n.d(t,{R:()=>i,x:()=>l});var s=n(6540);const a={},o=s.createContext(a);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1a4e3797.e9ceaa1e.js b/assets/js/1a4e3797.e9ceaa1e.js new file mode 100644 index 0000000000..8d6e4f4579 --- /dev/null +++ b/assets/js/1a4e3797.e9ceaa1e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2138],{5846:(e,t,r)=>{r.d(t,{W:()=>u});var s=r(6540),a=r(4586);const n=["zero","one","two","few","many","other"];function c(e){return n.filter((t=>e.includes(t)))}const l={locale:"en",pluralForms:c(["one","other"]),select:e=>1===e?"one":"other"};function o(){const{i18n:{currentLocale:e}}=(0,a.A)();return(0,s.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:c(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`),l}}),[e])}function u(){const e=o();return{selectMessage:(t,r)=>function(e,t,r){const s=e.split("|");if(1===s.length)return s[0];s.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${s.length}: ${e}`);const a=r.select(t),n=r.pluralForms.indexOf(a);return s[Math.min(n,s.length-1)]}(r,t,e)}}},1283:(e,t,r)=>{r.r(t),r.d(t,{default:()=>P});var s=r(6540),a=r(4586),n=r(5476),c=r(5260),l=r(8774),o=r(1312),u=r(5846),h=r(5391),i=r(6347),m=r(2303),d=r(1088);const p=function(){const e=(0,m.A)(),t=(0,i.W6)(),r=(0,i.zy)(),{siteConfig:{baseUrl:s}}=(0,a.A)(),n=e?new URLSearchParams(r.search):null,c=n?.get("q")||"",l=n?.get("ctx")||"",o=n?.get("version")||"",u=e=>{const t=new URLSearchParams(r.search);return e?t.set("q",e):t.delete("q"),t};return{searchValue:c,searchContext:l&&Array.isArray(d.Hg)&&d.Hg.some((e=>"string"==typeof e?e===l:e.path===l))?l:"",searchVersion:o,updateSearchPath:e=>{const r=u(e);t.replace({search:r.toString()})},updateSearchContext:e=>{const s=new URLSearchParams(r.search);s.set("ctx",e),t.replace({search:s.toString()})},generateSearchPageLink:e=>{const t=u(e);return`${s}search?${t.toString()}`}}};var g=r(5891),x=r(2384),f=r(6841),y=r(3810),C=r(7674),S=r(2849),j=r(4471);const A={searchContextInput:"searchContextInput_mXoe",searchQueryInput:"searchQueryInput_CFBF",searchResultItem:"searchResultItem_U687",searchResultItemPath:"searchResultItemPath_uIbk",searchResultItemSummary:"searchResultItemSummary_oZHr",searchQueryColumn:"searchQueryColumn_q7nx",searchContextColumn:"searchContextColumn_oWAF"};var I=r(3385),v=r(4848);function w(){const{siteConfig:{baseUrl:e},i18n:{currentLocale:t}}=(0,a.A)(),{selectMessage:r}=(0,u.W)(),{searchValue:n,searchContext:l,searchVersion:i,updateSearchPath:m,updateSearchContext:f}=p(),[y,C]=(0,s.useState)(n),[j,w]=(0,s.useState)(),[P,_]=(0,s.useState)(),b=`${e}${i}`,F=(0,s.useMemo)((()=>y?(0,o.T)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:y}):(0,o.T)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"})),[y]);(0,s.useEffect)((()=>{m(y),j&&(y?j(y,(e=>{_(e)})):_(void 0))}),[y,j]);const T=(0,s.useCallback)((e=>{C(e.target.value)}),[]);return(0,s.useEffect)((()=>{n&&n!==y&&C(n)}),[n]),(0,s.useEffect)((()=>{!async function(){const{wrappedIndexes:e,zhDictionary:t}=!Array.isArray(d.Hg)||l||d.dz?await(0,g.Z)(b,l):{wrappedIndexes:[],zhDictionary:[]};w((()=>(0,x.m)(e,t,100)))}()}),[l,b]),(0,v.jsxs)(s.Fragment,{children:[(0,v.jsxs)(c.A,{children:[(0,v.jsx)("meta",{property:"robots",content:"noindex, follow"}),(0,v.jsx)("title",{children:F})]}),(0,v.jsxs)("div",{className:"container margin-vert--lg",children:[(0,v.jsx)("h1",{children:F}),(0,v.jsxs)("div",{className:"row",children:[(0,v.jsx)("div",{className:(0,h.A)("col",{[A.searchQueryColumn]:Array.isArray(d.Hg),"col--9":Array.isArray(d.Hg),"col--12":!Array.isArray(d.Hg)}),children:(0,v.jsx)("input",{type:"search",name:"q",className:A.searchQueryInput,"aria-label":"Search",onChange:T,value:y,autoComplete:"off",autoFocus:!0})}),Array.isArray(d.Hg)?(0,v.jsx)("div",{className:(0,h.A)("col","col--3","padding-left--none",A.searchContextColumn),children:(0,v.jsxs)("select",{name:"search-context",className:A.searchContextInput,id:"context-selector",value:l,onChange:e=>f(e.target.value),children:[d.dz&&(0,v.jsx)("option",{value:"",children:(0,o.T)({id:"theme.SearchPage.searchContext.everywhere",message:"everywhere"})}),d.Hg.map((e=>{const{label:r,path:s}=(0,I.p)(e,t);return(0,v.jsx)("option",{value:s,children:r},s)}))]})}):null]}),!j&&y&&(0,v.jsx)("div",{children:(0,v.jsx)(S.A,{})}),P&&(P.length>0?(0,v.jsx)("p",{children:r(P.length,(0,o.T)({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:P.length}))}):(0,v.jsx)("p",{children:(0,o.T)({id:"theme.SearchPage.noResultsText",message:"No documents were found",description:"The paragraph for empty search result"})})),(0,v.jsx)("section",{children:P&&P.map((e=>(0,v.jsx)(R,{searchResult:e},e.document.i)))})]})]})}function R(e){let{searchResult:{document:t,type:r,page:s,tokens:a,metadata:n}}=e;const c=0===r,o=2===r,u=(c?t.b:s.b).slice(),h=o?t.s:t.t;c||u.push(s.t);let i="";if(d.CU&&a.length>0){const e=new URLSearchParams;for(const t of a)e.append("_highlight",t);i=`?${e.toString()}`}return(0,v.jsxs)("article",{className:A.searchResultItem,children:[(0,v.jsx)("h2",{children:(0,v.jsx)(l.A,{to:t.u+i+(t.h||""),dangerouslySetInnerHTML:{__html:o?(0,f.Z)(h,a):(0,y.C)(h,(0,C.g)(n,"t"),a,100)}})}),u.length>0&&(0,v.jsx)("p",{className:A.searchResultItemPath,children:(0,j.$)(u)}),o&&(0,v.jsx)("p",{className:A.searchResultItemSummary,dangerouslySetInnerHTML:{__html:(0,y.C)(t.t,(0,C.g)(n,"t"),a,100)}})]})}const P=function(){return(0,v.jsx)(n.A,{children:(0,v.jsx)(w,{})})}}}]); \ No newline at end of file diff --git a/assets/js/1a50dc2d.e1c2e887.js b/assets/js/1a50dc2d.e1c2e887.js new file mode 100644 index 0000000000..ceac5fa747 --- /dev/null +++ b/assets/js/1a50dc2d.e1c2e887.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7903],{2455:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>u});var a=t(4848),r=t(8453),o=t(1470),s=t(9365);const l={},c="Setup",i={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/setup.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Overview",permalink:"/dapp/opl/introduction"},next:{title:"DAO Contract",permalink:"/dapp/opl/host"}},d={},u=[{value:"Workspace",id:"workspace",level:2},{value:"Hardhat",id:"hardhat",level:2}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"setup",children:"Setup"}),"\n",(0,a.jsxs)(n.p,{children:["Let's get started and make our new project. You will need ",(0,a.jsx)(n.a,{href:"https://nodejs.org/en/download",children:"Node.js"}),"\nversion ",(0,a.jsx)(n.a,{href:"https://nodejs.org/en/blog/announcements/v18-release-announce",children:"18"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"We will be using a monorepo for both the frontend and backend of our dApp."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"mkdir opl-secret-ballot;\nmkdir opl-secret-ballot/backend;\nmkdir opl-secret-ballot/frontend;\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Our smart contracts will live inside a Hardhat project under\n",(0,a.jsx)(n.code,{children:"opl-secret-ballot/backend"}),", and our VueJS app will be in the\n",(0,a.jsx)(n.code,{children:"opl-secret-ballot/frontend"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"workspace",children:"Workspace"}),"\n",(0,a.jsxs)(n.p,{children:["We suggest using ",(0,a.jsx)(n.a,{href:"https://pnpm.io/motivation",children:(0,a.jsx)(n.code,{children:"pnpm"})}),", and creating a workspace\nfile ",(0,a.jsx)(n.code,{children:"opl-secret-ballot/pnpm-workspace.yaml"})," with the following content:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"packages: [frontend, backend]\n"})}),"\n",(0,a.jsx)(n.h2,{id:"hardhat",children:"Hardhat"}),"\n",(0,a.jsx)(n.p,{children:"Let's create a new Hardhat project."}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:["Currently we are compatible with Hardhat up to ",(0,a.jsx)(n.code,{children:"2.19"}),". You may need to\nspecify the version of Hardhat to install."]})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"cd opl-secret-ballot/backend && npx hardhat init\n"})}),"\n",(0,a.jsxs)(n.p,{children:["When initializing the Hardhat application, we would like to use the ",(0,a.jsx)(n.code,{children:"backend"}),"\ndirectory as the project root."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"Hardhat project root: \xb7 /Users/oasis/opl-secret-ballot/backend\n"})}),"\n",(0,a.jsxs)(n.p,{children:["We would like to set ",(0,a.jsx)(n.code,{children:"@oasisprotocol/secret-ballot-backend"})," as the package name\ninside ",(0,a.jsx)(n.code,{children:"package.json"})," at ",(0,a.jsx)(n.code,{children:"version"})," of ",(0,a.jsx)(n.code,{children:"1.0.0"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Finally, we need to install the following dependencies:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"@oasisprotocol/sapphire-contracts"})," contains the OPL Solidity smart contracts."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"@oasisprotocol/sapphire-hardhat"})," integrates Sapphire using the Hardhat\nconfig file."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"@openzeppelin/contracts"})," contains standardized DAO contracts which we will\nuse to build the secret ballot application."]}),"\n"]}),"\n",(0,a.jsxs)(o.A,{groupId:"npm2yarn",children:[(0,a.jsx)(s.A,{value:"npm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npm install -D @openzeppelin/contracts @oasisprotocol/sapphire-contracts @oasisprotocol/sapphire-hardhat\n"})})}),(0,a.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"pnpm add -D @openzeppelin/contracts @oasisprotocol/sapphire-contracts @oasisprotocol/sapphire-hardhat\n"})})}),(0,a.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"yarn add --dev @openzeppelin/contracts @oasisprotocol/sapphire-contracts @oasisprotocol/sapphire-hardhat\n"})})})]}),"\n",(0,a.jsx)(n.p,{children:"You should be able to start your localhost Hardhat node."})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>s});t(6540);var a=t(4164);const r={tabItem:"tabItem_Ymn6"};var o=t(4848);function s(e){let{children:n,hidden:t,className:s}=e;return(0,o.jsx)("div",{role:"tabpanel",className:(0,a.A)(r.tabItem,s),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>k});var a=t(6540),r=t(4164),o=t(3104),s=t(6347),l=t(205),c=t(7485),i=t(1682),d=t(9466);function u(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function p(e){const{values:n,children:t}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:t,attributes:a,default:r}}=e;return{value:n,label:t,attributes:a,default:r}}))}(t);return function(e){const n=(0,i.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const r=(0,s.W6)(),o=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,c.aZ)(o),(0,a.useCallback)((e=>{if(!o)return;const n=new URLSearchParams(r.location.search);n.set(o,e),r.replace({...r.location,search:n.toString()})}),[o,r])]}function b(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,o=p(e),[s,c]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=t.find((e=>e.default))??t[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:o}))),[i,u]=m({queryString:t,groupId:r}),[b,f]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[r,o]=(0,d.Dv)(t);return[r,(0,a.useCallback)((e=>{t&&o.set(e)}),[t,o])]}({groupId:r}),j=(()=>{const e=i??b;return h({value:e,tabValues:o})?e:null})();(0,l.A)((()=>{j&&c(j)}),[j]);return{selectedValue:s,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);c(e),u(e),f(e)}),[u,f,o]),tabValues:o}}var f=t(2303);const j={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(4848);function g(e){let{className:n,block:t,selectedValue:a,selectValue:s,tabValues:l}=e;const c=[],{blockElementScrollPositionUntilNextRender:i}=(0,o.a_)(),d=e=>{const n=e.currentTarget,t=c.indexOf(n),r=l[t].value;r!==a&&(i(n),s(r))},u=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.A)("tabs",{"tabs--block":t},n),children:l.map((e=>{let{value:n,label:t,attributes:o}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>c.push(e),onKeyDown:u,onClick:d,...o,className:(0,r.A)("tabs__item",j.tabItem,o?.className,{"tabs__item--active":a===n}),children:t??n},n)}))})}function v(e){let{lazy:n,children:t,selectedValue:r}=e;const o=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=o.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:o.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==r})))})}function w(e){const n=b(e);return(0,x.jsxs)("div",{className:(0,r.A)("tabs-container",j.tabList),children:[(0,x.jsx)(g,{...n,...e}),(0,x.jsx)(v,{...n,...e})]})}function k(e){const n=(0,f.A)();return(0,x.jsx)(w,{...e,children:u(e.children)},String(n))}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>l});var a=t(6540);const r={},o=a.createContext(r);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1a9d3710.5b27e96d.js b/assets/js/1a9d3710.5b27e96d.js new file mode 100644 index 0000000000..a4d038813f --- /dev/null +++ b/assets/js/1a9d3710.5b27e96d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8263],{1399:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>l,contentTitle:()=>a,default:()=>c,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var n=t(4848),i=t(8453);const s={},a="Token Delivery & KYC Guide",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/token-delivery-and-kyc.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"getInvolved",previous:{title:"Delegation Policy",permalink:"/get-involved/delegation-policy"}},l={},d=[];function u(e){const o={a:"a",admonition:"admonition",h1:"h1",li:"li",p:"p",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.h1,{id:"token-delivery--kyc-guide",children:"Token Delivery & KYC Guide"}),"\n",(0,n.jsx)(o.p,{children:"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!"}),"\n",(0,n.jsx)(o.p,{children:"Let's review the process for receiving your ROSE tokens from the Oasis Foundation:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"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.jsx)(o.a,{href:"https://airtable.com/shrGmpohTNnytBpQU",children:"token delivery question form"}),"."]}),"\n"]}),"\n",(0,n.jsx)(o.admonition,{type:"caution",children:(0,n.jsx)(o.p,{children:"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."})}),"\n",(0,n.jsx)(o.admonition,{type:"info",children:(0,n.jsx)(o.p,{children:"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."})}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"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"]}),"\n"]}),"\n",(0,n.jsx)(o.admonition,{type:"info",children:(0,n.jsx)(o.p,{children:"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."})}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Step 3: Submit the address of your Oasis account."})," After you complete the KYC process, you will receive a follow-up email from the Oasis Foundation with information on how to submit your Oasis account address via a unique code that connects your 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 account address."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Step 4: Receive the tokens deposited to your Oasis account."})," After you have completed KYC and submitted your Oasis account address, allow 1 to 2 weeks for your ROSE 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."]}),"\n"]}),"\n",(0,n.jsx)(o.admonition,{type:"caution",children:(0,n.jsxs)(o.p,{children:["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.jsx)(o.a,{href:"https://airtable.com/shrGmpohTNnytBpQU",children:"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."]})})]})}function c(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>a,x:()=>r});var n=t(6540);const i={},s=n.createContext(i);function a(e){const o=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function r(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1d621f19.efb10449.js b/assets/js/1d621f19.efb10449.js new file mode 100644 index 0000000000..d52c723030 --- /dev/null +++ b/assets/js/1d621f19.efb10449.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1939],{1254:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(4848),t=s(8453);const r={},o="Genesis Document",a={id:"node/genesis-doc",title:"Genesis Document",description:"A genesis document contains the initial state of an Oasis Network, and all the",source:"@site/docs/node/genesis-doc.md",sourceDirName:"node",slug:"/node/genesis-doc",permalink:"/node/genesis-doc",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/genesis-doc.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Upgrade Log",permalink:"/node/testnet/upgrade-log"},next:{title:"Run your node",permalink:"/node/run-your-node/"}},c={},d=[{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}];function h(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"genesis-document",children:"Genesis Document"}),"\n",(0,i.jsxs)(n.p,{children:["A genesis document contains the initial state of an Oasis Network, and all the\nnecessary information for launching that particular network (e.g. ",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),",\n",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more in-depth explanation of the genesis document, see the\n",(0,i.jsx)(n.a,{href:"/core/consensus/genesis",children:"Genesis Document"})," part of Oasis Core's developer\ndocumentation."]})}),"\n",(0,i.jsxs)(n.p,{children:["The important thing to note is that the genesis document is used to compute the\n",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-documents-hash",children:"genesis document's hash"}),".\nThis hash is used to verify for which network a given transaction is intended\nfor."]}),"\n",(0,i.jsx)(n.h2,{id:"genesis-file-vs-genesis-document",children:"Genesis File vs. Genesis Document"}),"\n",(0,i.jsx)(n.p,{children:"A genesis file is a JSON file corresponding to a serialized genesis document. As\nsuch, it is more convenient for distribution and sharing."}),"\n",(0,i.jsx)(n.p,{children:"When Oasis Node loads a genesis file, it converts it to a genesis document."}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Up to date information about the current genesis file and the current genesis\ndocument's hash can be found on the Network Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),",\n",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]})}),"\n",(0,i.jsx)(n.h2,{id:"parameters",children:"Parameters"}),"\n",(0,i.jsx)(n.p,{children:"This sections explains some of the key parameters of the genesis document."}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["The concrete parameter values in the following sections pertain to the ",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),".\nOther Oasis networks (e.g. ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),") might use different values."]})}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsx)(n.p,{children:"The token balances in a genesis document (or a genesis file) are enumerated in\nbase units."}),(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]})]}),"\n",(0,i.jsx)(n.h3,{id:"height-genesis-time-and-chain-id",children:"Height, Genesis Time and Chain ID"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"height"})})," parameter specifies the network's initial block height. When a\nnetwork is upgraded, its height is retained. For example, for the\n",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt upgrade"})," the height of the\nMainnet state dump was bumped by 1 from 3,027,600 to 3,027,601."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," is a human-readable version identifier for a network."]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-documents-hash",children:"genesis document's hash"}),",\nis the network's unique identifier."]})}),"\n",(0,i.jsx)(n.h3,{id:"registry",children:"Registry"}),"\n",(0,i.jsxs)(n.p,{children:["Within the ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry"})})," object, there are a broad range of parameters that\nspecify the initial set of node operators and their corresponding initial node\nstatuses."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.enable_runtime_governance_models"})})," The set of\n",(0,i.jsx)(n.a,{href:"/core/consensus/services/registry#runtimes",children:"runtime governance models"})," that are allowed to be used when creating/updating\nregistrations. It is set to ",(0,i.jsx)(n.code,{children:'{"entity": true, "runtime": true}'})," which means a\nruntime can choose between ",(0,i.jsx)(n.strong,{children:"entity governance"})," and ",(0,i.jsx)(n.strong,{children:"runtime-defined\ngovernance"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.entities"})})," The entity registrations for initial node operators,\nincluding public key and signature information."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime",children:[(0,i.jsx)(n.code,{children:"Runtime"})," structure"]}),"\ndocumentation."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime",children:[(0,i.jsx)(n.code,{children:"Runtime"})," structure"]})," documentation."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.nodes"})})," The node registrations for initial node operators,\nincluding public key and signature information."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["For a new network, the entity and node registrations are obtained via the entity\npackage collection process (e.g. ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-entities",children:"Mainnet Network Entities"}),")."]}),(0,i.jsx)(n.p,{children:"For an upgrade to an existing network, the network's state dump tool captures\nthe network's current entity and node registrations."})]}),"\n",(0,i.jsx)(n.h3,{id:"gas-costs",children:"Gas Costs"}),"\n",(0,i.jsx)(n.p,{children:"The following parameters define the gas costs for various types of transactions\non the network:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.gas_costs.add_escrow"})})," The cost for an add escrow (i.e.\nstake tokens) transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.gas_costs.burn"})})," The cost for a burn (i.e. destroy tokens)\ntransaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.gas_costs.reclaim_escrow"})})," The cost for a reclaim escrow\ntransaction (i.e. unstake tokens). The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.gas_costs.transfer"})})," The cost for a transfer transaction.\nThe value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.gas_costs.amend_commission_schedule"})})," The cost for\namending, or changing, a commission schedule. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.deregister_entity"})})," The cost for a deregister\nentity transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.register_entity"})})," The cost for a register entity\ntransaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.register_node"})})," The cost for a register node\ntransaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.register_runtime"})})," The cost for a register\nParaTime transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs.publish_ephemeral_secret"})})," The cost for\nkeymanager ephemeral secret publication transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs.publish_master_secret"})})," The cost for\nkeymanager master secret publication transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs.update_policy"})})," The cost for keymanager update\npolicy transaction. The value is set to 1000."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.gas_costs.compute_commit"})})," The cost for a ParaTime compute\ncommitment transaction. The value is set to 10000."]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsx)(n.p,{children:"In addition to the gas costs specified above, each transaction also incurs a\ncost proportional to its size."}),(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.p,{children:"For example, a staking transfer transaction of size 230 bytes would have a total\ngas cost of 1000 + 230."})]}),"\n",(0,i.jsx)(n.h3,{id:"root-hash",children:"Root Hash"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash"})})," object contains parameters related to the ",(0,i.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"Root Hash service"}),"\nand minimal state related to runtimes."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_runtime_messages"})})," The global limit on the number of\n",(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"messages"})," that can be emitted in each round by the runtime. The value is set\nto 256."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_evidence_age"})})," The maximum age (in the number of\nrounds) of submitted evidence for ",(0,i.jsx)(n.a,{href:"/adrs/0005-runtime-compute-slashing",children:"compute node slashing"}),". The value is set to\n100."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"staking",children:"Staking"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking"})})," object contains parameters controlling the Staking service and\nall state related to accounts, delegations, special pools of tokens..."]}),"\n",(0,i.jsx)(n.h4,{id:"token-supply--ledger",children:"Token Supply & Ledger"}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.common_pool"})})," The tokens (in base units) reserved for staking\nrewards to be paid out over time."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.governance_deposits"})})," The tokens (in base units) collected from\ngovernance proposal deposits."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.delegations"})})," The encoding of the initial delegations at the time\nof genesis."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Interpreting your account balance in the ",(0,i.jsx)(n.code,{children:"staking.ledger"})]})}),(0,i.jsxs)(n.p,{children:["Your account's ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"general.balance"})})," includes all of your tokens that have not\nbeen staked or delegated. Within your account's ",(0,i.jsx)(n.code,{children:"escrow"})," field, the\n",(0,i.jsx)(n.code,{children:"active.balance"})," holds the total amount of tokens are (actively) delegated ",(0,i.jsx)(n.em,{children:"to"}),"\nyou."]})]}),"\n",(0,i.jsx)(n.h4,{id:"delegations",children:"Delegations"}),"\n",(0,i.jsx)(n.p,{children:"The following parameters control how delegations behave on the network:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.allow_escrow_messages"})})," Indicator whether to enable support\nfor ",(0,i.jsx)(n.code,{children:"AddEscrow"})," and ",(0,i.jsx)(n.code,{children:"ReclaimEscrow"})," ",(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"runtime messages"}),".\nThe value is set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"staking-thresholds",children:"Node & ParaTime Token Thresholds"}),"\n",(0,i.jsxs)(n.p,{children:["There are several ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"entity"})}),", ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"node-compute"})}),", ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"node-keymanager"})}),", and\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"node-validator"})})," parameters are set to 100,000,000,000 base units for each,\nindicating that you need to stake at least 100 ROSE tokens in order to have your\nentity or any of the specified nodes go live on the network."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.thresholds"})})," parameters also specify the minimum\nthresholds for registering new ParaTimes. The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"runtime-compute"})})," and\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h4,{id:"rewards",children:"Rewards"}),"\n",(0,i.jsx)(n.p,{children:"The following parameters control the staking rewards on the network:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.a,{href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives",children:"Staking Incentives"})," doc."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.signing_reward_threshold_numerator"})})," and\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.fee_split_weight_propose"})})," The block proposer's share of\ntransaction fees. The value is set to 2."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.fee_split_weight_next_propose"})})," The next block proposer's\nshare of transaction fees. The value is set to 1."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.fee_split_weight_vote"})})," The block signer\u2019s/voter\u2019s share of\ntransaction fees. The value is set to 1."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"commission-schedule",children:"Commission Schedule"}),"\n",(0,i.jsx)(n.p,{children:"The following parameters control how commission rates and bounds can be defined\nand changed:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"slashing",children:"Slashing"}),"\n",(0,i.jsx)(n.p,{children:"These parameters specify key values for the network's slashing mechanism:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"committee-scheduler",children:"Committee Scheduler"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler"})})," object contains parameters controlling how various\ncommittees (validator, compute, key manager) are periodically ",(0,i.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"scheduled"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.min_validators"})})," The minimum size for the consensus\ncommittee. The value is set to 15 validators."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.max_validators"})})," The maximum size for the consensus\ncommittee. The value is set to 100 validators."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"random-beacon",children:"Random Beacon"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon"})})," object contains parameters controlling the network's random\nbeacon."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," Network's starting epoch. When a network is upgraded, its\nepoch is retained. For example, for the ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt upgrade"}),"\nthe epoch of the Mainnet state dump was bumped by 1 from 5,046 to 5,047."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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.']}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"vrf-beacon",children:"VRF Beacon"}),"\n",(0,i.jsx)(n.p,{children:"These parameters control the behavior of the VRF random beacon:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"governance",children:(0,i.jsx)(n.strong,{children:"Governance"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance"})})," object contains parameters controlling the network's\n",(0,i.jsx)(n.a,{href:"/core/consensus/services/governance",children:"on-chain governance"})," introduced in\nthe ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt upgrade"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.stake_threshold"})})," The percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes in\nterms of total voting power for a governance proposal to pass. The value is\nset to 68 (i.e. 68%)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:"The value is set to 336, which is expected to be approximately 14 days."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"consensus",children:"Consensus"}),"\n",(0,i.jsx)(n.p,{children:"The following parameters are used to define key values for the network's\nconsensus protocol:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.backend"})}),' Defines the backend consensus protocol. The value is\nset to "tendermint" indicating that the Tendermint BFT protocol is used.']}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_tx_size"})})," Maximum size (in bytes) for consensus-layer\ntransactions. The value is set to 32,768 bytes, or 32 kB."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_block_size"})})," Maximum block size (in bytes). The value\nis set to 22,020,096 bytes, or 22 MB."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_block_gas"})})," Maximum block gas. The value is set to 0,\nwhich specifies an unlimited amount of gas."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_evidence_size"})})," Maximum evidence size (in bytes). The\nvalue is set to 51,200 bytes, or 50 kB."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_interval"})})," The interval (in blocks) on\nwhich state checkpoints should be taken. The value is set to 10000."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_num_kept"})})," The number of past state\ncheckpoints to keep. The value is set to 2."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var i=s(6540);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1dbb95b6.a0c2cf12.js b/assets/js/1dbb95b6.a0c2cf12.js new file mode 100644 index 0000000000..8a2f186028 --- /dev/null +++ b/assets/js/1dbb95b6.a0c2cf12.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6938],{9497:(e,t,l)=>{l.r(t),l.d(t,{assets:()=>M,contentTitle:()=>O,default:()=>N,frontMatter:()=>D,metadata:()=>A,toc:()=>C});var o=l(4848),c=l(8453),n=(l(6540),l(8478)),i=l(5293);const a=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"}]}}'),s=e=>{const{colorMode:t}=(0,i.G)(),c={...e.chart,layout:{template:"dark"===t?a: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(0,o.jsxs)("div",{children:[(0,o.jsx)(n.A,{fallback:(0,o.jsxs)("div",{children:[(0,o.jsx)("img",{alt:e.label,style:{width:"100%"},className:"text--center",src:e.fallbackSvg}),(0,o.jsx)("p",{className:"text--center",children:(0,o.jsx)("i",{children:"Enable javascript to see interactive chart"})})]}),children:()=>{const t=l(8157),n=(0,l(4610).A)(t);return(0,o.jsx)(n,{data:c.data,layout:c.layout,config:c.config,useResizeHandler:!0,style:{width:"100%",height:e.height??"600px"}})}}),(0,o.jsx)("p",{})]})},r=l.p+"eade0b46da8fcc687b971f401cc035a9.svg",h=JSON.parse('{"US":[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],"M$":[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],"tO":[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],"Ad":[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],"_O":[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],"so":[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],"WD":{"_O":"Core Contributors","so":"Backers","Ad":"Foundation Endowment","tO":"Community & Ecosystem","M$":"Strategic Partners & Reserve","Yw":"Staking Rewards"},"Tj":{"_O":"#4f78ee","so":"#f04a3c","Ad":"#fbc339","tO":"#00ab5b","M$":"#ff7426","Yw":"#36bbc5"}}'),d=e=>e.reduce(((e,t)=>e+t),0),p=()=>{const e={data:[{values:[d(h._O),d(h.so),d(h.Ad),d(h.tO),d(h.M$),235e7],labels:[h.WD._O,h.WD.so,h.WD.Ad,h.WD.tO,h.WD.M$,h.WD.Yw],type:"pie",marker:{colors:[h.Tj._O,h.Tj.so,h.Tj.Ad,h.Tj.tO,h.Tj.M$,h.Tj.Yw]},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(0,o.jsx)(s,{label:"Token Distribution",height:400,chart:e,fallbackSvg:r})},u=l.p+"f00e9c1a71f2d8ec8fa31031daf02445.svg",E=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},k=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"})},m=()=>{const e={data:[{x:k(h.US),y:E(h._O),mode:"lines",name:h.WD._O,stackgroup:"one",marker:{color:h.Tj._O}},{x:k(h.US),y:E(h.so),mode:"lines",name:h.WD.so,stackgroup:"one",marker:{color:h.Tj.so}},{x:k(h.US),y:E(h.Ad),mode:"lines",name:h.WD.Ad,stackgroup:"one",marker:{color:h.Tj.Ad}},{x:k(h.US),y:E(h.tO),mode:"lines",name:h.WD.tO,stackgroup:"one",marker:{color:h.Tj.tO}},{x:k(h.US),y:E(h.M$),mode:"lines",name:h.WD.M$,stackgroup:"one",marker:{color:h.Tj.M$}},{x:[b(h.US),b(h.US)],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(0,o.jsx)(s,{label:"Circulation Schedule",chart:e,fallbackSvg:u})},f=l.p+"745e13edde95dc87e78290c8e9752885.svg",x=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":90000,"scale":283}]'),w={beta:{epoch:0,date:"2020-10-01T16:00:00Z"},mainnet:{epoch:1170,date:"2020-11-18T16:00:00.000Z"},epoch15835:{epoch:15835,date:"2022-07-20T16:11:11.000Z"},epoch18653:{epoch:18653,date:"2022-11-13T13:33:25.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"},block10M:{epoch:16653,date:"2022-08-23T09:29:12.000Z"},block11M:{epoch:18320,date:"2022-10-30T22:41:53.000Z"},block12M:{epoch:19987,date:"2023-01-07T03:06:08.000Z"},block13M:{epoch:21653,date:"2023-03-16T05:47:42.000Z"},block14M:{epoch:23320,date:"2023-05-22T22:04:26.000Z"},block15M:{epoch:24987,date:"2023-07-29T13:10:58.000Z"},block16M:{epoch:26653,date:"2023-10-05T04:13:33.000Z"},recent:{epoch:27320,date:"2023-11-01T03:48:29.000Z"}},y=(w.epoch15835.epoch-w.mainnet.epoch)/((new Date(w.epoch15835.date).getTime()-new Date(w.mainnet.date).getTime())/1e3/60/60),j=(w.recent.epoch-w.block12M.epoch)/((new Date(w.recent.date).getTime()-new Date(w.block12M.date).getTime())/1e3/60/60),v=1e8,T=e=>e.map((e=>{let{untilEpoch:t,scale:l}=e;const o=t>w.epoch18653.epoch?j:y,c=t>w.epoch18653.epoch?w.recent:w.epoch15835,n=(t-c.epoch)/o*60*60*1e3,i=new Date(new Date(c.date).getTime()+n).toISOString(),a=8760*o,s=1*l/v;return{untilEpoch:t,scale:l,date:i,rewardPerEpoch:s,yearlyCompoundedRate:Math.expm1(Math.log1p(s)*a)}})),S=()=>{const e=T(x),t={data:[{x:e.map((e=>e.date)),y:e.map((e=>e.yearlyCompoundedRate)),mode:"lines",name:"Annualized rewards",marker:{color:"#0500e2"},text:x.map((e=>`<i>Reward per epoch: ${100*e.scale*1/v}%<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:{}};return(0,o.jsx)(s,{label:"Staking Rewards Schedule (time estimated from epoch interval)",chart:t,fallbackSvg:f})};const D={},O="Token Metrics and Distribution",A={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/token-metrics-and-distribution.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Why Oasis?",permalink:"/general/oasis-network/why-oasis"},next:{title:"Frequently Asked Questions",permalink:"/general/oasis-network/faq"}},M={},C=[{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}];function F(e){const t={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,c.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"token-metrics-and-distribution",children:"Token Metrics and Distribution"}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Background illustration",src:l(7575).A+"",width:"4800",height:"2400"})}),"\n",(0,o.jsx)(t.h2,{id:"quick-token-facts",children:"Quick Token Facts"}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Token utility:"})," The ROSE token will be used for transaction fees, staking, and delegation at the consensus layer."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Staking rewards"}),": ~2.3 billion tokens will be automatically paid out as staking rewards to stakers and delegators for securing the network over time."]}),"\n",(0,o.jsx)(t.h2,{id:"token-distribution",children:"Token Distribution"}),"\n",(0,o.jsx)(t.p,{children:"The quantity of ROSE tokens reserved for various network functions, as a percentage of the total existing token supply, approximately follows the distribution below."}),"\n",(0,o.jsx)(t.admonition,{type:"caution",children:(0,o.jsx)(t.p,{children:"Please note that these percentages and allocations are subject to change as we finalize the logistics for the network and its related programs."})}),"\n",(0,o.jsx)(p,{}),"\n",(0,o.jsx)(t.h3,{id:"token-distribution-glossary",children:"Token Distribution Glossary"}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Backers"}),": Tokens sold directly to backers prior to mainnet launch. The vast majority of these sales took place in 2018."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Core Contributors"}),": Compensation to core contributors for contributing to the development of the Oasis Network."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Foundation Endowment"}),": Endowment to the Oasis Foundation to foster the development and maintenance of the Oasis Network."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Community and Ecosystem"}),": Funding programs and services that engage the Oasis Network community, including developer grants and other community incentives by the Oasis Foundation."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Strategic Partners and Reserve"}),": Funding programs and services provided by key strategic partners in the Oasis Network."]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.strong,{children:"Staking Rewards"}),": Rewards to be paid out on-chain to stakers and delegators for contributing to the security of the Oasis Network."]}),"\n",(0,o.jsx)(t.h3,{id:"circulating-supply",children:"Circulating Supply"}),"\n",(0,o.jsx)(t.p,{children:"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."}),"\n",(0,o.jsx)(t.p,{children:"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:"}),"\n",(0,o.jsx)(m,{}),"\n",(0,o.jsxs)(t.p,{children:["Alternative formats: ",(0,o.jsx)(t.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:l(1633).A+"",children:"CSV"}),", ",(0,o.jsx)(t.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:l(7021).A+"",children:"JSON"})]}),"\n",(0,o.jsx)(t.h2,{id:"fundraising-history",children:"Fundraising History"}),"\n",(0,o.jsx)(t.p,{children:"Between 2018 and 2020 Oasis has raised over $45 million from backers including:"}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"Fundraising History",src:l(7440).A+"",width:"1200",height:"816"})}),"\n",(0,o.jsx)(t.h2,{id:"staking-incentives",children:"Staking Incentives"}),"\n",(0,o.jsx)(t.p,{children:"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:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Minimum stake"}),": 100 tokens per entity"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Selection to the consensus committee"}),": Each entity can have at most one node elected to the consensus committee at a time."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"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."]}),"\n"]}),"\n",(0,o.jsx)(S,{}),"\n",(0,o.jsxs)(t.p,{children:["Alternative formats: ",(0,o.jsx)(t.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:l(4591).A+"",children:"CSV"}),", ",(0,o.jsx)(t.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:l(8027).A+"",children:"JSON"})]}),"\n",(0,o.jsx)(t.h2,{id:"delegation-policy",children:"Delegation Policy"}),"\n",(0,o.jsx)(t.p,{children:"The Oasis Protocol Foundation is committed to give delegations to entities participating in various incentivized networks."}),"\n",(0,o.jsxs)(t.p,{children:["For more details, see its ",(0,o.jsx)(t.a,{href:"/get-involved/delegation-policy",children:"Delegation Policy"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"change-log",children:"Change Log"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Mar 27, 2024:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:["Updated Staking Rewards Schedule after the\n",(0,o.jsx)(t.a,{href:"https://www.oasisscan.com/proposals/4",children:"governance proposal #4"})," passed (Mar\n27, 2024) which changed the staking rewards schedule."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Nov 2, 2023:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Improve epoch duration estimates inside Staking Rewards Schedule chart after Damask Upgrade."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Jul 28, 2022:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Created interactive Staking Rewards Schedule chart."}),"\n",(0,o.jsx)(t.li,{children:"Created interactive Token Distribution pie chart."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Jul 15, 2022:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Created interactive Token Circulation Schedule chart."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Apr 28, 2022:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Updated validator set to 120 as reflected in the Oasis Network 2022-04-11 Upgrade."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Nov 10, 2021:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Updated validator set to 110 as reflected in the Oasis Network 2021-08-31 Upgrade."}),"\n",(0,o.jsx)(t.li,{children:"Added Circulating Supply title to the part talking about Oasis Network's circulating supply."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"April 30, 2021:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Updated validator set to 100 as reflected in the Oasis Network Cobalt Upgrade."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Jan 15, 2021:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Added section on Foundation's Delegation Policy."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Nov 15, 2020:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.strong,{children:"Nov 2, 2020:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Updated Backers image to include more publicly-known backers."}),"\n",(0,o.jsx)(t.li,{children:"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."}),"\n"]}),"\n"]}),"\n"]})]})}function N(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(F,{...e})}):F(e)}},4591:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/files/data-e5840a71c24b3bb058b0873d28e4ddd2.csv"},8027:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/files/data-096ee9f59abc938aa6c4f2fd8ae065e8.json"},1633:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/files/data-3564fe57c5907977ab1cd7c274a1b895.csv"},7021:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/files/data-634123076dba9af3f2609c62957ba363.json"},7440:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/images/backers-68a28b448e9f1757941ef06bb6dd90e2.png"},7575:(e,t,l)=>{l.d(t,{A:()=>o});const o=l.p+"assets/images/metrics-background-17ff1b79c8113d871e481b777779d2ae.png"}}]); \ No newline at end of file diff --git a/assets/js/1df235ce.148220d1.js b/assets/js/1df235ce.148220d1.js new file mode 100644 index 0000000000..ad67489380 --- /dev/null +++ b/assets/js/1df235ce.148220d1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[952],{8317:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var o=t(4848),a=t(8453);const s={},i="Confidential Hello World",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/confidential-smart-contract.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Hello World",permalink:"/dapp/cipher/hello-world"},next:{title:"Emerald ParaTime",permalink:"/dapp/emerald/"}},c={},l=[{value:"Confidential cell",id:"confidential-cell",level:2},{value:"Confidential Instantiation and Calling",id:"confidential-instantiation-and-calling",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"confidential-hello-world",children:"Confidential Hello World"}),"\n",(0,o.jsx)(n.p,{children:"Confidential smart contract execution on Oasis is assured by three mechanisms:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"the contract is executed in a trusted execution environment,"}),"\n",(0,o.jsx)(n.li,{children:"the contract's storage on the blockchain is encrypted,"}),"\n",(0,o.jsx)(n.li,{children:"the client's transactions and queries are end-to-end encrypted."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"The first mechanism is implemented as part of the ParaTime attestation process\non the consensus layer and is opaque to the dApp developer."}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.h2,{id:"confidential-cell",children:"Confidential cell"}),"\n",(0,o.jsxs)(n.p,{children:["In the ",(0,o.jsx)(n.a,{href:"/dapp/cipher/hello-world",children:"hello world"})," example we used\n",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk_storage/cell/struct.PublicCell.html",children:(0,o.jsx)(n.code,{children:"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.jsx)(n.code,{children:"counter"})," in ",(0,o.jsx)(n.code,{children:'PublicCell::new(b"counter")'}),")."]}),"\n",(0,o.jsxs)(n.p,{children:["Cipher supports another primitive ",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk_storage/cell/struct.ConfidentialCell.html",children:(0,o.jsx)(n.code,{children:"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:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"the round number,"}),"\n",(0,o.jsx)(n.li,{children:"the number of the sub-call during current smart contract execution,"}),"\n",(0,o.jsx)(n.li,{children:"the number of confidential storage accesses from smart contracts in the\ncurrent block."}),"\n"]}),"\n",(0,o.jsx)(n.admonition,{type:"danger",children:(0,o.jsxs)(n.p,{children:["The location of the confidential cell inside the contract state is\n",(0,o.jsx)(n.strong,{children:"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."]})}),"\n",(0,o.jsxs)(n.p,{children:["To call the confidential cell getter and setter, you will need to provide the\ninstance of the ",(0,o.jsx)(n.em,{children:"confidential store"}),". The store is obtained by calling\n",(0,o.jsx)(n.code,{children:"confidential_store()"})," on the contract's ",(0,o.jsx)(n.em,{children:"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."]}),"\n",(0,o.jsx)(n.p,{children:"Now, let's look at how a confidential version of the hello world smart contract\nwould look like:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",metastring:'title="src/lib.rs"',children:'//! 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'})}),"\n",(0,o.jsx)(n.p,{children:"The contract is built the same way as its non-confidential counterpart:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"cargo build --target wasm32-unknown-unknown --release\n"})}),"\n",(0,o.jsx)(n.admonition,{type:"caution",children:(0,o.jsxs)(n.p,{children:["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.jsx)(n.strong,{children:"Do not put any sensitive data inside the smart contract code!"})]})}),"\n",(0,o.jsx)(n.p,{children:"Since the smart contracts store is public, uploading the Wasm code is\nthe same as for the non-confidential ones:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis contract upload hello_world.wasm\n"})}),"\n",(0,o.jsx)(n.h2,{id:"confidential-instantiation-and-calling",children:"Confidential Instantiation and Calling"}),"\n",(0,o.jsxs)(n.p,{children:["To generate an encrypted transaction, the ",(0,o.jsx)(n.code,{children:"oasis contract"})," subcommand\nexpects a ",(0,o.jsx)(n.code,{children:"--encrypted"})," flag. The client (",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsx)(n.p,{children:"Encrypted transactions have the following encrypted fields:\ncontract address, function name, parameters and the amounts and types of tokens\nsent."}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"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."]}),"\n",(0,o.jsx)(n.admonition,{type:"danger",children:(0,o.jsx)(n.p,{children:"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."})}),"\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"--gas-limit"})," parameter and ",(0,o.jsx)(n.em,{children:"guess"})," the sufficient\nvalue for now or we will get the ",(0,o.jsx)(n.code,{children:"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.jsx)(n.code,{children:"60000"}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis contract instantiate CODEID '{instantiate: {initial_counter: 42}}' --encrypted --gas-limit 400000\n"})}),"\n",(0,o.jsxs)(n.admonition,{type:"danger",children:[(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"out of gas"})," error can ",(0,o.jsx)(n.strong,{children:"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.jsx)(n.strong,{children:"timing attack"}),"\nknown from the design of cryptographic algorithms can succeed. To overcome this,\nyour code should ",(0,o.jsx)(n.strong,{children:"never contain branches depending on secret smart contract\nstate"}),"."]}),(0,o.jsxs)(n.p,{children:["A similar gas limit attack could reveal the ",(0,o.jsx)(n.strong,{children:"client's transaction parameters"}),".\nFor example, if calling function ",(0,o.jsx)(n.code,{children:"A"})," costs ",(0,o.jsx)(n.code,{children:"50,000"})," gas units and function ",(0,o.jsx)(n.code,{children:"B"}),"\n",(0,o.jsx)(n.code,{children:"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.jsx)(n.code,{children:"300,000"}),"."]})]}),"\n",(0,o.jsx)(n.p,{children:"Finally, we make a confidential call:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis contract call INSTANCEID '{say_hello: {who: \"me\"}}' --encrypted --gas-limit 400000\n"})}),"\n",(0,o.jsx)(n.admonition,{title:"Call Format",type:"tip",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html",children:"Context"})," object has a special ",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html#tymethod.call_format",children:(0,o.jsx)(n.code,{children:"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."]})}),"\n",(0,o.jsx)(n.admonition,{type:"danger",children:(0,o.jsxs)(n.p,{children:["Regardless of the encrypted transaction and confidential storage used in the\nsmart contract, any ",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html#tymethod.emit_event",children:"emitted event"})," will be public."]})}),"\n",(0,o.jsx)(n.admonition,{title:"Example",type:"info",children:(0,o.jsxs)(n.p,{children:["You can view and download a ",(0,o.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/contract-sdk/c10l-hello-world",children:"complete example"})," from the Oasis SDK repository."]})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>r});var o=t(6540);const a={},s=o.createContext(a);function i(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1e60058c.76ae55bb.js b/assets/js/1e60058c.76ae55bb.js new file mode 100644 index 0000000000..05f35e8989 --- /dev/null +++ b/assets/js/1e60058c.76ae55bb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[713],{140:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var t=n(4848),o=n(8453);const i={},r="Consensus Layer",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/README.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"High-Level Components",permalink:"/core/high-level-components"},next:{title:"Transactions",permalink:"/core/consensus/transactions"}},a={},l=[{value:"CometBFT",id:"cometbft",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}];function h(e){const s={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"consensus-layer",children:"Consensus Layer"}),"\n",(0,t.jsxs)(s.p,{children:["Oasis Core is designed around the principle of modularity. The ",(0,t.jsx)(s.em,{children:"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,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus",children:(0,t.jsx)(s.code,{children:"go/consensus"})}),", with the general interfaces in\n",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/api",children:(0,t.jsx)(s.code,{children:"go/consensus/api"})}),". The general rule is that anything outside of a specific\nconsensus backend package should be consensus backend agnostic."]}),"\n",(0,t.jsxs)(s.p,{children:["For more details about the actual API that the consensus backends must provide\nsee the ",(0,t.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc",children:"consensus backend API documentation"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["Currently the only supported consensus backend is ",(0,t.jsx)(s.a,{href:"https://cometbft.com/",children:"CometBFT"}),", a BFT consensus\nprotocol. For this reason some API surfaces may not be fully consensus backend\nagnostic."]}),"\n",(0,t.jsx)(s.p,{children:"Each consensus backend needs to provide the following services:"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/epochtime",children:"Epoch Time"}),", an epoch-based time keeping service."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/beacon",children:"Random Beacon"}),", a source of randomness for other services."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/staking",children:"Staking"}),", operations required to operate a PoS blockchain."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/registry",children:"Registry"}),", an entity/node/runtime public key and metadata registry service."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/scheduler",children:"Committee Scheduler"})," service."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/governance",children:"Governance"})," service."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/roothash",children:"Root Hash"}),", runtime commitment processing and minimal runtime state keeping\nservice."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"/core/consensus/services/keymanager",children:"Key Manager"})," policy state keeping service."]}),"\n"]}),"\n",(0,t.jsxs)(s.p,{children:["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,t.jsx)(s.a,{href:"/core/consensus/transactions",children:"consensus transaction"})," and submitted to the consensus layer for processing."]}),"\n",(0,t.jsxs)(s.p,{children:["Oasis Core defines an interface for each kind of service (in\n",(0,t.jsx)(s.code,{children:"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)."]}),"\n",(0,t.jsx)(s.h2,{id:"cometbft",children:"CometBFT"}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.img,{alt:"CometBFT",src:n(5146).A+""})}),"\n",(0,t.jsxs)(s.p,{children:["The CometBFT consensus backend lives in ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/cometbft",children:(0,t.jsx)(s.code,{children:"go/consensus/cometbft"})}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["For more information about CometBFT itself see\n",(0,t.jsx)(s.a,{href:"https://docs.cometbft.com/",children:"the CometBFT Core developer documentation"}),". This section assumes familiarity\nwith the CometBFT Core concepts and APIs. When used as an Oasis Core consensus\nbackend, CometBFT Core is used as a library and thus lives in the same\nprocess."]}),"\n",(0,t.jsx)(s.p,{children:"The CometBFT consensus backend is split into two major parts:"}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["The first part is the ",(0,t.jsx)(s.strong,{children:"ABCI application"})," that represents the core logic\nthat is replicated by CometBFT Core among the network nodes using the\nCometBFT BFT protocol for consensus."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["The second part is the ",(0,t.jsx)(s.strong,{children:"query and transaction submission glue"})," that makes\nit easy to interact with the ABCI application, presenting everything via the\nOasis Core Consensus interface."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"abci-application-multiplexer",children:"ABCI Application Multiplexer"}),"\n",(0,t.jsxs)(s.p,{children:["CometBFT Core consumes consensus layer logic via the ",(0,t.jsx)(s.a,{href:"https://github.com/cometbft/cometbft/blob/master/spec/abci/abci.md",children:"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,t.jsx)(s.em,{children:"ABCI application multiplexer"})," which\nperforms some common functions and dispatches transactions to the appropriate\nservice-specific handler."]}),"\n",(0,t.jsxs)(s.p,{children:["The multiplexer lives in ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/cometbft/abci/mux.go",children:(0,t.jsx)(s.code,{children:"go/consensus/cometbft/abci/mux.go"})})," with the\nmultiplexed applications, generally corresponding to services required by the\n",(0,t.jsx)(s.em,{children:"consensus layer"})," interface living in ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/cometbft/apps",children:(0,t.jsx)(s.code,{children:"go/consensus/cometbft/apps/<app>"})}),"."]}),"\n",(0,t.jsx)(s.h3,{id:"state-storage",children:"State Storage"}),"\n",(0,t.jsxs)(s.p,{children:["All application state for the CometBFT consensus backend is stored using our\n",(0,t.jsx)(s.a,{href:"/core/mkvs",children:"Merklized Key-Value Store"}),"."]}),"\n",(0,t.jsx)(s.h3,{id:"service-implementations",children:"Service Implementations"}),"\n",(0,t.jsxs)(s.p,{children:["Service implementations for the CometBFT consensus backend live in\n",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/cometbft",children:(0,t.jsx)(s.code,{children:"go/consensus/cometbft/<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."]}),"\n",(0,t.jsx)(s.h4,{id:"queries",children:"Queries"}),"\n",(0,t.jsxs)(s.p,{children:["Queries do not use the ",(0,t.jsx)(s.a,{href:"https://github.com/cometbft/cometbft/blob/master/spec/abci/abci.md#query-1",children:"ABCI query functionality"})," as that would incur needless\noverhead for our use case (with CometBFT Core running in the same process).\nInstead, each multiplexed service provides its own ",(0,t.jsx)(s.code,{children:"QueryFactory"})," which can be\nused to query state at a specific block height."]}),"\n",(0,t.jsxs)(s.p,{children:["An example of a ",(0,t.jsx)(s.code,{children:"QueryFactory"})," and the corresponding ",(0,t.jsx)(s.code,{children:"Query"})," interfaces for the\nstaking service are as follows:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:"// 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"})}),"\n",(0,t.jsxs)(s.p,{children:["Implementations of this interface generally directly access the underlying ABCI\nstate storage to answer queries. CometBFT implementations of Oasis Core\nconsensus services generally follow the following pattern (example from the\nstaking service API for querying ",(0,t.jsx)(s.code,{children:"TotalSupply"}),"):"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:"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"})}),"\n",(0,t.jsx)(s.h4,{id:"transactions",children:"Transactions"}),"\n",(0,t.jsxs)(s.p,{children:["Each ",(0,t.jsx)(s.a,{href:"/core/consensus/transactions",children:"serialized signed Oasis Core transaction"})," directly corresponds to a\n",(0,t.jsx)(s.a,{href:"https://docs.cometbft.com/v0.38/core/using-cometbft#transactions",children:"CometBFT transaction"}),". Submission is performed by pushing the serialized\ntransaction bytes into the ",(0,t.jsx)(s.a,{href:"https://github.com/cometbft/cometbft/blob/master/spec/abci/abci.md#mempool-connection",children:"mempool"})," where it first undergoes basic checks and\nis then gossiped to the CometBFT P2P network."]}),"\n",(0,t.jsx)(s.p,{children:"Handling of basic checks and transaction execution is performed by the ABCI\napplication multiplexer mentioned above."})]})}function d(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},5146:(e,s,n)=>{n.d(s,{A:()=>t});const t=n.p+"assets/images/oasis-core-consensus-cometbft-b8a8c686399e911605ee9c0bcfe687b5.svg"},8453:(e,s,n)=>{n.d(s,{R:()=>r,x:()=>c});var t=n(6540);const o={},i=t.createContext(o);function r(e){const s=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1fa6bbb5.8e04aee0.js b/assets/js/1fa6bbb5.8e04aee0.js new file mode 100644 index 0000000000..2fa03322ee --- /dev/null +++ b/assets/js/1fa6bbb5.8e04aee0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2684],{3589:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=s(4848),t=s(8453);const o={},r="Random Beacon",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/beacon.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Epoch Time",permalink:"/core/consensus/services/epochtime"},next:{title:"Staking",permalink:"/core/consensus/services/staking"}},c={},d=[{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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"random-beacon",children:"Random Beacon"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["The service interface definition lives in ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/beacon/api",children:(0,i.jsx)(n.code,{children:"go/beacon/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/beacon/api?tab=doc",children:"consensus service API documentation"})," and the ",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"beacon ADR specification"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"operation",children:"Operation"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/core/consensus/services/registry",children:"registry service"}),". In the initial\nimplementation, the curve is P-256."]}),"\n",(0,i.jsxs)(n.p,{children:["The beacon generation process is split into three sequential stages. Any\nfailures in the ",(0,i.jsx)(n.em,{children:"Commit"})," and ",(0,i.jsx)(n.em,{children:"Reveal"})," phases result in a failed protocol round,\nand the generation process will restart after disqualifying participants who\nhave induced the failure."]}),"\n",(0,i.jsx)(n.h3,{id:"commit-phase",children:"Commit Phase"}),"\n",(0,i.jsxs)(n.p,{children:["Upon epoch transition or a prior failed round the commit phase is initiated and\nthe consensus service will select ",(0,i.jsx)(n.code,{children:"particpants"})," nodes from the current validator\nset (in order of descending stake) to serve as entropy contributors."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"beacon.SCRAPECommit"})," transaction."]}),"\n",(0,i.jsxs)(n.p,{children:["Each commit phase lasts exactly ",(0,i.jsx)(n.code,{children:"commit_interval"})," blocks, at the end of which,\nthe round will be closed to further commits."]}),"\n",(0,i.jsxs)(n.p,{children:["At the end of the commit phase, the protocol state is evaluated to ensure that\n",(0,i.jsx)(n.code,{children:"threshold"})," of nodes have published encrypted shares, and if an insufficient\nnumber of nodes have published them, the round is considered to have failed."]}),"\n",(0,i.jsx)(n.p,{children:"The following behaviors are currently candidates for a node being marked as\nmalicious/non-particpatory and subject to exclusion from future rounds and\nslashing:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Not submitting a commitment."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Malformed commitments (corrupted/fails to validate/etc)."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Attempting to alter an existing commitment for a given epoch/round."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"reveal-phase",children:"Reveal Phase"}),"\n",(0,i.jsxs)(n.p,{children:["When the ",(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"beacon.PVSSReveal"})," transaction."]}),"\n",(0,i.jsxs)(n.p,{children:["Each reveal phase lasts exactly ",(0,i.jsx)(n.code,{children:"reveal_interval"})," blocks, at the end of which,\nthe round will be closed to further reveals."]}),"\n",(0,i.jsxs)(n.p,{children:["At the end of the reveal phase, the protocol state is evaluated to ensure that\n",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:"The following behaviors are currently candidates for a node being marked as\nmalicious/non-participatory and subject to exclusion from future rounds and\nslashing:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Not submitting a reveal."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Malformed commitments (corrupted/fails to validate/etc)."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Attempting to alter an existing reveal for a given Epoch/Round."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"complete-transition-wait-phase",children:"Complete (Transition Wait) Phase"}),"\n",(0,i.jsxs)(n.p,{children:["When the ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:"No meaningful protocol activity happens once a round has successfully completed,\nbeyond the scheduling of the next epoch transition."}),"\n",(0,i.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"pvss-commit",children:"PVSS Commit"}),"\n",(0,i.jsx)(n.p,{children:"Submits a PVSS commit."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"beacon.PVSSCommit\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type PVSSCommit struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Commit *pvss.Commit `json:"commit,omitempty"`\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"pvss-reveal",children:"PVSS Reveal"}),"\n",(0,i.jsx)(n.p,{children:"Submits a PVSS reveal."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"beacon.PVSSReveal\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type PVSSReveal struct {\n Epoch EpochTime `json:"epoch"`\n Round uint64 `json:"round"`\n\n Reveal *pvss.Reveal `json:"reveal,omitempty"`\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"participants"})," is the number of participants to be selected for each beacon\ngeneration protocol round."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"commit_interval"})," is the duration of the ",(0,i.jsx)(n.em,{children:"Commit"})," phase, in blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"reveal_interval"})," is the duration of the ",(0,i.jsx)(n.em,{children:"Reveal"})," phase, in blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"transition_delay"})," is the duration of the post ",(0,i.jsx)(n.em,{children:"Reveal"})," phase delay, in\nblocks."]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>a});var i=s(6540);const t={},o=i.createContext(t);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/20d2542b.159e1864.js b/assets/js/20d2542b.159e1864.js new file mode 100644 index 0000000000..a3075bc18f --- /dev/null +++ b/assets/js/20d2542b.159e1864.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9508],{3453:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>d});var i=s(4848),o=s(8453);const t={},r="Prerequisites",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/prerequisites.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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"}},c={},d=[{value:"Using the Development Docker Image",id:"using-the-development-docker-image",level:2}];function a(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(n.p,{children:"The following is a list of prerequisites required to start developing on Oasis\nCore:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"#using-the-development-docker-image",children:"see below"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"System packages:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/projectatomic/bubblewrap",children:"Bubblewrap"})," (at least version 0.3.3)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"http://gcc.gnu.org/",children:"GCC"})," (including C++ subpackage)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://clang.llvm.org/",children:"Clang"})," (including development package)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/protocolbuffers/protobuf",children:"Protobuf"})," compiler."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://www.gnu.org/software/make/",children:"GNU Make"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://cmake.org/",children:"CMake"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://www.freedesktop.org/wiki/Software/pkg-config",children:"pkg-config"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://www.openssl.org/",children:"OpenSSL"})," development package."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/seccomp/libseccomp",children:"libseccomp"})," development package."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["NOTE: On Ubuntu/Debian systems, compiling ",(0,i.jsx)(n.a,{href:"https://github.com/fortanix/rust-mbedtls",children:"mbedtls"})," crate when building the\n",(0,i.jsx)(n.code,{children:"oasis-core-runtime"})," binary requires having the ",(0,i.jsx)(n.code,{children:"gcc-multilib"})," package\ninstalled."]})}),"\n",(0,i.jsx)(n.p,{children:"On Fedora 29+, you can install all the above with:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"sudo dnf install bubblewrap gcc gcc-c++ clang-devel clang protobuf-compiler make cmake openssl-devel libseccomp-devel pkg-config\n"})}),"\n",(0,i.jsxs)(n.p,{children:["On Ubuntu 18.10+ (18.04 LTS provides overly-old ",(0,i.jsx)(n.code,{children:"bubblewrap"}),"), you can install\nall the above with:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"sudo apt install bubblewrap gcc g++ gcc-multilib libclang-dev clang protobuf-compiler make cmake libssl-dev libseccomp-dev pkg-config\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://golang.org",children:"Go"})," (at least version 1.22.2)."]}),"\n",(0,i.jsx)(n.p,{children:"If your distribution provides a new-enough version of Go, just use that."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Otherwise:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"install the Go version provided by your distribution,"}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.a,{href:"https://tip.golang.org/doc/code.html#GOPATH",children:["ensure ",(0,i.jsx)(n.code,{children:"$GOPATH/bin"})," is in your ",(0,i.jsx)(n.code,{children:"PATH"})]}),","]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://golang.org/doc/install#extra_versions",children:"install the desired version of Go"}),", e.g. 1.22.2, with:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"go install golang.org/dl/go1.22.2@latest\ngo1.22.2 download\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["instruct the build system to use this particular version of Go by setting\nthe ",(0,i.jsx)(n.code,{children:"OASIS_GO"})," environment variable in your ",(0,i.jsx)(n.code,{children:"~/.bashrc"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"export OASIS_GO=go1.22.2\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://www.rust-lang.org/",children:"Rust"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["We follow ",(0,i.jsx)(n.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust upstream's recommendation"})," on using\n",(0,i.jsx)(n.a,{href:"https://rustup.rs/",children:"rustup"})," to install and manage Rust versions."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.em,{children:"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."})}),"\n",(0,i.jsx)(n.p,{children:"Install it by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["NOTE: If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,i.jsxs)(n.a,{href:"https://github.com/rust-lang/rustup#other-installation-methods",children:["download ",(0,i.jsx)(n.code,{children:"rustup-init"})," executable for your platform"]}),"\nand run it manually."]})}),"\n",(0,i.jsxs)(n.p,{children:["This will run ",(0,i.jsx)(n.code,{children:"rustup-init"})," which will download and install the latest stable\nversion of Rust on your system."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://edp.fortanix.com",children:"Fortanix Rust EDP"})," utilities."]}),"\n",(0,i.jsx)(n.p,{children:"Install the Fortanix Rust EDP utilities by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"cargo install fortanix-sgx-tools\ncargo install sgxs-tools\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Oasis Core's Rust toolchain version with Fortanix SGX target."}),"\n",(0,i.jsxs)(n.p,{children:["The version of the Rust toolchain we use in Oasis Core is specified in the\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/rust-toolchain.toml",children:(0,i.jsx)(n.code,{children:"rust-toolchain.toml"})})," file."]}),"\n",(0,i.jsxs)(n.p,{children:["The rustup-installed versions of ",(0,i.jsx)(n.code,{children:"cargo"}),", ",(0,i.jsx)(n.code,{children:"rustc"})," and other tools will\n",(0,i.jsx)(n.a,{href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence",children:"automatically detect this file and use the appropriate version of the Rust\ntoolchain"})," when invoked from the Oasis core git\ncheckout directory."]}),"\n",(0,i.jsx)(n.p,{children:"To install the appropriate version of the Rust toolchain, make sure you are\nin an Oasis Core git checkout directory and run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rustup show\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"...\n\nactive toolchain\n----------------\n\nnightly-2024-01-08-x86_64-unknown-linux-gnu (overridden by '/code/rust-toolchain.toml')\nrustc 1.77.0-nightly (75c68cfd2 2024-01-07)\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(",(0,i.jsx)(n.strong,{children:"OPTIONAL"}),") ",(0,i.jsx)(n.a,{href:"https://github.com/mvdan/gofumpt",children:"gofumpt"})," and ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/golang.org/x/tools/cmd/goimports",children:"goimports"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Required if you plan to change any of the Go code in order for automated code\nformatting (",(0,i.jsx)(n.code,{children:"make fmt"}),") to work."]}),"\n",(0,i.jsx)(n.p,{children:"Download and install it with:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"${OASIS_GO:-go} install mvdan.cc/gofumpt@v0.6.0\n${OASIS_GO:-go} install golang.org/x/tools/cmd/goimports@v0.18.0\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(",(0,i.jsx)(n.strong,{children:"OPTIONAL"}),") ",(0,i.jsx)(n.a,{href:"https://golangci-lint.run/",children:"golangci-lint"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Required if you plan to change any of the Go code in order for automated code\nlinting (",(0,i.jsx)(n.code,{children:"make lint"}),") to work."]}),"\n",(0,i.jsx)(n.p,{children:"Download and install it with:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"curl -sSfL \\\nhttps://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \\\n | sh -s -- -b $(${OASIS_GO:-go} env GOPATH)/bin v1.56.1\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(",(0,i.jsx)(n.strong,{children:"OPTIONAL"}),") ",(0,i.jsx)(n.a,{href:"https://github.com/golang/protobuf",children:"protoc-gen-go"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Download and install it with:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"${OASIS_GO:-go} install google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["NOTE: If you didn't/can't add ",(0,i.jsx)(n.code,{children:"$GOPATH/bin"})," to your ",(0,i.jsx)(n.code,{children:"PATH"}),", you can install\n",(0,i.jsx)(n.code,{children:"protoc-gen-go"})," to ",(0,i.jsx)(n.code,{children:"/usr/local/bin"})," (which is in ",(0,i.jsx)(n.code,{children:"$PATH"}),") with:"]})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"sudo GOBIN=/usr/local/bin ${OASIS_GO:-go} install google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.em,{children:"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."})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(",(0,i.jsx)(n.strong,{children:"OPTIONAL"}),") ",(0,i.jsx)(n.a,{href:"https://github.com/jemalloc/jemalloc",children:"jemalloc"})," (version 5.2.1, built with ",(0,i.jsx)(n.code,{children:"'je_'"})," jemalloc-prefix)"]}),"\n",(0,i.jsxs)(n.p,{children:["Alternatively set ",(0,i.jsx)(n.code,{children:'OASIS_BADGER_NO_JEMALLOC="1"'})," environment variable when\nbuilding ",(0,i.jsx)(n.code,{children:"oasis-node"})," code, to build ",(0,i.jsx)(n.a,{href:"https://github.com/dgraph-io/badger/",children:"BadgerDB"})," without ",(0,i.jsx)(n.code,{children:"jemalloc"})," support."]}),"\n",(0,i.jsxs)(n.p,{children:["Download and install ",(0,i.jsx)(n.code,{children:"jemalloc"})," with:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["NOTE: jemalloc needs to be installed to the (default) ",(0,i.jsx)(n.code,{children:"/usr/local"})," prefix\n(i.e. you can't use ",(0,i.jsx)(n.code,{children:"./configure --prefix=$HOME/.local ..."}),") because upstream\nauthors ",(0,i.jsx)(n.a,{href:"https://github.com/dgraph-io/ristretto/blob/221ca9b2091d12e5d24aa5d7d56e49745fc175d8/z/calloc_jemalloc.go#L9-L13",children:"hardcode its path"}),"."]})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"In the following instructions, the top-level directory is the directory\nwhere the code has been checked out."}),"\n",(0,i.jsx)(n.h2,{id:"using-the-development-docker-image",children:"Using the Development Docker Image"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://docs.docker.com/install/",children:"recent version of Docker installed"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Oasis development environment with all the dependencies preinstalled is\navailable in the ",(0,i.jsx)(n.code,{children:"ghcr.io/oasisprotocol/oasis-core-dev:master"})," image.\nTo run a container, do the following in the top-level directory:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make docker-shell\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you are curious, this target will internally run the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsx)(n.p,{children:"All the following commands can then be used from inside the container. See the\nDocker documentation for detailed instructions on working with Docker\ncontainers."})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>l});var i=s(6540);const o={},t=i.createContext(o);function r(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/210fedca.b530e5fa.js b/assets/js/210fedca.b530e5fa.js new file mode 100644 index 0000000000..d806098bf9 --- /dev/null +++ b/assets/js/210fedca.b530e5fa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9221],{8949:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>d,default:()=>p,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var o=t(4848),i=t(8453);const s={},d="Wiping Node State",r={id:"node/run-your-node/maintenance/wiping-node-state",title:"Wiping Node State",description:"In certain situations, you may need to do a complete node redeployment with a",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/wiping-node-state.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},a={},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}];function c(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"wiping-node-state",children:"Wiping Node State"}),"\n",(0,o.jsx)(n.p,{children:"In certain situations, you may need to do a complete node redeployment with a\nclean state. Two common scenarios for this are during a breaking network upgrade\nor in cases of severe data corruption. If you need to wipe your node due to\nsevere corruption, it's important to note that your node will need some time to\ncatch up with the rest of the network."}),"\n",(0,o.jsxs)(n.p,{children:["The following instructions are based on the assumption that you have defined\nyour ",(0,o.jsx)(n.code,{children:"datadir"})," as ",(0,o.jsx)(n.code,{children:"/node/data"})," in your node's configuration."]}),"\n",(0,o.jsx)(n.h2,{id:"state-wipe-and-keep-node-identity",children:"State Wipe and Keep Node Identity"}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["Note that by default, the ",(0,o.jsx)(n.code,{children:"--preserve.mkvs_database"})," flag is set to true,\npreserving the runtime/paratime state."]})}),"\n",(0,o.jsx)(n.p,{children:"To wipe consensus state while preserving the runtime/paratime state follow\nthese instructions:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Stop the ",(0,o.jsx)(n.code,{children:"oasis-node"})," server process (this will depend on your own deployment\nsetup)."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Remove consensus state using the ",(0,o.jsx)(n.code,{children:"oasis-node unsafe-reset"})," command:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"# Do a dry run first to see which files will get deleted.\noasis-node unsafe-reset \\\n --datadir=/node/data \\\n --dry_run\n \n# Delete.\noasis-node unsafe-reset \\\n --datadir /node/data\n"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Start the ",(0,o.jsx)(n.code,{children:"oasis-node"})," server process."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.admonition,{type:"info",children:[(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"oasis-node"})," is very strict regarding the ownership of the files. If you\nencounter the following error:"]}),(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"common/Mkdir: path '/node/data' has invalid owner: 1000. Expected owner: 0\n"})}),(0,o.jsxs)(n.p,{children:["you need to run the ",(0,o.jsx)(n.code,{children:"oasis-node"})," command as the exact user that owns the files,\ne.g.:"]}),(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"sudo --user=#1000 -- oasis-node unsafe-reset --datadir=/node/data --dry_run --log.level info\n"})})]}),"\n",(0,o.jsx)(n.h2,{id:"full-state-wipe",children:"Full State Wipe"}),"\n",(0,o.jsx)(n.admonition,{type:"danger",children:(0,o.jsxs)(n.p,{children:["This is likely not what you want to do. This is destructive and will result in\nlosing private state required to operate the given node. ",(0,o.jsx)(n.strong,{children:"USE AT YOUR OWN\nRISK."})," A full state wipe will also mean that you'll need to generate a new node\nidentity (or copy the old one)."]})}),"\n",(0,o.jsx)(n.p,{children:"To perform a full state wipe follow these steps:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["Stop the ",(0,o.jsx)(n.code,{children:"oasis-node"})," server process (this will depend on your own deployment\nsetup)"]}),"\n",(0,o.jsxs)(n.li,{children:["Remove the ",(0,o.jsx)(n.code,{children:"/node/data"})," directory."]}),"\n",(0,o.jsx)(n.li,{children:"Redeploy your node. You'll need to copy your Node artifacts or create brand\nnew ones."}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>r});var o=t(6540);const i={},s=o.createContext(i);function d(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/220011ce.9077f6aa.js b/assets/js/220011ce.9077f6aa.js new file mode 100644 index 0000000000..752f382099 --- /dev/null +++ b/assets/js/220011ce.9077f6aa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1353],{3688:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var n=t(4848),l=t(8453);const i={},s="Ballot Contract",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/enclave.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"DAO Contract",permalink:"/dapp/opl/host"},next:{title:"Build",permalink:"/dapp/opl/build"}},r={},c=[{value:"Autoswitch",id:"autoswitch",level:4},{value:"Event",id:"event",level:4},{value:"Private",id:"private",level:4}];function d(e){const o={admonition:"admonition",code:"code",em:"em",h1:"h1",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.h1,{id:"ballot-contract",children:"Ballot Contract"}),"\n",(0,n.jsxs)(o.p,{children:["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,n.jsx)(o.em,{children:"enclave"})," smart contract."]}),"\n",(0,n.jsxs)(o.p,{children:["Create a new Solidity contract named ",(0,n.jsx)(o.code,{children:"BallotBoxV1.sol"}),"."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:'// 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'})}),"\n",(0,n.jsx)(o.h4,{id:"autoswitch",children:"Autoswitch"}),"\n",(0,n.jsxs)(o.p,{children:["In this tutorial, the ",(0,n.jsx)(o.em,{children:"enclave"})," smart contract will talk to the ",(0,n.jsx)(o.em,{children:"host"})," smart\ncontract deployed on the Binance Smart Chain (",(0,n.jsx)(o.code,{children:"bsc"}),")."]}),"\n",(0,n.jsx)(o.admonition,{type:"tip",children:(0,n.jsx)(o.p,{children:"Autoswitch will automatically pick the Testnet host network if the enclave network is also Testnet."})}),"\n",(0,n.jsx)(o.p,{children:"Autoswitch supports the following networks:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"ethereum"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"goerli"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"optimism"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"bsc"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"bsc-testnet"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"polygon"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"fantom"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"fantom-testnet"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"moonriver"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"arbitrum-one"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"arbitrum-nova"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"sapphire"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"sapphire-testnet"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"polygon-mumbai"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"avalanche"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"avalanche-fuji"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.code,{children:"arbitrum-testnet"})}),"\n"]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:' constructor(address dao) Enclave(dao, autoswitch("bsc")) {\n registerEndpoint("createBallot", _oplCreateBallot);\n }\n'})}),"\n",(0,n.jsx)(o.h4,{id:"event",children:"Event"}),"\n",(0,n.jsxs)(o.p,{children:["Closing a ballot has an effect on the host chain network (",(0,n.jsx)(o.code,{children:"postMessage()"}),"):"]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:' 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,n.jsx)(o.h4,{id:"private",children:"Private"}),"\n",(0,n.jsxs)(o.p,{children:["The private variable ",(0,n.jsx)(o.code,{children:"_ballots"})," is encrypted on Sapphire."]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-solidity",children:" mapping(ProposalId => Ballot) private _ballots;\n"})})]})}function p(e={}){const{wrapper:o}={...(0,l.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>s,x:()=>a});var n=t(6540);const l={},i=n.createContext(l);function s(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:s(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2237.8cd603c5.js b/assets/js/2237.8cd603c5.js new file mode 100644 index 0000000000..202043fd37 --- /dev/null +++ b/assets/js/2237.8cd603c5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2237],{3363:(e,t,i)=>{i.d(t,{A:()=>r});i(6540);var o=i(4164),s=i(1312),n=i(1107),a=i(4848);function r(e){let{className:t}=e;return(0,a.jsx)("main",{className:(0,o.A)("container margin-vert--xl",t),children:(0,a.jsx)("div",{className:"row",children:(0,a.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,a.jsx)(n.A,{as:"h1",className:"hero__title",children:(0,a.jsx)(s.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,a.jsx)("p",{children:(0,a.jsx)(s.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,a.jsx)("p",{children:(0,a.jsx)(s.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}},2237:(e,t,i)=>{i.r(t),i.d(t,{default:()=>d});i(6540);var o=i(1312),s=i(1003),n=i(5476),a=i(3363),r=i(4848);function d(){const e=(0,o.T)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.be,{title:e}),(0,r.jsx)(n.A,{children:(0,r.jsx)(a.A,{})})]})}}}]); \ No newline at end of file diff --git a/assets/js/2287f371.6b1b056b.js b/assets/js/2287f371.6b1b056b.js new file mode 100644 index 0000000000..f53d9360cf --- /dev/null +++ b/assets/js/2287f371.6b1b056b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5797],{9633:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>a,toc:()=>o});var r=t(4848),s=t(8453);const i={},c="ADR 0021: Forward-Secret Ephemeral Secrets",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0021-keymanager-ephemeral-secrets.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},l={},o=[{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}];function h(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"adr-0021-forward-secret-ephemeral-secrets",children:"ADR 0021: Forward-Secret Ephemeral Secrets"}),"\n",(0,r.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,r.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,r.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["2023-02-17:","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Rename ephemeral entropy to ephemeral secret"}),"\n",(0,r.jsx)(n.li,{children:"Update types and methods, add method for loading a secret"}),"\n",(0,r.jsx)(n.li,{children:"Define publish ephemeral secret transaction"}),"\n",(0,r.jsx)(n.li,{children:"Split instructions for generation and replication in two sections"}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.li,{children:"2022-12-01: Initial proposal"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,r.jsx)(n.p,{children:"Accepted"}),"\n",(0,r.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,r.jsx)(n.h3,{id:"runtime-encryption-key-rek",children:"Runtime encryption key (REK)"}),"\n",(0,r.jsxs)(n.p,{children:["Let the per-enclave ",(0,r.jsx)(n.code,{children:"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."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"// 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"})}),"\n",(0,r.jsx)(n.h3,{id:"ephemeral-secrets",children:"Ephemeral secrets"}),"\n",(0,r.jsx)(n.p,{children:"The key manger enclave will gain the following additional RPC methods:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'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'})}),"\n",(0,r.jsx)(n.p,{children:"Ephemeral secret generation will return a signed and encrypted ephemeral secret\nfor the requested epoch."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'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'})}),"\n",(0,r.jsx)(n.h3,{id:"ephemeral-secret-transaction",children:"Ephemeral secret transaction"}),"\n",(0,r.jsxs)(n.p,{children:["Key manager application will be augmented with a ",(0,r.jsx)(n.code,{children:"PublishEphemeralSecret"}),"\ntransaction that will accept the first published secret for an epoch and\ndiscard the others."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'MethodPublishEphemeralSecret = transaction.NewMethodName(\n ModuleName, "PublishEphemeralSecret", SignedEncryptedEphemeralSecret{}\n)\n'})}),"\n",(0,r.jsx)(n.h3,{id:"generation",children:"Generation"}),"\n",(0,r.jsx)(n.p,{children:"Each keymanager will, at a random time in a given epoch:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Check to see if another instance has published the next epoch's ephemeral\nsecret. If yes, go to step 4."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Execute a local ",(0,r.jsx)(n.code,{children:"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,r.jsx)(n.code,{children:"GenerateEphemeralSecretResponse"}),".\nOn failure, go to step 1."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Publish ",(0,r.jsx)(n.code,{children:"SignedEncryptedEphemeralSecret"})," to consensus via\na ",(0,r.jsx)(n.code,{children:"PublishEphemeralSecret"})," transaction."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"This key manager instance is DONE."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"replication",children:"Replication"}),"\n",(0,r.jsx)(n.p,{children:"Each key manager will:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Listen to the publications of new ephemeral secrets and forward them to\nthe enclave."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["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,r.jsx)(n.code,{children:"Ciphertexts"})," map, decrypt the secret and go to step 4."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Until a successful response is obtained, iterate through the enclaves\nin the ephemeral secret ",(0,r.jsx)(n.code,{children:"Ciphertexts"})," map, issuing\n",(0,r.jsx)(n.code,{children:"replicate_ephemeral_secret"})," RPC calls. On failure, repeat step 3."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"This key manager instance is DONE."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,r.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"It will be possible to publish ephemeral encrypted data to enclave\ninstances on-chain."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"There will be ephemeral secret per key manager committee."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Enclave compromise can not go back to previous epochs to compromise\nthe ephemeral secrets."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Ephemeral secrets are never encrypted with SGX sealing key nor stored in\ncold storage."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Forward-secrecy is imperfect due to the epoch granular nature of the\nephemeral secret."}),"\n"]}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>a});var r=t(6540);const s={},i=r.createContext(s);function c(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/24323d06.b06f5570.js b/assets/js/24323d06.b06f5570.js new file mode 100644 index 0000000000..8a1dfc9f56 --- /dev/null +++ b/assets/js/24323d06.b06f5570.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1229],{2796:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>a,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var s=t(4848),n=t(8453);const r={},i="Authenticated gRPC",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/authenticated-grpc.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Cryptography",permalink:"/core/crypto"},next:{title:"Merklized Key-Value Store (MKVS)",permalink:"/core/mkvs"}},a={},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}];function d(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.h1,{id:"authenticated-grpc",children:"Authenticated gRPC"}),"\n",(0,s.jsxs)(o.p,{children:["Oasis Core nodes communicate between themselves over various protocols. One of\nthose protocols is ",(0,s.jsx)(o.a,{href:"https://grpc.io",children:"gRPC"})," which is currently used for the following:"]}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsx)(o.li,{children:"Compute nodes talking to storage nodes."}),"\n",(0,s.jsx)(o.li,{children:"Compute nodes talking to key manager nodes."}),"\n",(0,s.jsx)(o.li,{children:"Key manager nodes talking to other key manager nodes."}),"\n",(0,s.jsx)(o.li,{children:"Clients talking to compute nodes."}),"\n",(0,s.jsx)(o.li,{children:"Clients talking to key manager nodes."}),"\n"]}),"\n",(0,s.jsx)(o.p,{children:"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."}),"\n",(0,s.jsx)(o.h2,{id:"tls",children:"TLS"}),"\n",(0,s.jsx)(o.p,{children:"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."}),"\n",(0,s.jsxs)(o.p,{children:["Instead of relying on Certificate Authorities, we use the ",(0,s.jsx)(o.a,{href:"/core/consensus/services/registry",children:"registry service"}),"\nprovided by the ",(0,s.jsx)(o.a,{href:"/core/consensus/",children:"consensus layer"}),". Each node publishes its own trusted public\nkeys in the registry as part of its ",(0,s.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node",children:"signed node descriptor"}),". TLS sessions use\nits own ephemeral ",(0,s.jsx)(o.a,{href:"/core/crypto",children:"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."]}),"\n",(0,s.jsx)(o.p,{children:"All TLS keys are ephemeral and nodes are encouraged to frequently rotate them\n(the Oasis Core implementation in this repository supports this automatically)."}),"\n",(0,s.jsxs)(o.p,{children:["For details on how certificate verification is performed see\n",(0,s.jsxs)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/crypto/tls/verify.go",children:["the ",(0,s.jsx)(o.code,{children:"VerifyCertificate"})," implementation"]})," in ",(0,s.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/crypto/tls",children:(0,s.jsx)(o.code,{children:"go/common/crypto/tls"})}),"."]}),"\n",(0,s.jsx)(o.h2,{id:"grpc",children:"gRPC"}),"\n",(0,s.jsx)(o.p,{children:"Oasis Core uses some specific conventions that depart from the most common gRPC\nsetups and are described in the following sections."}),"\n",(0,s.jsx)(o.h3,{id:"cbor-codec",children:"CBOR Codec"}),"\n",(0,s.jsxs)(o.p,{children:["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,s.jsx)(o.a,{href:"/core/encoding",children:"CBOR"})," for encoding of all messages used in our gRPC services."]}),"\n",(0,s.jsxs)(o.p,{children:["This requires that the codec is explicitly configured while setting up\nconnections. Our ",(0,s.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc",children:"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,s.jsx)(o.code,{children:"grpc.go"}),"\nfiles in various ",(0,s.jsx)(o.code,{children:"api"})," packages)."]}),"\n",(0,s.jsx)(o.h3,{id:"errors",children:"Errors"}),"\n",(0,s.jsx)(o.p,{children:"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."}),"\n",(0,s.jsxs)(o.p,{children:["Detailed errors are returned as part of the ",(0,s.jsx)(o.a,{href:"https://pkg.go.dev/google.golang.org/genproto/googleapis/rpc/status?tab=doc#Status",children:"gRPC error details structure"}),". The\n",(0,s.jsx)(o.code,{children:"Value"})," field of the first detail element contains the following CBOR-serialized\nstructure that specifies the (namespaced) error:"]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-golang",children:'type grpcError struct {\n Module string `json:"module,omitempty"`\n Code uint32 `json:"code,omitempty"`\n}\n'})}),"\n",(0,s.jsxs)(o.p,{children:["If you use the provided ",(0,s.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc",children:"gRPC helpers"})," any errors will be mapped to registered\nerror types automatically."]}),"\n",(0,s.jsx)(o.h3,{id:"service-naming-convention",children:"Service Naming Convention"}),"\n",(0,s.jsxs)(o.p,{children:["We use the same service method namespacing convention as gRPC over Protocol\nBuffers. All Oasis Core services have unique identifiers starting with\n",(0,s.jsx)(o.code,{children:"oasis-core."})," followed by the service identifier. A single slash (",(0,s.jsx)(o.code,{children:"/"}),") is used\nas the separator in method names, e.g., ",(0,s.jsx)(o.code,{children:"/oasis-core.Storage/SyncGet"}),"."]})]})}function h(e={}){const{wrapper:o}={...(0,n.R)(),...e.components};return o?(0,s.jsx)(o,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>i,x:()=>c});var s=t(6540);const n={},r=s.createContext(n);function i(e){const o=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),s.createElement(r.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/26373622.32a89621.js b/assets/js/26373622.32a89621.js new file mode 100644 index 0000000000..e45a0ebe54 --- /dev/null +++ b/assets/js/26373622.32a89621.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7162],{3049:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>h});var a=t(4848),s=t(8453),i=t(5965),r=t(6116);const o={description:"Guide to creating secure dApps on Sapphire"},c="Guide",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/guide.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},d={},h=[{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:"Encrypted Contract State",id:"encrypted-contract-state",level:3},{value:"End-to-End Encrypted Transactions and Calls",id:"end-to-end-encrypted-transactions-and-calls",level:3},{value:"<code>from</code> Address is Zero for Unsigned Calls",id:"from-address-is-zero-for-unsigned-calls",level:3},{value:"Override <code>receive</code> and <code>fallback</code> when Funding the Contract",id:"override-receive-and-fallback-when-funding-the-contract",level:3},{value:"Instant Finality",id:"instant-finality",level:3},{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}];function p(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components},{Details:o}=n;return o||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"guide",children:"Guide"}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"https://hardhat.org/tutorial",children:"Hardhat tutorial"}),", ",(0,a.jsx)(n.a,{href:"https://docs.soliditylang.org/en/v0.8.15/solidity-by-example.html",children:"Solidity docs"}),", and\n",(0,a.jsx)(n.a,{href:"/dapp/emerald/writing-dapps-on-emerald",children:"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)."]}),"\n",(0,a.jsx)(n.h2,{id:"oasis-consensus-layer-and-sapphire-paratime",children:"Oasis Consensus Layer and Sapphire ParaTime"}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network\nOverview"}),"). Sapphire is a ParaTime which implements the\nEthereum Virtual Machine (EVM)."]}),"\n",(0,a.jsxs)(n.p,{children:["The minimum and also expected block time in Sapphire is ",(0,a.jsx)(n.strong,{children:"6 seconds"}),". Any\nSapphire transaction will require at least this amount of time to be executed,\nand probably no more."]}),"\n",(0,a.jsxs)(n.p,{children:["ParaTimes, Sapphire included, are not allowed to directly access your tokens\nstored in consensus layer accounts. You will need to ",(0,a.jsx)(n.em,{children:"deposit"})," tokens from your\nconsensus account to Sapphire. Consult the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/#rose-and-the-paratimes",children:"Manage your\nTokens"})," chapter to learn more."]}),"\n",(0,a.jsx)(n.h2,{id:"testnet-and-mainnet",children:"Testnet and Mainnet"}),"\n",(0,a.jsx)(n.p,{children:"Sapphire is deployed on Testnet and Mainnet chains. Testnet should be\nconsidered unstable software and may also have its state wiped at any time. As\nthe name implies, only use Testnet for testing unless you're testing how\nangry your users get when state is wiped."}),"\n",(0,a.jsxs)(n.admonition,{title:"Never deploy production services on Testnet",type:"danger",children:[(0,a.jsxs)(n.p,{children:["Because Testnet state can be wiped in the future, you should ",(0,a.jsx)(n.strong,{children:"never"})," deploy a\nproduction service on Testnet! Just don't do it!"]}),(0,a.jsxs)(n.p,{children:["Also note that while Testnet does use proper TEEs, due to experimental\nsoftware and different security parameters, ",(0,a.jsx)(n.strong,{children:"confidentiality of Sapphire on\nTestnet is not guaranteed"})," -- all transactions and state published on the\nSapphire Testnet should be considered public."]})]}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["For testing purposes, visit our ",(0,a.jsx)(n.a,{href:"https://faucet.testnet.oasis.io/",children:"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."]})}),"\n",(0,a.jsx)(n.h2,{id:"sapphire-vs-ethereum",children:"Sapphire vs Ethereum"}),"\n",(0,a.jsxs)(n.p,{children:["Sapphire is generally compatible with Ethereum, the EVM, and all the user and\ndeveloper tooling that you are used to. In addition to confidentiality\nfeatures, you get a few extra benefits including the ability to ",(0,a.jsx)(n.strong,{children:"generate\nprivate entropy"}),", and ",(0,a.jsx)(n.strong,{children:"make signatures on-chain"}),". An example of a dApp that\nuses both is an HSM contract that generates an Ethereum wallet and signs\ntransactions sent to it via transactions."]}),"\n",(0,a.jsx)(n.p,{children:"There are also a few breaking changes compared to Ethereum though, but we think\nthat you'll quickly grasp them:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#encrypted-contract-state",children:"Encrypted Contract State"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#end-to-end-encrypted-transactions-and-calls",children:"End-to-End Encrypted Transactions and Calls"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"#from-address-is-zero-for-unsigned-calls",children:[(0,a.jsx)(n.code,{children:"from"})," Address is Zero for Unsigned Calls"]})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"#override-receive-and-fallback-when-funding-the-contract",children:["Override ",(0,a.jsx)(n.code,{children:"receive"})," and ",(0,a.jsx)(n.code,{children:"fallback"})," when Funding the Contract"]})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#instant-finality",children:"Instant Finality"})}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"Read below to learn more about them. Otherwise, Sapphire is like Emerald, a\nfast, cheap Ethereum."}),"\n",(0,a.jsx)(n.h3,{id:"encrypted-contract-state",children:"Encrypted Contract State"}),"\n",(0,a.jsxs)(n.p,{children:["The 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,a.jsx)(n.code,{children:"private"}),",\nbut with the further restriction that not even full nodes can read the values.\nPublic or access-controlled values are provided instead through explicit\ngetters."]}),"\n",(0,a.jsxs)(n.p,{children:["Calling ",(0,a.jsx)(n.code,{children:"eth_getStorageAt()"})," will return zero."]}),"\n",(0,a.jsx)(n.h3,{id:"end-to-end-encrypted-transactions-and-calls",children:"End-to-End Encrypted Transactions and Calls"}),"\n",(0,a.jsx)(n.p,{children:"Transactions and calls are end-to-end encrypted into the contract. Only the\ncaller and the contract can see the data sent to/received from the ParaTime.\nThis ends up defeating some utility of block explorers, however."}),"\n",(0,a.jsx)(n.p,{children:"The status of the transaction is public and so are the error code, the revert\nmessage and logs (emitted events)."}),"\n",(0,a.jsxs)(n.h3,{id:"from-address-is-zero-for-unsigned-calls",children:[(0,a.jsx)(n.code,{children:"from"})," Address is Zero for Unsigned Calls"]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"from"})," address using of calls is derived from a signature attached to the\ncall. Unsigned calls have their sender set to the zero address. This allows\ncontract authors to write getters that release secrets to authenticated callers\n(e.g. by checking the ",(0,a.jsx)(n.code,{children:"msg.sender"})," value), but without requiring a transaction\nto be posted on-chain."]}),"\n",(0,a.jsxs)(n.h3,{id:"override-receive-and-fallback-when-funding-the-contract",children:["Override ",(0,a.jsx)(n.code,{children:"receive"})," and ",(0,a.jsx)(n.code,{children:"fallback"})," when Funding the Contract"]}),"\n",(0,a.jsx)(n.p,{children:"In Ethereum, you can fund a contract by sending Ether along the transaction in\ntwo ways:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["a transaction must call a ",(0,a.jsx)(n.em,{children:"payable"})," function in the contract, or"]}),"\n",(0,a.jsxs)(n.li,{children:["not calling any specific function (i.e. empty ",(0,a.jsx)(n.em,{children:"calldata"}),"). In this case,\nthe payable ",(0,a.jsx)(n.code,{children:"receive()"})," and/or ",(0,a.jsx)(n.code,{children:"fallback()"})," functions need to be defined in\nthe contract. If no such functions exist, the transaction will revert."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"The behavior described above is the same in Sapphire when using EVM transactions\nto fund a contract."}),"\n",(0,a.jsxs)(n.p,{children:["However, the Oasis Network also uses ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/",children:"Oasis-native transactions"})," such as a\ndeposit to a ParaTime account or a transfer. In this case, ",(0,a.jsxs)(n.strong,{children:["you will be able to\nfund the contract's account even though the contract may not implement payable\n",(0,a.jsx)(n.code,{children:"receive()"})," or ",(0,a.jsx)(n.code,{children:"fallback()"}),"!"]})," Or, if these functions do exist, ",(0,a.jsx)(n.strong,{children:"they will not\nbe triggered"}),". You can send such Oasis-native transactions by using the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis\nCLI"})," for example."]}),"\n",(0,a.jsx)(n.h3,{id:"instant-finality",children:"Instant Finality"}),"\n",(0,a.jsx)(n.p,{children:"The Oasis Network is a proof of stake network where 2/3+ of the validator nodes\nneed to verify each block in order to consider it final. However, in Ethereum\nthe signatures of those validator nodes can be submitted minutes after the block\nis proposed, which makes the block proposal mechanism independent of the\nvalidation, but adds uncertainty if and when will the proposed block actually be\nfinalized."}),"\n",(0,a.jsxs)(n.p,{children:["In the Oasis Network, the 2/3+ of signatures need to be provided immediately\nafter the block is proposed and ",(0,a.jsx)(n.strong,{children:"the network will halt, until the required\nnumber signatures are provided"}),". This means that you can rest assured that any\nvalidated block is final. As a consequence, the cross-chain bridges are more\nresponsive yet safe on the Oasis Network."]}),"\n",(0,a.jsx)(n.h2,{id:"integrating-sapphire",children:"Integrating Sapphire"}),"\n",(0,a.jsxs)(n.p,{children:["Once ROSE tokens are ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/#rose-and-the-paratimes",children:"deposited into Sapphire"}),", it should\nbe painless for users to begin using dApps. To achieve this ideal user\nexperience, we have to modify the dApp a little, but it's made simple by our\ncompatibility library, ",(0,a.jsx)(n.a,{href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime",children:"@oasisprotocol/sapphire-paratime"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["There are compatibility layers in other languages, which may be found in ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/clients",children:"the repo"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"writing-secure-dapps",children:"Writing Secure dApps"}),"\n",(0,a.jsx)(n.h3,{id:"wallets",children:"Wallets"}),"\n",(0,a.jsx)(n.p,{children:"Sapphire is compatible with popular self-custodial wallets including MetaMask,\nLedger, Brave, and so forth. You can also use libraries like Ethers, Viem, and Wagmi\nto create programmatic wallets. In general, if it generates secp256k1 signatures,\nit'll work just fine."}),"\n",(0,a.jsx)(n.h3,{id:"languages--frameworks",children:"Languages & Frameworks"}),"\n",(0,a.jsxs)(n.p,{children:["Sapphire is programmable using any language that targets the EVM, such as Solidity,\nFe or Vyper. If you prefer to use an Ethereum framework like Hardhat or Foundry,\nyou can 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 endpoints\n",(0,a.jsx)(n.a,{href:"/dapp/sapphire/#rpc-endpoints",children:"here"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"transactions--calls",children:"Transactions & Calls"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Client, Key Manager, Compute Node diagram",src:t(695).A+""})}),"\n",(0,a.jsxs)(n.p,{children:["The figure above illustrates the flow of a ",(0,a.jsx)(n.strong,{children:"confidential smart contract\ntransaction"})," on Sapphire."]}),"\n",(0,a.jsxs)(n.p,{children:["Transactions and calls must be encrypted and signed for maximum security.\nThe ",(0,a.jsx)(n.a,{href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime",children:"@oasisprotocol/sapphire-paratime"})," npm package will make your life\neasy. It'll handle cryptography and signing for you."]}),"\n",(0,a.jsxs)(n.p,{children:["You should be aware that taking actions based on the value of private data may\n",(0,a.jsx)(n.strong,{children:"leak the private data through side channels"})," like time spent, gas use and\naccessed memory locations. If you need to branch on private data, you should in\nmost cases ensure that both branches exhibit the same time/gas and storage\npatterns."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also make ",(0,a.jsx)(n.strong,{children:"confidential smart contract calls"})," on Sapphire. If you\nuse ",(0,a.jsx)(n.code,{children:"msg.sender"})," for access control in your contract, the call ",(0,a.jsx)(n.strong,{children:"must be\nsigned"}),", otherwise ",(0,a.jsx)(n.code,{children:"msg.sender"})," will be zeroed. On the other hand, set the\n",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsx)(n.p,{children:"Inside the smart contract code, there is no way of knowing whether the\nclient's call data were originally encrypted or not."})}),"\n",(0,a.jsxs)(o,{children:[(0,a.jsx)("summary",{children:"Detailed confidential smart contract transaction flow on Sapphire"}),(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Diagram of the detailed confidential smart contract transaction flow on Sapphire",src:t(4807).A+"",width:"1087",height:"4156"})})]}),"\n",(0,a.jsxs)(o,{children:[(0,a.jsx)("summary",{children:"Detailed confidential smart contract call flow on Sapphire"}),(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Diagram of the detailed confidential smart contract call flow on Sapphire",src:t(6119).A+"",width:"1087",height:"3798"})})]}),"\n",(0,a.jsx)(n.h3,{id:"contract-state",children:"Contract State"}),"\n",(0,a.jsxs)(n.p,{children:["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 ",(0,a.jsx)(n.strong,{children:"size of either is not hidden"}),". Your\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 may need to obfuscate that, too. See ",(0,a.jsx)(n.a,{href:"/dapp/sapphire/security#storage-access-patterns",children:"Security chapter"})," for more\nrecommendations."]}),"\n",(0,a.jsx)(n.admonition,{title:"Contract state leaks a fine-grained access pattern",type:"danger",children:(0,a.jsx)(n.p,{children:"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."})}),"\n",(0,a.jsx)(n.p,{children:"Contract state may be made available to third parties through logs/events, or\nexplicit getters."}),"\n",(0,a.jsx)(n.h3,{id:"contract-logs",children:"Contract Logs"}),"\n",(0,a.jsxs)(n.p,{children:["Contract logs/events (e.g., those emitted by the Solidity ",(0,a.jsx)(n.code,{children:"emit"})," keyword)\nare exactly like Ethereum. Data contained in events is ",(0,a.jsx)(n.em,{children:"not"})," encrypted.\nPrecompiled contracts are available to help you encrypt data that you can\nthen pack into an event, however."]}),"\n",(0,a.jsx)(n.admonition,{title:"Unmodified contracts may leak state through logs",type:"danger",children:(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.code,{children:"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."]})}),"\n",(0,a.jsx)(n.h2,{id:"contract-verification",children:"Contract Verification"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://sourcify.dev/",children:"Sourcify"})," is the preferred service for the ",(0,a.jsx)(n.a,{href:"https://ethereum.org/en/developers/docs/smart-contracts/verifying/",children:"verification of smart\ncontracts"})," deployed on Sapphire. Make sure you have\nthe ",(0,a.jsx)(n.strong,{children:"address of each deployed contract"})," available (your deployment scripts\nshould report those) and the ",(0,a.jsx)(n.strong,{children:"contracts JSON metadata file"})," generated when\ncompiling contracts (Hardhat stores it inside the ",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsxs)(n.admonition,{title:"Contract deployment encryption",type:"warning",children:[(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"Do not deploy your contract with an encrypted contract deployment transaction,\nif you want to verify it."})," For example, if your ",(0,a.jsx)(n.code,{children:"hardhat.config.ts"}),"\nor deployment script contains ",(0,a.jsx)(n.code,{children:"import '@oasisprotocol/sapphire-hardhat'"})," or\n",(0,a.jsx)(n.code,{children:"import '@oasisprotocol/sapphire-paratime'"})," lines at the beginning, you should\ncomment those out for the deployment."]}),(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.code,{children:"eth_getCode"})," RPC, but this will not work correctly\nfor contracts with immutable variables."]})]}),"\n",(0,a.jsx)(n.p,{children:"To verify a contract deployed on Sapphire Mainnet or Testnet:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Visit the ",(0,a.jsx)(n.a,{href:"https://sourcify.dev/",children:"Sourcify"}),' website and hit the "VERIFY CONTRACT" button.']}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Sourcify website",src:t(1023).A+"",width:"1564",height:"979"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Upload the contracts JSON metadata file."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Sourcify: Upload metadata JSON file",src:t(6372).A+"",width:"1564",height:"979"})}),"\n",(0,a.jsx)(n.admonition,{title:"Store your metadata files",type:"tip",children:(0,a.jsxs)(n.p,{children:["For production deployments, it is generally a good idea to ",(0,a.jsx)(n.strong,{children:"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."]})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:'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 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.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Sourcify: Verify contract",src:t(2669).A+"",width:"1564",height:"2420"})}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["If everything goes well, you will get a ",(0,a.jsx)(n.em,{children:"Perfect match"})," notice and your\ncontract is now verified. Congratulations!"]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["In case of a ",(0,a.jsx)(n.em,{children:"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,a.jsx)(n.code,{children:".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."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also explore other verification methods on Sourcify by reading the\n",(0,a.jsx)(n.a,{href:"https://docs.sourcify.dev/docs/how-to-verify/",children:"official Sourcify contract verification instructions"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"running-a-private-oasis-network-locally",children:"Running a Private Oasis Network Locally"}),"\n",(0,a.jsxs)(n.p,{children:["For convenient development and testing of your dApps the Oasis team prepared\nthe ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-localnet",children:"ghcr.io/oasisprotocol/sapphire-localnet"})," Docker image\nwhich brings you a complete Oasis network stack to your desktop. The Localnet\nSapphire instance ",(0,a.jsx)(n.strong,{children:"mimics confidential transactions"}),", but it does not run in a\ntrusted execution environment nor does it require Intel's SGX on your computer.\nThe network is isolated from the Mainnet or Testnet and consists of a:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"single Oasis validator node with 1-second block time and 30-second epoch,"}),"\n",(0,a.jsx)(n.li,{children:"single Oasis client node,"}),"\n",(0,a.jsx)(n.li,{children:"single compute node running Oasis Sapphire,"}),"\n",(0,a.jsx)(n.li,{children:"single key manager node,"}),"\n",(0,a.jsx)(n.li,{children:"PostgreSQL instance,"}),"\n",(0,a.jsx)(n.li,{children:"Oasis Web3 gateway with transaction indexer and enabled Oasis RPCs,"}),"\n",(0,a.jsx)(n.li,{children:"helper script which populates the account(s) for you."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"To run the image, execute:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-localnet\n"})}),"\n",(0,a.jsx)(n.p,{children:"After a while, the tool will show you something like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"sapphire-localnet 2024-05-28-git37b7166 (oasis-core: 24.0-gitfb49717, sapphire-paratime: 0.7.3-testnet, oasis-web3-gateway: 5.1.0)\n\n * Starting oasis-net-runner with sapphire...\n * Waiting for Postgres to start...\n * Waiting for Oasis node to start.....\n * Starting oasis-web3-gateway...\n * Bootstrapping network (this might take a minute)...\n * Waiting for key manager......\n * Populating accounts...\n\nAvailable Accounts\n==================\n(0) 0x41b0C13e747F8Cb1c4E980712504437cb1792327 (10000 TEST)\n(1) 0xa521f94f8a38b1d027D526017EB229327B9D6cA0 (10000 TEST)\n(2) 0x1e0f8369215D6C5Af5E14eD6A0D6ae7372776A79 (10000 TEST)\n(3) 0xB60cA28B491747a27C057AdBF3E71F3CCC52332C (10000 TEST)\n(4) 0x88D7d924e521a6d07008a373D5b33281148ffEDc (10000 TEST)\n\nPrivate Keys\n==================\n(0) 0x617346c545d62b8213ea907acf1b570a7405683e2c6dcaf963fc21fd677e0c56\n(1) 0xf82d6e09208b0bd44a397f7e73b05c564e6c9f70b151ee7677e2bb8d6ce5d882\n(2) 0xeb2f21d20086f3dd6bfe7184dad1cb8b0fb802f27b1334e836a19eda0a43a1c2\n(3) 0x82b0203d6063992b1052004b90411c45d4f3afab696346f006e74c6abd8f855e\n(4) 0x7179c6e1add3a2993822653b9c98fe606f47fb6d4c0d0d81b31b067cf6bb5f83\n\nHD Wallet\n==================\nMnemonic: coach genre beach child crunch champion tell adult critic peace canoe stable\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\n * Listening on http://localhost:8545 and ws://localhost:8546. Chain ID: 0x5afd\n * Container start-up took 66 seconds, node log level is set to warn.\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Those familiar with local dApp environments will find the output above similar\nto ",(0,a.jsx)(n.code,{children:"geth --dev"})," or ",(0,a.jsx)(n.code,{children:"ganache-cli"})," commands or the ",(0,a.jsx)(n.code,{children:"geth-dev-assistant"})," npm\npackage. ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-localnet",children:"sapphire-localnet"})," will spin up a private Oasis Network locally,\ngenerate and populate test accounts and make the following Web3 endpoints\navailable for you to use:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"http://localhost:8545"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"ws://localhost:8546"})}),"\n"]}),"\n",(0,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsxs)(n.p,{children:["If you prefer using the same mnemonics each time (e.g. for testing purposes)\nor to populate just a single account, use ",(0,a.jsx)(n.code,{children:"-to"})," flag and pass the mnemonics or\nthe wallet addresses. By passing the ",(0,a.jsx)(n.code,{children:"-test-mnemonic"})," flag you can fund the\nstandard test accounts provided by the ",(0,a.jsx)(n.code,{children:"hardhat node"})," commmand and that are\ntypically used for solidity unit tests."]}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:'docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-localnet -to "bench remain brave curve frozen verify dream margin alarm world repair innocent" -n3\ndocker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-localnet -to "0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2,0xbDA5747bFD65F08deb54cb465eB87D40e51B197E"\ndocker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/sapphire-localnet -test-mnemonic\n'})})]}),"\n",(0,a.jsxs)(n.admonition,{title:"Running on Apple M chips",type:"note",children:[(0,a.jsxs)(n.p,{children:["There is currently no ",(0,a.jsx)(n.code,{children:"arm64"})," build available for M Macs, so you will need to\nforce the docker image to use the ",(0,a.jsx)(n.code,{children:"linux/x86_64"})," platform, like this:"]}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"docker run -it -p8545:8545 -p8546:8546 --platform linux/x86_64 ghcr.io/oasisprotocol/sapphire-localnet\n"})})]}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/sapphire-localnet",children:"sapphire-localnet"})," runs in ephemeral mode. Any smart contract and wallet balance\nwill be lost after you quit the Docker container!"]})}),"\n",(0,a.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,a.jsx)(i.A,{item:(0,r.$)("/node/run-your-node/paratime-client-node")}),"\n",(0,a.jsx)(i.A,{item:(0,r.$)("/node/web3")})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>g});t(6540);var a=t(4164),s=t(8774),i=t(4142),r=t(5846),o=t(6654),c=t(1312),l=t(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:n,children:t}=e;return(0,h.jsx)(s.A,{href:n,className:(0,a.A)("card padding--lg",d.cardContainer),children:t})}function u(e){let{href:n,icon:t,title:s,description:i}=e;return(0,h.jsxs)(p,{href:n,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,a.A)("text--truncate",d.cardTitle),title:s,children:[t," ",s]}),i&&(0,h.jsx)("p",{className:(0,a.A)("text--truncate",d.cardDescription),title:i,children:i})]})}function m(e){let{item:n}=e;const t=(0,i.Nr)(n),a=function(){const{selectMessage:e}=(0,r.W)();return n=>e(n,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,h.jsx)(u,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??a(n.items.length)}):null}function f(e){let{item:n}=e;const t=(0,o.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,i.cC)(n.docId??void 0);return(0,h.jsx)(u,{href:n.href,icon:t,title:n.label,description:n.description??a?.description})}function g(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(f,{item:n});case"category":return(0,h.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},5846:(e,n,t)=>{t.d(n,{W:()=>l});var a=t(6540),s=t(4586);const i=["zero","one","two","few","many","other"];function r(e){return i.filter((n=>e.includes(n)))}const o={locale:"en",pluralForms:r(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,a.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:r(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),o}}),[e])}function l(){const e=c();return{selectMessage:(n,t)=>function(e,n,t){const a=e.split("|");if(1===a.length)return a[0];a.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${a.length}: ${e}`);const s=t.select(n),i=t.pluralForms.indexOf(s);return a[Math.min(i,a.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>i});var a=t(2252);function s(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&s(n.items)}}function i(e){const n=(0,a.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)s(n.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]}},6119:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/c10l-smart-contract-call.mmd-bba499f12d79733189ed91fd919480b9.svg"},4807:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/c10l-smart-contract-tx.mmd-1979dfebd7f16fb909380088da1c7be2.svg"},1023:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/sourcify1-898a49b3519501962fe80f3ba09314b1.png"},6372:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/sourcify2-d95710724b0373068c2ac0f857e07928.png"},2669:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/sourcify3-8be00790df0e04f4720273e6cde8a867.png"},695:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/client-km-compute-e82d4c5748974134adbf78d76ca7bc03.svg"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var a=t(6540);const s={},i=a.createContext(s);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/277e601e.06461f2c.js b/assets/js/277e601e.06461f2c.js new file mode 100644 index 0000000000..f270197798 --- /dev/null +++ b/assets/js/277e601e.06461f2c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6698],{6014:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var i=s(4848),r=s(8453);const t={},o="Cobalt Upgrade",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/previous-upgrades/cobalt-upgrade.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Damask Upgrade",permalink:"/node/mainnet/previous-upgrades/damask-upgrade"},next:{title:"Upgrade to Mainnet",permalink:"/node/mainnet/previous-upgrades/mainnet-upgrade"}},d={},c=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"cobalt-upgrade",children:"Cobalt Upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["This document provides an overview of the proposed criteria and changes for the Cobalt Mainnet upgrade. This has been ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/community/discussions/18",children:"reviewed and approved by community members and validators of the Oasis Network"})," and is being reproduced and summarized here for easy access."]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"As proposed by the community, the Cobalt upgrade on Mainnet will kick off around April 28, 2021 at 16:00 UTC."})}),"\n",(0,i.jsx)(n.h2,{id:"major-features",children:"Major Features"}),"\n",(0,i.jsxs)(n.p,{children:["All features for the Cobalt upgrade are implemented as part of ",(0,i.jsx)(n.strong,{children:"Oasis Core 21.1.1"})," which is a protocol-breaking release. Summary of the major features is as follows:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/community/discussions/5#discussioncomment-282746",children:"suggested earlier by the community"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"mechanics-of-the-upgrade",children:"Mechanics of the Upgrade"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"This section will be updated with more details as we get closer to the upgrade."})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["For the actual steps that node operators need to make on their nodes, see the ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#cobalt-upgrade",children:"Upgrade Log"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"proposed-state-changes",children:"Proposed State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the ",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsx)(n.h3,{id:"general",children:(0,i.jsx)(n.strong,{children:"General"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"height"})})," will be set to the height of the Mainnet state dump + 1, i.e.",(0,i.jsx)(n.code,{children:"3027601"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"genesis_time"})})," will be set to",(0,i.jsx)(n.code,{children:"2021-04-28T16:00:00Z"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"oasis-2"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be set to",(0,i.jsx)(n.code,{children:"13807"}),"(approximately 1 year from the Cobalt upgrade)."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"epoch-time",children:(0,i.jsx)(n.strong,{children:"Epoch Time"})}),"\n",(0,i.jsxs)(n.p,{children:["The **",(0,i.jsx)(n.code,{children:"epochtime"}),"**object will be removed since it became obsolete with the new ",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"improved random beacon"}),". It will be replaced with the new ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon"})})," object described ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade#random-beacon",children:"below"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"registry",children:(0,i.jsx)(n.strong,{children:"Registry"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["**",(0,i.jsx)(n.code,{children:"registry.params.enable_runtime_governance_models"})," ** is a new parameter that specifies the set of ",(0,i.jsx)(n.a,{href:"/core/consensus/services/registry#runtimes",children:"runtime governance models"})," that are allowed to be used when creating/updating registrations. It will be set to:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'{\n "entity": true,\n "runtime": true\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes"})})," list contains the registered runtimes' descriptors. In the Cobalt upgrade, it will be migrated from a list of ",(0,i.jsx)(n.em,{children:"signed"})," runtime descriptors to a list of runtime descriptors. The migration will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.suspended_runtimes"})})," list contains the suspended registered runtimes' descriptors. In the Cobalt upgrade, it will be migrated from a list of ",(0,i.jsx)(n.em,{children:"signed"})," suspended runtime descriptors to a list of suspended runtime descriptors. The migration will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Inactive registered entities in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.entities"})})," (and their corresponding nodes in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.nodes"})}),") that don't pass the ",(0,i.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"minimum staking thresholds"})," will be removed. The removal will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["Removing entities from ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.entities"})})," will effectively deregister them but the entities' accounts in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.ledger"})})," will remain intact."]}),(0,i.jsxs)(n.p,{children:["Deregistered entities can always re-register by submitting the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#entity-registration",children:"entity registration transaction"})," after the upgrade."]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.node_statuses"})})," object contains the registered nodes' statuses. In the Cobalt upgrade, each node's status will get a new parameter: ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"election_eligible_after"})}),". This parameter specifies at which epoch a node is eligible to be ",(0,i.jsx)(n.a,{href:"/core/consensus/services/scheduler",children:"scheduled into various committees"}),". All nodes will have the parameter set to ",(0,i.jsx)(n.code,{children:"0"})," which means they are immediately eligible. The migration will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"root-hash",children:(0,i.jsx)(n.strong,{children:"Root Hash"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"roothash.params.max_runtime_messages"})," ** is a new parameter that specifies the global limit on the number of ",(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"messages"})," that can be emitted in each round by the runtime. It will be set to ",(0,i.jsx)(n.code,{children:"256"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_evidence_age"})})," is a new parameter that specifies the maximum age (in the number of rounds) of submitted evidence for ",(0,i.jsx)(n.a,{href:"/adrs/0005-runtime-compute-slashing",children:"compute node slashing"}),". It will be set to ",(0,i.jsx)(n.code,{children:"100"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"staking",children:(0,i.jsx)(n.strong,{children:"Staking"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"staking.governance_deposits"})," ** are the tokens collected from governance proposal deposits. The initial balance will be set to ",(0,i.jsx)(n.code,{children:'"0"'}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.allow_escrow_messages"})})," is a new parameter indicating whether to enable support for the newly added ",(0,i.jsx)(n.code,{children:"AddEscrow"})," and ",(0,i.jsx)(n.code,{children:"ReclaimEscrow"})," ",(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"runtime messages"})," . It will be set to",(0,i.jsx)(n.code,{children:"true"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.slashing.0"})})," will be renamed to ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.slashing.consensus-equivocation"})}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:'"100000000000"'})," (i.e. 100,000,000,000 base units, or 100 ROSE tokens)."]}),"\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"committee-scheduler",children:(0,i.jsx)(n.strong,{children:"Committee Scheduler"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.max_validators"})})," is the maximum size of the consensus committee (i.e. the validator set). It will be increased from ",(0,i.jsx)(n.code,{children:"80"})," to",(0,i.jsx)(n.code,{children:"100"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"random-beacon",children:(0,i.jsx)(n.strong,{children:"Random Beacon"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon"})})," object contains parameters controlling the new ",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"improved random beacon"})," introduced in the Cobalt upgrade."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the epoch of Mainnet's state dump + 1, i.e. ",(0,i.jsx)(n.code,{children:"5047"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.backend"})})," configures the random beacon backend to use. It will be set to ",(0,i.jsx)(n.code,{children:'"pvss"'})," indicating that the beacon implementing a ",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"PVSS (publicly verifiable secret sharing) scheme"})," should be used."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"20"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"10"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.pvss_parameters.commit_interval"})})," is the duration of the Commit phase (in blocks). It will be set to ",(0,i.jsx)(n.code,{children:"400"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.pvss_parameters.reveal_interval"})})," is the duration of the Reveal phase (in blocks). It will be set to ",(0,i.jsx)(n.code,{children:"196"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.pvss_parameters.transition_delay"})})," is the duration of the post Reveal phase (in blocks). It will be set to ",(0,i.jsx)(n.code,{children:"4"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"governance",children:(0,i.jsx)(n.strong,{children:"Governance"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance"})})," object contains parameters controlling the network's ",(0,i.jsx)(n.a,{href:"/core/consensus/services/governance",children:"on-chain governance"})," introduced in the Cobalt upgrade**.**"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:'"10000000000000"'})," (i.e. 10,000,000,000,000 base units, or 10,000 ROSE tokens)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"168"}),", which is expected to be approximately 7 days."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"75"})," (i.e. 75%)."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.threshold"})})," is the minimum percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes in order for a proposal to be accepted. It will be set to ",(0,i.jsx)(n.code,{children:"90"}),"(i.e. 90%)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["It will be set to ",(0,i.jsx)(n.code,{children:"336"}),", which is expected to be approximately 14 days."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"192"}),", which is expected to be approximately 8 days."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"consensus",children:(0,i.jsx)(n.strong,{children:"Consensus"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_evidence_num"})})," parameter will be removed and replaced by the"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_evidence_size"})})," parameter."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_evidence_size"})})," is a new parameter specifying the maximum evidence size in bytes. It replaces the ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_evidence_num"})})," parameter and will be set to",(0,i.jsx)(n.code,{children:"51200"})," (51,200 bytes, or 50 kB)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_interval"})})," parameter controls the interval (in blocks) on which state checkpoints should be taken. It will be set to ",(0,i.jsx)(n.code,{children:"10000"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_num_kept"})})," parameter specifies the number of past state checkpoints to keep. It will be set to ",(0,i.jsx)(n.code,{children:"2"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"8388608"})," (8,388,608 bytes, or 8 MB)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"other",children:"Other"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"Mainnet genesis file"})," to include the Oasis network's genesis quote: ",(0,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis Community Member Daniyar Borangaziyev]:"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"runtime-state-root-migration",children:"Runtime State Root Migration"}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, each runtime's state root will need to be updated for the ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#runtime-operators",children:"runtime storage migration"})," that is performed during this upgrade."]}),"\n",(0,i.jsxs)(n.p,{children:["At this time, there is only one active runtime on the Mainnet, namely Second State's Oasis Ethereum ParaTime with ID (Base64-encoded) ",(0,i.jsx)(n.code,{children:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wM="}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.runtime_states.<RUNTIME-ID>.state_root"})})," will be set to the (Base64-encoded) migrated state root."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes.[id=<RUNTIME-ID>].genesis.state_root"})})," will be set to the (Base64-encoded) migrated state root."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes.[id=<RUNTIME-ID>].genesis.state"})})," will be set to ",(0,i.jsx)(n.code,{children:"null"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes.[id=<RUNTIME-ID>].genesis.round"})})," will be set to the same value as ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.runtime_states.<RUNTIME-ID>.round"})}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"launch-support",children:"Launch Support"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["For any additional support, please reach out via the ",(0,i.jsxs)(n.a,{href:"/get-involved/",children:[(0,i.jsx)(n.strong,{children:"#nodeoperators"})," Oasis Community Slack channel"]})," with your questions, comments, and feedback related to Cobalt upgrade."]}),"\n",(0,i.jsxs)(n.p,{children:["To follow the network, please use one of the many ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards",children:"community block explorers"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var i=s(6540);const r={},t=i.createContext(r);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/27f9eba8.98e440e3.js b/assets/js/27f9eba8.98e440e3.js new file mode 100644 index 0000000000..54d198ac85 --- /dev/null +++ b/assets/js/27f9eba8.98e440e3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4827],{7220:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var t=o(4848),i=o(8453);const r={},s="Delegation Policy",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/delegation-policy.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},l={},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}];function c(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"delegation-policy",children:"Delegation Policy"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"This page describes the Oasis Protocol Foundation's Delegation Policy."}),"\n",(0,t.jsx)(n.h2,{id:"requirements-for-receiving-delegations",children:"Requirements for Receiving Delegations"}),"\n",(0,t.jsx)(n.h3,{id:"code-of-conduct",children:"Code of Conduct"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Ensure commission rates and commission rate bounds are no greater than 20%."}),"\n",(0,t.jsx)(n.li,{children:"Ensure commission rates are +/- 10% of the weighted median network commission\nrate."}),"\n",(0,t.jsxs)(n.li,{children:["Ensure your entity\u2019s website, social media and/or contact info in the\n",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/metadata-registry",children:"Oasis Metadata Registry"})," is up-to-date."]}),"\n",(0,t.jsx)(n.li,{children:"Do not use 'Oasis' in your entity name, and do not use any Oasis Foundation\nlogos or branding in your entity logo."}),"\n",(0,t.jsx)(n.li,{children:"Refrain from dishonest, fraudulent or malicious behavior."}),"\n",(0,t.jsx)(n.li,{children:"Participate in on-chain governance and network upgrades proposed by Oasis\nFoundation."}),"\n",(0,t.jsx)(n.li,{children:"Be available and coordinate with the node operator community in case of\nunplanned network upgrades."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"If there is any violation of the above Code of Conduct, Oasis Foundation\nreserves the right to revoke your entire delegation."}),"\n",(0,t.jsx)(n.h3,{id:"performance-requirements",children:"Performance Requirements"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Maintain active validator status."}),"\n",(0,t.jsx)(n.li,{children:"Maintain >99% uptime for your validator node as well as Emerald and/or Cipher\nParaTime nodes (if you run them)."}),"\n",(0,t.jsx)(n.li,{children:"Ensure your nodes are upgraded within 1 hour after a planned network upgrade."}),"\n",(0,t.jsx)(n.li,{children:"Ensure your nodes are upgraded within 24 hours after an unplanned network\nupgrade."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"how-to-earn-delegations",children:"How to Earn Delegations?"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Have a meaningful amount of self-delegation and/or delegations from the Oasis\ncommunity."}),"\n",(0,t.jsx)(n.li,{children:"Operate Emerald and/or Cipher ParaTime nodes on Mainnet."}),"\n",(0,t.jsx)(n.li,{children:"Operate validator and/or ParaTime nodes on Testnet"}),"\n",(0,t.jsx)(n.li,{children:"Participate in community discussion on the network\u2019s future roadmap."}),"\n",(0,t.jsx)(n.li,{children:"Actively participate on the Oasis Network Community server on Discord\nand help answer questions from other community members."}),"\n",(0,t.jsx)(n.li,{children:"Build or contribute to tools, services or dApps that benefit developers, node\noperators and/or the overall Oasis community."}),"\n",(0,t.jsx)(n.li,{children:"Contribute code to Oasis projects."}),"\n",(0,t.jsx)(n.li,{children:"Find and report issues related to any of the network protocols and/or their\nimplementations."}),"\n",(0,t.jsx)(n.li,{children:"Demonstrate a track record of successfully operating nodes on other major\nnetworks."}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>a});var t=o(6540);const i={},r=t.createContext(i);function s(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/29c77900.6b41bb76.js b/assets/js/29c77900.6b41bb76.js new file mode 100644 index 0000000000..dc6f268be3 --- /dev/null +++ b/assets/js/29c77900.6b41bb76.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9194],{9865:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=t(4848),o=t(8453);const i={},r="Stake Requirements",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/stake-requirements.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Hardware Requirements",permalink:"/node/run-your-node/prerequisites/hardware-recommendations"},next:{title:"Install the Oasis Node",permalink:"/node/run-your-node/prerequisites/oasis-node"}},d={},c=[{value:"Mainnet",id:"mainnet",level:2},{value:"Testnet",id:"testnet",level:2}];function u(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"stake-requirements",children:"Stake Requirements"}),"\n",(0,s.jsx)(n.p,{children:"This page provides an overview of the stake requirements to become a validator\non the consensus layer of the Oasis Network."}),"\n",(0,s.jsx)(n.h2,{id:"mainnet",children:"Mainnet"}),"\n",(0,s.jsx)(n.p,{children:"To become a validator on the Oasis Network, you will need to have enough\ntokens staked in your escrow account."}),"\n",(0,s.jsx)(n.p,{children:"Currently, you are going to need:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["100 ROSE staked for your entity's registration since that is the\n",(0,s.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"staking thresholds"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["100 ROSE staked for your validator node's registration since that is the\n",(0,s.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"staking thresholds"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["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,s.jsx)(n.a,{href:"https://www.oasisscan.com/validators",children:"Oasis Scan"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["For more information about obtaining information on your entity's account, see\nthe ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#show",children:"Account Get Info"})," doc."]}),"\n",(0,s.jsxs)(n.p,{children:["Staking thresholds may change in the future. Read the\n",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-native-token",children:"native token information"})," to see the current values used by the network."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["To determine if you are eligible to receive a delegation from the Oasis Protocol\nFoundation, see the ",(0,s.jsx)(n.a,{href:"/get-involved/delegation-policy",children:"Delegation Policy"})," document."]})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["The size of the consensus committee (i.e. the validator set) is configured by\nthe ",(0,s.jsxs)(n.a,{href:"/node/genesis-doc#consensus",children:[(0,s.jsx)(n.strong,{children:"max_validators"})," consensus parameter"]}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"testnet",children:"Testnet"}),"\n",(0,s.jsxs)(n.p,{children:["For the Testnet you are going to need TEST tokens. You can receive a limited\nnumber of TEST by using our ",(0,s.jsx)(n.a,{href:"https://faucet.testnet.oasis.io/",children:"Oasis Network Testnet Faucet"}),". For\nmore tokens please contact us at our official ",(0,s.jsx)(n.a,{href:"https://oasis.io/discord",children:"Discord #testnet\nchannel"}),"."]})]})}function l(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var s=t(6540);const o={},i=s.createContext(o);function r(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2c58cae2.660e1450.js b/assets/js/2c58cae2.660e1450.js new file mode 100644 index 0000000000..4029167b9e --- /dev/null +++ b/assets/js/2c58cae2.660e1450.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7460],{2389:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=s(4848),i=s(8453);const o={description:"How to build your first smart contract on Oasis"},r="Prerequisites",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/prerequisites.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},a={},c=[{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) Go",id:"optional-go",level:3},{value:"Oasis CLI Installation",id:"oasis-cli-installation",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,n.jsx)(t.p,{children:"This chapter 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!"}),"\n",(0,n.jsxs)(t.p,{children:["If you already have everything set up, feel free to skip to the ",(0,n.jsx)(t.a,{href:"/dapp/cipher/hello-world",children:"next\nchapter"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"environment-setup",children:"Environment Setup"}),"\n",(0,n.jsx)(t.p,{children:"The following is a list of prerequisites required to start developing using the\nOasis SDK:"}),"\n",(0,n.jsx)(t.h3,{id:"rust",children:(0,n.jsx)(t.a,{href:"https://www.rust-lang.org/",children:"Rust"})}),"\n",(0,n.jsxs)(t.p,{children:["We follow ",(0,n.jsx)(t.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust upstream's recommendation"})," on using\n",(0,n.jsx)(t.a,{href:"https://rustup.rs/",children:"rustup"})," to install and manage Rust versions."]}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"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."})}),"\n",(0,n.jsx)(t.p,{children:"Install it by running:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n"})}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsxs)(t.p,{children:["If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,n.jsxs)(t.a,{href:"https://rust-lang.github.io/rustup/installation/other.html",children:["download ",(0,n.jsx)(t.code,{children:"rustup-init"})," executable for your platform"]}),"\nand run it manually."]})}),"\n",(0,n.jsxs)(t.p,{children:["This will run ",(0,n.jsx)(t.code,{children:"rustup-init"})," which will download and install the latest stable\nversion of Rust on your system."]}),"\n",(0,n.jsx)(t.h4,{id:"rust-toolchain-version",children:"Rust Toolchain Version"}),"\n",(0,n.jsxs)(t.p,{children:["The version of the Rust toolchain we use in the Oasis SDK is specified in the\n",(0,n.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,n.jsx)(t.code,{children:"rust-toolchain.toml"})})," file."]}),"\n",(0,n.jsxs)(t.p,{children:["The rustup-installed versions of ",(0,n.jsx)(t.code,{children:"cargo"}),", ",(0,n.jsx)(t.code,{children:"rustc"})," and other tools will\n",(0,n.jsx)(t.a,{href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence",children:"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,n.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,n.jsx)(t.code,{children:"rust-toolchain.toml"})}),"\nfile to your project's top-level directory as well."]}),"\n",(0,n.jsx)(t.p,{children:"To install the appropriate version of the Rust toolchain, make sure you are\nin the project directory and run:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"rustup show\n"})}),"\n",(0,n.jsx)(t.p,{children:"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"...\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"})}),"\n",(0,n.jsxs)(t.h3,{id:"optional-go",children:["(OPTIONAL) ",(0,n.jsx)(t.a,{href:"https://golang.org",children:"Go"})]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.em,{children:"Required if you want to use the Go Client SDK."})}),"\n",(0,n.jsxs)(t.p,{children:["At least version ",(0,n.jsx)(t.strong,{children:"1.20.2"})," is required. If your distribution provides a\nnew-enough version of Go, just use that."]}),"\n",(0,n.jsx)(t.p,{children:"Otherwise:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"install the Go version provided by your distribution,"}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:[(0,n.jsxs)(t.a,{href:"https://tip.golang.org/doc/code.html#GOPATH",children:["ensure ",(0,n.jsx)(t.code,{children:"$GOPATH/bin"})," is in your ",(0,n.jsx)(t.code,{children:"PATH"})]}),","]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://golang.org/doc/install#extra_versions",children:"install the desired version of Go"}),", e.g. 1.20.5, with2"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"go get golang.org/dl/go1.20.2\ngo1.20.5 downloa2\n"})}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"oasis-cli-installation",children:"Oasis CLI Installation"}),"\n",(0,n.jsxs)(t.p,{children:["The rest of the guide uses the Oasis CLI as an easy way to interact with the\nsmart contract. You can use ",(0,n.jsx)(t.a,{href:"https://github.com/oasisprotocol/cli/releases",children:"one of the binary releases"})," or\n",(0,n.jsx)(t.a,{href:"https://github.com/oasisprotocol/cli/blob/master/README.md",children:"compile it yourself"}),"."]})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>l});var n=s(6540);const i={},o=n.createContext(i);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2c7b4985.4b0cfbe8.js b/assets/js/2c7b4985.4b0cfbe8.js new file mode 100644 index 0000000000..2b999efd18 --- /dev/null +++ b/assets/js/2c7b4985.4b0cfbe8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5365],{651:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"High-Level Components","slug":"core/high-level-components","permalink":"/core/high-level-components","sidebar":"oasisCore","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/2d94235f.68387768.js b/assets/js/2d94235f.68387768.js new file mode 100644 index 0000000000..07c9658e60 --- /dev/null +++ b/assets/js/2d94235f.68387768.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2230],{5284:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>p});var s=o(4848),n=o(8453);const r={},i="Tools & Services",a={id:"dapp/tools/README",title:"Tools & Services",description:"Oasis integrates with a number of services and provides tooling support for",source:"@site/docs/dapp/tools/README.md",sourceDirName:"dapp/tools",slug:"/dapp/tools/",permalink:"/dapp/tools/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/tools/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Writing dApps on Emerald",permalink:"/dapp/emerald/writing-dapps-on-emerald"},next:{title:"Integrating BAND Oracle",permalink:"/dapp/tools/band"}},c={},p=[];function d(e){const t={a:"a",em:"em",h1:"h1",p:"p",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"tools--services",children:"Tools & Services"}),"\n",(0,s.jsxs)(t.p,{children:["Oasis integrates with a number of services and provides tooling support for\ndevelopers using ",(0,s.jsx)(t.a,{href:"https://remix.run/docs/en/main",children:"Remix"})," (",(0,s.jsx)(t.em,{children:"unencrypted transactions only"}),"), ",(0,s.jsx)(t.a,{href:"/dapp/sapphire/guide#contract-verification",children:"Sourcify"}),",\n",(0,s.jsx)(t.a,{href:"/dapp/sapphire/guide#running-a-private-oasis-network-locally",children:"Docker"}),", and more. Please reach out to us on ",(0,s.jsx)(t.a,{href:"https://oasis.io/discord",children:"Discord"})," if\nyou are using a tool that has problems integrating with Oasis."]})]})}function l(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>a});var s=o(6540);const n={},r=s.createContext(n);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2e8d1096.72b543bd.js b/assets/js/2e8d1096.72b543bd.js new file mode 100644 index 0000000000..b2c12bf14e --- /dev/null +++ b/assets/js/2e8d1096.72b543bd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2458],{5795:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var t=s(4848),i=s(8453);const o={},r="ADR 0003: Consensus/Runtime Token Transfer",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0003-consensus-runtime-token-transfer.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},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:"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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0003-consensusruntime-token-transfer",children:"ADR 0003: Consensus/Runtime Token Transfer"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2020-09-16: Beneficiary allowance, add message results"}),"\n",(0,t.jsx)(n.li,{children:"2020-09-08: Initial draft"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Accepted"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"Introducing such a mechanism would allow the consensus layer tokens to be used\ninside runtimes for various functions. This ADR proposes such a mechanism."}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"On a high level, this proposal adds support for consensus/runtime token\ntransfers as follows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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,t.jsx)(n.a,{href:"https://eips.ethereum.org/EIPS/eip-20",children:"ERC-20 Token Standard"}),".\nPreviously such functionality was already present but was removed in\n",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/2021",children:"oasis-core#2021"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"addresses",children:"Addresses"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following new address context for the runtime\naccounts:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"oasis-core/address: runtime\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Initial version for the address context is ",(0,t.jsx)(n.code,{children:"0"}),". To derive the address, the\nstandard address derivation scheme is used, with the runtime's 32-byte\nidentifier used as the ",(0,t.jsx)(n.code,{children:"data"})," part."]}),"\n",(0,t.jsx)(n.h3,{id:"state",children:"State"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces/updates the following consensus state in the staking\nmodule:"}),"\n",(0,t.jsx)(n.h4,{id:"general-accounts",children:"General Accounts"}),"\n",(0,t.jsx)(n.p,{children:"The general account data structure is modified to include an additional field\nstoring the allowances as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type GeneralAccount struct {\n // ... existing fields omitted ...\n\n Allowances map[Address]quantity.Quantity `json:"allowances,omitempty"`\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"transaction-methods",children:"Transaction Methods"}),"\n",(0,t.jsx)(n.p,{children:"This proposal adds the following new transaction methods in the staking module:"}),"\n",(0,t.jsx)(n.h4,{id:"allow",children:"Allow"}),"\n",(0,t.jsx)(n.p,{children:"Allow enables an account holder to set an allowance for a beneficiary."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"staking.Allow\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Body:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type Allow struct {\n Beneficiary Address `json:"beneficiary"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"beneficiary"})," specifies the beneficiary account address."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"amount_change"})," specifies the absolute value of the amount of base units to\nchange the allowance for."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"negative"})," specifies whether the ",(0,t.jsx)(n.code,{children:"amount_change"})," should be subtracted instead\nof added."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The transaction signer implicitly specifies the general account. Upon executing\nthe allow the following actions are performed:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If either the ",(0,t.jsx)(n.code,{children:"disable_transfers"})," staking consensus parameter is set to ",(0,t.jsx)(n.code,{children:"true"}),"\nor the ",(0,t.jsx)(n.code,{children:"max_allowances"})," staking consensus parameter is set to zero, the method\nfails with ",(0,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["It is checked whether either the transaction signer address or the\n",(0,t.jsx)(n.code,{children:"beneficiary"})," address are reserved. If any are reserved, the method fails with\n",(0,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Address specified by ",(0,t.jsx)(n.code,{children:"beneficiary"})," is compared with the transaction signer\naddress. If the addresses are the same, the method fails with\n",(0,t.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The account indicated by the signer is loaded."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"ErrTooManyAllowances"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The set of allowances is updated so that the allowance is updated as specified\nby ",(0,t.jsx)(n.code,{children:"amount_change"}),"/",(0,t.jsx)(n.code,{children:"negative"}),". In case the change would cause the allowance to\nbe equal to zero or negative, the allowance is removed."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The account is saved."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The corresponding ",(0,t.jsx)(n.code,{children:"AllowanceChangeEvent"})," is emitted with the following\nstructure:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["Where ",(0,t.jsx)(n.code,{children:"allowance"})," contains the new total allowance, the ",(0,t.jsx)(n.code,{children:"amount_change"}),"\ncontains the absolute amount the allowance has changed for and ",(0,t.jsx)(n.code,{children:"negative"}),"\nspecifies whether the allowance has been reduced rather than increased. The\nevent is emitted even if the new allowance is zero."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"withdraw",children:"Withdraw"}),"\n",(0,t.jsx)(n.p,{children:"Withdraw enables a beneficiary to withdraw from the given account."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"staking.Withdraw\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Body:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type Withdraw struct {\n From Address `json:"from"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"from"})," specifies the account address to withdraw from."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"amount"})," specifies the amount of base units to withdraw."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The transaction signer implicitly specifies the destination general account.\nUpon executing the withdrawal the following actions are performed:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If either the ",(0,t.jsx)(n.code,{children:"disable_transfers"})," staking consensus parameter is set to ",(0,t.jsx)(n.code,{children:"true"}),"\nor the ",(0,t.jsx)(n.code,{children:"max_allowances"})," staking consensus parameter is set to zero, the method\nfails with ",(0,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["It is checked whether either the transaction signer address or the\n",(0,t.jsx)(n.code,{children:"from"})," address are reserved. If any are reserved, the method fails with\n",(0,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Address specified by ",(0,t.jsx)(n.code,{children:"from"})," is compared with the transaction signer address.\nIf the addresses are the same, the method fails with ",(0,t.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The source account indicated by ",(0,t.jsx)(n.code,{children:"from"})," is loaded."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The destination account indicated by the transaction signer is loaded."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"amount"})," is deducted from the source general account balance. If this would\ncause the balance to go negative, the method fails with\n",(0,t.jsx)(n.code,{children:"ErrInsufficientBalance"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"amount"})," is added to the destination general account balance."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Both source and destination accounts are saved."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The corresponding ",(0,t.jsx)(n.code,{children:"TransferEvent"})," is emitted."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The corresponding ",(0,t.jsx)(n.code,{children:"AllowanceChangeEvent"})," is emitted with the updated\nallowance."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"queries",children:"Queries"}),"\n",(0,t.jsxs)(n.p,{children:["This proposal adds the following new query methods in the staking module by\nupdating the ",(0,t.jsx)(n.code,{children:"staking.Backend"})," interface as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"messages",children:"Messages"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Each message has an associated gas cost that needs to be paid by the\nsubmitter (e.g. as part of the ",(0,t.jsx)(n.code,{children:"roothash.ExecutorCommit"})," method call). The gas\ncost is split among the committee members."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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)."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Messages are serialized using a sum type describing all possible messages,\nwhere each message type is assigned a ",(0,t.jsx)(n.em,{children:"field name"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type Message struct {\n Message1 *Message1 `json:"message1,omitempty"`\n Message2 *Message2 `json:"message2,omitempty"`\n // ...\n}\n'})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["All messages are versioned by embeding the ",(0,t.jsx)(n.code,{children:"cbor.Versioned"})," structure which\nprovides a single ",(0,t.jsx)(n.code,{children:"uint16"})," field ",(0,t.jsx)(n.code,{children:"v"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"A change is made to how messages are included in commitments, to reduce the\nsize of submitted transactions."}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"ComputeResultsHeader"})," is changed so that the ",(0,t.jsx)(n.code,{children:"Messages"})," field is replaced\nwith a ",(0,t.jsx)(n.code,{children:"MessagesHash"})," field containing a hash of the CBOR-encoded messages\nemitted by the runtime."]}),"\n",(0,t.jsxs)(n.p,{children:["At the same time ",(0,t.jsx)(n.code,{children:"ComputeBody"})," is changed to include an additional field\n",(0,t.jsx)(n.code,{children:"Messages"})," as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type ComputeBody struct {\n // ... existing fields omitted ...\n Messages []*block.Message `json:"messages,omitempty"`\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"Messages"})," field must only be populated in the commitment by the\ntransaction scheduler and must match the ",(0,t.jsx)(n.code,{children:"MessagesHash"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If any of the included messages is deemed ",(0,t.jsx)(n.em,{children:"malformed"}),", the round fails and the\nruntime state is not updated."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"In order to support messages that fail to execute, a new roothash event is\nemitted for each executed message:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type MessageEvent struct {\n Index uint32 `json:"index,omitempty"`\n Module string `json:"module,omitempty"`\n Code uint32 `json:"code,omitempty"`\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Where the ",(0,t.jsx)(n.code,{children:"index"})," specifies the index of the executed message and the ",(0,t.jsx)(n.code,{children:"module"}),"\nand ",(0,t.jsx)(n.code,{children:"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)."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following runtime messages:"}),"\n",(0,t.jsx)(n.h4,{id:"staking-method-call",children:"Staking Method Call"}),"\n",(0,t.jsx)(n.p,{children:"The staking method call message enables a runtime to call one of the supported\nstaking module methods."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Field name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"staking\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Body:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type StakingMessage struct {\n cbor.Versioned\n\n Transfer *staking.Transfer `json:"transfer,omitempty"`\n Withdraw *staking.Withdraw `json:"withdraw,omitempty"`\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"v"})," must be set to ",(0,t.jsx)(n.code,{children:"0"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"transfer"})," indicates that the ",(0,t.jsx)(n.code,{children:"staking.Transfer"})," method should be executed."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"withdraw"})," indicates that the ",(0,t.jsx)(n.code,{children:"staking.Withdraw"})," method should be executed."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Exactly one of the supported method fields needs to be non-nil, otherwise the\nmessage is considered malformed."}),"\n",(0,t.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,t.jsx)(n.h4,{id:"staking",children:"Staking"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following new consensus parameters in the staking\nmodule:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"max_allowances"})," (uint32) specifies the maximum number of allowances an\naccount can store. Zero means that allowance functionality is disabled."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"roothash",children:"Roothash"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following new consensus parameters in the roothash\nmodule:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"0"})," disables the use of runtime messages."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"runtime-host-protocol",children:"Runtime Host Protocol"}),"\n",(0,t.jsx)(n.p,{children:"This proposal modifies the runtime host protocol as follows:"}),"\n",(0,t.jsx)(n.h4,{id:"host-to-runtime-initialization",children:"Host to Runtime: Initialization"}),"\n",(0,t.jsxs)(n.p,{children:["The existing ",(0,t.jsx)(n.code,{children:"RuntimeInfoRequest"})," message body is updated to contain a field\ndenoting the consensus backend used by the host and its consensus protocol\nversion as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'type RuntimeInfoRequest struct {\n ConsensusBackend string `json:"consensus_backend"`\n ConsensusProtocolVersion uint64 `json:"consensus_protocol_version"`\n\n // ... existing fields omitted ...\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h4,{id:"host-to-runtime-transaction-batch-dispatch",children:"Host to Runtime: Transaction Batch Dispatch"}),"\n",(0,t.jsxs)(n.p,{children:["The existing ",(0,t.jsx)(n.code,{children:"RuntimeExecuteTxBatchRequest"})," and ",(0,t.jsx)(n.code,{children:"RuntimeCheckTxBatchRequest"}),"\nmessage bodies are updated to include the consensus layer light block at the\nlast finalized round height (specified in ",(0,t.jsx)(n.code,{children:".Block.Header.Round"}),") and the list of\n",(0,t.jsx)(n.code,{children:"MessageEvent"}),"s emitted while processing the runtime messages emitted in the\nprevious round as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.p,{children:"The information from the light block can be used to access consensus layer\nstate."}),"\n",(0,t.jsx)(n.h4,{id:"runtime-to-host-read-only-storage-access",children:"Runtime to Host: Read-only Storage Access"}),"\n",(0,t.jsxs)(n.p,{children:["The existing ",(0,t.jsx)(n.code,{children:"HostStorageSyncRequest"})," message body is updated to include an\nendpoint identifier as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["The newly introduced ",(0,t.jsx)(n.code,{children:"endpoint"})," field can take the following values:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"consensus"})," denotes the consensus state endpoint, providing access to\nconsensus state."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"rust-runtime-support-library",children:"Rust Runtime Support Library"}),"\n",(0,t.jsxs)(n.p,{children:["The Rust runtime support library (",(0,t.jsx)(n.code,{children:"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:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Decoding light blocks."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Decoding staking-related state structures."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The Tendermint-specific functionality should be part of a separate crate."}),"\n",(0,t.jsx)(n.h3,{id:"expected-userconsensusruntime-flow",children:"Expected User/Consensus/Runtime Flow"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Scenario:"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Flow:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Account holder sets an allowance of 50 tokens for runtime X by submitting an\nallow transaction to the consensus layer."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Account holder submits a runtime transaction that performs some action costing\n50 tokens."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Account holder's runtime transaction is executed in runtime X round R:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtime X emits a message to transfer 50 tokens from the user's account to\nthe runtime's own account."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"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."})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtime X submits commitments to the consensus layer."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"When finalizing round R for runtime X, the consensus layer transfers 50 tokens\nfrom the account holder's account to the runtime X account."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Corresponding message result event is emitted, indicating success."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"When runtime X processes round R+1, the runtime receives the set of emitted\nmessage result events."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtime X processes message result events, using the index field to match the\ncorresponding pending action and executes whatever action it queued."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"In case the message result event would indicate failure, the pending action\ncan be pruned."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Consensus layer tokens can be transferred into and out of runtimes, enabling\nmore use cases."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Any tokens must be explicitly made available to the runtime which limits the\ndamage from badly written or malicious runtimes."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Account holders can change the allowance at any time."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Account holders may mistakenly transfer tokens directly into a runtime account\nwhich may cause such tokens to be locked forever."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The runtime must handle all message results in the next round as otherwise it\ncannot easily get past messages."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://eips.ethereum.org/EIPS/eip-20",children:"ERC-20 Token Standard"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/2021",children:"oasis-core#2021"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>a});var t=s(6540);const i={},o=t.createContext(i);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/2ea67962.8100332f.js b/assets/js/2ea67962.8100332f.js new file mode 100644 index 0000000000..ba3d948095 --- /dev/null +++ b/assets/js/2ea67962.8100332f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5653],{2048:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var s=i(4848),o=i(8453);const t={},r="Install the Oasis Node",d={id:"node/run-your-node/prerequisites/oasis-node",title:"Install the Oasis Node",description:"The Oasis node is a binary that is created from the [Oasis Core] repository's",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/oasis-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},a={},l=[{value:"Set up the Oasis Node's Working Directory",id:"set-up-the-oasis-nodes-working-directory",level:2},{value:"Setting Up the <code>/node</code> Directory",id:"setting-up-the-node-directory",level:3},{value:"Copying the Genesis File to the server",id:"copying-the-genesis-file-to-the-server",level:3},{value:"Obtain the <code>oasis-node</code> Binary",id:"obtain-the-oasis-node-binary",level:2},{value:"Downloading a Binary Release",id:"downloading-a-binary-release",level:3},{value:"Building From Source",id:"building-from-source",level:3},{value:"Adding <code>oasis-node</code> Binary to <code>PATH</code>",id:"adding-oasis-node-binary-to-path",level:3},{value:"Running ParaTimes",id:"running-paratimes",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"install-the-oasis-node",children:"Install the Oasis Node"}),"\n",(0,s.jsxs)(n.p,{children:["The Oasis node is a binary that is created from the ",(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"Oasis Core"})," repository's\n",(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go",children:(0,s.jsx)(n.code,{children:"go/"})})," directory. It is a single executable that contains the logic for running\nyour node in various ",(0,s.jsx)(n.a,{href:"/node/#validator-and-paratime-nodes",children:"roles"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsx)(n.p,{children:"The Oasis Node is currently only supported on x86_64 Linux systems."})}),"\n",(0,s.jsx)(n.h2,{id:"set-up-the-oasis-nodes-working-directory",children:"Set up the Oasis Node's Working Directory"}),"\n",(0,s.jsx)(n.p,{children:"Before we install the Oasis node we need to ensure that we have a place to\nstore necessary files."}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["We will reference the working directory on the server as ",(0,s.jsx)(n.code,{children:"/node"}),"\nthroughout the documentation."]})}),"\n",(0,s.jsxs)(n.h3,{id:"setting-up-the-node-directory",children:["Setting Up the ",(0,s.jsx)(n.code,{children:"/node"})," Directory"]}),"\n",(0,s.jsxs)(n.p,{children:["In the ",(0,s.jsx)(n.code,{children:"/node"})," directory, create the following subdirectories:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"etc/"}),": this is to store the configuration and ",(0,s.jsx)(n.code,{children:"entity.json"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"data/"}),": this is to store the node's data"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"bin/"}),": this is to store the ",(0,s.jsx)(n.code,{children:"oasis-node"})," binary"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"runtimes/"}),": this is to store the ParaTime ",(0,s.jsx)(n.code,{children:".orc"})," bundles"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["You can make this directory structure with the ",(0,s.jsx)(n.strong,{children:"corresponding permissions"})," by\nexecuting the following command:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"mkdir -m700 -p /node/{etc,bin,runtimes,data}\n"})}),"\n",(0,s.jsx)(n.h3,{id:"copying-the-genesis-file-to-the-server",children:"Copying the Genesis File to the server"}),"\n",(0,s.jsxs)(n.p,{children:["The latest Genesis file can be found in the Network Parameters page (",(0,s.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),",\n",(0,s.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),"). You should download the latest ",(0,s.jsx)(n.code,{children:"genesis.json"})," file and\ncopy it to ",(0,s.jsx)(n.code,{children:"/node/etc/genesis.json"})," on the ",(0,s.jsx)(n.code,{children:"server"}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"obtain-the-oasis-node-binary",children:["Obtain the ",(0,s.jsx)(n.code,{children:"oasis-node"})," Binary"]}),"\n",(0,s.jsx)(n.h3,{id:"downloading-a-binary-release",children:"Downloading a Binary Release"}),"\n",(0,s.jsxs)(n.p,{children:["For convenience, we provide binaries that have been built by the Oasis Protocol\nFoundation. Links to the binaries are provided in the Network Parameters page\n(",(0,s.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,s.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,s.jsx)(n.h3,{id:"building-from-source",children:"Building From Source"}),"\n",(0,s.jsx)(n.p,{children:"Although highly suggested, building from source is currently beyond the scope of\nthis documentation."}),"\n",(0,s.jsxs)(n.p,{children:["See ",(0,s.jsx)(n.a,{href:"../../../core/development-setup/build-environment-setup-and-building",children:"Oasis Core's Build Environment Setup and Building"}),"\ndocumentation for more details."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["The code in the current ",(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/",children:(0,s.jsx)(n.code,{children:"master"})})," branch may be incompatible with the code used\nby other nodes on the network. Make sure to use the version specified on the\nNetwork Parameters page (",(0,s.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,s.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]})}),"\n",(0,s.jsxs)(n.h3,{id:"adding-oasis-node-binary-to-path",children:["Adding ",(0,s.jsx)(n.code,{children:"oasis-node"})," Binary to ",(0,s.jsx)(n.code,{children:"PATH"})]}),"\n",(0,s.jsxs)(n.p,{children:["To install the ",(0,s.jsx)(n.code,{children:"oasis-node"})," binary next to your Oasis node data directory,\ncopy/symlink it to e.g. ",(0,s.jsx)(n.code,{children:"/node/bin"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To install the ",(0,s.jsx)(n.code,{children:"oasis-node"})," binary for the current user, copy/symlink it to\n",(0,s.jsx)(n.code,{children:"~/.local/bin"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To install the ",(0,s.jsx)(n.code,{children:"oasis-node"})," binary for all users of the system, copy it to\n",(0,s.jsx)(n.code,{children:"/usr/local/bin"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"running-paratimes",children:"Running ParaTimes"}),"\n",(0,s.jsxs)(n.p,{children:["If you intend to ",(0,s.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"run a ParaTime node"})," you will need to\nadditionally install the following software packages:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://github.com/projectatomic/bubblewrap",children:"Bubblewrap"})," 0.4.1+, needed for\ncreating process sandboxes."]}),"\n",(0,s.jsx)(n.p,{children:"On Ubuntu 20.04+, you can install it with:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"sudo apt install bubblewrap\n"})}),"\n",(0,s.jsx)(n.p,{children:"On Fedora, you can install it with:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"sudo dnf install bubblewrap\n"})}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>d});var s=i(6540);const o={},t=s.createContext(o);function r(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/30129561.7b9f34da.js b/assets/js/30129561.7b9f34da.js new file mode 100644 index 0000000000..b61e9dfa4c --- /dev/null +++ b/assets/js/30129561.7b9f34da.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1662],{8931:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var s=i(4848),n=i(8453);const o={},a="Runtime Host Protocol",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/runtime-host-protocol.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime Layer",permalink:"/core/runtime/"},next:{title:"Runtime IDs",permalink:"/core/runtime/identifiers"}},c={},l=[{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}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"runtime-host-protocol",children:"Runtime Host Protocol"}),"\n",(0,s.jsx)(t.p,{children:"The Runtime Host Protocol (RHP) is a simple RPC protocol which is used to\ncommunicate between a runtime and an Oasis Core Compute Node."}),"\n",(0,s.jsx)(t.h2,{id:"transport",children:"Transport"}),"\n",(0,s.jsxs)(t.p,{children:["The RHP assumes a reliable byte stream oriented transport underneath. The only\ncurrent implementation uses AF_LOCAL sockets and ",(0,s.jsx)(t.a,{href:"https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#streams",children:"Fortanix ABI streams"})," backed\nby shared memory to communicate with runtimes inside Intel SGX enclaves."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Runtime Execution",src:i(1029).A+""})}),"\n",(0,s.jsx)(t.h2,{id:"framing",children:"Framing"}),"\n",(0,s.jsxs)(t.p,{children:["All RHP messages use simple length-value framing with the value being encoded\nusing ",(0,s.jsx)(t.a,{href:"/core/encoding",children:"canonical CBOR"}),". The frames are serialized on the wire as follows:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:"[4-byte message length (big endian)] [CBOR-serialized message]\n"})}),"\n",(0,s.jsx)(t.p,{children:"Maximum allowed message size is 16 MiB."}),"\n",(0,s.jsx)(t.h2,{id:"messages",children:"Messages"}),"\n",(0,s.jsxs)(t.p,{children:["Each ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Message",children:"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."]}),"\n",(0,s.jsxs)(t.p,{children:["See the API reference (",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body",children:"Go"}),", ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime/src/types.rs",children:"Rust"}),") for a list of all supported message bodies.\nIn case the request resulted in an error, the special ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Error",children:(0,s.jsx)(t.code,{children:"Error"})})," response body\nmust be used."]}),"\n",(0,s.jsx)(t.h2,{id:"operation",children:"Operation"}),"\n",(0,s.jsx)(t.p,{children:"RHP allows two forms of communication:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"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,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body",children:"messages"})," are prefixed with ",(0,s.jsx)(t.code,{children:"Runtime"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Runtime-to-host"})," where the runtime submits requests to the host and the\nhost provides responses. All such request ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Body",children:"messages"})," are prefixed with\n",(0,s.jsx)(t.code,{children:"Host"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"In its lifetime, from connection establishment to its termination, the RHP\nconnection goes through the following states:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"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,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime",children:"Rust implementation"})," only supports runtime\nmode while the ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol",children:"Go implementation"})," can be initialized in either mode by using\neither ",(0,s.jsxs)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#Connection",children:[(0,s.jsx)(t.code,{children:"InitHost"})," or ",(0,s.jsx)(t.code,{children:"InitGuest"})]}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"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,s.jsx)(t.em,{children:"ready"})," state. If the initialization failed, it will\ninstead transition into ",(0,s.jsx)(t.em,{children:"closed"})," state."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"Ready"})," is the state when the connection can be used to exchange messages in\neither direction."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"Closed"})," is the state of the connection after it is considered closed. No\nmessages may be exchanged at this point."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"If either the runtime or the host generates an invalid message, either end may\nterminate the connection (and/or the runtime process)."}),"\n",(0,s.jsx)(t.h3,{id:"initialization",children:"Initialization"}),"\n",(0,s.jsxs)(t.p,{children:["Before a connection can be used, it must be initialized as either representing\nthe runtime end or the host (compute node) end. The ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime",children:"Rust implementation"})," only\nsupports being initialized as the runtime and the ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol",children:"Go implementation"})," is\ncurrently only used as the host. If one uses the ",(0,s.jsxs)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime",children:[(0,s.jsx)(t.code,{children:"oasis-core-runtime"})," crate"]}),"\nto build a runtime, initialization is handled automatically."]}),"\n",(0,s.jsx)(t.p,{children:"The initialization procedure is driven by the host and it proceeds as follows:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The host sends ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeInfoRequest",children:(0,s.jsx)(t.code,{children:"RuntimeInfoRequest"})})," providing the runtime with its\n",(0,s.jsx)(t.a,{href:"/core/runtime/identifiers",children:"designated identifier"}),". The identifier comes from the ",(0,s.jsx)(t.a,{href:"/core/consensus/services/registry#runtimes",children:"registry service"})," in\nthe consensus layer."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The runtime must reply with a ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeInfoResponse",children:(0,s.jsx)(t.code,{children:"RuntimeInfoResponse"})})," specifying its own\nversion and the version of the runtime host protocol that it supports. If the\nprotocol version is incompatible, initialization fails."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h3,{id:"remote-attestation",children:"Remote Attestation"}),"\n",(0,s.jsxs)(t.p,{children:["When a runtime is executed in a TEE, it must perform remote attestation\nimmediately after initialization. The ",(0,s.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/runtime",children:"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."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.em,{children:"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."})}),"\n",(0,s.jsx)(t.p,{children:"Upon initialization the host performs the following steps:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"[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."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The host sends ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakInitRequest",children:(0,s.jsx)(t.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"The initialization then proceeds as follows, with the following steps also\nbeing performed as part of periodic re-attestation:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The host sends ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakReportRequest",children:(0,s.jsx)(t.code,{children:"RuntimeCapabilityTEERakReportRequest"})})," requesting the runtime\nto generate an attestation report."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The runtime prepares an attestation report based on the information provided\nduring the first initialization step. It responds with\n",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakReportResponse",children:(0,s.jsx)(t.code,{children:"RuntimeCapabilityTEERakReportResponse"})})," containing the public part of the\nRAK, the attestation report (binding RAK to the TEE identity) and a replay\nprotection nonce."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"[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,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCapabilityTEERakAvrRequest",children:(0,s.jsx)(t.code,{children:"RuntimeCapabilityTEERakAvrRequest"})}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.em,{children:"[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."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["The compute node will submit remote attestation information to the consensus\n",(0,s.jsx)(t.a,{href:"/core/consensus/services/registry#runtimes",children:"registry service"})," as part of its ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node",children:"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."]}),"\n",(0,s.jsx)(t.h3,{id:"host-to-runtime",children:"Host-to-runtime"}),"\n",(0,s.jsx)(t.p,{children:"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)."}),"\n",(0,s.jsx)(t.h4,{id:"transaction-batch-dispatch",children:"Transaction Batch Dispatch"}),"\n",(0,s.jsxs)(t.p,{children:["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,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeCheckTxBatchRequest",children:(0,s.jsx)(t.code,{children:"RuntimeCheckTxBatchRequest"})})," message. The runtime\nshould perform the required non-expensive checks, but should not fully execute\nthe transactions."]}),"\n",(0,s.jsxs)(t.p,{children:["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,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeExecuteTxBatchRequest",children:(0,s.jsx)(t.code,{children:"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)."]}),"\n",(0,s.jsx)(t.h4,{id:"enclaverpc",children:"EnclaveRPC"}),"\n",(0,s.jsx)(t.h4,{id:"key-manager-policy-update",children:"Key Manager Policy Update"}),"\n",(0,s.jsx)(t.h4,{id:"abort",children:"Abort"}),"\n",(0,s.jsxs)(t.p,{children:["The host can request the runtime to abort processing the current batch by\nsending the ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeAbortRequest",children:(0,s.jsx)(t.code,{children:"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."]}),"\n",(0,s.jsx)(t.p,{children:"In case the runtime does not reply quickly enough the host may terminate the\nruntime and start a new instance."}),"\n",(0,s.jsx)(t.h4,{id:"extensions",children:"Extensions"}),"\n",(0,s.jsxs)(t.p,{children:["RHP provides a way for runtimes to support custom protocol extensions by\nutilizing the ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeLocalRPCCallRequest",children:(0,s.jsx)(t.code,{children:"RuntimeLocalRPCCallRequest"})})," and ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#RuntimeLocalRPCCallResponse",children:(0,s.jsx)(t.code,{children:"RuntimeLocalRPCCallResponse"})}),"\nmessages."]}),"\n",(0,s.jsx)(t.h3,{id:"runtime-to-host",children:"Runtime-to-host"}),"\n",(0,s.jsx)(t.p,{children:"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)."}),"\n",(0,s.jsx)(t.h4,{id:"enclaverpc-to-remote-endpoints",children:"EnclaveRPC to Remote Endpoints"}),"\n",(0,s.jsx)(t.h4,{id:"read-only-runtime-storage-access",children:"Read-only Runtime Storage Access"}),"\n",(0,s.jsxs)(t.p,{children:["The host exposes the ",(0,s.jsx)(t.a,{href:"/core/mkvs#read-syncer",children:"MKVS read syncer"})," interface (via the\n",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostStorageSyncRequest",children:(0,s.jsx)(t.code,{children:"HostStorageSyncRequest"})})," message) to enable runtimes read-only access to\nglobal runtime storage."]}),"\n",(0,s.jsx)(t.h4,{id:"untrusted-local-storage-access",children:"Untrusted Local Storage Access"}),"\n",(0,s.jsxs)(t.p,{children:["The host exposes a simple key-value local store that can be used by the runtime\nto store arbitrary instance-specific data. ",(0,s.jsx)(t.strong,{children:"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."})]}),"\n",(0,s.jsxs)(t.p,{children:["There are two local storage operations, namely get and set, exposed via\n",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostLocalStorageGetRequest",children:(0,s.jsx)(t.code,{children:"HostLocalStorageGetRequest"})})," and ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/host/protocol?tab=doc#HostLocalStorageSetRequest",children:(0,s.jsx)(t.code,{children:"HostLocalStorageSetRequest"})})," messages,\nrespectively."]})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1029:(e,t,i)=>{i.d(t,{A:()=>s});const s="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+"},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>r});var s=i(6540);const n={},o=s.createContext(n);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/30beaf32.f17a2683.js b/assets/js/30beaf32.f17a2683.js new file mode 100644 index 0000000000..4386c00f32 --- /dev/null +++ b/assets/js/30beaf32.f17a2683.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4139],{5806:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>d,default:()=>m,frontMatter:()=>c,metadata:()=>h,toc:()=>u});var r=n(4848),a=n(8453),i=n(1470),s=n(9365),o=n(5965),l=n(6116);const c={},d="Quickstart",h={id:"dapp/sapphire/quickstart",title:"Quickstart",description:"In this tutorial, you will build and deploy a unique dApp that requires",source:"@site/docs/dapp/sapphire/quickstart.mdx",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/quickstart",permalink:"/dapp/sapphire/quickstart",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/quickstart.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Sapphire ParaTime",permalink:"/dapp/sapphire/"},next:{title:"Guide",permalink:"/dapp/sapphire/guide"}},p={},u=[{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 some Sapphire Testnet tokens",id:"get-some-sapphire-testnet-tokens",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}];function f(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"quickstart",children:"Quickstart"}),"\n",(0,r.jsx)("p",{style:{width:"100%"},children:(0,r.jsx)("iframe",{style:{margin:"auto",display:"block"},width:"560",height:"315",src:"https://www.youtube.com/embed/LDLz06X_KNY?si=tS1-b1hncG6wo9oL",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})}),"\n",(0,r.jsx)(t.p,{children:"In this tutorial, you will build and deploy a unique dApp that requires\nconfidentiality to work. By the end of the tutorial, you should feel\ncomfortable setting up your Eth development environment to target Sapphire,\nand know how and when to use confidentiality."}),"\n",(0,r.jsx)(t.p,{children:"The expected completion time of this tutorial is 15 minutes."}),"\n",(0,r.jsx)(t.admonition,{title:"Sunsetting Truffle",type:"info",children:(0,r.jsxs)(t.p,{children:["Per Consensys ",(0,r.jsx)(t.a,{href:"https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat",children:"announcement"}),", Oasis will no longer support Truffle as of\n2023-10-05 and encourage immediate ",(0,r.jsx)(t.a,{href:"https://trufflesuite.com/docs/truffle/how-to/migrate-to-hardhat/",children:"migration"})," to Hardhat. Please see our\nrepository for the archived Truffle ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/docs/blob/2f4a1a3c217b82687ab9440bf051762ae369ed45/docs/dapp/sapphire/quickstart.mdx",children:"tutorial"})," and the deprecated ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/tree/3a85e42e6c1cc090c28a521cf7df6353aa8a30c8/examples/truffle",children:"example"}),"."]})}),"\n",(0,r.jsx)(t.h2,{id:"create-a-sapphire-native-dapp",children:"Create a Sapphire-Native dApp"}),"\n",(0,r.jsxs)(t.p,{children:["Porting an existing Eth app is cool, and will provide benefits such as\nprotection against MEV.\nHowever, starting from scratch with confidentiality in mind can unlock some\nreally novel dApps and provide a ",(0,r.jsx)(t.a,{href:"/dapp/sapphire/guide#writing-secure-dapps",children:"higher level of security"}),"."]}),"\n",(0,r.jsxs)(t.p,{children:["One simple-but-useful dApp that takes advantage of confidentiality is a\n",(0,r.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Dead_man%27s_switch",children:"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!"]}),"\n",(0,r.jsx)(t.h3,{id:"init-a-new-hardhat-project",children:"Init a new Hardhat project"}),"\n",(0,r.jsx)(t.p,{children:"We're going to use Hardhat, but Sapphire should be compatible with your dev\nenvironment of choice. Let us know if things are not as expected!"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:"Make & enter a new directory"}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"npx hardhat@~2.19.2 init"})," then create a TypeScript project."]}),"\n",(0,r.jsxs)(t.li,{children:["Add ",(0,r.jsx)(t.a,{href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-hardhat",children:(0,r.jsx)(t.code,{children:"@oasisprotocol/sapphire-hardhat"})})," as dependency:"]}),"\n"]}),"\n",(0,r.jsxs)(i.A,{groupId:"npm2yarn",children:[(0,r.jsx)(s.A,{value:"npm",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"npm install -D @oasisprotocol/sapphire-hardhat\n"})})}),(0,r.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"pnpm add -D @oasisprotocol/sapphire-hardhat\n"})})}),(0,r.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"yarn add --dev @oasisprotocol/sapphire-hardhat\n"})})})]}),"\n",(0,r.jsxs)(t.ol,{start:"4",children:["\n",(0,r.jsxs)(t.li,{children:["Install ",(0,r.jsx)(t.code,{children:"@nomicfoundation/hardhat-toolbox"}),", TypeScript and other peer\ndependencies required by HardHat."]}),"\n"]}),"\n",(0,r.jsx)(t.h3,{id:"add-the-sapphire-testnet-to-hardhat",children:"Add the Sapphire Testnet to Hardhat"}),"\n",(0,r.jsxs)(t.p,{children:["Open up your ",(0,r.jsx)(t.code,{children:"hardhat.config.ts"})," and drop in these lines."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-diff",children:'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.io",\n+ accounts: process.env.PRIVATE_KEY\n+ ? [process.env.PRIVATE_KEY]\n+ : [],\n+ chainId: 0x5aff,\n+ },\n+ },\n };\n\n export default config;\n'})}),"\n",(0,r.jsxs)(t.p,{children:["By importing ",(0,r.jsx)(t.code,{children:"@oasisprotocol/sapphire-hardhat"})," at the top of the config file,\n",(0,r.jsx)(t.strong,{children:"any network config entry corresponding to the Sapphire's chain ID will\nautomatically be wrapped with Sapphire specifics for encrypting and signing the\ntransactions"}),"."]}),"\n",(0,r.jsx)(t.h3,{id:"get-some-sapphire-testnet-tokens",children:"Get some Sapphire Testnet tokens"}),"\n",(0,r.jsxs)(t.p,{children:["Now for the fun part. We need to configure the Sapphire network and get some tokens.\nHit up the one and only ",(0,r.jsx)(t.a,{href:"https://faucet.testnet.oasis.io",children:"Oasis Testnet faucet"}),' and select "Sapphire".\nSubmit the form and be on your way.']}),"\n",(0,r.jsx)(t.h3,{id:"get-the-contract",children:"Get the Contract"}),"\n",(0,r.jsxs)(t.p,{children:["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.jsx)(t.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/stable/clients/js/1.x/examples/hardhat/contracts/Vigil.sol",children:"Vigil.sol"})," into ",(0,r.jsx)(t.code,{children:"contracts/Vigil.sol"}),"."]}),"\n",(0,r.jsxs)(t.p,{children:["While you're there, also place ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/stable/clients/js/1.x/examples/hardhat/scripts/run-vigil.ts",children:"run-vigil.ts"})," into ",(0,r.jsx)(t.code,{children:"scripts/run-vigil.ts"}),".\nWe'll need that later."]}),"\n",(0,r.jsx)(t.h4,{id:"vigilsol-the-interesting-parts",children:"Vigil.sol, the interesting parts"}),"\n",(0,r.jsx)(t.p,{children:"The key state variables are:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-solidity",children:" SecretMetadata[] public _metas;\n bytes[] private _secrets;\n"})}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"_metas"})," is marked with ",(0,r.jsx)(t.code,{children:"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."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"_secrets"})," is ",(0,r.jsx)(t.code,{children:"private"})," and therefore truly secret; only the contract can\naccess the data contained in this mapping."]}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"And the methods we'll care most about are"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"createSecret"}),", which adds an entry to both ",(0,r.jsx)(t.code,{children:"_metas"})," and ",(0,r.jsx)(t.code,{children:"_secrets"}),"."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.code,{children:"revealSecret"}),", which acts as an access-controlled getter for the data\ncontained with ",(0,r.jsx)(t.code,{children:"_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."]}),"\n"]}),"\n",(0,r.jsx)(t.p,{children:"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."}),"\n",(0,r.jsx)(t.h3,{id:"run-the-contract",children:"Run the Contract"}),"\n",(0,r.jsxs)(t.p,{children:["And to wrap things up, we'll put ",(0,r.jsx)(t.code,{children:"Vigil"})," through its paces.\nFirst, let's see what's actually going on."]}),"\n",(0,r.jsx)(t.p,{children:"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!"}),"\n",(0,r.jsx)(t.p,{children:"Anyway, make it happen by running"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:'PRIVATE_KEY="0x..." npx hardhat run scripts/run-vigil.ts --network sapphire-testnet\n'})}),"\n",(0,r.jsx)(t.p,{children:"And if you see something like the following, you'll know you're well on the road\nto deploying confidential dApps on Sapphire."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:"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"})}),"\n",(0,r.jsx)(t.h2,{id:"all-done",children:"All done!"}),"\n",(0,r.jsxs)(t.p,{children:["Congratulations, you made it through the Sapphire tutorial! If you have any\nquestions, please check out the ",(0,r.jsx)(t.a,{href:"/dapp/sapphire/guide",children:"guide"})," and join the discussion on the\n",(0,r.jsx)(t.a,{href:"/get-involved/#social-media-channels",children:"#sapphire-paratime Discord channel"}),"."]}),"\n",(0,r.jsx)(t.p,{children:"Best of luck on your future forays into confidentiality!"}),"\n",(0,r.jsx)(t.admonition,{title:"Example",type:"info",children:(0,r.jsxs)(t.p,{children:["Visit the Sapphire ParaTime repository to download the ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/stable/clients/js/1.x/examples/hardhat",children:"Hardhat"}),"\nexample of this quickstart."]})}),"\n",(0,r.jsx)(t.admonition,{title:"Example",type:"info",children:(0,r.jsxs)(t.p,{children:["If your project involves building a web frontend, we recommend that you check\nout the official ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/demo-starter",children:"Oasis starter"})," files."]})}),"\n",(0,r.jsx)(t.h2,{id:"see-also",children:"See also"}),"\n",(0,r.jsx)(o.A,{item:(0,l.$)("/dapp/sapphire/browser")}),"\n",(0,r.jsx)(o.A,{item:(0,l.$)("/node/run-your-node/paratime-client-node")}),"\n",(0,r.jsx)(o.A,{item:(0,l.$)("/node/web3")})]})}function m(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(f,{...e})}):f(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var r=n(4164),a=n(8774),i=n(4142),s=n(5846),o=n(6654),l=n(1312),c=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=n(4848);function p(e){let{href:t,children:n}=e;return(0,h.jsx)(a.A,{href:t,className:(0,r.A)("card padding--lg",d.cardContainer),children:n})}function u(e){let{href:t,icon:n,title:a,description:i}=e;return(0,h.jsxs)(p,{href:t,children:[(0,h.jsxs)(c.A,{as:"h2",className:(0,r.A)("text--truncate",d.cardTitle),title:a,children:[n," ",a]}),i&&(0,h.jsx)("p",{className:(0,r.A)("text--truncate",d.cardDescription),title:i,children:i})]})}function f(e){let{item:t}=e;const n=(0,i.Nr)(t),r=function(){const{selectMessage:e}=(0,s.W)();return t=>e(t,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,h.jsx)(u,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??r(t.items.length)}):null}function m(e){let{item:t}=e;const n=(0,o.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.cC)(t.docId??void 0);return(0,h.jsx)(u,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,h.jsx)(m,{item:t});case"category":return(0,h.jsx)(f,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},9365:(e,t,n)=>{n.d(t,{A:()=>s});n(6540);var r=n(4164);const a={tabItem:"tabItem_Ymn6"};var i=n(4848);function s(e){let{children:t,hidden:n,className:s}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.A)(a.tabItem,s),hidden:n,children:t})}},1470:(e,t,n)=>{n.d(t,{A:()=>w});var r=n(6540),a=n(4164),i=n(3104),s=n(6347),o=n(205),l=n(7485),c=n(1682),d=n(9466);function h(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((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 <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)??[]}function p(e){const{values:t,children:n}=e;return(0,r.useMemo)((()=>{const e=t??function(e){return h(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}(n);return function(e){const t=(0,c.X)(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,n])}function u(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 a=(0,s.W6)(),i=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 <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 n??null}({queryString:t,groupId:n});return[(0,l.aZ)(i),(0,r.useCallback)((e=>{if(!i)return;const t=new URLSearchParams(a.location.search);t.set(i,e),a.replace({...a.location,search:t.toString()})}),[i,a])]}function m(e){const{defaultValue:t,queryString:n=!1,groupId:a}=e,i=p(e),[s,l]=(0,r.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(t){if(!u({value:t,tabValues:n}))throw new Error(`Docusaurus error: The <Tabs> 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:i}))),[c,h]=f({queryString:n,groupId:a}),[m,g]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[a,i]=(0,d.Dv)(n);return[a,(0,r.useCallback)((e=>{n&&i.set(e)}),[n,i])]}({groupId:a}),x=(()=>{const e=c??m;return u({value:e,tabValues:i})?e:null})();(0,o.A)((()=>{x&&l(x)}),[x]);return{selectedValue:s,selectValue:(0,r.useCallback)((e=>{if(!u({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),h(e),g(e)}),[h,g,i]),tabValues:i}}var g=n(2303);const x={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=n(4848);function y(e){let{className:t,block:n,selectedValue:r,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.a_)(),d=e=>{const t=e.currentTarget,n=l.indexOf(t),a=o[n].value;a!==r&&(c(t),s(a))},h=e=>{let t=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const n=l.indexOf(e.currentTarget)+1;t=l[n]??l[0];break}case"ArrowLeft":{const n=l.indexOf(e.currentTarget)-1;t=l[n]??l[l.length-1];break}}t?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.A)("tabs",{"tabs--block":n},t),children:o.map((e=>{let{value:t,label:n,attributes:i}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:r===t?0:-1,"aria-selected":r===t,ref:e=>l.push(e),onKeyDown:h,onClick:d,...i,className:(0,a.A)("tabs__item",x.tabItem,i?.className,{"tabs__item--active":r===t}),children:n??t},t)}))})}function j(e){let{lazy:t,children:n,selectedValue:a}=e;const i=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=i.find((e=>e.props.value===a));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:i.map(((e,t)=>(0,r.cloneElement)(e,{key:t,hidden:e.props.value!==a})))})}function v(e){const t=m(e);return(0,b.jsxs)("div",{className:(0,a.A)("tabs-container",x.tabList),children:[(0,b.jsx)(y,{...t,...e}),(0,b.jsx)(j,{...t,...e})]})}function w(e){const t=(0,g.A)();return(0,b.jsx)(v,{...e,children:h(e.children)},String(t))}},5846:(e,t,n)=>{n.d(t,{W:()=>c});var r=n(6540),a=n(4586);const i=["zero","one","two","few","many","other"];function s(e){return i.filter((t=>e.includes(t)))}const o={locale:"en",pluralForms:s(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,a.A)();return(0,r.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:s(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`),o}}),[e])}function c(){const e=l();return{selectMessage:(t,n)=>function(e,t,n){const r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const a=n.select(t),i=n.pluralForms.indexOf(a);return r[Math.min(i,r.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>i});var r=n(2252);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,r.r)();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]}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var r=n(6540);const a={},i=r.createContext(a);function s(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/34c89262.e6413576.js b/assets/js/34c89262.e6413576.js new file mode 100644 index 0000000000..e377e44453 --- /dev/null +++ b/assets/js/34c89262.e6413576.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7194],{5502:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var r=t(4848),i=t(8453);const s={},o="ADR 0015: Randomized Paratime Proposer Selection",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0015-vrf-per-block-entropy.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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={},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:"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}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"adr-0015-randomized-paratime-proposer-selection",children:"ADR 0015: Randomized Paratime Proposer Selection"}),"\n",(0,r.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,r.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,r.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"2022-09-14: Initial import"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,r.jsx)(n.p,{children:"Proposed"}),"\n",(0,r.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,r.jsxs)(n.p,{children:["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,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/",children:"1"}),", and randomizing the Paratime block proposer."]}),"\n",(0,r.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,r.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsx)(n.p,{children:"Let each node have a distinct long-term VRF keypair, that is published as\npart of the node's descriptor (as per ADR 0010)."}),"\n",(0,r.jsxs)(n.p,{children:["Let Tendermint actually implement ",(0,r.jsx)(n.code,{children:"ExtendVote"}),"/",(0,r.jsx)(n.code,{children:"VerifyVoteExtension"})," as\nper certain versions of the ABCI++ spec",(0,r.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/main/docs/rfc/tendermint-core/rfc-013-abci%2B%2B.md",children:"2"}),". Note that it appears that this\nwill NOT be in Tendermint 0.37.x, but instead is scheduled for a later\nrelease."]}),"\n",(0,r.jsx)(n.h3,{id:"vote-extension",children:"Vote extension"}),"\n",(0,r.jsxs)(n.p,{children:["ABCI++ introduces a notion of an application defined ",(0,r.jsx)(n.code,{children:"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."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:'type OasisVoteExtension struct {\n // Pi is the proposer\'s VRF proof for the current block height.\n Pi []byte `json:"pi"`\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"For the genesis block +1 (No previous beta), let the VRF alpha_string input\nbe derived as:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.code,{children:'TupleHash256((chain_context, I2OSP(height,8)), 256, "oasis-core:tm-vrf/alpha")'})}),"\n",(0,r.jsx)(n.p,{children:"For subsequent blocks, let the VRF alpha_string input be derived as:"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:'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."]}),"\n",(0,r.jsxs)(n.p,{children:["Blocks must have a valid ",(0,r.jsx)(n.code,{children:"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."]}),"\n",(0,r.jsx)(n.h3,{id:"proposer-selection",children:"Proposer selection"}),"\n",(0,r.jsx)(n.p,{children:"Instead of round-robin through the per-epoch list of primary (non-backup)\nworkers, the index for the node can be selected as thus:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,r.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,r.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,r.jsx)(n.p,{children:"The paratime block proposer(s) will be randomized."}),"\n",(0,r.jsx)(n.p,{children:"This can be done without having to patch tendermint."}),"\n",(0,r.jsx)(n.p,{children:"In theory, the system will have a way to generate entropy at the consensus\nlayer again."}),"\n",(0,r.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.p,{children:"People may be tempted to abuse this entropy for other things (eg: inside\nparatimes), which would be incorrect (block proposer can cheat)."}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,r.jsx)(n.h2,{id:"references",children:"References"})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var r=t(6540);const i={},s=r.createContext(i);function o(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/35e64e57.ad74e548.js b/assets/js/35e64e57.ad74e548.js new file mode 100644 index 0000000000..8867421ec5 --- /dev/null +++ b/assets/js/35e64e57.ad74e548.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4447],{2865:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var i=s(4848),t=s(8453);const r={},o="Eden Upgrade",a={id:"node/mainnet/eden-upgrade",title:"Eden Upgrade",description:"This document provides an overview of the changes for the Eden Mainnet",source:"@site/docs/node/mainnet/eden-upgrade.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/eden-upgrade",permalink:"/node/mainnet/eden-upgrade",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/eden-upgrade.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Mainnet",permalink:"/node/mainnet/"},next:{title:"Previous Upgrades",permalink:"/node/mainnet/previous-upgrades"}},d={},l=[{value:"Major Features",id:"major-features",level:2},{value:"Mechanics of the Upgrade",id:"mechanics-of-the-upgrade",level:2},{value:"Voting",id:"voting",level:3},{value:"Upgrade Instructions",id:"upgrade-instructions",level:3},{value:"Configuration Changes",id:"configuration-changes",level:3},{value:"Data Directory Changes",id:"data-directory-changes",level:3},{value:"State Changes",id:"state-changes",level:3},{value:"General",id:"general",level:4},{value:"Registry",id:"registry",level:4},{value:"Root Hash",id:"root-hash",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:"Consensus",id:"consensus",level:4},{value:"Other",id:"other",level:4}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"eden-upgrade",children:"Eden Upgrade"}),"\n",(0,i.jsx)(n.p,{children:"This document provides an overview of the changes for the Eden Mainnet\nupgrade."}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"The Eden upgrade on Mainnet is scheduled at epoch 28017 which will happen\non 2023-11-29 at 10:02 AM UTC."})}),"\n",(0,i.jsx)(n.h2,{id:"major-features",children:"Major Features"}),"\n",(0,i.jsxs)(n.p,{children:["All features for the Eden upgrade are implemented as part of\n",(0,i.jsx)(n.strong,{children:"Oasis Core 23.0.x"})," release series which is a consensus protocol-breaking\nrelease."]}),"\n",(0,i.jsx)(n.p,{children:"Summary of the major features is as follows:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"On-Chain Governance"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Node Operators UX"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"Enhancements have been made to bolster security and optimize the efficiency\nof specific queries."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Key Rotations"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The upgrade introduces major updates to facilitate key rotations, both for\nephemeral and state keys.","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"ParaTime Confidential Query Latency"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"ParaTime Upgrades"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"ParaTime Performance"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"The upgrade improves runtime performance, especially in scenarios involving\nnode failures. Should nodes malfunction, the impact on performance will now\nbe significantly reduced."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"mechanics-of-the-upgrade",children:"Mechanics of the Upgrade"}),"\n",(0,i.jsx)(n.h3,{id:"voting",children:"Voting"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["On 2023-11-14, an upgrade proposal was proposed, which was accepted with\nmore than 86% of the total voting power of the validator set.\nThe upgrade is now scheduled for epoch ",(0,i.jsx)(n.strong,{children:"28017"}),"\n(2023-11-29, start at 10:02 AM UTC)."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Eden upgrade proposal has the ID number 3."})}),"\n",(0,i.jsxs)(n.p,{children:["For optimal voting experience, we recommend using the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"}),".\nFollow these steps to cast your vote:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import-file",children:"Import your keys into the wallet"})}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis wallet import-file my_entity entity.pem\n"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Cast your vote"}),":"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis network governance cast-vote 3 yes\n"})}),"\n",(0,i.jsx)(n.h3,{id:"upgrade-instructions",children:"Upgrade Instructions"}),"\n",(0,i.jsx)(n.p,{children:"The following steps should be performed only after the network has reached the\nupgrade epoch and has halted:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Wait for the network to reach the upgrade epoch and halt. The node\nwill automatically stop without any action required on your part. After the\nnetwork has halted, proceed to the next steps."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Download the Mainnet genesis file published in the\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2023-11-29",children:"Mainnet 2023-11-29 release"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["Mainnet state at epoch ",(0,i.jsx)(n.strong,{children:"28017"})," will be exported and migrated to a 23.0.x\ncompatible genesis file."]}),(0,i.jsx)(n.p,{children:"The new genesis file will be published on the above link soon after reaching the\nupgrade epoch."})]}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Verify the provided Mainnet upgrade genesis file by comparing it to the\nlocal network state dump."}),"\n",(0,i.jsxs)(n.p,{children:["Find the ",(0,i.jsx)(n.code,{children:"genesis-oasis-3-at-HEIGHT.json"})," file in the ",(0,i.jsx)(n.code,{children:"exports"})," subdirectory in\nyour data dir (e.g. ",(0,i.jsx)(n.code,{children:"/node/"}),", ",(0,i.jsx)(n.code,{children:"/srv/oasis/node/"}),") and run ",(0,i.jsx)(n.code,{children:"sha256sum"})," on it.\nAfterwards, compare it with the hash that we will share on the\n",(0,i.jsx)(n.code,{children:"#node-operators"})," Discord channel."]}),"\n",(0,i.jsxs)(n.p,{children:["The state changes are described in the ",(0,i.jsx)(n.a,{href:"#state-changes",children:"State Changes"}),"\nsection below."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Replace the old genesis file with the new Mainnet genesis file."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Ensure your node will remain stopped by disabling auto-starting via your\nprocess manager (e.g., ",(0,i.jsx)(n.a,{href:"https://systemd.io/",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org/",children:"Supervisor"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Back up the entire data directory of your node. Verify that the backup\nincludes the following folders:"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["for consensus: ",(0,i.jsx)(n.code,{children:"tendermint/abci-state"})," and ",(0,i.jsx)(n.code,{children:"tendermint/data"})]}),"\n",(0,i.jsxs)(n.li,{children:["for runtimes: ",(0,i.jsx)(n.code,{children:"runtimes/*/mkvs_storage.badger.db"})," and\n",(0,i.jsx)(n.code,{children:"runtimes/*/worker-local-storage.badger.db"})]}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"7",children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),". This must be performed ",(0,i.jsx)(n.em,{children:"before"})," replacing the Oasis Node\nbinary. In case you are upgrading ParaTimes/runtimes ensure you read the\nfollowing section:"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsx)(n.p,{children:"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,i.jsx)(n.p,{children:"To safely wipe the blockchain state on a runtime while preserving the runtime\nstate, follow these steps:"}),(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Dry run:"})," initiate a dry run to preview which files will be deleted by\nrunning the following command:"]}),"\n"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# specify 'datadir' as your node's data directory\noasis-node unsafe-reset \\\n --datadir=/node/data \\\n --dry_run\n"})}),(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Wipe blockchain state:"})," after reviewing the dry run results, proceed with\nthe reset by running:"]}),"\n"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# specify 'datadir' as your node's data directory\noasis-node unsafe-reset \\\n --datadir=/node/data\n"})}),(0,i.jsx)(n.p,{children:"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."})]}),"\n",(0,i.jsxs)(n.ol,{start:"8",children:["\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v23.0.7",children:"23.0.7"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Oasis Core 23.0.7 binary in our published releases is built only for Ubuntu\n22.04 (GLIBC>=2.32). You'll have to build it yourself if you're using prior\nUbuntu versions (or other distributions using older system libraries)."})}),"\n",(0,i.jsxs)(n.ol,{start:"9",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Perform any needed ",(0,i.jsx)(n.a,{href:"#configuration-changes",children:"configuration changes"})," described\nbelow."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(only Rosetta Gateway operators) Replace old version of Oasis Rosetta\nGateway with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.6.0",children:"2.6.0"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"(only Emerald paratime operators) Upgrade Emerald to version 11.0.0."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Start your node and re-enable auto-starting via your process manager."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"configuration-changes",children:"Configuration Changes"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["To see the full extent of the changes examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/stable/23.0.x/CHANGELOG.md",children:"Change Log"})," of the 23.0.x\nrelease."]})}),"\n",(0,i.jsxs)(n.p,{children:["The node configuration has been refactored so that everything is now configured\nvia a YAML configuration file and ",(0,i.jsx)(n.strong,{children:"configuring via command-line options is no\nlonger supported"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node config migrate --in config.yml --out new-config.yml\n"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"After you are satisfied with the new configuration file, replace the old file\nwith the new one as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"mv new-config.yml config.yml\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"The configuration format for seed nodes has changed and it now requires the\nnode's P2P public key to be used. In case your old configuration file contains\nknown Mainnet seed nodes, this transformation is performed automatically."}),(0,i.jsx)(n.p,{children:"However, if it contains unknown seed nodes then the conversion did not happen\nautomatically and you may need to obtain the seed node's P2P public key. For\nMainnet you can use the following addresses:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:26656"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:9200"})}),"\n"]}),(0,i.jsx)(n.p,{children:"Please be aware that every seed node should be configured to listen on two\ndistinct ports. One is dedicated to peer discovery within the CometBFT P2P\nnetwork, while the other is used to bootstrap the Oasis P2P network."})]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"For those running the Emerald ParaTime, please make sure to upgrade to Emerald\nversion 11.0.0 before or soon after the network upgrade is completed."})}),"\n",(0,i.jsx)(n.h3,{id:"data-directory-changes",children:"Data Directory Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The subdirectory (located inside the node's data directory) used to store\nconsensus-related data, previously called ",(0,i.jsx)(n.code,{children:"tendermint"})," (after the consensus\nlayer protocol backend) has been renamed to ",(0,i.jsx)(n.code,{children:"consensus"})," in Oasis Core 23.0.x. If\nany of your scripts rely on specific directory names, please make sure to update\nthem to reflect the changed sdirectory name."]}),"\n",(0,i.jsx)(n.h3,{id:"state-changes",children:"State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["All state changes will be done automatically with the migration command provided\nby the new version of ",(0,i.jsx)(n.code,{children:"oasis-node"}),". It can be used as follows to derive the same\ngenesis file from an existing state dump at the correct height (assuming there\nis a ",(0,i.jsx)(n.code,{children:"genesis.json"})," present in the current working directory):"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node genesis migrate --genesis.new_chain_id oasis-4\n"})})]}),"\n",(0,i.jsx)(n.h4,{id:"general",children:"General"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"oasis-4"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be removed as it is no longer used."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"registry",children:"Registry"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes[].txn_scheduler.propose_batch_timeout"})})," specifies how\nlong to wait before accepting proposal from the next backup scheduler. It will\nbe set to ",(0,i.jsx)(n.code,{children:"5000000000"})," (5 seconds). Previously the value was represented in\nthe number of consensus layer blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.prove_freshness"})})," specifies the cost of the\nfreshness proof transaction. It will be set to ",(0,i.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"keymanager.params.gas_costs.update_policy"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"tee_features": {\n "sgx": {\n "pcs": true,\n "signed_attestations": true,\n "max_attestation_age": 1200\n },\n "freshness_proofs": true\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"5"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"root-hash",children:"Root Hash"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_past_roots_stored"})})," specifies the maximum number of\npast runtime state roots that are stored in consensus state for each runtime.\nIt will be set to ",(0,i.jsx)(n.code,{children:"1200"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"staking",children:"Staking"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.commission_schedule_rules.min_commission_rate"})})," specifies\nthe minimum commission rate. It will be set to ",(0,i.jsx)(n.code,{children:"0"})," to maintain the existing\nbehavior."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.thresholds.node-observer"})})," specifies the stake threshold\nfor registering an observer node. It will be set to ",(0,i.jsx)(n.code,{children:"100000000000"})," base units\n(or ",(0,i.jsx)(n.code,{children:"100"})," tokens), same as for existing compute nodes."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"key-manager",children:"Key Manager"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs"})})," specify the cost of key manager\ntransactions. These will be set to the following values:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"gas_costs": {\n "publish_ephemeral_secret": 1000,\n "publish_master_secret": 1000,\n "update_policy": 1000\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"random-beacon",children:"Random Beacon"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the epoch\nof Mainnet's state dump + 1, ",(0,i.jsx)(n.code,{children:"28017"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"governance",children:"Governance"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.enable_change_parameters_proposal"})})," specifies whether\nparameter change governance proposals are allowed. It will be set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"consensus",children:"Consensus"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_block_size"})})," specifies the maximum block size in the\nconsensus layer. It will be set to ",(0,i.jsx)(n.code,{children:"1048576"})," (1 MiB)."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"other",children:"Other"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"Mainnet genesis file"}),"\nto include the Oasis Network's genesis quote:"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n'})}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var i=s(6540);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/370b1912.bc08f543.js b/assets/js/370b1912.bc08f543.js new file mode 100644 index 0000000000..f4082119e0 --- /dev/null +++ b/assets/js/370b1912.bc08f543.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1376],{2710:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var t=n(4848),i=n(8453);const r={},o="ADR 0012: Runtime Message Results",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0012-runtime-message-results.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},a={},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:"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}];function d(e){const s={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"adr-0012-runtime-message-results",children:"ADR 0012: Runtime Message Results"}),"\n",(0,t.jsx)(s.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(s.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(s.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:"2021-12-04: Initial version"}),"\n",(0,t.jsx)(s.li,{children:"2021-12-10: Extend the implementation section"}),"\n",(0,t.jsx)(s.li,{children:"2022-01-27: Update the concrete result types"}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(s.p,{children:"Accepted"}),"\n",(0,t.jsx)(s.h2,{id:"context",children:"Context"}),"\n",(0,t.jsxs)(s.p,{children:["Currently, the results of emitted runtime messages are ",(0,t.jsx)(s.code,{children:"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."]}),"\n",(0,t.jsxs)(s.p,{children:["One of such is supporting staking by runtimes. Currently, a runtime can emit an\n",(0,t.jsx)(s.code,{children:"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."]}),"\n",(0,t.jsxs)(s.p,{children:["Similarly, for ",(0,t.jsx)(s.code,{children:"ReclaimEscrow"}),", the runtime doesn't have the direct information\nat which epoch the stake gets debonded."]}),"\n",(0,t.jsx)(s.p,{children:"The only way to currently obtain this data is to subscribe to consensus events,\nsomething which runtime doesn't have access to."}),"\n",(0,t.jsxs)(s.p,{children:["Adding results to ",(0,t.jsx)(s.code,{children:"MessageEvent"})," solves both of the mentioned use cases:"]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["for ",(0,t.jsx)(s.code,{children:"AddEscrow"})," the result should contain amount of shares obtained with the\nescrow"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["for ",(0,t.jsx)(s.code,{children:"ReclaimEscrow"})," the result should contain the amount of shares and epoch\nat which the stake gets debonded"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsxs)(s.p,{children:["Implement support for arbitrary result data in ",(0,t.jsx)(s.code,{children:"MessageEvent"})," runtime message\nresults."]}),"\n",(0,t.jsx)(s.h2,{id:"implementation",children:"Implementation"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Result field is added to ",(0,t.jsx)(s.code,{children:"roothash.MessageEvent"})," struct:"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'// 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'})}),"\n",(0,t.jsxs)(s.p,{children:["The ",(0,t.jsx)(s.code,{children:"Result"})," field is runtime message specific and is present only when the\nmessage execution was successful (",(0,t.jsx)(s.code,{children:"Code"})," is ",(0,t.jsx)(s.code,{children:"errors.CodeNoError"}),")."]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"ExecuteMessage"})," method in ",(0,t.jsx)(s.code,{children:"MessageSubscriber"})," interface is updated to include\na response:"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:"// 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"})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"Publish"})," method of the ",(0,t.jsx)(s.code,{children:"MessageDispatcher"})," interface is updated to include\nthe response:"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:"// 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"})}),"\n",(0,t.jsxs)(s.p,{children:["In case the ",(0,t.jsx)(s.code,{children:"Publish"})," ",(0,t.jsx)(s.code,{children:"error"})," is ",(0,t.jsx)(s.code,{children:"nil"})," the Roothash backend propagates the\nresult to the emitted ",(0,t.jsx)(s.code,{children:"MessageEvent"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["With these changes the runtime is able to obtain message execution results via\n",(0,t.jsx)(s.code,{children:"MessageEvents"})," in ",(0,t.jsx)(s.code,{children:"RoundResults"}),"."]}),"\n",(0,t.jsx)(s.h3,{id:"message-execution-results",children:"Message Execution Results"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"AddEscrow"})," message execution result is the ",(0,t.jsx)(s.code,{children:"AddEscrowResult"}),":"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"ReclaimEscrow"})," message execution result is the\n",(0,t.jsx)(s.code,{children:"ReclaimEscrowResult"}),":"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"Transfer"})," message execution result is the ",(0,t.jsx)(s.code,{children:"TransferResult"}),":"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'type TransferResult struct {\n From Address `json:"from"`\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"Withdraw"})," message execution result is the ",(0,t.jsx)(s.code,{children:"WithdrawResult"}),":"]}),"\n"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"UpdateRuntime"})," message execution result is the registry ",(0,t.jsx)(s.code,{children:"Runtime"})," descriptor."]}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(s.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsx)(s.p,{children:"All the functionality for runtimes to support staking is implemented."}),"\n",(0,t.jsx)(s.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsx)(s.p,{children:"Requires breaking changes."}),"\n",(0,t.jsx)(s.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsx)(s.h3,{id:"alternatives-considered",children:"Alternatives considered"}),"\n",(0,t.jsx)(s.p,{children:"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."})]})}function u(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>o,x:()=>c});var t=n(6540);const i={},r=t.createContext(i);function o(e){const s=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/393bd7b1.a783c641.js b/assets/js/393bd7b1.a783c641.js new file mode 100644 index 0000000000..acc9fb31ea --- /dev/null +++ b/assets/js/393bd7b1.a783c641.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6380],{9502:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Running Tests and Development Networks","slug":"core/development-setup/running-tests-and-development-networks","permalink":"/core/development-setup/running-tests-and-development-networks","sidebar":"oasisCore","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/3ae86dfc.a20476b6.js b/assets/js/3ae86dfc.a20476b6.js new file mode 100644 index 0000000000..66c8ed41b0 --- /dev/null +++ b/assets/js/3ae86dfc.a20476b6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1915],{8395:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>d});var o=t(4848),s=t(8453);const i={},c="Encoding",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/encoding.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Common Functionality",permalink:"/core/common-functionality"},next:{title:"Cryptography",permalink:"/core/crypto"}},a={},d=[];function l(e){const n={a:"a",h1:"h1",p:"p",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"encoding",children:"Encoding"}),"\n",(0,o.jsxs)(n.p,{children:["All messages exchanged by different components in Oasis Core are encoded using\n",(0,o.jsx)(n.a,{href:"https://tools.ietf.org/html/rfc7049",children:"canonical CBOR as defined by RFC 7049"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"When describing different messages in the documentation, we use Go structs with\nfield annotations that specify how different fields translate to their encoded\nform."})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>r});var o=t(6540);const s={},i=o.createContext(s);function c(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3b03afbf.3f03199b.js b/assets/js/3b03afbf.3f03199b.js new file mode 100644 index 0000000000..2d17361bc9 --- /dev/null +++ b/assets/js/3b03afbf.3f03199b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8398],{3621:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"oasisCore","navigation":{"previous":{"title":"Overview","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/3bc542c3.eb38a924.js b/assets/js/3bc542c3.eb38a924.js new file mode 100644 index 0000000000..b885a79b8f --- /dev/null +++ b/assets/js/3bc542c3.eb38a924.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5596],{7191:(e,o,s)=>{s.r(o),s.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var n=s(4848),t=s(8453);const i={description:"Not comfortable keeping the keys on your own?"},r="Custody Providers & Protocols",a={id:"general/manage-tokens/holding-rose-tokens/custody-providers",title:"Custody Providers & Protocols",description:"Not comfortable keeping the keys on your own?",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/holding-rose-tokens/custody-providers.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Not comfortable keeping the keys on your own?"},sidebar:"general",previous:{title:"3rd Party Wallets and Services",permalink:"/general/manage-tokens/holding-rose-tokens"},next:{title:"Ledger Hardware Wallet",permalink:"/general/manage-tokens/holding-rose-tokens/ledger-wallet"}},l={},d=[{value:"Custody Providers",id:"custody-providers",level:2},{value:"Copper.co",id:"copperco",level:3},{value:"Anchorage",id:"anchorage",level:3},{value:"Finoa",id:"finoa",level:3},{value:"Decentralized Custody Protocols",id:"decentralized-custody-protocols",level:2},{value:"Oasis Safe",id:"oasis-safe",level:3}];function c(e){const o={a:"a",admonition:"admonition",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.h1,{id:"custody-providers--protocols",children:"Custody Providers & Protocols"}),"\n",(0,n.jsxs)(o.p,{children:["Another way to hold your ROSE is by involving custodial partners\u2014either\nby giving them complete custody over your tokens\n(",(0,n.jsx)(o.a,{href:"#custody-providers",children:"Custody Providers"}),") or just require a multi-signature\ntransaction to move them and then splitting some of those keys among trusted\nparties (",(0,n.jsx)(o.a,{href:"#decentralized-custody-protocols",children:"Decentralized Custody Protocols"}),").\nWe've partnered with industry-leaders who support a number of top crypto\nassets. You can pick among the custodial providers or decentralized custody\nprotocols below."]}),"\n",(0,n.jsx)(o.h2,{id:"custody-providers",children:"Custody Providers"}),"\n",(0,n.jsx)(o.admonition,{type:"info",children:(0,n.jsx)(o.p,{children:"Below are some simple ways to get in touch, but please do reach out to them\ndirectly for more information on insurance, fees and cross-chain support."})}),"\n",(0,n.jsx)(o.h3,{id:"copperco",children:(0,n.jsx)(o.a,{href:"https://copper.co",children:"Copper.co"})}),"\n",(0,n.jsx)(o.p,{children:"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."}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Delegation options:"})," Copper.co allows delegation to any validator running a node on the Oasis Network."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Min holding:"})," No threshold for assets under custody. They do not onboard individuals as clients. Suitable for larger token holders."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Sign up:"})," Email ",(0,n.jsx)(o.a,{href:"mailto:betty.sharples@copper.co",children:"betty.sharples@copper.co"})," to set up an account."]}),"\n"]}),"\n",(0,n.jsx)(o.h3,{id:"anchorage",children:(0,n.jsx)(o.a,{href:"https://anchorage.com",children:"Anchorage"})}),"\n",(0,n.jsx)(o.p,{children:"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."}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Delegation options:"})," Anchorage allows delegation to any validator running a node on the Oasis Network."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Min holding:"})," Minimum custody requirements. Suitable for larger token holders."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Sign up:"})," Please sign up ",(0,n.jsx)(o.a,{href:"https://www.anchorage.com/get-started/",children:"here"}),"."]}),"\n"]}),"\n",(0,n.jsx)(o.h3,{id:"finoa",children:(0,n.jsx)(o.a,{href:"https://finoa.io",children:"Finoa"})}),"\n",(0,n.jsx)(o.p,{children:"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)."}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Delegation options:"})," Finoa offers delegation to a number of select validators including Bison Trails, Blockdaemon, Chorus One, Figment Networks, and more."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Min holding:"})," No threshold for assets under custody. Please check out details at ",(0,n.jsx)(o.a,{href:"https://www.finoa.io",children:"finoa.io"}),"."]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Sign up:"})," Email ",(0,n.jsx)(o.a,{href:"mailto:oasis@finoa.io",children:"oasis@finoa.io"})," to set up an account."]}),"\n"]}),"\n",(0,n.jsx)(o.h2,{id:"decentralized-custody-protocols",children:"Decentralized Custody Protocols"}),"\n",(0,n.jsx)(o.h3,{id:"oasis-safe",children:(0,n.jsx)(o.a,{href:"https://safe.oasis.io",children:"Oasis Safe"})}),"\n",(0,n.jsxs)(o.p,{children:["Unlock a new way of ownership! Oasis Safe is the most trusted ",(0,n.jsx)(o.strong,{children:"decentralized\ncustody protocol"})," and collective asset management (",(0,n.jsx)(o.em,{children:"multisignature"})," support)\nplatform running on ",(0,n.jsx)(o.strong,{children:"Oasis Sapphire"}),"."]}),"\n",(0,n.jsxs)(o.p,{children:["Visit ",(0,n.jsx)(o.a,{href:"https://safe.oasis.io",children:"safe.oasis.io"})," and login with your MetaMask or other Ethereum-compatible\nwallet."]})]})}function h(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,o,s)=>{s.d(o,{R:()=>r,x:()=>a});var n=s(6540);const t={},i=n.createContext(t);function r(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3bfc3ca9.615efe2d.js b/assets/js/3bfc3ca9.615efe2d.js new file mode 100644 index 0000000000..efc1d4b0a3 --- /dev/null +++ b/assets/js/3bfc3ca9.615efe2d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2425],{5709:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>u,frontMatter:()=>a,metadata:()=>l,toc:()=>h});var s=t(4848),o=t(8453),r=t(2550),i=t(6116);const a={description:"gRPC proxy for Oasis node"},c="gRPC proxy for your Oasis node",l={id:"node/grpc",title:"gRPC proxy for your Oasis node",description:"gRPC proxy for Oasis node",source:"@site/docs/node/grpc.mdx",sourceDirName:"node",slug:"/node/grpc",permalink:"/node/grpc",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/grpc.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"gRPC proxy for Oasis node"},sidebar:"operators",previous:{title:"Web3 Gateway",permalink:"/node/web3"}},d={},h=[{value:"gRPC Proxy with Envoy",id:"envoy",level:2},{value:"Tunnel Unix socket via SSH",id:"tunnel-unix-socket-via-ssh",level:2},{value:"See also",id:"see-also",level:2}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"grpc-proxy-for-your-oasis-node",children:"gRPC proxy for your Oasis node"}),"\n",(0,s.jsxs)(n.p,{children:["The Oasis node API is exposed via the ",(0,s.jsx)(n.a,{href:"/core/oasis-node/rpc",children:"gRPC protocol"}),". It enables communication\nwith external applications such as the Oasis CLI, dApps running in your browser\nthat need to perform actions on the consensus layer or a ParaTime, services for\nmonitoring and controlling your node and similar."]}),"\n",(0,s.jsx)(n.admonition,{title:"Web3 gateway",type:"tip",children:(0,s.jsxs)(n.p,{children:["The Oasis gRPC ",(0,s.jsx)(n.strong,{children:"is not related to the standardized Web3 JSON-RPC API"}),". For\nEVM-compatible dApps configure a ",(0,s.jsx)(n.a,{href:"/node/web3",children:"Web3 gateway"})," instead which is also compatible\nwith other Ethereum tooling."]})}),"\n",(0,s.jsx)(n.p,{children:"The gRPC proxy may perform the following:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"makes gRPC available to in-browser applications via gRPC-Web,"}),"\n",(0,s.jsx)(n.li,{children:"filters out control methods such as shutting down your node,"}),"\n",(0,s.jsx)(n.li,{children:"authentication,"}),"\n",(0,s.jsx)(n.li,{children:"load balances the traffic to multiple Oasis nodes."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["This chapter will show you how to set up a ",(0,s.jsx)(n.strong,{children:"public"})," gRPC endpoint using Envoy\nso that it exposes only a ",(0,s.jsxs)(n.strong,{children:["safe subset of the ",(0,s.jsx)(n.a,{href:"/core/oasis-node/rpc#services",children:"Oasis RPC services"})]}),". The\nfinal section presents an alternative approach to communicate with your node by\n",(0,s.jsx)(n.strong,{children:"securely tunnelling the Unix socket over the network"}),", so it can safely be\nused by the client, but ",(0,s.jsx)(n.strong,{children:"does not filter out any services"}),"."]}),"\n",(0,s.jsx)(n.admonition,{title:"Never expose the UNIX socket directly!",type:"danger",children:(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"oasis-node"})," deliberately exposes the RPC interface only via an AF_LOCAL\nsocket called ",(0,s.jsx)(n.code,{children:"internal.sock"})," located in the node's data directory.\nThis socket should ",(0,s.jsx)(n.strong,{children:"never be directly exposed over the network"})," as it has no\nauthentication and allows full control\u2014including shutting down your node."]})}),"\n",(0,s.jsx)(n.h2,{id:"envoy",children:"gRPC Proxy with Envoy"}),"\n",(0,s.jsxs)(n.p,{children:["Let's set up a typical public Oasis endpoint using the ",(0,s.jsx)(n.a,{href:"https://www.envoyproxy.io/",children:"Envoy HTTP proxy"})," with\nthe following behavior:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"whitelisted methods for checking the network status, performing queries and\nsubmitting transactions,"}),"\n",(0,s.jsx)(n.li,{children:"no control methods allowed and no queries that are CPU or I/O intensive,"}),"\n",(0,s.jsxs)(n.li,{children:["lives on ",(0,s.jsx)(n.code,{children:"grpc.example.com"})," with TLS-enabled connection and certificates\nthat you already have from Let's Encrypt,"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"internal.sock"})," of the Oasis node is accessible at ",(0,s.jsx)(n.code,{children:"/node/data/internal.sock"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{title:"Example hostnames",type:"info",children:(0,s.jsxs)(n.p,{children:["This chapter uses various hostnames under the ",(0,s.jsx)(n.code,{children:"example.com"})," domain. These only\nserve as an example and in a real deployment you should replace them with your\nown domain."]})}),"\n",(0,s.jsxs)(n.p,{children:["Envoy already has built-in support for gRPC so after installing Envoy, simply\nput the configuration below inside your ",(0,s.jsx)(n.code,{children:"envoy.yaml"})," and then execute the proxy\nwith ",(0,s.jsx)(n.code,{children:"envoy -c envoy.yaml"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",metastring:'title="envoy.yaml"',children:'# Envoy gRPC-web proxy configuration\n---\nadmin:\n address:\n socket_address:\n address: "127.0.0.1"\n port_value: 10000\nstatic_resources:\n listeners:\n - name: listener_0\n address:\n socket_address:\n address: "0.0.0.0"\n port_value: 443\n filter_chains:\n - filters:\n - name: envoy.filters.network.http_connection_manager\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n codec_type: AUTO\n stat_prefix: ingress_http\n access_log:\n - name: envoy.file_access_log\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog\n path: /dev/stdout\n route_config:\n virtual_hosts:\n - name: vh_0\n domains:\n - "*"\n routes:\n - match:\n safe_regex:\n regex: "\\\n/oasis-core\\\\.(\\\n Beacon/(\\\n ConsensusParameters|\\\n GetBaseEpoch|\\\n GetBeacon|\\\n GetEpoch|\\\n GetEpochBlock|\\\n GetFutureEpoch)|\\\n Consensus/(\\\n EstimateGas|\\\n GetBlock|\\\n GetChainContext|\\\n GetGenesisDocument|\\\n GetNextBlockState|\\\n GetParameters|\\\n GetSignerNonce|\\\n GetStatus|\\\n GetTransactions|\\\n GetTransactionsWithResults|\\\n GetUnconfirmedTransactions|\\\n SubmitTx)|\\\n Governance/(\\\n ActiveProposals|\\\n ConsensusParameters|\\\n GetEvents|\\\n PendingUpgrades|\\\n Proposal|\\\n Proposals|\\\n Votes)|\\\n NodeController/(\\\n GetStatus)|\\\n Registry/(\\\n ConsensusParameters|\\\n GetEntity|\\\n GetEvents|\\\n GetNode|\\\n GetNodeByConsensusAddress|\\\n GetNodeStatus|\\\n GetRuntime|\\\n GetRuntimes)|\\\n RootHash/(\\\n ConsensusParameters|\\\n GetEvents|\\\n GetGenesisBlock|\\\n GetLastRoundResults|\\\n GetLatestBlock|\\\n GetRuntimeState)|\\\n RuntimeClient/(\\\n CheckTx|\\\n GetBlock|\\\n GetEvents|\\\n GetGenesisBlock|\\\n GetLastRetainedBlock|\\\n GetTransactions|\\\n GetTransactionsWithResults|\\\n Query|\\\n SubmitTx|\\\n SubmitTxMeta|\\\n SubmitTxNoWait|\\\n WatchBlocks)|\\\n Scheduler/(\\\n ConsensusParameters|\\\n GetCommittees|\\\n GetValidators)|\\\n Staking/(\\\n Account|\\\n Allowance|\\\n CommonPool|\\\n ConsensusParameters|\\\n DebondingDelegationInfosFor|\\\n DebondingDelegationsFor|\\\n DebondingDelegationsTo|\\\n DelegationInfosFor|\\\n DelegationsFor|\\\n DelegationsTo|\\\n GetEvents|\\\n GovernanceDeposits|\\\n LastBlockFees|\\\n Threshold|\\\n TokenSymbol|\\\n TokenValueExponent|\\\n TotalSupply))\\\n"\n route:\n cluster: oasis_node_grpc\n timeout: "0s"\n max_stream_duration:\n grpc_timeout_header_max: "0s"\n - match:\n prefix: /oasis-core\n direct_response:\n status: 404\n body:\n inline_string: Only some methods are allowed on this proxy.\n typed_per_filter_config:\n envoy.filters.http.cors:\n "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy\n expose_headers: grpc-status,grpc-message,grpc-status-details-bin\n allow_origin_string_match:\n - exact: \'*\'\n allow_headers: content-type,x-grpc-web,x-user-agent\n max_age: \'1728000\'\n http_filters:\n - name: envoy.health_check\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck\n pass_through_mode: false\n headers:\n - name: :path\n string_match:\n exact: /health\n - name: envoy.filters.http.grpc_web\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb\n - name: envoy.filters.http.cors\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors\n - name: envoy.filters.http.router\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router\n transport_socket:\n name: envoy.transport_sockets.tls\n typed_config:\n "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext\n common_tls_context:\n alpn_protocols:\n - h2,http/1.1\n tls_certificates:\n - certificate_chain:\n filename: /etc/letsencrypt/live/grpc.example.com/fullchain.pem\n private_key:\n filename: /etc/letsencrypt/live/grpc.example.com/privkey.pem\n clusters:\n - name: oasis_node_grpc\n connect_timeout: 0.25s\n load_assignment:\n cluster_name: cluster_0\n endpoints:\n - lb_endpoints:\n - endpoint:\n address:\n pipe:\n path: /node/data/internal.sock\n typed_extension_protocol_options:\n envoy.extensions.upstreams.http.v3.HttpProtocolOptions:\n "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions\n explicit_http_config:\n http2_protocol_options: {}\nlayered_runtime:\n layers:\n - name: static\n static_layer:\n re2:\n max_program_size:\n error_level: 1000000\n'})}),"\n",(0,s.jsx)(n.h2,{id:"tunnel-unix-socket-via-ssh",children:"Tunnel Unix socket via SSH"}),"\n",(0,s.jsxs)(n.p,{children:["SSH supports forwarding a Unix socket over a secure layer. The command below\nwill establish a secure shell to the ",(0,s.jsx)(n.code,{children:"example.com"})," server and then tunnel\nthe ",(0,s.jsx)(n.code,{children:"internal.sock"})," file inside the data directory to a Unix socket inside your\nhome folder:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"ssh oasis@example.com -L /home/user/oasis-node-internal.sock:/node/data/internal.sock\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"/home/user/oasis-node-internal.sock"})," can now be used to safely connect to\nthe Oasis node ",(0,s.jsx)(n.strong,{children:"as if it was running locally without filtering any services"}),".\nFor example, using the ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/network#add-local",children:"Oasis CLI"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network add-local my-oasis-node unix:/home/user/oasis-node-internal.sock\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network status --network my-oasis-node\n"})}),"\n",(0,s.jsx)(n.admonition,{title:"Permanent SSH channel",type:"tip",children:(0,s.jsxs)(n.p,{children:["To make a tunneled Unix socket over SSH permanent, consider using ",(0,s.jsx)(n.a,{href:"https://www.harding.motd.ca/autossh/",children:"autossh"}),"."]})}),"\n",(0,s.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,s.jsx)(r.A,{items:[(0,i.$)("/node/run-your-node/"),(0,i.$)("/node/web3")]})]})}function u(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>x});t(6540);var s=t(4164),o=t(8774),r=t(4142),i=t(5846),a=t(6654),c=t(1312),l=t(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:n,children:t}=e;return(0,h.jsx)(o.A,{href:n,className:(0,s.A)("card padding--lg",d.cardContainer),children:t})}function u(e){let{href:n,icon:t,title:o,description:r}=e;return(0,h.jsxs)(p,{href:n,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,s.A)("text--truncate",d.cardTitle),title:o,children:[t," ",o]}),r&&(0,h.jsx)("p",{className:(0,s.A)("text--truncate",d.cardDescription),title:r,children:r})]})}function m(e){let{item:n}=e;const t=(0,r.Nr)(n),s=function(){const{selectMessage:e}=(0,i.W)();return n=>e(n,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,h.jsx)(u,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??s(n.items.length)}):null}function g(e){let{item:n}=e;const t=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",s=(0,r.cC)(n.docId??void 0);return(0,h.jsx)(u,{href:n.href,icon:t,title:n.label,description:n.description??s?.description})}function x(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(g,{item:n});case"category":return(0,h.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},2550:(e,n,t)=>{t.d(n,{A:()=>c});t(6540);var s=t(4164),o=t(4142),r=t(5965),i=t(4848);function a(e){let{className:n}=e;const t=(0,o.$S)();return(0,i.jsx)(c,{items:t.items,className:n})}function c(e){const{items:n,className:t}=e;if(!n)return(0,i.jsx)(a,{...e});const c=(0,o.d1)(n);return(0,i.jsx)("section",{className:(0,s.A)("row",t),children:c.map(((e,n)=>(0,i.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,i.jsx)(r.A,{item:e})},n)))})}},5846:(e,n,t)=>{t.d(n,{W:()=>l});var s=t(6540),o=t(4586);const r=["zero","one","two","few","many","other"];function i(e){return r.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:i(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,o.A)();return(0,s.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:i(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function l(){const e=c();return{selectMessage:(n,t)=>function(e,n,t){const s=e.split("|");if(1===s.length)return s[0];s.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${s.length}: ${e}`);const o=t.select(n),r=t.pluralForms.indexOf(o);return s[Math.min(r,s.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>r});var s=t(2252);function o(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&o(n.items)}}function r(e){const n=(0,s.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)o(n.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]}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>a});var s=t(6540);const o={},r=s.createContext(o);function i(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3e5e0bf3.182e9c03.js b/assets/js/3e5e0bf3.182e9c03.js new file mode 100644 index 0000000000..8bc71ab9b7 --- /dev/null +++ b/assets/js/3e5e0bf3.182e9c03.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2530],{5658:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var i=t(4848),s=t(8453);const o={},a="ADR 0007: Improved Random Beacon",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0007-improved-random-beacon.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},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:"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}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-0007-improved-random-beacon",children:"ADR 0007: Improved Random Beacon"}),"\n",(0,i.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,i.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2020-10-22: Initial version"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Any one who considers arithmetical methods of producing random digits\nis, of course, in a state of sin."}),"\n",(0,i.jsx)(n.p,{children:"--Dr. John von Neumann"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"A better random beacon which is harder for an adversary to manipulate\nis required to provide entropy for secure committee elections."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.p,{children:'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.'}),"\n",(0,i.jsx)(n.p,{children:"Note: This document assumes the reader understands SCRAPE. Details\nregarding the underlying SCRAPE implementation are omitted for brevity."}),"\n",(0,i.jsx)(n.h3,{id:"node-descriptor",children:"Node Descriptor"}),"\n",(0,i.jsx)(n.p,{children:"The node descriptor of each node will be extended to include the following\ndatastructure."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"For the purposes of the initial implementation, the curve will be P-256."}),"\n",(0,i.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,i.jsx)(n.p,{children:"The beacon module will have the following consensus parameters that\ncontrol behavior."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"Fields:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Participants"})," - The number of participants to be selected for each\nbeacon generation protocol round."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Threshold"})," - The minimum number of participants which must\nsuccessfully contribute entropy for the final output to be\nconsidered valid."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"Threshold"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"CommitInterval"})," - The duration of the Commit phase, in blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"RevealInterval"})," - The duration of the Reveal phase, in blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"TransitionDelay"})," - The duration of the post Reveal phase delay, in blocks."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"consensus-state-and-events",children:"Consensus State and Events"}),"\n",(0,i.jsx)(n.p,{children:"The on-chain beacon will maintain and make available the following consensus\nstate."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,i.jsx)(n.p,{children:"Fields:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Height"})," - The block height at which the last event was emitted."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Epoch"})," - The epoch in which this beacon is being generated."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Round"})," - The epoch beacon generation round."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"State"})," - The beacon generation step (commit/reveal/complete)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Instance"})," - The SCRAPE protocol state (encrypted/decrypted shares of\nall participants)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Participants"})," - The node IDs of the nodes selected to participate\nin this beacon generation round."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Entropy"})," - The final raw entropy, if any."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"BadParticipants"})," - A map of nodes that were selected, but have failed\nto execute the protocol correctly."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"CommitDeadline"})," - The height in blocks by which participants must\nsubmit their encrypted shares."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"RevealDeadline"})," - The height in blocks by which participants must\nsubmit their decrypted shares."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"TransitionHeight"})," - The height at which the epoch will transition\nassuming this round completes successfully."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Upon transition to a next step of the protocol, the on-chain beacon will\nemit the following event."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,i.jsxs)(n.p,{children:["Field definitions are identical to that of those in the ",(0,i.jsx)(n.code,{children:"SCRAPEState"}),"\ndatastructure."]}),"\n",(0,i.jsx)(n.h2,{id:"transactions",children:"Transactions"}),"\n",(0,i.jsx)(n.p,{children:"Participating nodes will submit the following transactions when required,\nsigned by the node identity key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"Fields:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Epoch"})," - The epoch in which the transaction is applicable."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Round"})," - The epoch beacon generation round for the transaction."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Commit"})," - The SCRAPE commit consisting of PVSS shares encrypted to\nevery participant."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Reveal"})," - The SCRAPE reveal consisting of the decrypted result of\nPVSS shares received from every participant."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"beacon-generation",children:"Beacon Generation"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h4,{id:"commit-phase",children:"Commit Phase"}),"\n",(0,i.jsxs)(n.p,{children:["Upon epoch transition or a prior failed round the commit phase is initiated\nthe consensus application will select ",(0,i.jsx)(n.code,{children:"Particpants"})," nodes from the current\nvalidator set (in order of decending stake) to serve as entropy contributors."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"SCRAPEState"})," structure is (re)-initialized, and a ",(0,i.jsx)(n.code,{children:"SCRAPEEvent"})," is\nbroadcast to signal to the participants that they should generate and\nsubmit their encrypted shares via a ",(0,i.jsx)(n.code,{children:"SCRAPECommit"})," transaction."]}),"\n",(0,i.jsxs)(n.p,{children:["Each commit phase lasts exactly ",(0,i.jsx)(n.code,{children:"CommitInterval"})," blocks, at the end of which,\nthe round will be closed to further commits."]}),"\n",(0,i.jsxs)(n.p,{children:["At the end of the commit phase, the SCRAPE protocol state is evaluated\nto ensure that ",(0,i.jsx)(n.code,{children:"Threshold"}),"/",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["The following behaviors are currently candidates for a node being marked\nas malicious/non-particpatory (",(0,i.jsx)(n.code,{children:"BadParticipant"}),") and subject to exclusion\nfrom future rounds and slashing."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Not submitting a commitment."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Malformed commitments (corrupted/fails to validate/etc)."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Attempting to alter an existing commitment for a given Epoch/Round."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"reveal-phase",children:"Reveal Phase"}),"\n",(0,i.jsxs)(n.p,{children:["When the ",(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"SCRAPEState"})," structure and broadcasting a\n",(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"SCRAPEReveal"})," transaction."]}),"\n",(0,i.jsxs)(n.p,{children:["Each reveal phase lasts exactly ",(0,i.jsx)(n.code,{children:"RevealInterval"})," blocks, at the end of which,\nthe round will be closed to further reveals."]}),"\n",(0,i.jsxs)(n.p,{children:["At the end of the reveal phase, the SCRAPE protocol state is evaluated to\nensure that ",(0,i.jsx)(n.code,{children:"Threshold"}),"/",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["The following behaviors are currently candidates for a node being marked\nas malicious/non-participatory (",(0,i.jsx)(n.code,{children:"BadParticipant"}),") and subject to exclusion\nfrom future rounds and slashing."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Not submitting a reveal."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Malformed commitments (corrupted/fails to validate/etc)."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Attempting to alter an existing reveal for a given Epoch/Round."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Note: It is possible for anybody who can observe consensus state to derive\nthe entropy the moment a threshold number of ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h4,{id:"complete-transition-wait-phase",children:"Complete (Transition Wait) Phase"}),"\n",(0,i.jsxs)(n.p,{children:["When the ",(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"SCRAPEState"})," structure and broadcasting a ",(0,i.jsx)(n.code,{children:"SCRAPEEvent"})," to signal to\nparticipants the completion of the round."]}),"\n",(0,i.jsx)(n.p,{children:"No meaningful protocol activity happens one a round has successfully\ncompleted, beyond the scheduling of the next epoch transition."}),"\n",(0,i.jsx)(n.h3,{id:"misc-changesnotes",children:"Misc. Changes/Notes"}),"\n",(0,i.jsx)(n.p,{children:"Nodes MUST not be slashed for non-participation if they have not had\nthe opportunity to propose any blocks during the relevant interval."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The random beacon output is unbaised, provided that at least one\nparticipant is honest."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The amount of consensus state required is relatively small."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"All protocol messages and steps can be verified on-chain, and misbehavior\ncan be attributed."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The final output can be generated on-chain."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Epoch intervals are theoretically variable under this proposal, as the\nbeacon generation needs to be re-ran with new participants upon failure."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"A new failure mode is introduced at the consensus layer, where the\nbeacon generation protocol exhausts eligible participants."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The commit and reveal steps of the protocol are rather slow, especially\nas the number of participants increases."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://eprint.iacr.org/2017/216.pdf",children:"SCRAPE: SCalabe Randomness Attested by Public Entities"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/pull/3180",children:"oasis-core#3180"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>r});var i=t(6540);const s={},o=i.createContext(s);function a(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3fb4947e.50773520.js b/assets/js/3fb4947e.50773520.js new file mode 100644 index 0000000000..3da7c6ef55 --- /dev/null +++ b/assets/js/3fb4947e.50773520.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1053],{3536:(e,r,s)=>{s.r(r),s.d(r,{assets:()=>n,contentTitle:()=>c,default:()=>l,frontMatter:()=>i,metadata:()=>d,toc:()=>a});var t=s(4848),o=s(8453);const i={},c="Metrics",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/metrics.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"RPC",permalink:"/core/oasis-node/rpc"},next:{title:"oasis-node CLI",permalink:"/core/oasis-node/cli"}},n={},a=[{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>CometBFT</em>",id:"metrics-reported-by-cometbft",level:3}];function h(e){const r={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h1,{id:"metrics",children:"Metrics"}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.code,{children:"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:"]}),"\n",(0,t.jsxs)(r.ul,{children:["\n",(0,t.jsxs)(r.li,{children:[(0,t.jsx)(r.em,{children:"Pull mode"})," listens on given address and waits for Prometheus to scrape the\nmetrics."]}),"\n"]}),"\n",(0,t.jsxs)(r.h2,{id:"configuring-oasis-node-in-pull-mode",children:["Configuring ",(0,t.jsx)(r.code,{children:"oasis-node"})," in Pull Mode"]}),"\n",(0,t.jsxs)(r.p,{children:["To run ",(0,t.jsx)(r.code,{children:"oasis-node"})," in ",(0,t.jsx)(r.em,{children:"pull mode"})," set flag ",(0,t.jsx)(r.code,{children:"--metrics.mode pull"})," and provide\nthe listen address with ",(0,t.jsx)(r.code,{children:"--metrics.address"}),". For example"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{children:"oasis-node --metrics.mode pull --metrics.address localhost:3000\n"})}),"\n",(0,t.jsxs)(r.p,{children:["Then, add the following segment to your ",(0,t.jsx)(r.code,{children:"prometheus.yml"})," and restart\nPrometheus:"]}),"\n",(0,t.jsx)(r.pre,{children:(0,t.jsx)(r.code,{className:"language-yaml",children:" - job_name : 'oasis-node'\n\n scrape_interval: 5s\n\n static_configs:\n - targets: ['localhost:3000']\n"})}),"\n",(0,t.jsxs)(r.h2,{id:"metrics-reported-by-oasis-node",children:["Metrics Reported by ",(0,t.jsx)(r.code,{children:"oasis-node"})]}),"\n",(0,t.jsxs)(r.p,{children:[(0,t.jsx)(r.code,{children:"oasis-node"})," reports metrics starting with ",(0,t.jsx)(r.code,{children:"oasis_"}),"."]}),"\n",(0,t.jsx)(r.p,{children:"The following metrics are currently reported:"}),"\n",(0,t.jsxs)(r.table,{children:[(0,t.jsx)(r.thead,{children:(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.th,{children:"Name"}),(0,t.jsx)(r.th,{children:"Type"}),(0,t.jsx)(r.th,{children:"Description"}),(0,t.jsx)(r.th,{children:"Labels"}),(0,t.jsx)(r.th,{children:"Package"})]})}),(0,t.jsxs)(r.tbody,{children:[(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_abci_db_size"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Total size of the ABCI database (MiB)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/cometbft/abci/mux.go",children:"consensus/cometbft/abci"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_codec_size"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"CBOR codec message size (bytes)."}),(0,t.jsx)(r.td,{children:"call, module"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/cbor/codec.go",children:"common/cbor"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_consensus_proposed_blocks"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of blocks proposed by the node."}),(0,t.jsx)(r.td,{children:"backend"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/metrics/metrics.go",children:"consensus/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_consensus_signed_blocks"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of blocks signed by the node."}),(0,t.jsx)(r.td,{children:"backend"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/metrics/metrics.go",children:"consensus/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_finalized_rounds"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of finalized rounds."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/metrics.go",children:"roothash"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_client_calls"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of gRPC calls."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_client_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"gRPC call latency (seconds)."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_client_stream_writes"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of gRPC stream writes."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_server_calls"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of gRPC calls."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_server_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"gRPC call latency (seconds)."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_grpc_server_stream_writes"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of gRPC stream writes."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/grpc/grpc.go",children:"common/grpc"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_cpu_stime_seconds"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"CPU system time spent by worker as reported by /proc/<PID>/stat (seconds)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/cpu.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_cpu_utime_seconds"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"CPU user time spent by worker as reported by /proc/<PID>/stat (seconds)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/cpu.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_disk_read_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Read data from block storage by the worker as reported by /proc/<PID>/io (bytes)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_disk_usage_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of datadir of the worker (bytes)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_disk_written_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Written data from block storage by the worker as reported by /proc/<PID>/io (bytes)"}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/disk.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_mem_rss_anon_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of resident anonymous memory of worker as reported by /proc/<PID>/status (bytes)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_mem_rss_file_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of resident file mappings of worker as reported by /proc/<PID>/status (bytes)"}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_mem_rss_shmem_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of resident shared memory of worker."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_mem_vm_size_bytes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Virtual memory size of worker (bytes)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/mem.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_net_receive_bytes_total"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Received data for each network device as reported by /proc/net/dev (bytes)."}),(0,t.jsx)(r.td,{children:"device"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_net_receive_packets_total"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Received data for each network device as reported by /proc/net/dev (packets)."}),(0,t.jsx)(r.td,{children:"device"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_net_transmit_bytes_total"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Transmitted data for each network device as reported by /proc/net/dev (bytes)."}),(0,t.jsx)(r.td,{children:"device"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_node_net_transmit_packets_total"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Transmitted data for each network device as reported by /proc/net/dev (packets)."}),(0,t.jsx)(r.td,{children:"device"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/net.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_p2p_blocked_peers"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of blocked P2P peers."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/p2p/metrics.go",children:"p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_p2p_connections"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of P2P connections."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/p2p/metrics.go",children:"p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_p2p_peers"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of connected P2P peers."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/p2p/metrics.go",children:"p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_p2p_protocols"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of supported P2P protocols."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/p2p/metrics.go",children:"p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_p2p_topics"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of supported P2P topics."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/p2p/metrics.go",children:"p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_registry_entities"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of registry entities."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go",children:"registry"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_registry_nodes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of registry nodes."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go",children:"registry"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_registry_runtimes"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of registry runtimes."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/metrics.go",children:"registry"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_rhp_failures"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of failed Runtime Host calls."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go",children:"runtime/host/protocol"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_rhp_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Runtime Host call latency (seconds)."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go",children:"runtime/host/protocol"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_rhp_successes"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of successful Runtime Host calls."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go",children:"runtime/host/protocol"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_rhp_timeouts"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of timed out Runtime Host calls."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/protocol/connection.go",children:"runtime/host/protocol"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_roothash_block_interval"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Time between roothash blocks (seconds)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/roothash/metrics.go",children:"roothash"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_storage_failures"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of storage failures."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go",children:"storage/api"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_storage_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Storage call latency (seconds)."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go",children:"storage/api"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_storage_successes"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of storage successes."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go",children:"storage/api"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_storage_value_size"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Storage call value size (bytes)."}),(0,t.jsx)(r.td,{children:"call"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/storage/api/metrics.go",children:"storage/api"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_tee_attestations_failed"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of failed TEE attestations."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/sgx/metrics.go",children:"runtime/host/sgx"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_tee_attestations_performed"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of TEE attestations performed."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/sgx/metrics.go",children:"runtime/host/sgx"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_tee_attestations_successful"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of successful TEE attestations."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/sgx/metrics.go",children:"runtime/host/sgx"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_accepted_transactions"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of accepted transactions (passing check tx)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_local_queue_size"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of the local transactions schedulable queue (number of entries)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_pending_check_size"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of the pending to be checked queue (number of entries)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_pending_schedule_size"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of the main schedulable queue (number of entries)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_rejected_transactions"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of rejected transactions (failing check tx)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_txpool_rim_queue_size"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Size of the roothash incoming message transactions schedulable queue (number of entries)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/txpool/metrics.go",children:"runtime/txpool"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_up"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Is oasis-test-runner active for specific scenario."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-node/cmd/common/metrics/metrics.go",children:"oasis-node/cmd/common/metrics"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_aborted_batch_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of aborted batches."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_batch_processing_time"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Time it takes for a batch to finalize (seconds)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_batch_runtime_processing_time"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Time it takes for a batch to be processed by the runtime (seconds)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_batch_size"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Number of transactions in a batch."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_client_lb_healthy_instance_count"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of healthy instances in the load balancer."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/loadbalance/metrics.go",children:"runtime/host/loadbalance"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_client_lb_requests"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of requests processed by the given load balancer instance."}),(0,t.jsx)(r.td,{children:"runtime, lb_instance"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/runtime/host/loadbalance/metrics.go",children:"runtime/host/loadbalance"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Current epoch number as seen by the worker."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_epoch_transition_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of epoch transitions."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_execution_discrepancy_detected_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of detected execute discrepancies."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_committee_p2p_peers"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of executor committee P2P peers."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_is_backup_worker"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"1 if worker is currently an executor backup worker, 0 otherwise."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_is_worker"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"1 if worker is currently an executor worker, 0 otherwise."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_liveness_live_ratio"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Ratio between live and total rounds. Reports 1 if node is not in committee."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_liveness_live_rounds"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of live rounds in last epoch."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_executor_liveness_total_rounds"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of total rounds in last epoch."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_failed_round_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of failed roothash rounds."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_compute_runtime_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of compute runtimes using the key manager."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_consensus_ephemeral_secret_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest ephemeral secret."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_consensus_master_secret_generation_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Generation number of the latest master secret."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_consensus_master_secret_proposal_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest master secret proposal."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_consensus_master_secret_proposal_generation_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Generation number of the latest master secret proposal."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_consensus_master_secret_rotation_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest master secret rotation."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_ephemeral_secret_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest ephemeral secret loaded into the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_generated_ephemeral_secret_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest ephemeral secret generated by the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_generated_master_secret_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest master secret generated by the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_generated_master_secret_generation_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Generation number of the latest master secret generated by the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_master_secret_generation_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Generation number of the latest master secret as seen by the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_master_secret_proposal_epoch_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Epoch number of the latest master secret proposal loaded into the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_master_secret_proposal_generation_number"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Generation number of the latest master secret proposal loaded into the enclave."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_enclave_rpc_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of remote Enclave RPC requests via P2P."}),(0,t.jsx)(r.td,{children:"method"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/p2p/metrics.go",children:"worker/keymanager/p2p"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_keymanager_policy_update_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of key manager policy updates."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/keymanager/metrics.go",children:"worker/keymanager"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_node_registered"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Is oasis node registered (binary)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go",children:"worker/registration"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_node_registration_eligible"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Is oasis node eligible for registration (binary)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go",children:"worker/registration"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_node_status_frozen"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Is oasis node frozen (binary)."}),(0,t.jsx)(r.td,{}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go",children:"worker/registration"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_node_status_runtime_faults"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Number of runtime faults."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go",children:"worker/registration"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_node_status_runtime_suspended"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"Runtime node suspension status (binary)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/registration/worker.go",children:"worker/registration"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_processed_block_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of processed roothash blocks."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/common/committee/node.go",children:"worker/common/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_processed_event_count"}),(0,t.jsx)(r.td,{children:"Counter"}),(0,t.jsx)(r.td,{children:"Number of processed roothash events."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_storage_commit_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Latency of storage commit calls (state + outputs) (seconds)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/compute/executor/committee/metrics.go",children:"worker/compute/executor/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_storage_full_round"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"The last round that was fully synced and finalized."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go",children:"worker/storage/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_storage_pending_round"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"The last round that is in-flight for syncing."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go",children:"worker/storage/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_storage_round_sync_latency"}),(0,t.jsx)(r.td,{children:"Summary"}),(0,t.jsx)(r.td,{children:"Storage round sync latency (seconds)."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go",children:"worker/storage/committee"})})]}),(0,t.jsxs)(r.tr,{children:[(0,t.jsx)(r.td,{children:"oasis_worker_storage_synced_round"}),(0,t.jsx)(r.td,{children:"Gauge"}),(0,t.jsx)(r.td,{children:"The last round that was synced but not yet finalized."}),(0,t.jsx)(r.td,{children:"runtime"}),(0,t.jsx)(r.td,{children:(0,t.jsx)(r.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/worker/storage/committee/metrics.go",children:"worker/storage/committee"})})]})]})]}),"\n",(0,t.jsx)(r.h2,{id:"consensus-backends",children:"Consensus backends"}),"\n",(0,t.jsxs)(r.h3,{id:"metrics-reported-by-cometbft",children:["Metrics Reported by ",(0,t.jsx)(r.em,{children:"CometBFT"})]}),"\n",(0,t.jsxs)(r.p,{children:["When ",(0,t.jsx)(r.code,{children:"oasis-node"})," is configured to use ",(0,t.jsx)(r.a,{href:"/core/consensus/#cometbft",children:"CometBFT"})," for BFT consensus, all\nCometBFT metrics are also reported. Consult\n",(0,t.jsx)(r.a,{href:"https://docs.cometbft.com/v0.38/core/metrics",children:"CometBFT-core documentation"})," for a list of reported by CometBFT."]})]})}function l(e={}){const{wrapper:r}={...(0,o.R)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,r,s)=>{s.d(r,{R:()=>c,x:()=>d});var t=s(6540);const o={},i=t.createContext(o);function c(e){const r=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),t.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4079c408.8391fec3.js b/assets/js/4079c408.8391fec3.js new file mode 100644 index 0000000000..e48872cb87 --- /dev/null +++ b/assets/js/4079c408.8391fec3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7010],{9952:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>a});var s=i(4848),t=i(8453);const r={},o="ADR 0013: Runtime Upgrade Improvements",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0013-runtime-upgrades.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},d={},a=[{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}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-0013-runtime-upgrade-improvements",children:"ADR 0013: Runtime Upgrade Improvements"}),"\n",(0,s.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,s.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"2022-01-25: Initial version"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Accepted"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.p,{children:"Implement support for seamless breaking runtime upgrades."}),"\n",(0,s.jsx)(n.h2,{id:"implementation",children:"Implementation"}),"\n",(0,s.jsx)(n.p,{children:"Runtime descriptor related changes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,s.jsx)(n.p,{children:"The intended workflow here is to:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Deploy runtimes with the initial Deployment populated."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["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,s.jsx)(n.code,{children:"ValidFrom"}),' epoch or the runtime will fail\nto be scheduled (no special handling is done, this is the existing\n"insufficient nodes" condition).']}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Aborting or altering pending updates via the deployment of a new version\nof the descriptor with the removed/ammended not-yet-valid ",(0,s.jsx)(n.code,{children:"Deployments"}),"\nis possible in this design, but perhaps should be forbidden."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Altering exisiting ",(0,s.jsx)(n.code,{children:"Deployments"})," entries is strictly forbidden,\nexcept the removal of superceded descriptors."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Deploying descriptors with ",(0,s.jsx)(n.code,{children:"Deployments"})," that will never be valid\n(as in one that is superceded by a newer version) is strictly\nforbidden."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The existing node descriptor is a flat vector of ",(0,s.jsx)(n.code,{children:"Runtime"})," entries\ncontaining the runtime ID, version, and TEE information, so no changes\nare required."]}),"\n",(0,s.jsxs)(n.p,{children:["On transition to an epoch where a new version takes effect, the consensus\nlayer MAY prune the descriptor's ",(0,s.jsx)(n.code,{children:"Deployments"})," field of superceded versions."]}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Seamless runtime upgrades will be possible."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The code changes required are relatively minimal, and this is likely\nthe simplest possible solution that will work."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"It may be overly simplistic."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>l});var s=i(6540);const t={},r=s.createContext(t);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/409fc1d8.f93f904c.js b/assets/js/409fc1d8.f93f904c.js new file mode 100644 index 0000000000..1a812e9f68 --- /dev/null +++ b/assets/js/409fc1d8.f93f904c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1502],{3334:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>h});var t=s(4848),i=s(8453);const r={},o="ADR 0011: Incoming Runtime Messages",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0011-incoming-runtime-messages.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},h=[{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}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0011-incoming-runtime-messages",children:"ADR 0011: Incoming Runtime Messages"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2022-01-07: Update based on insights from implementation"}),"\n",(0,t.jsx)(n.li,{children:"2021-12-09: Introduce an explicit fee field, clarify token transfers"}),"\n",(0,t.jsx)(n.li,{children:"2021-10-26: Initial draft"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Accepted"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/adrs/0003-consensus-runtime-token-transfer",children:"ADR 3"}),") and allows\nthe consensus layer to act on a runtime's behalf. This mechanism is currently\nused for ",(0,t.jsx)(n.em,{children:"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,t.jsx)(n.a,{href:"/adrs/0004-runtime-governance",children:"ADR 4"}),") is in effect."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"On a high level this proposal affects the following components:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["A new transaction method ",(0,t.jsx)(n.code,{children:"roothash.SubmitMsg"})," is added to the roothash\nconsensus service to queue a new message for the specific runtime."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Additional per-runtime state is added to the roothash service containing the\ncurrently queued messages, sorted by arrival time."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The runtime host protocol is updated to allow the host to push arbitrary\nincoming messages in addition to the transaction batch."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The runtime descriptor is updated to include a field that specifies the\nmaximum size of the incoming message queue."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"incoming-message",children:"Incoming Message"}),"\n",(0,t.jsx)(n.p,{children:"Each incoming message is represented as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"executor-commitments",children:"Executor Commitments"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.p,{children:"Where the hash of included incoming messages is computed as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:"// 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"})}),"\n",(0,t.jsx)(n.p,{children:"Note that this also requires the enclave RAK signature (for runtimes requiring\nthe use of TEEs) to be computed over this updated new header."}),"\n",(0,t.jsx)(n.h3,{id:"runtime-block-header",children:"Runtime Block Header"}),"\n",(0,t.jsxs)(n.p,{children:["The runtime block header is updated to include the ",(0,t.jsx)(n.code,{children:"InMessagesHash"})," field as\nfollows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"runtime-descriptor",children:"Runtime Descriptor"}),"\n",(0,t.jsxs)(n.p,{children:["This proposal updates the runtime transaction scheduler parameters (stored under\nthe ",(0,t.jsx)(n.code,{children:"txn_scheduler"})," field of the runtime descriptor) as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["It also updates the runtime staking parameters (stored under the ",(0,t.jsx)(n.code,{children:"staking"})," field\nof the runtime descriptor) as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"state",children:"State"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces/updates the following consensus state in the roothash\nmodule:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["Incoming message queue metadata (",(0,t.jsx)(n.code,{children:"0x28"}),")"]})}),"\n",(0,t.jsx)(n.p,{children:"Metadata for the incoming message queue."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"0x28 <H(runtime-id) (hash.Hash)>\n"})}),"\n",(0,t.jsx)(n.p,{children:"The value is the following CBOR-serialized structure:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.strong,{children:["Incoming message queue item (",(0,t.jsx)(n.code,{children:"0x29"}),")"]})}),"\n",(0,t.jsx)(n.p,{children:"A queue of incoming messages pending to be delivered to the runtime in the\nnext round."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"0x29 <H(runtime-id) (hash.Hash)> <sequence-no (uint64)>\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The value is a CBOR-serialized ",(0,t.jsx)(n.code,{children:"IncomingMessage"})," structure."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"transaction-methods",children:"Transaction Methods"}),"\n",(0,t.jsx)(n.p,{children:"This proposal updates the following transaction methods in the roothash module:"}),"\n",(0,t.jsx)(n.h4,{id:"submit-message",children:"Submit Message"}),"\n",(0,t.jsx)(n.p,{children:"The submit message method allows anyone to submit incoming runtime messages to\nbe queued for delivery to the given runtime."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"roothash.SubmitMsg\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Body:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"id"})," specifies the destination runtime's identifier."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"data"})," arbitrary data to be sent to the runtime for processing."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The transaction signer implicitly specifies the caller. Upon executing the\nsubmit message method the following actions are performed:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Gas is accounted for (new ",(0,t.jsx)(n.code,{children:"submitmsg"})," gas operation)."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The runtime descriptor for runtime ",(0,t.jsx)(n.code,{children:"id"})," is retrieved. If the runtime does not\nexist or is currently suspended the method fails with ",(0,t.jsx)(n.code,{children:"ErrInvalidRuntime"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"txn_scheduler.max_in_messages"})," field in the runtime descriptor is\nchecked. If it is equal to zero the method fails with\n",(0,t.jsx)(n.code,{children:"ErrIncomingMessageQueueFull"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If the value of the ",(0,t.jsx)(n.code,{children:"fee"})," field is smaller than the value of the\n",(0,t.jsx)(n.code,{children:"staking.min_in_msg_fee"})," field in the runtime descriptor the method fails with\n",(0,t.jsx)(n.code,{children:"ErrIncomingMessageInsufficientFee"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The number of tokens corresponding to ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"ErrInsufficientBalance"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The incoming queue metadata structure is fetched. If it doesn't yet exist it\nis populated with zero values."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If the value of the ",(0,t.jsx)(n.code,{children:"size"})," field in the metadata structure is equal to or\nlarger than the value of the ",(0,t.jsx)(n.code,{children:"txn_scheduler.max_in_messages"})," field in the\nruntime descriptor the method fails with ",(0,t.jsx)(n.code,{children:"ErrIncomingMessageQueueFull"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.code,{children:"IncomingMessage"})," structure is generated based on the caller and method\nbody and the value of the ",(0,t.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"size"})," and ",(0,t.jsx)(n.code,{children:"next_sequence_number"})," fields are incremented and the updated\nmetadata is saved."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"queries",children:"Queries"}),"\n",(0,t.jsxs)(n.p,{children:["This proposal adds the following new query methods in the roothash module by\nupdating the ",(0,t.jsx)(n.code,{children:"roothash.Backend"})," interface as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"runtime-host-protocol",children:"Runtime Host Protocol"}),"\n",(0,t.jsx)(n.p,{children:"This proposal updates the existing host to runtime requests in the runtime host\nprotocol as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsx)(n.h3,{id:"rust-runtime-support-library",children:"Rust Runtime Support Library"}),"\n",(0,t.jsxs)(n.p,{children:["This proposal updates the ",(0,t.jsx)(n.code,{children:"transaction::Dispatcher"})," trait as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-rust",children:"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"})}),"\n",(0,t.jsx)(n.h3,{id:"executor-processing",children:"Executor Processing"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"The executor may perform checks to estimate resource use early, similarly to how\nchecks are performed for transactions as they arrive."}),"\n",(0,t.jsx)(n.h3,{id:"runtime-processing",children:"Runtime Processing"}),"\n",(0,t.jsxs)(n.p,{children:["The proposal requires that messages are processed by the runtime in queue order\n(e.g. on each round ",(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.p,{children:'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.'}),"\n",(0,t.jsxs)(n.p,{children:["Specifying these details is left to the runtime implementation although the SDK\nis expected to adopt an approach with separate ",(0,t.jsx)(n.code,{children:"max_inmsg_gas"})," and\n",(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.h3,{id:"root-hash-commitment-processing",children:"Root Hash Commitment Processing"}),"\n",(0,t.jsx)(n.p,{children:"The processing of executor commitments is modified as follows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"No changes are made to the discrepancy detection and resolution protocols\nbesides the newly added fields being taken into account in discrepancy\ndetermination."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["After a successful round, the ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"size"})," field and the\n",(0,t.jsx)(n.code,{children:"InMessagesHash"})," is added to the newly emitted block header."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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)."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Storing the queue will increase the size of consensus layer state."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Allows rollup-like constructions where all transactions are posted to the\nconsensus layer first and the runtime is just executing those."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Retrieving the result of processing an incoming message is more involved."}),"\n"]}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var t=s(6540);const i={},r=t.createContext(i);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/414b6464.d976e5a4.js b/assets/js/414b6464.d976e5a4.js new file mode 100644 index 0000000000..8d0fd3ab68 --- /dev/null +++ b/assets/js/414b6464.d976e5a4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1644],{1517:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>d,contentTitle:()=>o,default:()=>c,frontMatter:()=>r,metadata:()=>l,toc:()=>a});var t=n(4848),i=n(8453);const r={},o="Testnet",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/testnet/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Upgrade Log",permalink:"/node/mainnet/upgrade-log"},next:{title:"Upgrade Log",permalink:"/node/testnet/upgrade-log"}},d={},a=[{value:"ParaTimes",id:"paratimes",level:2},{value:"Sapphire",id:"sapphire",level:3},{value:"Cipher",id:"cipher",level:3},{value:"Emerald",id:"emerald",level:3},{value:"Key Manager",id:"key-manager",level:3}];function h(e){const s={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"testnet",children:"Testnet"}),"\n",(0,t.jsx)(s.p,{children:"These are the current parameters for the Testnet, a test-only network for\ntesting out upcoming features and changes to the protocol."}),"\n",(0,t.jsxs)(s.admonition,{type:"danger",children:[(0,t.jsx)(s.p,{children:(0,t.jsx)(s.strong,{children:"The Testnet may be subject to frequent version upgrades and state resets."})}),(0,t.jsxs)(s.p,{children:["Also note that while the Testnet does use actual TEEs, due to experimental\nsoftware and different security parameters, ",(0,t.jsx)(s.strong,{children:"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."]})]}),"\n",(0,t.jsx)(s.admonition,{type:"info",children:(0,t.jsxs)(s.p,{children:["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,t.jsx)(s.a,{href:"https://faucet.testnet.oasis.io",children:"Testnet Faucet"}),". Note that these are test-only tokens and account balances, as any other state, may be frequently reset."]})}),"\n",(0,t.jsx)(s.p,{children:"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."}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Latest Testnet version: ",(0,t.jsx)(s.strong,{children:"2023-10-12"})]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/testnet-artifacts/releases/download/2023-10-12/genesis.json",children:"Genesis file"}),":","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["SHA256: ",(0,t.jsx)(s.code,{children:"02ce385c050b2a5c7cf0e5e34f5e4930f7804bb21efba2d1d3aa8215123aab68"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Genesis document's hash (",(0,t.jsx)(s.a,{href:"/node/genesis-doc#genesis-file-vs-genesis-document",children:"explanation"}),"):","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Oasis seed node addresses:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:26656"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:9200"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"kqsc8ETIgG9LCmW5HhSEUW80WIpwKhS7hRQd8FrnkJ0=@34.140.116.202:26656"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"kqsc8ETIgG9LCmW5HhSEUW80WIpwKhS7hRQd8FrnkJ0=@34.140.116.202:9200"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.admonition,{type:"tip",children:(0,t.jsx)(s.p,{children:"Feel free to use other seed nodes besides the one provided here."})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"Oasis Core"})," version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.2",children:"24.2"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway",children:"Oasis Rosetta Gateway"})," version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.7.0",children:"2.7.0"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.admonition,{type:"info",children:(0,t.jsx)(s.p,{children:"The Oasis Node is part of the Oasis Core release."})}),"\n",(0,t.jsx)(s.h2,{id:"paratimes",children:"ParaTimes"}),"\n",(0,t.jsx)(s.p,{children:"This chapter 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."}),"\n",(0,t.jsx)(s.h3,{id:"sapphire",children:"Sapphire"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Oasis Core version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.2",children:"24.2"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime identifier:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime bundle version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.8.2-testnet",children:"0.8.2-testnet"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.8.1-testnet",children:"0.8.1-testnet"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Web3 Gateway version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v5.1.0",children:"5.1.0"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["IAS proxy address:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"jaFE5Lq6GS76ya1V7a+XlGQTgttAagXEtknO4Tv1wLs=@185.56.138.83:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.admonition,{type:"tip",children:(0,t.jsxs)(s.p,{children:["Feel free to use other IAS proxies besides the ones provided here or ",(0,t.jsx)(s.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})}),"\n",(0,t.jsx)(s.h3,{id:"cipher",children:"Cipher"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Oasis Core version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.2",children:"24.2"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime identifier:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"0000000000000000000000000000000000000000000000000000000000000000"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime bundle version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v3.1.2-testnet",children:"3.1.2-testnet"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v3.1.1-testnet",children:"3.1.1-testnet"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["IAS proxy address:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"jaFE5Lq6GS76ya1V7a+XlGQTgttAagXEtknO4Tv1wLs=@185.56.138.83:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.admonition,{type:"tip",children:(0,t.jsxs)(s.p,{children:["Feel free to use other IAS proxies besides the ones provided here or ",(0,t.jsx)(s.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})}),"\n",(0,t.jsx)(s.h3,{id:"emerald",children:"Emerald"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Oasis Core version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.2",children:"24.2"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime identifier:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"00000000000000000000000000000000000000000000000072c8215e60d5bca7"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime bundle version (or ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/emerald-paratime/tree/v11.0.0-testnet#building",children:"build your own"}),"):","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v11.0.0-testnet",children:"11.0.0-testnet"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Web3 Gateway version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v5.1.0",children:"5.1.0"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"key-manager",children:"Key Manager"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Oasis Core version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.2",children:"24.2"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime identifier:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"4000000000000000000000000000000000000000000000004a1a53dff2ae482d"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["Runtime bundle version:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/keymanager-paratime/releases/tag/v0.5.0-testnet",children:"0.5.0-testnet"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["IAS proxy address:","\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"y4XO1ZETqgtHeZzLLmJLYAzpEfdGSJLvtd8bhIz+v3s=@34.86.197.181:8650"})}),"\n",(0,t.jsx)(s.li,{children:(0,t.jsx)(s.code,{children:"jaFE5Lq6GS76ya1V7a+XlGQTgttAagXEtknO4Tv1wLs=@185.56.138.83:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.admonition,{type:"tip",children:(0,t.jsxs)(s.p,{children:["Feel free to use other IAS proxies besides the ones provided here or ",(0,t.jsx)(s.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})})]})}function c(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>o,x:()=>l});var t=n(6540);const i={},r=t.createContext(i);function o(e){const s=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/433ff9f9.6ace070c.js b/assets/js/433ff9f9.6ace070c.js new file mode 100644 index 0000000000..9f5b2325c9 --- /dev/null +++ b/assets/js/433ff9f9.6ace070c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4411],{9009:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>c,default:()=>p,frontMatter:()=>t,metadata:()=>d,toc:()=>i});var s=a(4848),o=a(8453);const t={title:"Network",description:"Managing Mainnet, Testnet or Localnet endpoints"},c="Manage Your Oasis Networks",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/network.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,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"}},r={},i=[{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 Network Chain Context",id:"set-chain-context",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>committees</code>",id:"committees",level:4},{value:"<code><id></code>",id:"show-id",level:4},{value:"Status of the Network's Endpoint",id:"status",level:3}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"manage-your-oasis-networks",children:"Manage Your Oasis Networks"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"network"})," command is used to manage the Mainnet, Testnet or Localnet\nendpoints Oasis CLI will be connecting to."]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"network"})," command is commonly used:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["on network upgrades, because the chain domain separation context is changed\ndue to a new ",(0,s.jsx)(n.a,{href:"/core/consensus/genesis#genesis-documents-hash",children:"genesis document"}),","]}),"\n",(0,s.jsxs)(n.li,{children:["when setting up a local ",(0,s.jsx)(n.code,{children:"oasis-node"})," instance instead of relying on public\ngRPC endpoints,"]}),"\n",(0,s.jsxs)(n.li,{children:["when running a private Localnet with ",(0,s.jsx)(n.code,{children:"oasis-net-runner"}),","]}),"\n",(0,s.jsx)(n.li,{children:"when examining network properties such as the native token, the network\nregistry, the validator set and others."}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Oasis CLI supports both ",(0,s.jsx)(n.strong,{children:"remote endpoints via the secure gRPC protocol"})," and\n",(0,s.jsx)(n.strong,{children:"local Unix socket endpoints"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsx)(n.p,{children:"When running the Oasis CLI for the first time, it will automatically configure\nthe current Mainnet and Testnet endpoints."})}),"\n",(0,s.jsx)(n.h2,{id:"add",children:"Add a Network"}),"\n",(0,s.jsxs)(n.p,{children:["Invoke ",(0,s.jsx)(n.code,{children:"network add <name> <chain-context> <rpc-endpoint>"})," to add a new\nendpoint with a specific chain domain separation context and a gRPC address.\nThis command is useful, if you want to connect to your own instance of the Oasis\nnode instead of relying on the public gRPC endpoints."]}),"\n",(0,s.jsx)(n.p,{children:"For TCP/IP endpoints, run:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network add testnet_alt 0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76 testnet2.grpc.oasis.io:443\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"? Description: Testnet alternative\n? Denomination symbol: TEST\n? Denomination decimal places: (9)\n"})}),"\n",(0,s.jsx)(n.p,{children:"For Unix sockets, use:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network add testnet_local 0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76 unix:/node_testnet/data/internal.sock\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"? Description: Testnet network, local node\n? Denomination symbol: TEST\n? Denomination decimal places: (9)\n"})}),"\n",(0,s.jsx)(n.h2,{id:"add-local",children:"Add a Local Network"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"network add-local <name> <rpc-endpoint>"})," command can be used if you are\nrunning ",(0,s.jsx)(n.code,{children:"oasis-node"})," on your local machine. In this case, Oasis CLI will\nautodetect the native token symbol and decimal places, the chain domain\nseparation context and registered ParaTimes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"oasis network add-local testnet_local unix:/node_testnet/data/internal.sock\n"})}),"\n",(0,s.jsx)(n.h2,{id:"list",children:"List Networks"}),"\n",(0,s.jsxs)(n.p,{children:["Invoke ",(0,s.jsx)(n.code,{children:"network list"})," to list all configured networks."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet (*) \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\ntestnet_alt \t50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a\ttestnet2.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"#set-default",children:"default network"})," is marked with the ",(0,s.jsx)(n.code,{children:"(*)"})," sign."]}),"\n",(0,s.jsx)(n.h2,{id:"remove",children:"Remove a Network"}),"\n",(0,s.jsxs)(n.p,{children:["Use ",(0,s.jsx)(n.code,{children:"network remove <name>"})," to remove the given network configuration including\nall dependant ParaTimes."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network remove testnet_alt\n"})}),"\n",(0,s.jsx)(n.h2,{id:"set-chain-context",children:"Set Network Chain Context"}),"\n",(0,s.jsxs)(n.p,{children:["To change the chain context of a network, use\n",(0,s.jsx)(n.code,{children:"network set-chain-context <name> <chain-context>"}),"."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Chain contexts represent a root of trust in the network, so before changing them\nfor production networks make sure you have verified them against a trusted\nsource like the ",(0,s.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"})," and ",(0,s.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"})," chapters in the official Oasis\ndocumentation."]})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local (*)\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network set-chain-context mainnet_local 01234513331133a715c7a150313877dF1d33e77a715c7a150313877dF1d33e77\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local (*)\t01234513331133a715c7a150313877dF1d33e77a715c7a150313877dF1d33e77\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.h2,{id:"set-default",children:"Set Default Network"}),"\n",(0,s.jsxs)(n.p,{children:["To change the default network for future Oasis CLI operations, use\n",(0,s.jsx)(n.code,{children:"network set-default <name>"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet (*) \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network set-default mainnet_local\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local (*)\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.h2,{id:"set-rpc",children:"Change a Network's RPC Endpoint"}),"\n",(0,s.jsxs)(n.p,{children:["To change the RPC address of the already configured network, run\n",(0,s.jsx)(n.code,{children:"network set-rpc <name> <new_endpoint>"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet (*) \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\ntestnet_alt \t50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a\ttestnet2.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network set-rpc testnet_alt testnet3.grpc.oasis.io:443\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network list\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"NAME \tCHAIN CONTEXT \tRPC \nmainnet (*) \tbb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\tgrpc.oasis.io:443 \t\nmainnet_local\tb11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535\tunix:/node/data/internal.sock\t\ntestnet \t0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76\ttestnet.grpc.oasis.io:443 \t\ntestnet_alt \t50304f98ddb656620ea817cc1446c401752a05a249b36c9b90dba4616829977a\ttestnet3.grpc.oasis.io:443 \t\n"})}),"\n",(0,s.jsx)(n.h2,{id:"advanced",children:"Advanced"}),"\n",(0,s.jsx)(n.h3,{id:"governance",children:"Governance Operations"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"network governance"})," command is aimed towards validators for proposing\nor voting on-chain for network upgrades or changes to other crucial network\nparameters."]}),"\n",(0,s.jsx)(n.h4,{id:"governance-list",children:(0,s.jsx)(n.code,{children:"list"})}),"\n",(0,s.jsxs)(n.p,{children:["Use ",(0,s.jsx)(n.code,{children:"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."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network governance list --network testnet\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"ID\tKIND \tSUBMITTER \tCREATED AT\tCLOSES AT\tSTATE \n1 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t5633 \t5645 \tpassed\t\n2 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t7525 \t7537 \tpassed\t\n3 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t8817 \t8829 \tpassed\t\n4 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t14183 \t14195 \tpassed\t\n5 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t14869 \t14881 \tpassed\t\n6 \tcancel upgrade 5 \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t14895 \t14907 \tpassed\t\n7 \tupgrade \toasis1qrs2dl6nz6fcxxr3tq37laxlz6hxk6kuscnr6rxj\t14982 \t14994 \tpassed\t\n8 \tupgrade \toasis1qpwaggvmhwq5uk40clase3knt655nn2tdy39nz2f\t29493 \t29505 \tpassed\t\n9 \tchange parameters (governance)\toasis1qrx85mv85k708ylww597rd42enlzhdmeu56wqj72\t30693 \t30705 \tpassed\t\n10\tchange parameters (staking) \toasis1qqxxut9x74dutu587f9nj8787qz4dm0ueu05l88c\t33059 \t33071 \tpassed\t\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network"})," selector is available for the\n",(0,s.jsx)(n.code,{children:"governance list"})," command."]})}),"\n",(0,s.jsx)(n.h4,{id:"governance-show",children:(0,s.jsx)(n.code,{children:"show"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"network governance show <proposal-id>"})," shows detailed information on\npast or opened governance proposals on the consensus layer."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network governance show 9 --network testnet\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"=== PROPOSAL STATUS ===\nNetwork: testnet\nProposal ID: 9\nStatus: passed\nSubmitted By: oasis1qrx85mv85k708ylww597rd42enlzhdmeu56wqj72\nCreated At: epoch 30693\nResults:\n - yes: 43494459676132712\n - no: 0\n - abstain: 0\n\n=== PROPOSAL CONTENT ===\nChange Parameters:\n Module: governance\n Changes: \n - Parameter: upgrade_cancel_min_epoch_diff\n Value: 15\n\n=== VOTED STAKE ===\nTotal voting stake: 43777341677851724\nVoted stake: 43494459676132712 (99.35%)\nVoted yes stake: 43494459676132712 (100.00%)\nThreshold: 68%\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can also view individual validator votes by passing the ",(0,s.jsx)(n.code,{children:"--show-votes"}),"\nparameter:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network governance show 9 --show-votes --network testnet\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"=== PROPOSAL STATUS ===\nNetwork: testnet\nProposal ID: 9\nStatus: passed\nSubmitted By: oasis1qrx85mv85k708ylww597rd42enlzhdmeu56wqj72\nCreated At: epoch 30693\nResults:\n - yes: 43494459676132712\n - no: 0\n - abstain: 0\n\n=== PROPOSAL CONTENT ===\nChange Parameters:\n Module: governance\n Changes: \n - Parameter: upgrade_cancel_min_epoch_diff\n Value: 15\n\n=== VOTED STAKE ===\nTotal voting stake: 43777341677851724\nVoted stake: 43494459676132712 (99.35%)\nVoted yes stake: 43494459676132712 (100.00%)\nThreshold: 68%\n\n=== VALIDATORS VOTED ===\n 1. oasis1qqv25adrld8jjquzxzg769689lgf9jxvwgjs8tha,<none>,11072533240458237 (25.29%): yes\n 2. oasis1qz2tg4hsatlxfaf8yut9gxgv8990ujaz4sldgmzx,<none>,10922431911536365 (24.95%): yes\n 3. oasis1qz424yg28jqmgfq3xvly6ky64jqnmlylfc27d7cp,<none>,10786148310722167 (24.64%): yes\n 4. oasis1qq2vzcvxn0js5unsch5me2xz4kr43vcasv0d5eq4,<none>,10713346213415943 (24.47%): yes\n\n=== VALIDATORS NOT VOTED ===\n 1. oasis1qrwncs459lauc77zw23efdn9dmfcp23cxv095l5z,GateOmega,43681995855414 (0.10%)\n 2. oasis1qq60zmsfca0gvmm3v8906pn5zqtt4ee2ssexramg,Validatrium,37519643115923 (0.09%)\n 3. oasis1qrkwv688m3naejcy8rhycls8r78ga0th4qaun90k,Tuzem,13051121909522 (0.03%)\n 4. oasis1qrg430wr84xqh2pm6hv609v7jx9j3gt7xykmjl65,cherkes,12829194880949 (0.03%)\n 5. oasis1qzjm0zwfg4egs9kk4d9rkujudzk8pjp5rvxyr3ag,Munay Network,12777089617060 (0.03%)\n 6. oasis1qqsxhxedvzt0et3sahcqcjw02p4kcz92dqtjuzwh,BroMyb,12062754356510 (0.03%)\n 7. oasis1qpq97fm6lf87jzms9agd6z902nh7axtxvus6m352,LDV,11442842011460 (0.03%)\n 8. oasis1qpz97gfrvj5xzx8jx7x9zweeq0rcf2q6jg4a09qz,Stardust,11304018972474 (0.03%)\n 9. oasis1qrkf98prkpf05kd6he7wcvpzr9sd6gs2jvrn5keh,glebanyy,10964792231490 (0.03%)\n 10. oasis1qzxtc82d7gmcr5yazlu786gkwcvukz3zvu9ph5la,ushakov,10954729838903 (0.03%)\n 11. oasis1qpgg65qg7r7yy2a0qp2yufvcsyl2lm46lg03g6cp,Breathe and Stake,10942254111385 (0.02%)\n 12. oasis1qrruwg0y4au55efu0pcgl0nanaq6p3sdwv0jhzv5,Dobrynya Hukutu4,10753083746804 (0.02%)\n 13. oasis1qq6k7q4uukpucz322m8dhy0pt0gvfdgrvcvrx2rm,Spectrum Staking,10724618200610 (0.02%)\n 14. oasis1qr2jxg57ch6p3787t2a8973v8zn8g82nxuex0773,Doorgod,9959349109598 (0.02%)\n 15. oasis1qrp0cgv0u5mxm7l3ruzqyk57g6ntz6f8muymfe4p,ELYSIUM,9536638984147 (0.02%)\n 16. oasis1qrfeessnrnyaggvyvne52aple2f8vaw93vt608sz,Julia-Ju,7765469996624 (0.02%)\n 17. oasis1qz9x0zpja6n25hc5242k2e60l6a7ke2zsq9cqrqz,SerGo,5553178612897 (0.01%)\n 18. oasis1qq4fj0fdydz83zvcgt4kn38ea7ncm3dj8qkcfnm4,Wanderer Staking,5471851136155 (0.01%)\n 19. oasis1qzcemlzf7zv2jxsufex4h9mjaqwy4upnzy7qrl7x,Making.Cash Validator,5461635837440 (0.01%)\n 20. oasis1qrq7hgvv26003hy89klcmy3mnedrmyd7lvf0k6qn,Perfect Stake,4040750411525 (0.01%)\n 21. oasis1qqxxut9x74dutu587f9nj8787qz4dm0ueu05l88c,Princess Stake,3406051188880 (0.01%)\n 22. oasis1qq45am6gzaur2rxhk26av9qf7ryhgca6ecg28clu,Jr,2201101606599 (0.01%)\n 23. oasis1qz7rce6dmnh9qtr9nltsyy69d69j3a95rqm3jmxw,Everstake,2171181028607 (0.00%)\n 24. oasis1qz8w4erh0kkwpmdtwd3dt9ueaz9hmzfpecjhd7t4,Chloris Network,2011713919098 (0.00%)\n 25. oasis1qzlzczsdme4scprjjh4h4vtljnmx3ag4vgpdnqln,Alexander (aka Bambarello) Validator,1757051650379 (0.00%)\n 26. oasis1qzwe6xywazp29tp20974wgxhdcpdf6yxfcn2jxvv,Simply Staking,1388519563110 (0.00%)\n 27. oasis1qq2vdcvkyzdghcrrdhvujk3tvva84wd9yvt68zyx,Lusia,1300150706950 (0.00%)\n 28. oasis1qphcvmsh6mw98vtg0cg4dvdsen5tm0g3e58eqpnp,Appload,1221281508316 (0.00%)\n 29. oasis1qpc66dgff4wrkj8kac4njrl2uvww3c9m5ycjwar2,Forbole-Testnet,1112551173826 (0.00%)\n 30. oasis1qzz9wdgt4hxfmcelfgyg8ne827a47pvh4g4jamtu,max999,1096825296654 (0.00%)\n 31. oasis1qz5zfcaqqud75naqln92ez7czjxf0dpyj5rmtfls,alexandr0,1096729833573 (0.00%)\n 32. oasis1qz4532s3lhkpju7fd3mxqfvaw98pjq5htss4g4w0,RedHead,1096422596648 (0.00%)\n 33. oasis1qphhz4u08xgt4wk85x4t8xv6g3nxy8fq5ue4htxr,Kumaji,1042663336329 (0.00%)\n 34. oasis1qrrggkf3jxa3mqjj0uzfpn8wg5hpsn5hdvusqspc,Bit Cat\ud83d\ude3b ,959384168121 (0.00%)\n 35. oasis1qz6tqn2ktffz2jjlj2fwqlhw7f2rwwud5ghh54yv,WeHaveServers.com,933754283937 (0.00%)\n 36. oasis1qpswaz4djukz0zanquyh2vswk59up22emysq5am9,StakeService,879748845930 (0.00%)\n 37. oasis1qq87z733lxx87zyuutee5xpxcksqk3mj9uq3xvaq,w3coins,819152557031 (0.00%)\n 38. oasis1qrcf5mwjyu7hahwfjgwmywhy9cjyaqdd5vkj7ah3,ou812,418376899484 (0.00%)\n 39. oasis1qpxaq8thpx3y8wumn6hmfx70rvk0j9cxrgz9h27k,Colossus,410141268162 (0.00%)\n 40. oasis1qr4vsan850vmztuy9r2pex4fj4wxnmhvlgclg500,<none>,327983310482 (0.00%)\n 41. oasis1qqgvqelw8kmcd8k4cqypcsyajkl3gq6ppc4t34n2,AnkaStake,220810245010 (0.00%)\n 42. oasis1qrpp8h9wl3wtqn04nvyx4dcrlz3jzqazugec7pxz,CryptoSJ.net,213393794996 (0.00%)\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"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!"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network"})," selector is available for the\n",(0,s.jsx)(n.code,{children:"governance show"})," command."]})}),"\n",(0,s.jsx)(n.h4,{id:"governance-cast-vote",children:(0,s.jsx)(n.code,{children:"cast-vote"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"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,s.jsx)(n.code,{children:"yes"}),",\n",(0,s.jsx)(n.code,{children:"no"})," or ",(0,s.jsx)(n.code,{children:"abstein"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network governance cast-vote 5 yes\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"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"})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network and account"})," selectors are available for the\n",(0,s.jsx)(n.code,{children:"governance cast-vote"})," command."]})}),"\n",(0,s.jsx)(n.h4,{id:"governance-create-proposal",children:(0,s.jsx)(n.code,{children:"create-proposal"})}),"\n",(0,s.jsxs)(n.p,{children:["To submit a new governance proposal use ",(0,s.jsx)(n.code,{children:"network governance create-proposal"}),".\nThe following proposal types are currently supported:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"cancel-upgrade <proposal-id>"}),": Cancel network proposed upgrade. Provide the\nID of the network upgrade proposal you wish to cancel."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"parameter-change <module-name> <changes.json>"}),": Network parameter change\nproposal. Provide the consensus module name and the parameter changes JSON.\nValid module names are: ",(0,s.jsx)(n.code,{children:"staking"}),", ",(0,s.jsx)(n.code,{children:"governance"}),", ",(0,s.jsx)(n.code,{children:"keymanager"}),", ",(0,s.jsx)(n.code,{children:"scheduler"}),",\n",(0,s.jsx)(n.code,{children:"registry"}),", and ",(0,s.jsx)(n.code,{children:"roothash"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"upgrade <descriptor.json>"}),": Network upgrade proposal. Provide a JSON file\ncontaining the upgrade descriptor."]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network and account"})," selectors are available for all\n",(0,s.jsx)(n.code,{children:"governance create-proposal"})," subcommands."]})}),"\n",(0,s.jsx)(n.h3,{id:"show",children:"Show Network Properties"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"network show"})," shows the network property stored in the registry, scheduler,\ngenesis document or on chain."]}),"\n",(0,s.jsxs)(n.p,{children:["By passing ",(0,s.jsx)(n.code,{children:"--height <block_number>"})," with a block number, you can obtain a\nhistoric value of the property."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network"})," selector is available for the\n",(0,s.jsx)(n.code,{children:"network show"})," command."]})}),"\n",(0,s.jsx)(n.p,{children:"The command expects one of the following parameters:"}),"\n",(0,s.jsx)(n.h4,{id:"show-entities",children:(0,s.jsx)(n.code,{children:"entities"})}),"\n",(0,s.jsxs)(n.p,{children:["Shows all registered entities in the network registry. See the\n",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#entity",children:(0,s.jsx)(n.code,{children:"account entity"})})," command, if you want to register or update your own entity."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"This call is not enabled on public Oasis gRPC endpoints. You will have to run\nyour own client node to enable this functionality."})}),"\n",(0,s.jsx)(n.h4,{id:"show-nodes",children:(0,s.jsx)(n.code,{children:"nodes"})}),"\n",(0,s.jsxs)(n.p,{children:["Shows all registered nodes in the network registry. See the ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#entity",children:(0,s.jsx)(n.code,{children:"account entity"})}),",\nto add a node to your entity."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"This call is not enabled on public Oasis gRPC endpoints. You will have to run\nyour own client node to enable this functionality."})}),"\n",(0,s.jsx)(n.h4,{id:"show-paratimes",children:(0,s.jsx)(n.code,{children:"paratimes"})}),"\n",(0,s.jsx)(n.p,{children:"Shows all registered ParaTimes in the network registry."}),"\n",(0,s.jsx)(n.h4,{id:"show-validators",children:(0,s.jsx)(n.code,{children:"validators"})}),"\n",(0,s.jsx)(n.p,{children:"Shows all IDs of the nodes in the validator set."}),"\n",(0,s.jsx)(n.h4,{id:"show-native-token",children:(0,s.jsx)(n.code,{children:"native-token"})}),"\n",(0,s.jsx)(n.p,{children:"Shows information of the network's native tokens such as its symbol, the number\nof decimal points, total supply, debonding period and staking thresholds."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show native-token\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"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"})}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsxs)(n.p,{children:["Next, we can observe that the ",(0,s.jsx)(n.strong,{children:"total supply"})," is 10 billion tokens and that\nabout 1.3 billion tokens are in the ",(0,s.jsx)(n.strong,{children:"common pool"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"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,s.jsx)(n.em,{children:"escrow"}),") at least\n300 tokens."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["Each runtime may also require a ",(0,s.jsx)(n.strong,{children:"minimum ParaTime-specific escrow"})," for\nrunning a compute node. Use the ",(0,s.jsx)(n.a,{href:"#show-id",children:(0,s.jsx)(n.code,{children:"network show id"})}),"\ncommand and pass a corresponding Paratime ID to see it."]})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"runtime-"})," fields show you the required staked amount for\n",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/paratime#register",children:(0,s.jsx)(n.strong,{children:"registering a new ParaTime"})})," of any kind (compute,\nkey manager) was 50,000 tokens at time of writing."]}),"\n",(0,s.jsx)(n.h4,{id:"show-gas-costs",children:(0,s.jsx)(n.code,{children:"gas-costs"})}),"\n",(0,s.jsx)(n.p,{children:"Shows minimum gas costs for each consensus transaction."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show gas-costs\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"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"})}),"\n",(0,s.jsxs)(n.p,{children:["Above, we can see that the ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#gas-limit",children:"maximum amount of gas"})," our\ntransaction can spend must be set to at least 1000 ",(0,s.jsx)(n.strong,{children:"gas units"}),", otherwise it\nwill be rejected by the network."]}),"\n",(0,s.jsx)(n.h4,{id:"committees",children:(0,s.jsx)(n.code,{children:"committees"})}),"\n",(0,s.jsx)(n.p,{children:"Shows runtime committees."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show committees\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"=== COMMITTEE ===\nParatime: sapphire(000000000000000000000000000000000000000000000000f80306c9858e7279)\nHeight: 19241881\n\nENTITY ID NODE ID ROLE \nT5k7PtOR01oZrdnZveDpO9AFpMUhEREZk7WSSfm8Gtg= RT7JKF5T1hlKXTYZsp4SL07f4IHG6O0SQppf8wnfr+Y= worker \noOVxTw2hEYgYvSrTjjKODCt/Soy3OLcQV9YBy/PF/xY= Io86AKuu7YDnya+fVnldHBybFggwCoXeQPu3Wj8kHW4= worker \nsDi9ZxHYB+rHTpVh4abNFXDMRSecfGe4QzbyGK8ZgQg= FEMUVK91HEULeQpMZj07jN2giNKjd6HPK3VdjsIQcjY= worker \nRMa2ER0wvraR+4u5QOGOrRTwmMVOYNcOot7sFppPRP0= DW4/7kVEumpZV1CmntaQBncSV36t6QoE0QwQd5pLIZU= worker \n21+iPu/omYBN7X5cUY4QnD4b9VVuAiW/u8uABqt2VjM= x8DFPc8E9BZxLJKbh51xj41es3R53AkJERfMEyRCrbk= worker \n7nCBfl1vRS4kn7G2yJZeZdwE8OFA4avUphWdCRrFhJM= drsZxbpqG5h+4tq/JKWqmoVGXmQUirVCjD8GLBuNj9M= worker \niGs5cCGos/I5KQv82MwgGMNENaxy3bhuWdFXtINcu0U= HH/jnBO0AqHocNg4aS7MiMjiKmta1VP0ceRc0iILMAw= worker \nko5wr5SMqhKb+P1kimM1EF/T4SqvW/WjSOwPHigQl+k= aJFHeID4Q7qUfMa42dRwaa9PQrZ/cVDiE3WNt4bQjo0= worker \nUDV5FoaIkssdSFWC4asZtxvsyagoyrIS5rPX8p/np2U= 86y1tHzH9GlxvS0Bneh5l2AUDXYO6VMrzx75JvJViNE= worker \nBdSzNycR8Y3MdHooxU0vtOEPr3ZG9KD5p8wxHtvueUU= +JOOp6OMmzldm9Dy7Cnbl/FE66bNkU0TJquOYnQIv7s= worker \nnw+8VTk+LbrZ4mSmeKYuQGu/swFgAOpPB5ls4STzh1g= XCiPWblWT3n1aN2NI0vslmlfV9GOkxE2Ih2SI66ZR38= backup-worker\nJ2nwlXuYEPNZ0mMH2Phg5RofbZzj65xDvQMNdy9Ji0E= ITrwEekdZNqXrEzvw3GT6Q3AtHDd51f19nD2nVU/f0c= backup-worker\nsDi9ZxHYB+rHTpVh4abNFXDMRSecfGe4QzbyGK8ZgQg= FEMUVK91HEULeQpMZj07jN2giNKjd6HPK3VdjsIQcjY= backup-worker\n6XvrCu3wqMKYc5a0d5UZzG7ZGeb3j//MzcqUMUHkMCk= C+AWG4iXz590kCdbO/DAb4sBZr+umjyp683ucmawdM4= backup-worker\nT5k7PtOR01oZrdnZveDpO9AFpMUhEREZk7WSSfm8Gtg= RT7JKF5T1hlKXTYZsp4SL07f4IHG6O0SQppf8wnfr+Y= backup-worker\nRFpWeibJDHnfgoq9mO1BJcxyDbIstDi22ZBhvgXvE1Y= YTHRajyCrIwOiys1ktOarSUyV1NVolvAw6DQqhaXg6w= backup-worker\nLQaKibf9tD8KXO210NhiDUHzXTsRIeK5l/3ITmfg118= 7/WyW54TO+31VkXZcj4xIAgv5kWxR6azSEjwrSAte3Y= backup-worker\nhNBVs2ay1IWvufQwX0TbYA6X4ocKaMpzpyaMTHggi6Q= bKvnByvx8qwF41EqOG6wdmatGzz/qT2nbHC8i8VM65k= backup-worker\nUDV5FoaIkssdSFWC4asZtxvsyagoyrIS5rPX8p/np2U= 86y1tHzH9GlxvS0Bneh5l2AUDXYO6VMrzx75JvJViNE= backup-worker\n9yOiPY3NnNMpEzB+6XS/OqahzFwwX8mFhmT2fvbxlVI= mIKW8IEDWZZxCRtDTvWQLpslvfUBwWxVAxLakwq25C8= backup-worker\nnZoBfua/odt7fZThkfzGQo2oBp8UnEj+VpG52SB8onM= 70ibfZrA3+d9O4qNnecsXceTCvsLTywOjNQfN83MYQQ= backup-worker\n1JttHp0rBBBHDOpPl8fAiLTcN9tUzxJGjk7llFcvhZQ= rK6mrmCRi2dYPNraNwqg2jgEVi4sd6hi53JmT2HVGxQ= backup-worker\n4gbOOU09bcyvM53Up1lTnP+sLb0feniJu0OcUUPCBSs= +zVbgQqOdY90Z2NQKXFByNT0OwLxj/Ho4j4qT5u2yKM= backup-worker\nfhXoWYc8Ml153jBBvFrQ4CRY7vnbCk9j269rVLeg7cE= NM/XberrrMrvavGDCYc9CX8HPT1TPz1YHWuBaDArDHc= backup-worker\nWXs7ElBlm30la2fG4oZDpubeFu5sKkjDVeflWo+YuIA= ST2B7aeKSspiFNy325rIh8alQIRVCDyZ5t8f2NKN3PU= backup-worker\n\n=== COMMITTEE ===\nParatime: emerald(000000000000000000000000000000000000000000000000e2eaa99fc008f87f)\nHeight: 19241881\n\nENTITY ID NODE ID ROLE \nL4OY/0mNEduAS9z6jh2xLp72b8gZURgcrd76AOiRIXk= fGqOEIbBxaM2YmMcKq4PbpUOd9+s3TcS4AxaTChGuz0= worker \ng9UqzvW6JvfKrflRKbCPBpm41rH/O+4apCK+KkD2tG4= 4wqhqp5wDAfvQxNZUUSDmM2fVYrkxKq/tqjnnCe72Uw= worker \nPrCDIA3uyoLqNOZJ1PrRWdyviFn6K0PWFz91qQ9QyTw= o8p0FlVg1Wlv+ZLKojWS7c0P4xZHklFt9frLW4B4QlE= worker \nbTok0el8GbmUzTAAgcQ78uww/TsgeWwXpM3N2S49qBQ= cb/avZHoAQkZiHGzkjJxEkVsqiiiJzL/5fHp1TsDTdY= worker \nBTAJNDyd6/UQ+pfhTDdPGsothzJ+C5/C/g52a3DIlMw= RV/KmNN7oWH7qDjx/7kn+o9nsyd52CPUauF9MGvxl70= worker \n4gbOOU09bcyvM53Up1lTnP+sLb0feniJu0OcUUPCBSs= +zVbgQqOdY90Z2NQKXFByNT0OwLxj/Ho4j4qT5u2yKM= worker \nRMa2ER0wvraR+4u5QOGOrRTwmMVOYNcOot7sFppPRP0= 4mcgJKfEa6RqWh9NqSJ+/yfs6X8dU0tG1dI1L0lFNzM= worker \n6XvrCu3wqMKYc5a0d5UZzG7ZGeb3j//MzcqUMUHkMCk= VtP8ubAEY1p8iOshGDUqxrZGstnswozt7h1wlMAvba8= worker \n1YeMK0NAZtE1ZK8u6KWddkKGZoD5VLfG9EAZI3b8HzE= bhVU8RdrUXE7XgI7hIIdMFOhsomBFmPEnNU9zFPTHzY= worker \ncVGc1fI6xu0WeI2GUrLIwDpH/JtBE3PwD+P66YkSKg8= giemTZIHjRmBA3FzYMK01eokfs8L/VmusK3M5+lUdGc= worker \n4gbOOU09bcyvM53Up1lTnP+sLb0feniJu0OcUUPCBSs= +zVbgQqOdY90Z2NQKXFByNT0OwLxj/Ho4j4qT5u2yKM= backup-worker\np1VsfSsedbKn/5GzkPsr15XD+/AOIfbPda1/2yT84N4= S2eoEMq6Qzms5Yd/fIOhSEacHp7Pym0BfgBEmsijEDw= backup-worker\nbTok0el8GbmUzTAAgcQ78uww/TsgeWwXpM3N2S49qBQ= cb/avZHoAQkZiHGzkjJxEkVsqiiiJzL/5fHp1TsDTdY= backup-worker\nsDi9ZxHYB+rHTpVh4abNFXDMRSecfGe4QzbyGK8ZgQg= Dpj1ibIMtTHMh/i5qh0eZcGGmOVODELSHvg/ZFBIPbY= backup-worker\nUFXCpcvXBOHbxtObG4psGcn+LgZOedvDDUAqVengpPk= rczLI7bYocBYyQ+bsnHPNPKc+SJpunQiuxip/tNlolw= backup-worker\nRMa2ER0wvraR+4u5QOGOrRTwmMVOYNcOot7sFppPRP0= 4mcgJKfEa6RqWh9NqSJ+/yfs6X8dU0tG1dI1L0lFNzM= backup-worker\nkupW3Pt0XMeERSkdDWyZMU4oZrk0wGysVXVyqX3rylc= BZvhmvc1YZpXteI2nPhBDyC2jxi04MHEbKXB1DpTM1w= backup-worker\n6XvrCu3wqMKYc5a0d5UZzG7ZGeb3j//MzcqUMUHkMCk= VtP8ubAEY1p8iOshGDUqxrZGstnswozt7h1wlMAvba8= backup-worker\nTWLcdgEfahwyFPTC7nN3rZacPO2aXlLfZIDt7uXbzEI= 5uD3zbTZGhivYt1ZQw/Yr/Bcg2t6zEdyR9Ogg5ipkho= backup-worker\noOVxTw2hEYgYvSrTjjKODCt/Soy3OLcQV9YBy/PF/xY= jVPUq8aUDKe9jawIs7wPB4NBml27ft5kICIY7SBh/yQ= backup-worker\nWXs7ElBlm30la2fG4oZDpubeFu5sKkjDVeflWo+YuIA= RzMsfs49HQDT5fIVKQ+flR/sCJjrkKDPsc5ZS6O7VdM= backup-worker\n1YeMK0NAZtE1ZK8u6KWddkKGZoD5VLfG9EAZI3b8HzE= bhVU8RdrUXE7XgI7hIIdMFOhsomBFmPEnNU9zFPTHzY= backup-worker\ncVGc1fI6xu0WeI2GUrLIwDpH/JtBE3PwD+P66YkSKg8= giemTZIHjRmBA3FzYMK01eokfs8L/VmusK3M5+lUdGc= backup-worker\nnZoBfua/odt7fZThkfzGQo2oBp8UnEj+VpG52SB8onM= urRVg0K+6UhuxOnRE1/wIiPuuTu188orpsLDTz5NFTw= backup-worker\nUkwjS1YvEfHx9b6MMT5Q1WvCY3aWn2lxRDsB/Pw+zGk= CdkWAAnsdYg0g6yl90Eiqdwqer6NK9yIxWWvPR3fwD8= backup-worker\nPrCDIA3uyoLqNOZJ1PrRWdyviFn6K0PWFz91qQ9QyTw= o8p0FlVg1Wlv+ZLKojWS7c0P4xZHklFt9frLW4B4QlE= backup-worker\nnw+8VTk+LbrZ4mSmeKYuQGu/swFgAOpPB5ls4STzh1g= XCiPWblWT3n1aN2NI0vslmlfV9GOkxE2Ih2SI66ZR38= backup-worker\nBTAJNDyd6/UQ+pfhTDdPGsothzJ+C5/C/g52a3DIlMw= RV/KmNN7oWH7qDjx/7kn+o9nsyd52CPUauF9MGvxl70= backup-worker\n1JttHp0rBBBHDOpPl8fAiLTcN9tUzxJGjk7llFcvhZQ= dN/aIe69HWFUHtOy/oqWdp1jw4fzOIljXLbMI79ilTo= backup-worker\nuxSkvFu6x4MIYV+M1VrDu3m/qbADs/1Ae3mWAcEmnaQ= 0qOmNfZvPDnjyzPU/97x1FWsl0d3UsImNiSNXd7lE/0= backup-worker\n21+iPu/omYBN7X5cUY4QnD4b9VVuAiW/u8uABqt2VjM= x8DFPc8E9BZxLJKbh51xj41es3R53AkJERfMEyRCrbk= backup-worker\nBdSzNycR8Y3MdHooxU0vtOEPr3ZG9KD5p8wxHtvueUU= CZgE+WU9T8YpTnPRosJYFqos9S8W53jGQKeRrRxMeQc= backup-worker\nFDqRmM1FyhaGas+lquWmGAKgMsU2rj7UESAlnOHtxco= qnRAoObwndP/P9otTzQ/9Z2+vmSQ1Pch7G4tGBSTxCo= backup-worker\nko5wr5SMqhKb+P1kimM1EF/T4SqvW/WjSOwPHigQl+k= aJFHeID4Q7qUfMa42dRwaa9PQrZ/cVDiE3WNt4bQjo0= backup-worker\nAX8zJsi0DnrrdwCi/8JJptXSy62kZgQcAYKlCYD4oN8= BqCqG8wuMVdnONN5bysITf0mYQD5FD+TEF5wrJttsSQ= backup-worker\naiTgGyYB2l4uAMG93Ajq5S4EXPIRkYDg1ICLjWD45Ck= pGkBYly79y2gJUEOau8XN04ErcfwrObO+W5+CYXJW5k= backup-worker\nkfr2A6K6TlvhQm4nz88Hczzkd2Aq5PlkxSpnmUUBAFs= KUjJArjDn1TtZOi6AgYki1fUTC2PrU0LJFJ4ppHt3NQ= backup-worker\ncgXH87+sYoe2mXsdDKWCyRvWZ8JqnVnxJkCq09LlBoI= 6ioksdd5uKtlNnPmCpu1NYohfamlb/QHiD8EhMuTbfw= backup-worker\nN+3/m12DoAqzFS0yF3R/kXSkSj7pZnWhq8nRCo/MKwk= zibJtnvTpDotvOK3a3nNYmlYwg/K4TdZB781TQCEAT4= backup-worker\n/ylWdaid2DDlI4BMVkX6gAR6eaBYlLolHbjCmHitrzc= 9sk2Nq2DFGv932dnavOIr02RnfQUOngggsn2HUEEfRg= backup-worker\n\n=== COMMITTEE ===\nParatime: cipher(000000000000000000000000000000000000000000000000e199119c992377cb)\nHeight: 19241881\n\nENTITY ID NODE ID ROLE \nbTok0el8GbmUzTAAgcQ78uww/TsgeWwXpM3N2S49qBQ= LI48Ol5Is045ijOAjiCiKFHKOyzwuGL6mMTr3F5cMdM= worker \n1YeMK0NAZtE1ZK8u6KWddkKGZoD5VLfG9EAZI3b8HzE= /dBEDGDBCu6TF5w9crktZ9aloTBpOGGSa6A8uVNunAo= worker \nsDi9ZxHYB+rHTpVh4abNFXDMRSecfGe4QzbyGK8ZgQg= FEMUVK91HEULeQpMZj07jN2giNKjd6HPK3VdjsIQcjY= worker \nko5wr5SMqhKb+P1kimM1EF/T4SqvW/WjSOwPHigQl+k= aJFHeID4Q7qUfMa42dRwaa9PQrZ/cVDiE3WNt4bQjo0= worker \n1JttHp0rBBBHDOpPl8fAiLTcN9tUzxJGjk7llFcvhZQ= kgTUu0eXQWfPaE8Li8NgXf0bsjXdupxIfM8moGrTMK4= worker \nUDV5FoaIkssdSFWC4asZtxvsyagoyrIS5rPX8p/np2U= VonN99SPIvJ6Aq8dS5JQG9g50svyuLwMHjXZYAAtLKo= backup-worker\nRMa2ER0wvraR+4u5QOGOrRTwmMVOYNcOot7sFppPRP0= k0g6YN7CFSgjaPU1EjVWXhzPVmEset+3sQ3c3NJ8Ys4= backup-worker\ncgXH87+sYoe2mXsdDKWCyRvWZ8JqnVnxJkCq09LlBoI= 6ioksdd5uKtlNnPmCpu1NYohfamlb/QHiD8EhMuTbfw= backup-worker\nnw+8VTk+LbrZ4mSmeKYuQGu/swFgAOpPB5ls4STzh1g= XCiPWblWT3n1aN2NI0vslmlfV9GOkxE2Ih2SI66ZR38= backup-worker\nWazI78lMcmjyCH5+5RKkkfOTUR+XheHIohlqMu+a9As= uvPTOOyC+Kb+Hl3Pw34S3/YC9IerAdZncyW08LIaTtw= backup-worker\nPrCDIA3uyoLqNOZJ1PrRWdyviFn6K0PWFz91qQ9QyTw= vI2QpEG/5LYwU+Fp52QsYxdRMRoy9j+pdJSb23tW3ng= backup-worker\nYDHYz/R+Y7pCodhmgkCqzoqqN54gzRfVE5fjZriX+RI= 7Rz1yAFZcAD06OOTZxx5LLDg2L5+1Me4304xZB8cgxU= backup-worker\nzAhtGrpk1L3bBLaP5enm3natUTCoj7MEFryq9+MG4tE= PsfFUQrXqGoFtowWZcoc8ilh8xHP94LvNYHvqQHpw1E= backup-worker\nwCGlLKUiTNr9Ba49YA6dDuqm9rdtPcKKsKzHqMBn+rc= vlG7mUtP7s2PsnARfyrI3mW/q4pcqRi3SHk2GxmQ2NM= backup-worker\nJ2nwlXuYEPNZ0mMH2Phg5RofbZzj65xDvQMNdy9Ji0E= ITrwEekdZNqXrEzvw3GT6Q3AtHDd51f19nD2nVU/f0c= backup-worker\noOVxTw2hEYgYvSrTjjKODCt/Soy3OLcQV9YBy/PF/xY= Io86AKuu7YDnya+fVnldHBybFggwCoXeQPu3Wj8kHW4= backup-worker\n\n"})}),"\n",(0,s.jsx)(n.h4,{id:"show-id",children:(0,s.jsx)(n.code,{children:"<id>"})}),"\n",(0,s.jsx)(n.p,{children:"The provided ID can be one of the following:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If the ",(0,s.jsx)(n.a,{href:"/core/runtime/identifiers",children:"ParaTime ID"})," is provided, Oasis CLI shows ParaTime information stored\nin the network's registry."]}),"\n",(0,s.jsx)(n.p,{children:"For example, at time of writing information on Sapphire stored in the Mainnet\nregistry were as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show 000000000000000000000000000000000000000000000000f80306c9858e7279\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\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'})}),"\n",(0,s.jsxs)(n.p,{children:["Network validators may be interested in the ",(0,s.jsx)(n.strong,{children:"ParaTime staking threshold"}),"\nstored inside the ",(0,s.jsx)(n.code,{children:"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,s.jsx)(n.a,{href:"#show-native-token",children:(0,s.jsx)(n.code,{children:"network show native-token"})})," command."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"If the entity ID is provided, Oasis CLI shows information on the entity and\nits corresponding nodes in the network registry. For example:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "v": 2,\n "id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=",\n "nodes": [\n "Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM="\n ]\n}\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network show Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM=\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\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'})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"status",children:"Status of the Network's Endpoint"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"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:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"the last proposed consensus block,"}),"\n",(0,s.jsx)(n.li,{children:"whether the node's storage is synchronized with the network,"}),"\n",(0,s.jsx)(n.li,{children:"the Oasis Core software version,"}),"\n",(0,s.jsx)(n.li,{children:"connected peers,"}),"\n",(0,s.jsx)(n.li,{children:"similar information as above for each ParaTime, if the node is running it."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"At time of writing, the following status of the official gRPC endpoint for\nMainnet was reported:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network status\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:"=== NETWORK STATUS ===\nNetwork: mainnet\nNode's ID: mVyn1iZkOAlP7AQRuhYHahAkUEGJmywY1G8raR5u/3I=\nCore version: 23.0.9\n\n==== Consensus ====\nStatus: ready\nVersion: 7.0.0\nChain context: bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55\nLatest height: 18458209 (2024-03-21 10:47:52 +0100 CET)\nLatest block hash: eb3fbe258b3066935de32158ac1b0cf2d3f79f5558682eee8f04f3afc80374ae\nLatest epoch: 30750\nIs validator: false\nRegistration: false\n\n==== ParaTimes ====\ncipher (000000000000000000000000000000000000000000000000e199119c992377cb):\n Kind: compute\n Is confidential: true\n Status: ready\n Latest round: 1612018 (2024-03-21 10:47:52 +0100 CET)\n Last finalized round: 1612018\n Storage status: syncing rounds\n Active version: 3.0.2\n Available version(s): 2.6.2, 3.0.2\n Number of peers: 30\nemerald (000000000000000000000000000000000000000000000000e2eaa99fc008f87f):\n Kind: compute\n Is confidential: false\n Status: ready\n Latest round: 9509250 (2024-03-21 10:47:52 +0100 CET)\n Last finalized round: 9509250\n Storage status: syncing rounds\n Active version: 11.0.0\n Available version(s): 10.0.0, 11.0.0\n Number of peers: 29\nsapphire (000000000000000000000000000000000000000000000000f80306c9858e7279):\n Kind: compute\n Is confidential: true\n Status: ready\n Latest round: 2958958 (2024-03-21 10:47:52 +0100 CET)\n Last finalized round: 2958958\n Storage status: syncing rounds\n Active version: 0.7.0\n Available version(s): 0.7.0\n Number of peers: 39\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can also view output in json format by passing the ",(0,s.jsx)(n.code,{children:"--format json"}),"\nparameter:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"oasis network status --format json\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n "software_version": "23.0.9",\n "identity": {\n "node": "mVyn1iZkOAlP7AQRuhYHahAkUEGJmywY1G8raR5u/3I=",\n "consensus": "CQVOWxM6nNl4zeatY2TC5ZtJ4vz6joP+HAZIbqwyKgw=",\n "tls": "NV7emPy4aoIScppvKMqJZpVN+q/6pqDrop9yvNbUpwU="\n },\n "consensus": {\n "status": "ready",\n "version": {\n "major": 7\n },\n "backend": "tendermint",\n "features": 3,\n "latest_height": 18270232,\n "latest_hash": "a586e2fc45b1d70f9b37331a5767cd365ec249a7cacb5630033c154dccb66ce7",\n "latest_time": "2024-03-08T10:46:02+01:00",\n "latest_epoch": 30437,\n "latest_state_root": {\n "ns": "0000000000000000000000000000000000000000000000000000000000000000",\n "version": 18270231,\n "root_type": 1,\n "hash": "420851d6af33cef0af7c16abce92db3a6d10fbd4ea1ee04d54b82764a30a5738"\n },\n "genesis_height": 16817956,\n "genesis_hash": "7670c86852c214f4e2b5ad571f4c2c344c630afdb409f7a5a3adce5a85240f31",\n "last_retained_height": 16817956,\n "last_retained_hash": "7670c86852c214f4e2b5ad571f4c2c344c630afdb409f7a5a3adce5a85240f31",\n "chain_context": "bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55",\n "is_validator": false,\n "p2p": {\n "pub_key": "/YOH7B2pk8Iff19lzWQ1qkKJ+PbXJtcyP6k7avW6NkE=",\n "peer_id": "e4f393164321e67b2ad1d62cd698aa175d4f7165",\n "addresses": [\n "/YOH7B2pk8Iff19lzWQ1qkKJ+PbXJtcyP6k7avW6NkE=@34.135.216.16:26656"\n ],\n "peers": [\n "9a4d7c9aabbab2967aea6ad01a8a8632c64a38f4@131.153.164.23:51314",\n "68d63f77952a6c2e5f0f7040402cba93cdeaa70a@95.216.72.47:38756",\n "140a7c1411ff0de81c8fa6744f31fdf654063eaa@135.181.22.224:26656",\n "4390496facda27743a10c2c0c5ff2c7e454e6e5d@95.216.37.80:45508",\n "1be3c26045608e81bd7c27a7aaa0366a70181f1b@131.153.164.11:49462",\n "19b24c4124e6a5e5eaf9508537544252e9202555@18.176.52.160:43004",\n "dba1969fc288a52d69d8cc8e08f9e5ef6882e42a@188.42.245.84:37856",\n "eb474e45eea6de5330f13d910a6be36864e439de@143.42.108.67:33896",\n "136d2d3b17be220719ab23a0611bc68e52323e5a@95.217.204.115:53792",\n "dc7ac801187cf1600072a4caad315e4f492c9b18@91.235.116.246:49064",\n "53c9ffebd7c2e96c1302ebe7bcd31382a69e5348@135.181.2.18:38514",\n "b74f519bb45738233bd8b5723accf0fa967fee46@131.153.158.203:46988",\n "c717bacf4fe474f881c31b63330a9d45bf9698ab@95.217.77.154:55244",\n "95d97246a37d44a226021cf9f5014b976e022416@20.232.103.170:53852",\n "0666e962c44875289b8355a4a8bf9d58c88c387e@52.194.107.16:30389",\n "f7e8a17f275543353d713315863577aad9a455c7@131.153.57.230:47004",\n "04e6c48bfb04f4642ce257d3a973aca74b265fdd@104.198.241.118:37838",\n "bf4cbb24920f04ae34ec7b568d79d89e44563413@66.165.251.58:33824",\n "d064899fa00e860734e3cb9839e6945f0fc8dce2@91.216.245.188:26656",\n "f4bde78f8ad065d3b74c3baf3e65e8ac9067789c@54.82.200.23:64728",\n "d6503409d1be441f290bb45aafe3c8f2343c0d02@94.130.25.75:25123",\n "3a0aa443bcafd6360fba8173c88be772dd010c3d@80.64.208.190:1720",\n "d6aabd0a4c9ec030828be419059cc77c19137510@93.157.248.142:26656",\n "ca0e733b946ef09491e2ad26f5425c404465b774@80.64.208.171:35165",\n "de3249501db9312f53556af293ca8f7d1ff5b093@87.119.223.15:59628",\n "c2ffb6c7b77aa504f4816789e5a4d4a42f29f36d@3.112.138.57:47988",\n "752af3d38aea5e8eff69161833658031f3d5ac44@217.79.252.130:44368",\n "8aa27f84baa1a340fb672f75027ec4655fd78968@34.135.12.249:52220",\n "322c5bce6cf858e4dedc1057fff879f2ca819e3d@15.235.183.125:60642",\n "8703c37574622728b19ac7cb76508284fb381279@86.111.48.51:47994",\n "ae36c8f46b340315691c7bf0bd8c77012fb2f86d@134.119.191.179:48932",\n "108fa65cc0e82191dbdc64cd7fc916907acb0c17@34.71.93.50:26656",\n "24c362d09c1bedd98b9fe207916227f9b3d7d34e@66.85.141.242:53474",\n "cfbd5780a731690862b6ed42ab0fbd966dc4a14c@13.115.221.102:41614",\n "ffa875d275e8a30f1e0ded2af542fee3ceff4f2d@162.55.95.170:36756",\n "239246b126e70e8023201b2c4066cfb6eaf7d50c@52.194.8.37:59952",\n "4e98fd9344befa108c9ab714d673212bba5dc1b8@47.243.161.117:50270",\n "36189358cbed896d5ee7af2f0582d010b937403f@18.176.159.242:9313",\n "59ef3fe6a5e6520da1fc67e9684d74bb433f1320@47.242.42.58:35440",\n "3cc19a3fde93e22ce954c223aaf54c5e2e84cd32@142.132.213.82:26656",\n "5fb93f5ac86efeddc35062f7f3e789f1a0cd39d7@142.132.194.124:42358",\n "d22834f65843ac1aeabd424803699fd4b86b0a77@178.63.47.146:52052",\n "59e633dcef4db5f79a65dafc410e7815ea105e8e@135.181.179.38:16656",\n "a81d024f7f42ab190bb60f457c79c29abc2a9bb1@162.55.245.211:35566",\n "e7ad5f2aec34b3486ad91a40bd4439f67da77440@95.111.240.82:60716",\n "41df0b7f45a1b2164805b61576293ce04a0a57ec@165.232.81.5:49402",\n "ed8d710f7ba7a12df9f143a62aac322300124653@159.69.183.181:37520",\n "ec89299f6538af21aad50ee9a02b5ae2a1e3a67d@131.153.164.21:44180",\n "dd0d0ae872577c53a2a5e5886d2df1dec08e3311@65.109.20.222:40346",\n "5114f3918d2ce178376837e25baa31dd6ca75bc3@15.165.142.244:44556",\n "f2c77c2243949dbe0c1fe60146429e81f2a56b6e@92.42.109.183:58922",\n "d8b549e447292d1b36987a70836e0b59e3b75121@54.208.50.80:26656",\n "f5ba16af030d45322508bf43ee83fd93f0491b5d@66.85.141.186:57306",\n "2ae1b6657b434aa34bde472f880051ec0e1423b2@134.119.190.191:42154",\n "d11601b05409a7a6b887f533bafe60890ab9ea66@47.242.195.167:35402",\n "bbfac1c724eb4e3f7787b6b2db96f99fda5d252d@65.108.6.54:32884",\n "f8b16418e95d6508b98479f7ba086c57baf4bee1@167.172.31.178:26656",\n "24e7035e8380ca2cfbce8850522a628f93ba70cf@45.125.23.194:60234",\n "c36236d658276737cd96ceffd700d80895053812@157.90.199.94:52664",\n "b2b267a52aec2bc9203e4efb4bb06da4ed37ae12@95.217.34.120:56976",\n "5e2538898cba75f1d58a9a8bc33059a72d8ec80e@174.138.162.2:46720",\n "e15e2a29672bc0784b45ea1bf81d51e0fc5f1bbb@134.119.194.139:39384",\n "6c18886e0b16d93410db563fc7d66804b74b9796@23.88.38.81:26777",\n "85d744388148b6d2c10a66b40ef7c9e73e5a99cc@212.126.35.132:33970",\n "412890d778a3d90123a156ff01e8af563622ffaf@164.68.120.119:42900",\n "378ce07a57fc2d7caffd2d3a8a15ecafa0cebc88@35.79.207.60:1261",\n "0107967d77c59c9f2741bf8ca2d1ad393913f1ff@65.109.34.46:26656",\n "e2bcd89092c40eaee9694c9389ff687ab1d8a6b7@148.251.246.233:45818",\n "e983bcecaae17c3c77be98eeae9740e773f03799@8.217.165.72:40986",\n "232730ebcb4350c9390ceb85d690563474e4caea@157.90.89.253:26686",\n "925583eb4e02a5cb69e18fd5eddac27ffad639e5@195.189.97.15:42656",\n "78ddec184305cb332a4f223331fa387d91f57301@51.79.176.85:40294",\n "4c8622ff6fc152a13fe394f95c85f0c32a991d6f@65.21.90.141:27656",\n "4eeba1ead5b7ede2c968426d0104935bf7ee8a49@212.232.29.233:49322",\n "a51cda7babb0994b52fe70ff658915ebdd5f167a@93.115.25.138:60204",\n "15c88aac912c1020b3d49a90fb894dff738c476a@131.153.164.15:26656",\n "1b611282f1f06262b38fdd16958dd70f083f532d@80.64.208.154:36889",\n "ecc168dd1bef0d6e325d7191d546c18dfbeadac2@54.199.153.43:42473",\n "2d1b795f1cf73cfce05f43cdeec7ea7d01a52cac@35.232.154.67:38088",\n "e527309ff618bfc41904bbb93317781aaccefd1a@84.234.97.201:44462",\n "c426e80e4972e3efb0a85588e6f3712f53e463e9@142.132.203.173:44226",\n "d0c65475d3db97663678d7546ae6fa68c5464e5e@131.153.205.66:46844",\n "aa246b072060eb700001fe25cd03bbb42a72fff4@193.34.212.218:34726",\n "bd8c0023bd9046c13b7bccf1bef3b2a0ba0541d4@52.204.103.24:47011",\n "273d1d2ab06c0caf522fd63a0d8948dd9d4fd439@65.109.30.110:40366",\n "b8994b04adf1393b4957ccfd3406361455046897@159.69.59.60:39980",\n "e6e6cdb013ec62313e1062e8247f10edb4daa113@95.217.144.50:60244",\n "49991aac0a36020204b14cb4311ab5b42fb8f771@93.115.25.171:48408",\n "51dd31bb5e86b2014b16e058f00fff8a9dc81e83@65.108.127.220:60148",\n "36abd07fba6e9fe6c28a8106e7e314ba4ac738bc@92.42.109.101:33444",\n "1638e5805abc75ee7575bea77a246e3b81a7c23c@135.181.62.168:26656",\n "c06a9e8cc5e33997d4d224418d9e936887fa5ed3@185.107.80.40:45312",\n "e98583c0682d6c65991923f6d0dad5d6599fc756@54.249.45.3:35356",\n "82af2cf1624cebbf3cb91efb0639c4296d8fd434@51.222.154.19:26656",\n "56cb4457419f814c0c3722e8cc84558b36d1dbf0@131.153.158.145:51058",\n "7ca85f4942e424935f9b8e5fc3fd52465d0b6e53@65.21.73.113:35790",\n "645d7abf7b0e89845b5cdc74baa9131099966332@34.252.55.98:59878",\n "d02357dfe32dadfa21fbad9129a793d836627d2c@95.217.118.121:16656",\n "4f6c97a1ede39d37c2445037e2493a9ba45eb6c2@92.204.248.255:48548",\n "184f768af5a8fa8bb4e9336261da4bb47757b0c7@185.188.42.107:46258",\n "0435bcb4c96099853a5577a179193eeffac1ad56@136.244.86.89:42430",\n "b9b9a5d34b7cf19fc22fc8055608c39f506cd46a@129.226.155.121:13549",\n "462dc40e72a895c054b885a6777c8eb609fe0169@34.48.1.200:59758",\n "078adc90344d7c7c261625ea4a3d5f223d4618fd@146.59.85.227:43726",\n "4bc1ce84911cea6a17ee3c5564fd658e09798245@80.64.208.193:17990",\n "9fb0071d9630e2e1592e912d52565933ee292549@65.108.201.32:52640",\n "bff37dfb8bda01e432369e8267272ebc47e32523@178.63.93.41:46318",\n "b22d7ed700f22390e0f4e3de051561b032a80818@84.39.245.93:39652",\n "806d29e0c3a2072cd35544a01b279d74d222b575@64.25.109.153:56770",\n "1ecee321d4ac42a818ce14b4ac1f10775ea3ba56@78.46.18.44:33102",\n "ac6ccf89de3c109e6dd9f92d3210d7bc9887a0ee@193.201.82.155:55662",\n "b7c38b98134fb29257d05145fd997645e9333484@165.154.224.206:38834",\n "e27f6b7a350b4cc2b48a6cbe94b0a02b0dcb0bf3@35.199.49.168:60736",\n "0d8b2a311c5089230f9c1aacb925682fd64eabe4@13.125.182.16:52190",\n "52114be29ad3ea06c81feec22c8e4321205144ae@95.214.53.217:53468",\n "5e163829692be3dd1c5bc42ffbc836453516f4d8@51.89.190.189:43414",\n "1520ced3b1f1445988a72cbeda48a3d748860a62@70.165.57.67:20714"\n ]\n }\n },\n "light_client": {\n "latest_height": 18269956,\n "latest_hash": "a4a723371efe4eaef2cb6d98204961daa67ff6052b48a9445fff3f8413ee0c3b",\n "latest_time": "2024-03-08T10:18:42+01:00",\n "oldest_height": 16817956,\n "oldest_hash": "7670c86852c214f4e2b5ad571f4c2c344c630afdb409f7a5a3adce5a85240f31",\n "oldest_time": "2023-11-29T11:02:19+01:00",\n "peer_ids": [\n "12D3KooWDK97pWjMJDuu5Rq1eALHG2eyxzf2JAFccDh7sDgQUVwJ",\n "12D3KooWPxb48tCvx8mytzYwn7FU4qsmF5QUiK2upd16NXkctmUY",\n "12D3KooWA6en49Pg7fwLgZMUZGwURNyB98yDAJh9j74vV74kdD7V"\n ]\n },\n "runtimes": {\n "000000000000000000000000000000000000000000000000e199119c992377cb": {\n "descriptor": {\n "v": 3,\n "id": "000000000000000000000000000000000000000000000000e199119c992377cb",\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": 11,\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": 5000000000\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": 11\n }\n },\n "worker": {\n "validator_set": {},\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 11\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": 2\n },\n "valid_from": 20492,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggyJORh2eP/BKGIVTGWwyQowE65kx2EdME5DtKjbMcPxE="\n },\n {\n "version": {\n "major": 3,\n "patch": 2\n },\n "valid_from": 28186,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVgg2sZMDBwkVsRPxVr1GDArubMyzKn6Im0fhYgOh4CbSM4="\n }\n ]\n },\n "latest_round": 1433155,\n "latest_hash": "1e74144d52c955b33f8f5314d5febecddf5858ec4db28aca1567824af6503a87",\n "latest_time": "2024-03-08T10:46:02+01:00",\n "latest_state_root": {\n "ns": "000000000000000000000000000000000000000000000000e199119c992377cb",\n "version": 1433155,\n "root_type": 1,\n "hash": "b50a6918a1c2cfaef743025ac3cc8e78cbaed8c376751632564b81ef018a104d"\n },\n "genesis_round": 44054,\n "genesis_hash": "7f14a395c6daa1ec492152a29c8c27f5b84fba94e09652d765d6d0937ba2abfb",\n "last_retained_round": 44054,\n "last_retained_hash": "7f14a395c6daa1ec492152a29c8c27f5b84fba94e09652d765d6d0937ba2abfb",\n "committee": {\n "status": "ready",\n "active_version": {\n "major": 3,\n "patch": 2\n },\n "latest_round": 1433155,\n "latest_height": 18270232,\n "executor_roles": null,\n "scheduler_rank": 18446744073709551615,\n "peers": [\n "/ip4/51.210.116.110/tcp/30002/p2p/12D3KooWEvfS5EdnpcC8etv8eiE3oSkhWid2FEXb5oAisZT3AJyo",\n "/ip4/66.85.156.122/tcp/30002/p2p/12D3KooWN2wNNar6xWQuRem6QGaWie5u3StWWmdZm4xeZ4CFKADE",\n "/ip4/51.222.41.188/tcp/30002/p2p/12D3KooWKTvsowgyv3WRTVm2dvEBtxpKsshWKtKJmGriGDPdzRBM",\n "/ip4/93.107.154.131/tcp/30002/p2p/12D3KooWQZXoU1GFSSWsmqWALRz2nvukxENCPBKJGndTca3gfW8o",\n "/ip4/134.119.219.154/tcp/20103/p2p/12D3KooWCdX3M9s1HicZVDqEtuyJ8NPDihR4cZDdNroYxJgiCtsD",\n "/ip4/131.153.59.34/tcp/26892/p2p/12D3KooWB4GhP7dXsBnFjTpkgr3sCmwkKxcmDhkHKNxZ3CrGgHDR",\n "/ip4/51.89.234.42/tcp/30002/p2p/12D3KooWS74Wqr1ZYLWafymznv4ib48DzDdmgZzVqMkM2ntNg5DZ",\n "/ip4/80.64.208.193/tcp/30002/p2p/12D3KooWJArUJBm2ikBb8ZfDmVeXTrawXz9qscP1kCSuye2oraQv",\n "/ip4/131.153.164.15/tcp/30002/p2p/12D3KooWCixcEb3YyZqQnANYX9YLVuAxQ2tNaRapQuYh9TeTTFZV",\n "/ip4/131.153.99.10/tcp/30002/p2p/12D3KooWKPMS72iRgPDWczMVzKyYa3DSZmc771XDNXnMWVPnjfmJ",\n "/ip4/2.56.188.205/tcp/30003/p2p/12D3KooWApMJjg1bGe85Ag5WZVxnmvxhk3izxV3rD4KiWDeKQ2xK",\n "/ip4/134.119.190.237/tcp/30002/p2p/12D3KooWSPgs5SCss4U2RRXuuBhGv5HMcsZwsVNW426TtFUxJBKA",\n "/ip4/66.85.154.218/tcp/30002/p2p/12D3KooWRRbEUSjnw3FwLm368wd8pArGRG6YCYMhAdA8oWG1CgkT",\n "/ip4/131.153.57.226/tcp/30002/p2p/12D3KooWDzq86WGEqEHcVCYfhukxuYKPq7cjrCxwsYg5euBpTcfi",\n "/ip4/51.81.57.69/tcp/30002/p2p/12D3KooWAcrMmjagXif4ocSDeZxWT4XA8LMNinHASwrmG2uV64H5",\n "/ip4/51.91.75.150/tcp/30002/p2p/12D3KooWQaNYjegtZyFtyrRNCF1yxB3sgGtBgY8asgEpFEcXPJiS",\n "/ip4/84.234.97.201/tcp/30004/p2p/12D3KooWJy5LhH2z79Zu2Ki7HWjmwcHDxRuCNzLFxtz7ksYFQxXo",\n "/ip4/51.222.44.106/tcp/30002/p2p/12D3KooWSJ4WnjUY76cfiifujynaxD15QnCdQfzxuJsyqzat24rp",\n "/ip4/174.138.162.2/tcp/30002/p2p/12D3KooWAYVr6x3xpw7PCywXwbsneDc4eAN9SiaT4TndL61xE64J",\n "/ip4/131.153.158.97/tcp/30002/p2p/12D3KooWSnJtBMWpaYmwZgkHQApefXzuQhUxRencTzwyuXzuWpFf",\n "/ip4/212.232.29.235/tcp/35002/p2p/12D3KooWSHF3gtW3thCZVJ3HJJTHNyJMB273iEVbJHVPpRYpdmmb",\n "/ip4/80.64.208.194/tcp/30002/p2p/12D3KooWGTfuY6Umye8348GDgbfghM6gwLbFDQEdbpeXbahFRE5R",\n "/ip4/131.153.154.13/tcp/30002/p2p/12D3KooWGfyNBqnppXZ1jo8zRcav3uKunj85HGbEDqj67d72jbJv",\n "/ip4/66.85.139.42/tcp/25002/p2p/12D3KooWMqPvVGdzgz56jHVsAjL1W8YwR2FpiFvpR8SCw6SZxX32",\n "/ip4/185.107.80.40/tcp/30002/p2p/12D3KooWHHG9fq9bLSKSdtQXBtqMJj4K3zyDCUJU9PvEKj7CBFbw",\n "/ip4/131.153.165.57/tcp/30002/p2p/12D3KooWStTpimpJLSa85gsWG17SGpdh43pHogQDhzFGiKXDQAJe",\n "/ip4/34.135.12.249/tcp/9002/p2p/12D3KooWNxPsNEZa1P8cFoqHwevBAzjx81hAxUXPLs9nKajbUoy8",\n "/ip4/34.71.93.50/tcp/9002/p2p/12D3KooWD5SCMPhVVtSQEX4jbZym37BtNAADzr3XjrLYG558abKN",\n "/ip4/135.181.112.38/tcp/9200/p2p/12D3KooWSyaGh3PZScCVDZKteMTEszm4GXPBP2Fv8k5QfTLUvbhF",\n "/ip4/89.212.17.232/tcp/9200/p2p/12D3KooWPcz11AarnbjJaJyxz1y5C9nbVfVuJJqqbvFTrZ5RXRko",\n "/ip4/195.201.202.101/tcp/34648/p2p/12D3KooWMEnRxPekFYjyRvr6sTahT5LtCWiBaLmakoXgBbk9F7tQ"\n ],\n "host": {\n "versions": [\n {\n "major": 2,\n "minor": 6,\n "patch": 2\n },\n {\n "major": 3,\n "patch": 2\n }\n ]\n }\n },\n "storage": {\n "status": "syncing rounds",\n "last_finalized_round": 1433155\n },\n "provisioner": "sandbox"\n },\n "000000000000000000000000000000000000000000000000e2eaa99fc008f87f": {\n "descriptor": {\n "v": 3,\n "id": "000000000000000000000000000000000000000000000000e2eaa99fc008f87f",\n "entity_id": "TAv9qXjV4yBphnKLJcNkzois1TLoYUjaRPrMfY58Apo=",\n "genesis": {\n "state_root": "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",\n "round": 0\n },\n "kind": 1,\n "tee_hardware": 0,\n "executor": {\n "group_size": 10,\n "group_backup_size": 30,\n "allowed_stragglers": 1,\n "round_timeout": 2,\n "max_messages": 256,\n "min_live_rounds_percent": 50,\n "min_live_rounds_eval": 10,\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": 5000000000\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": 30\n }\n },\n "worker": {\n "validator_set": {},\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 30\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 "major": 10\n },\n "valid_from": 21437\n },\n {\n "version": {\n "major": 11\n },\n "valid_from": 28017\n }\n ]\n },\n "latest_round": 9322034,\n "latest_hash": "448e91c56b20536951d17f67fc71e975dcadfe33c4cf3307ec038ab8890712a4",\n "latest_time": "2024-03-08T10:46:02+01:00",\n "latest_state_root": {\n "ns": "000000000000000000000000000000000000000000000000e2eaa99fc008f87f",\n "version": 9322034,\n "root_type": 1,\n "hash": "cb811c51d318d72fdad434ec390f122210ec3d7f9001b78dccfd7095d0fe8c02"\n },\n "genesis_round": 7875129,\n "genesis_hash": "602632dba1fe37719925835a0e30e155668addf9cf91307d14b08c1362f38c80",\n "last_retained_round": 7875129,\n "last_retained_hash": "602632dba1fe37719925835a0e30e155668addf9cf91307d14b08c1362f38c80",\n "committee": {\n "status": "ready",\n "active_version": {\n "major": 11\n },\n "latest_round": 9322034,\n "latest_height": 18270232,\n "executor_roles": null,\n "scheduler_rank": 18446744073709551615,\n "peers": [\n "/ip4/65.108.127.220/tcp/46002/p2p/12D3KooWCM5fJRX7SZP2LzBqs9wQ1xdkf79u4HZjYVzPVUKYFhbq",\n "/ip4/88.198.49.137/tcp/46657/p2p/12D3KooWBsGC8isMUPqC56wkaLsq1cYgfkyybFXrsZMhjJBR7AHx",\n "/ip4/51.210.116.110/tcp/30002/p2p/12D3KooWEvfS5EdnpcC8etv8eiE3oSkhWid2FEXb5oAisZT3AJyo",\n "/ip4/34.48.1.200/tcp/30002/p2p/12D3KooW9whHFUP4G5apBgKNDMc1Uc4yb3E3opvPgqVrPC9T6Kvu",\n "/ip4/195.14.6.187/tcp/9200/p2p/12D3KooWALMakdAtrHbEHCMKXVaKuUqucYYRo9vXUQavjDj65eQQ",\n "/ip4/65.108.71.225/tcp/35002/p2p/12D3KooWML9Lyua1yqZa34FJpcydEYUzWNMHLrRj1NsnPbG3dvqH",\n "/ip4/66.85.156.122/tcp/30002/p2p/12D3KooWN2wNNar6xWQuRem6QGaWie5u3StWWmdZm4xeZ4CFKADE",\n "/ip4/51.222.41.188/tcp/30002/p2p/12D3KooWKTvsowgyv3WRTVm2dvEBtxpKsshWKtKJmGriGDPdzRBM",\n "/ip4/34.85.239.136/tcp/30002/p2p/12D3KooWEWDthPgwwhe1bvDp5rwTNs4M2q1UHUKtMyXBW4JCrfJs",\n "/ip4/131.153.59.34/tcp/26892/p2p/12D3KooWB4GhP7dXsBnFjTpkgr3sCmwkKxcmDhkHKNxZ3CrGgHDR",\n "/ip4/51.89.234.42/tcp/30002/p2p/12D3KooWS74Wqr1ZYLWafymznv4ib48DzDdmgZzVqMkM2ntNg5DZ",\n "/ip4/131.153.164.15/tcp/30002/p2p/12D3KooWCixcEb3YyZqQnANYX9YLVuAxQ2tNaRapQuYh9TeTTFZV",\n "/ip4/131.153.164.23/tcp/20103/p2p/12D3KooWLZ8qr2rUZKhMzj3kEFCSfEaSM7m9gKkexQ9hNLh3J42p",\n "/ip4/131.153.99.10/tcp/30002/p2p/12D3KooWKPMS72iRgPDWczMVzKyYa3DSZmc771XDNXnMWVPnjfmJ",\n "/ip4/66.85.154.218/tcp/30002/p2p/12D3KooWRRbEUSjnw3FwLm368wd8pArGRG6YCYMhAdA8oWG1CgkT",\n "/ip4/131.153.57.230/tcp/30002/p2p/12D3KooWDzq86WGEqEHcVCYfhukxuYKPq7cjrCxwsYg5euBpTcfi",\n "/ip4/51.91.75.150/tcp/30002/p2p/12D3KooWQaNYjegtZyFtyrRNCF1yxB3sgGtBgY8asgEpFEcXPJiS",\n "/ip4/51.222.44.106/tcp/30002/p2p/12D3KooWSJ4WnjUY76cfiifujynaxD15QnCdQfzxuJsyqzat24rp",\n "/ip4/174.138.162.2/tcp/30002/p2p/12D3KooWAYVr6x3xpw7PCywXwbsneDc4eAN9SiaT4TndL61xE64J",\n "/ip4/74.118.139.149/tcp/30002/p2p/12D3KooWPbvwm5SvjmYm4ghavhN3LHT4AV9MGeyPdUUxFqwjhwcC",\n "/ip4/135.181.112.38/tcp/9200/p2p/12D3KooWSyaGh3PZScCVDZKteMTEszm4GXPBP2Fv8k5QfTLUvbhF",\n "/ip4/104.198.128.161/tcp/9002/p2p/12D3KooWMRnHvBkAieXoWFCUwm8CanK8pNTK3qe7SM7qQqRaxetA",\n "/ip4/131.153.205.66/tcp/9200/p2p/12D3KooWC8aPyvutEPaBiRx2Sq1HK5DkBfxrtvicd7bShJY72Ham",\n "/ip4/89.212.17.232/tcp/9200/p2p/12D3KooWPcz11AarnbjJaJyxz1y5C9nbVfVuJJqqbvFTrZ5RXRko",\n "/ip4/195.201.202.101/tcp/34648/p2p/12D3KooWMEnRxPekFYjyRvr6sTahT5LtCWiBaLmakoXgBbk9F7tQ",\n "/ip4/43.157.5.35/tcp/9200/p2p/12D3KooWKEfhVy5mG6S2MerWVpYRUU9LJPVfnSN8agntumGwJ77P",\n "/ip4/34.135.12.249/tcp/9002/p2p/12D3KooWNxPsNEZa1P8cFoqHwevBAzjx81hAxUXPLs9nKajbUoy8",\n "/ip4/3.253.128.73/tcp/9200/p2p/12D3KooWHfda8yH4DRkvhSKiYqjFtwwtFkThMGRNNKyduR7Dz2wk",\n "/ip4/93.115.25.171/tcp/9200/p2p/12D3KooWCgRyX8HKYvtWcy5JBcFQ2NSrKXAR8YFsKruzfjgTN8in",\n "/ip4/34.71.93.50/tcp/9002/p2p/12D3KooWD5SCMPhVVtSQEX4jbZym37BtNAADzr3XjrLYG558abKN",\n "/ip4/157.90.89.253/tcp/9200/p2p/12D3KooWH6xTgP5rNRNKza4GD4S37btCwJzbrddLjrc4GprxpqbH"\n ],\n "host": {\n "versions": [\n {\n "major": 11\n },\n {\n "major": 10\n }\n ]\n }\n },\n "storage": {\n "status": "syncing rounds",\n "last_finalized_round": 9322034\n },\n "provisioner": "sandbox"\n },\n "000000000000000000000000000000000000000000000000f80306c9858e7279": {\n "descriptor": {\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": 10,\n "group_backup_size": 15,\n "allowed_stragglers": 4,\n "round_timeout": 2,\n "max_messages": 256,\n "min_live_rounds_eval": 60,\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": 5000000000\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": 15\n }\n },\n "worker": {\n "validator_set": {},\n "max_nodes": {\n "limit": 1\n },\n "min_pool_size": {\n "limit": 15\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": 7\n },\n "valid_from": 28190,\n "tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVgg5ww4lVfjy7mcDs3AfHnvq2Q4JbzXkh+UCeOukPjcJpc="\n }\n ]\n },\n "latest_round": 2775514,\n "latest_hash": "5f6ab3e90ea2778dfe2526a5e4d1466289abe5f09c2f7fec82e6f6b3ca3d7d83",\n "latest_time": "2024-03-08T10:46:02+01:00",\n "latest_state_root": {\n "ns": "000000000000000000000000000000000000000000000000f80306c9858e7279",\n "version": 2775514,\n "root_type": 1,\n "hash": "03f951006fea6ade82c9b1d350043784d61c4794d5bfd13145c2569348d0d20b"\n },\n "genesis_round": 1357486,\n "genesis_hash": "151309e2bee057eff11500d83834c59edaa0defdceabddf8d27bcf8dbbf11aa3",\n "last_retained_round": 1357486,\n "last_retained_hash": "151309e2bee057eff11500d83834c59edaa0defdceabddf8d27bcf8dbbf11aa3",\n "committee": {\n "status": "ready",\n "active_version": {\n "minor": 7\n },\n "latest_round": 2775514,\n "latest_height": 18270232,\n "executor_roles": null,\n "scheduler_rank": 18446744073709551615,\n "peers": [\n "/ip4/66.85.147.250/tcp/30005/p2p/12D3KooWN7fWvPgXqaD42LfpnZPdSrJpfjY7koPvL7MuJ6a9Zsag",\n "/ip4/93.107.154.131/tcp/30002/p2p/12D3KooWQZXoU1GFSSWsmqWALRz2nvukxENCPBKJGndTca3gfW8o",\n "/ip4/134.119.219.154/tcp/20103/p2p/12D3KooWCdX3M9s1HicZVDqEtuyJ8NPDihR4cZDdNroYxJgiCtsD",\n "/ip4/84.39.245.93/tcp/30102/p2p/12D3KooWP97nqRjJdQ32x1aLyGbhD5ruLYtZiJBVG4JD4Yy8fqgF",\n "/ip4/131.153.59.34/tcp/26892/p2p/12D3KooWB4GhP7dXsBnFjTpkgr3sCmwkKxcmDhkHKNxZ3CrGgHDR",\n "/ip4/51.89.234.42/tcp/30002/p2p/12D3KooWS74Wqr1ZYLWafymznv4ib48DzDdmgZzVqMkM2ntNg5DZ",\n "/ip4/131.153.164.15/tcp/30002/p2p/12D3KooWCixcEb3YyZqQnANYX9YLVuAxQ2tNaRapQuYh9TeTTFZV",\n "/ip4/131.153.99.10/tcp/30002/p2p/12D3KooWKPMS72iRgPDWczMVzKyYa3DSZmc771XDNXnMWVPnjfmJ",\n "/ip4/66.85.154.218/tcp/30002/p2p/12D3KooWRRbEUSjnw3FwLm368wd8pArGRG6YCYMhAdA8oWG1CgkT",\n "/ip4/131.153.57.230/tcp/30002/p2p/12D3KooWDzq86WGEqEHcVCYfhukxuYKPq7cjrCxwsYg5euBpTcfi",\n "/ip4/2.56.188.205/tcp/9200/p2p/12D3KooWFDWBBH6nskRDFEjvRghvp5Tu3DQ2ZStsBtjyS3wmpXcV",\n "/ip4/51.91.75.150/tcp/30002/p2p/12D3KooWQaNYjegtZyFtyrRNCF1yxB3sgGtBgY8asgEpFEcXPJiS",\n "/ip4/174.138.162.2/tcp/30002/p2p/12D3KooWAYVr6x3xpw7PCywXwbsneDc4eAN9SiaT4TndL61xE64J",\n "/ip4/131.153.158.97/tcp/30002/p2p/12D3KooWSnJtBMWpaYmwZgkHQApefXzuQhUxRencTzwyuXzuWpFf",\n "/ip4/92.42.109.101/tcp/30002/p2p/12D3KooWQyAVM5NVfYJHWZn6a5phHe8wZH3n3CVVNA7SF2JUtQu4",\n "/ip4/51.222.44.106/tcp/30002/p2p/12D3KooWSJ4WnjUY76cfiifujynaxD15QnCdQfzxuJsyqzat24rp",\n "/ip4/212.232.29.235/tcp/35002/p2p/12D3KooWSHF3gtW3thCZVJ3HJJTHNyJMB273iEVbJHVPpRYpdmmb",\n "/ip4/131.153.154.13/tcp/30002/p2p/12D3KooWGfyNBqnppXZ1jo8zRcav3uKunj85HGbEDqj67d72jbJv",\n "/ip4/66.85.139.42/tcp/25002/p2p/12D3KooWMqPvVGdzgz56jHVsAjL1W8YwR2FpiFvpR8SCw6SZxX32",\n "/ip4/185.107.80.40/tcp/30002/p2p/12D3KooWHHG9fq9bLSKSdtQXBtqMJj4K3zyDCUJU9PvEKj7CBFbw",\n "/ip4/131.153.165.57/tcp/30002/p2p/12D3KooWStTpimpJLSa85gsWG17SGpdh43pHogQDhzFGiKXDQAJe",\n "/ip4/51.210.116.110/tcp/30002/p2p/12D3KooWEvfS5EdnpcC8etv8eiE3oSkhWid2FEXb5oAisZT3AJyo",\n "/ip4/66.85.156.122/tcp/30002/p2p/12D3KooWN2wNNar6xWQuRem6QGaWie5u3StWWmdZm4xeZ4CFKADE",\n "/ip4/51.222.41.188/tcp/30002/p2p/12D3KooWKTvsowgyv3WRTVm2dvEBtxpKsshWKtKJmGriGDPdzRBM",\n "/ip4/131.153.158.145/tcp/20103/p2p/12D3KooWJebHaWqqsDXm38apaWT4RX83N119L8mMHh7GemZtKzQe",\n "/ip4/131.153.158.241/tcp/20103/p2p/12D3KooWL5r52yBoHmRL7gesjUZMM8QSf8Yi1iWLNh6fACEsoJQR",\n "/ip4/131.153.158.195/tcp/20103/p2p/12D3KooWJvttMywMUmxoNPzeE7NDRGSN56qQCNSoZmd95AEbfZhq",\n "/ip4/131.153.158.203/tcp/20103/p2p/12D3KooWPo5FYGDQQikFhrFfzHDw2XPKAfhX5NAtp4HePHFgKQQ2",\n "/ip4/20.231.83.188/tcp/9002/p2p/12D3KooWMRFWewSpssbH1ouKAPFohTwZWerY8q7HYnnRdbqHwW88",\n "/ip4/135.181.112.38/tcp/9200/p2p/12D3KooWSyaGh3PZScCVDZKteMTEszm4GXPBP2Fv8k5QfTLUvbhF",\n "/ip4/20.232.103.170/tcp/9002/p2p/12D3KooWDeXUzwZg4miWeBatCxhtzsq1VoReBZY651cCJPJQjkBX",\n "/ip4/89.212.17.232/tcp/9200/p2p/12D3KooWPcz11AarnbjJaJyxz1y5C9nbVfVuJJqqbvFTrZ5RXRko",\n "/ip4/131.153.164.11/tcp/20103/p2p/12D3KooWA6en49Pg7fwLgZMUZGwURNyB98yDAJh9j74vV74kdD7V",\n "/ip4/195.201.202.101/tcp/34648/p2p/12D3KooWMEnRxPekFYjyRvr6sTahT5LtCWiBaLmakoXgBbk9F7tQ",\n "/ip4/131.153.158.115/tcp/20103/p2p/12D3KooWPQbAYgnij8kwBZbDH2ArZV8Ch9vgHSP8bCKMph1S6FMm",\n "/ip4/44.213.118.127/tcp/9200/p2p/12D3KooWK52QkQdGFnjHLUVUurKZnCdUBFacnJ3gyCHWbqDthaet",\n "/ip4/131.153.147.30/tcp/9200/p2p/12D3KooWJQCVuzE6chjFRdHnn2M4SCXngZ87TmdDU3ccosMaQ4kt",\n "/ip4/34.135.12.249/tcp/9002/p2p/12D3KooWNxPsNEZa1P8cFoqHwevBAzjx81hAxUXPLs9nKajbUoy8",\n "/ip4/131.153.158.147/tcp/20103/p2p/12D3KooW9vQWrHSZZn3mKGZkFgCsP5XPHGnszr4A54etg67tR5YK",\n "/ip4/20.163.238.123/tcp/9002/p2p/12D3KooWLT8joftMLzdnDt1Lb2rZKNYZZ1PEWPg81GpcJMaErkzm",\n "/ip4/34.71.93.50/tcp/9002/p2p/12D3KooWD5SCMPhVVtSQEX4jbZym37BtNAADzr3XjrLYG558abKN",\n "/ip4/20.124.126.75/tcp/9002/p2p/12D3KooWQTkXHYy6UnSaHuZvET5JL3fe5fV5P1eqs7So2Fz5nsdT"\n ],\n "host": {\n "versions": [\n {\n "minor": 7\n },\n {\n "minor": 6,\n "patch": 4\n }\n ]\n }\n },\n "storage": {\n "status": "syncing rounds",\n "last_finalized_round": 2775514\n },\n "provisioner": "sandbox"\n }\n },\n "registration": {\n "last_attempt_successful": false,\n "last_attempt": "0001-01-01T00:00:00Z",\n "last_registration": "0001-01-01T00:00:00Z"\n },\n "p2p": {\n "pub_key": "/YOH7B2pk8Iff19lzWQ1qkKJ+PbXJtcyP6k7avW6NkE=",\n "peer_id": "12D3KooWSsyeFEkSTrGTWXhnnpVGPExNeNX7FYtuVUkrWLUYVkSU",\n "addresses": [\n "34.135.216.16:9002"\n ],\n "num_peers": 99,\n "num_connections": 102,\n "protocols": {\n "/oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/keymanager/4000000000000000000000000000000000000000000000008c5ea5e49b4bc9ac/2.0.0": 6,\n "/oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/light/1.0.0": 99,\n "/oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/storagesync/000000000000000000000000000000000000000000000000e199119c992377cb/2.0.0": 34,\n "/oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/storagesync/000000000000000000000000000000000000000000000000e2eaa99fc008f87f/2.0.0": 34,\n "/oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/storagesync/000000000000000000000000000000000000000000000000f80306c9858e7279/2.0.0": 47\n },\n "topics": {\n "oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/tx/000000000000000000000000000000000000000000000000e199119c992377cb/5.0.0": 34,\n "oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/tx/000000000000000000000000000000000000000000000000e2eaa99fc008f87f/5.0.0": 34,\n "oasis/bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55/tx/000000000000000000000000000000000000000000000000f80306c9858e7279/5.0.0": 48\n }\n }\n}\n'})}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network"})," selector is available for the\n",(0,s.jsx)(n.code,{children:"network status"})," command."]})})]})}function p(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>c,x:()=>d});var s=a(6540);const o={},t=s.createContext(o);function c(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4414cbb7.d3186a61.js b/assets/js/4414cbb7.d3186a61.js new file mode 100644 index 0000000000..f9a625d490 --- /dev/null +++ b/assets/js/4414cbb7.d3186a61.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4918],{6052:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>t,toc:()=>a});var i=s(4848),r=s(8453);const o={},l="Mainnet",t={id:"node/mainnet/README",title:"Mainnet",description:"Network Parameters",source:"@site/docs/node/mainnet/README.md",sourceDirName:"node/mainnet",slug:"/node/mainnet/",permalink:"/node/mainnet/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Overview",permalink:"/node/"},next:{title:"Eden Upgrade",permalink:"/node/mainnet/eden-upgrade"}},d={},a=[{value:"Network Parameters",id:"network-parameters",level:2},{value:"ParaTimes",id:"paratimes",level:2},{value:"Sapphire",id:"sapphire",level:3},{value:"Cipher",id:"cipher",level:3},{value:"Emerald",id:"emerald",level:3},{value:"Key Manager",id:"key-manager",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"mainnet",children:"Mainnet"}),"\n",(0,i.jsx)(n.h2,{id:"network-parameters",children:"Network Parameters"}),"\n",(0,i.jsx)(n.p,{children:"These are the current parameters for the Mainnet:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/download/2023-11-29/genesis.json",children:"Genesis file"}),":","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["SHA256: ",(0,i.jsx)(n.code,{children:"b14e45e97da0216a16c25096fd216f591e4d526aa6abac110ac23cb327b64ba1"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Genesis file is signed by ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/blob/master/README.md#pgp-keys-of-current-maintainers",children:"network's current maintainers"}),". To verify its\nauthenticity, follow the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/blob/master/README.md#verifying-genesis-file-signatures",children:"PGP verification instructions"}),"."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Genesis document's hash (",(0,i.jsx)(n.a,{href:"/node/genesis-doc#genesis-file-vs-genesis-document",children:"explanation"}),"):","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"bb3d748def55bdfb797a2ac53ee6ee141e54cd2ab2dc2375f4a0703a178e6e55"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Oasis seed node addresses:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:26656"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"H6u9MtuoWRKn5DKSgarj/dzr2Z9BsjuRHgRAoXITOcU=@35.199.49.168:9200"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"90em3ItdQkFy15GtWqCKHi5j7uEUmZPZIzBt7I5d6w4=@146.148.13.130:26656"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"90em3ItdQkFy15GtWqCKHi5j7uEUmZPZIzBt7I5d6w4=@146.148.13.130:9200"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Feel free to use other seed nodes besides the one provided here."})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"Oasis Core"})," version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.1",children:"24.1"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway",children:"Oasis Rosetta Gateway"})," version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.7.0",children:"2.7.0"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Oasis Node is part of the Oasis Core release."})}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsx)(n.p,{children:"Do not use a newer version of Oasis Core since it likely contains changes that\nare incompatible with the version of Oasis Core used by other nodes."})}),"\n",(0,i.jsxs)(n.p,{children:["If you want to join our Testnet, see the ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"})," docs\nfor the current Testnet parameters."]}),"\n",(0,i.jsx)(n.h2,{id:"paratimes",children:"ParaTimes"}),"\n",(0,i.jsx)(n.p,{children:"This section contains parameters for various ParaTimes known to be deployed on the Mainnet."}),"\n",(0,i.jsx)(n.h3,{id:"sapphire",children:"Sapphire"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Oasis Core version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.1",children:"24.1"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime identifier:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000f80306c9858e7279"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime bundle version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/releases/tag/v0.7.3",children:"0.7.3"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Oasis Web3 Gateway version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v5.1.0",children:"5.1.0"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["IAS proxy address:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Feel free to use other IAS proxies besides the one provided here or\n",(0,i.jsx)(n.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"cipher",children:"Cipher"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Oasis Core version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.1",children:"24.1"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime identifier:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000e199119c992377cb"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime bundle version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v3.0.5",children:"3.0.5"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["IAS proxy address:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Feel free to use other IAS proxies besides the one provided here or\n",(0,i.jsx)(n.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"emerald",children:"Emerald"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Oasis Core version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.1",children:"24.1"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime identifier:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000e2eaa99fc008f87f"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime bundle version (or ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/emerald-paratime/tree/v11.0.0#building",children:"build your own"}),"):","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v11.0.0",children:"11.0.0"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Web3 Gateway version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases/tag/v5.1.0",children:"5.1.0"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Check the ",(0,i.jsx)(n.a,{href:"/dapp/emerald/#rpc-endpoints",children:"Emerald ParaTime page"})," on how to access\nthe public Web3 endpoint."]})}),"\n",(0,i.jsx)(n.h3,{id:"key-manager",children:"Key Manager"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Oasis Core version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v24.1",children:"24.1"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime identifier:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"4000000000000000000000000000000000000000000000008c5ea5e49b4bc9ac"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Runtime bundle version:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/keymanager-paratime/releases/tag/v0.5.0",children:"0.5.0"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["IAS proxy address:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw=@34.86.108.137:8650"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"tuDyXwaajTEbNWb1QIlf8FWHsdkaB4W1+TjzP1QID/U=@131.153.243.17:8650"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Feel free to use other IAS proxies besides the one provided here or\n",(0,i.jsx)(n.a,{href:"/node/run-your-node/ias-proxy",children:"run your own"}),"."]})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>t});var i=s(6540);const r={},o=i.createContext(r);function l(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/489.8e09de33.js b/assets/js/489.8e09de33.js new file mode 100644 index 0000000000..67e1bfd08f --- /dev/null +++ b/assets/js/489.8e09de33.js @@ -0,0 +1,2 @@ +/*! For license information please see 489.8e09de33.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[489],{489:(t,e,n)=>{"use strict";t.exports=n(810)},2542:(t,e,n)=>{"use strict";var i=n(6573),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},897:(t,e,n)=>{"use strict";var i="aaDataset",s="aaValue",r="aaDatum",o=n(6573),a=n(1348),u=n(9272),c=n(2542),l=n(4436);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},1540:(t,e,n)=>{"use strict";var i=n(6573),s=n(1348),r=n(4436),o=n(897),a=n(2542);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},2324:(t,e,n)=>{"use strict";var i=n(6573),s=n(1348);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},4436:(t,e,n)=>{"use strict";var i=n(874),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}}},9272: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>'}},9629:(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(6573),r=n(1348),o=n(4436);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},7360:(t,e,n)=>{"use strict";var i="aaAttrs",s=n(6573),r=n(1348),o=n(2324),a=n(9629),u=n(1540),c=n(9272),l=n(2542);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(6353),t.exports=h},1348:t=>{"use strict";t.exports={element:null}},9715: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]]}},6573:(t,e,n)=>{"use strict";var i,s=n(8937),r=n(1348);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)}}},6903:(t,e,n)=>{"use strict";var i=n(6573),s=n(2281),r=n(9715);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)}},6353:(t,e,n)=>{"use strict";t.exports={hits:n(6903),popularIn:n(6839)}},6839:(t,e,n)=>{"use strict";var i=n(6573),s=n(2281),r=n(9715);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([])}}))}}},810:(t,e,n)=>{"use strict";var i=n(9539);n(1348).element=i;var s=n(6573);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(7360),a=n(2324);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},2281:t=>{t.exports="0.38.1"},9539: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)},8937: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},874:(t,e,n)=>{"use strict";var i,s,r,o=[n(5741),n(1856),n(1015),n(6486),n(5723),n(6345)],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())}},6486:(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)}}},1015:(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}}},1856:(t,e,n)=>{"use strict";e.test=function(){return"function"==typeof n.g.queueMicrotask},e.install=function(t){return function(){n.g.queueMicrotask(t)}}},5723:(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}}},6345:(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/489.8e09de33.js.LICENSE.txt b/assets/js/489.8e09de33.js.LICENSE.txt new file mode 100644 index 0000000000..4f7ccd8a76 --- /dev/null +++ b/assets/js/489.8e09de33.js.LICENSE.txt @@ -0,0 +1 @@ +/*! https://mths.be/cssesc v3.0.0 by @mathias */ diff --git a/assets/js/4a27219a.734861b4.js b/assets/js/4a27219a.734861b4.js new file mode 100644 index 0000000000..ab721b60ea --- /dev/null +++ b/assets/js/4a27219a.734861b4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3746],{9214:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>s,toc:()=>a});var i=t(4848),r=t(8453);const o={},d="Refreshing Node Certificates",s={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/refreshing-certificates.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},c={},a=[{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}];function l(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"refreshing-node-certificates",children:"Refreshing Node Certificates"}),"\n",(0,i.jsx)(n.h2,{id:"refreshing-sentry-client-tls-certificate-on-the-validator-node",children:"Refreshing Sentry Client TLS Certificate on the Validator Node"}),"\n",(0,i.jsx)(n.h3,{id:"steps-on-the-validator-node",children:"Steps on the Validator Node"}),"\n",(0,i.jsxs)(n.p,{children:["Go to your validator node's data directory, e.g. ",(0,i.jsx)(n.code,{children:"/node/data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"cd <PATH-TO-DATADIR>\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["We recommend backing up your validator's private and public keys (i.e. all ",(0,i.jsx)(n.code,{children:"*.pem"})," files) in your node's data directory before continuing."]})}),"\n",(0,i.jsx)(n.p,{children:"Remove the validator's current sentry client TLS private key and certificate by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rm sentry_client_tls_identity.pem sentry_client_tls_identity_cert.pem\n"})}),"\n",(0,i.jsx)(n.p,{children:"Re-generate node's keys by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node identity init --datadir ./\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["This should keep all your other node's keys (i.e. ",(0,i.jsx)(n.code,{children:"beacon.pem"}),", ",(0,i.jsx)(n.code,{children:"consensus.pem"}),", ",(0,i.jsx)(n.code,{children:"consensus_pub.pem"}),", ",(0,i.jsx)(n.code,{children:"identity.pem"}),", ",(0,i.jsx)(n.code,{children:"identity_pub.pem"}),", ...) intact."]})}),"\n",(0,i.jsx)(n.p,{children:"Then run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node identity show-sentry-client-pubkey --datadir ./\n"})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"control.authorized_pubkey"})," list."]}),"\n",(0,i.jsx)(n.p,{children:"Restart your validator node."}),"\n",(0,i.jsx)(n.h3,{id:"steps-on-the-sentry-node",children:"Steps on the Sentry Node"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Before using the below sentry node configuration snippet, replace the following variables:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ validator_sentry_client_grpc_public_key }}"}),": The validator node's new sentry client TLS public key encoded in Base64-encoding (e.g. ",(0,i.jsx)(n.code,{children:"KjVEdeGbtdxffQaSxIkLE+kW0sINI5/5YR/lgUkuEcw="}),")."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"... 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"})}),"\n",(0,i.jsx)(n.p,{children:"Restart your sentry node."}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"The validator node will re-register itself automatically once it's connected to the network through the sentry again."})}),"\n",(0,i.jsx)(n.h2,{id:"refreshing-tls-certificate-on-the-sentry-node",children:"Refreshing TLS Certificate on the Sentry Node"}),"\n",(0,i.jsx)(n.h3,{id:"steps-on-the-sentry-node-1",children:"Steps on the Sentry Node"}),"\n",(0,i.jsxs)(n.p,{children:["Go to your sentry node's data directory, e.g. ",(0,i.jsx)(n.code,{children:"/node/data"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"cd <PATH-TO-DATADIR>\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["We recommend backing up your sentry's private and public keys (i.e. all ",(0,i.jsx)(n.code,{children:"*.pem"})," files) in your node's data directory before continuing."]})}),"\n",(0,i.jsx)(n.p,{children:"Remove the sentry's current TLS private key and certificate by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rm tls_identity.pem tls_identity_cert.pem\n"})}),"\n",(0,i.jsx)(n.p,{children:"Re-generate node's keys by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node identity init --datadir ./\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["This should keep all your other node's keys (i.e. ",(0,i.jsx)(n.code,{children:"beacon.pem"}),", ",(0,i.jsx)(n.code,{children:"consensus.pem"}),", ",(0,i.jsx)(n.code,{children:"consensus_pub.pem"}),", ",(0,i.jsx)(n.code,{children:"identity.pem"}),", ",(0,i.jsx)(n.code,{children:"identity_pub.pem"}),", ...) intact."]})}),"\n",(0,i.jsx)(n.p,{children:"Then run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node identity show-tls-pubkey --datadir ./\n"})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"worker.sentry.address"})," list."]}),"\n",(0,i.jsx)(n.p,{children:"Restart your sentry node."}),"\n",(0,i.jsx)(n.h3,{id:"steps-on-the-validator-node-1",children:"Steps on the Validator Node"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Before using the below validator node configuration snippet, replace the following variables:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ sentry_node_grpc_public_key }}"}),": The sentry node's new TLS public key encoded in Base64-encoding (e.g. ",(0,i.jsx)(n.code,{children:"1dA4/NuYPSWXYaKpLhaofrZscIb2FDKtJclCMnVC0Xc="}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ sentry_node_private_ip }}"}),": The private IP address of the sentry node over which sentry node should be accessible to the validator."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'... 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: /node/etc/entity.json\n sentry:\n address:\n - "{{ sentry_node_grpc_public_key }}@{{ sentry_node_private_ip }}:9009"\n\n... trimmed ...\n'})}),"\n",(0,i.jsx)(n.p,{children:"Restart your validator node."})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>s});var i=t(6540);const r={},o=i.createContext(r);function d(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4ae0b297.3bf39688.js b/assets/js/4ae0b297.3bf39688.js new file mode 100644 index 0000000000..b0b1b2f4e7 --- /dev/null +++ b/assets/js/4ae0b297.3bf39688.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8121],{4695:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var o=t(4848),s=t(8453);const r={},i="Hello World",a={id:"dapp/cipher/hello-world",title:"Hello World",description:"This chapter 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/contract/hello-world.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Prerequisites",permalink:"/dapp/cipher/prerequisites"},next:{title:"Confidential Hello World",permalink:"/dapp/cipher/confidential-smart-contract"}},l={},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}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"hello-world",children:"Hello World"}),"\n",(0,o.jsx)(n.p,{children:"This chapter will show you how to quickly create, build and test a minimal\nOasis WebAssembly smart contract."}),"\n",(0,o.jsx)(n.h2,{id:"repository-structure-and-dependencies",children:"Repository Structure and Dependencies"}),"\n",(0,o.jsxs)(n.p,{children:["First we create the basic directory structure for the hello world contract using\nRust's ",(0,o.jsx)(n.a,{href:"https://doc.rust-lang.org/cargo",children:(0,o.jsx)(n.code,{children:"cargo"})}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"cargo init --lib hello-world\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This will create the ",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.code,{children:"rust-toolchain"})," containing the following information:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:'[toolchain]\nchannel = "nightly-2024-07-09"\ncomponents = [ "rustfmt", "clippy" ]\ntargets = [ "x86_64-fortanix-unknown-sgx", "wasm32-unknown-unknown" ]\nprofile = "minimal"\n'})}),"\n",(0,o.jsx)(n.p,{children:"After you complete this guide, the minimal runtime directory structure will look\nas follows:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"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.toml # Rust toolchain version configuration.\n\u2514\u2500\u2500 src\n \u2514\u2500\u2500 lib.rs # Smart contract source code.\n"})}),"\n",(0,o.jsx)(n.h2,{id:"smart-contract-definition",children:"Smart Contract Definition"}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.code,{children:"Cargo.toml"})," to look like the following:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-toml",metastring:'title="Cargo.toml"',children:'[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'})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsx)(n.p,{children:"We are using Git tags for releases instead of releasing Rust packages on\ncrates.io."})}),"\n",(0,o.jsxs)(n.p,{children:["After you have updated your ",(0,o.jsx)(n.code,{children:"Cargo.toml"})," the next thing is to define the hello\nworld smart contract. To do this, edit ",(0,o.jsx)(n.code,{children:"src/lib.rs"})," with the following\ncontent:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-rust",metastring:'title="src/lib.rs"',children:'//! 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'})}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/main/contract-sdk/src/contract.rs",children:"Oasis Contract SDK"}),"."]}),"\n",(0,o.jsx)(n.admonition,{title:"PublicCell object",type:"tip",children:(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"PublicCell<T>"})," can use any type ",(0,o.jsx)(n.code,{children:"T"})," which implements ",(0,o.jsx)(n.code,{children:"oasis_cbor::Encode"})," and\n",(0,o.jsx)(n.code,{children:"oasis_cbor::Decode"}),"."]})}),"\n",(0,o.jsx)(n.admonition,{title:"Context object",type:"tip",children:(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"ctx"})," argument contains the contract context analogous to ",(0,o.jsx)(n.code,{children:"msg"})," and ",(0,o.jsx)(n.code,{children:"this"}),"\nin the EVM world. To learn more head to the ",(0,o.jsx)(n.a,{href:"https://api.docs.oasis.io/oasis-sdk/oasis_contract_sdk/context/trait.Context.html",children:"Context"})," trait in our Rust API."]})}),"\n",(0,o.jsx)(n.h2,{id:"testing",children:"Testing"}),"\n",(0,o.jsx)(n.p,{children:"To run unit tests type:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-sh",children:'RUSTFLAGS="-C target-feature=+aes,+ssse3" cargo test\n'})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsx)(n.p,{children:"Running unit tests locally requires a physical or virtualized Intel-compatible\nCPU with AES and SSSE3 instruction sets."})}),"\n",(0,o.jsx)(n.h2,{id:"building-for-deployment",children:"Building for Deployment"}),"\n",(0,o.jsx)(n.p,{children:"In order to build the smart contract before it can be uploaded to the target\nchain, run:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"cargo build --target wasm32-unknown-unknown --release\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This will generate a binary file called ",(0,o.jsx)(n.code,{children:"hello_world.wasm"})," under\n",(0,o.jsx)(n.code,{children:"target/wasm32-unknown-unknown/release"})," which contains the smart contract\ncompiled into WebAssembly. This file can be directly deployed on chain."]}),"\n",(0,o.jsx)(n.h2,{id:"deploying-the-contract",children:"Deploying the Contract"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.p,{children:"First, switch the default network to Cipher Testnet to avoid the need to pass\nit to every following invocation."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"oasis network set-default testnet\noasis paratime set-default testnet cipher\n"})}),"\n",(0,o.jsx)(n.p,{children:"The first deployment step that needs to be performed only once for the given\nbinary is uploading the Wasm binary."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"oasis contract upload hello_world.wasm\n"})}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"oasis contract instantiate CODEID '{instantiate: {initial_counter: 42}}'\n"})}),"\n",(0,o.jsx)(n.p,{children:"After successful execution it shows the instance ID that you need for calling\nthe instantiated contract. Next, you can test calling the contract."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"oasis contract call INSTANCEID '{say_hello: {who: \"me\"}}'\n"})}),"\n",(0,o.jsx)(n.admonition,{title:"Example",type:"info",children:(0,o.jsxs)(n.p,{children:["You can view and download a ",(0,o.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/contract-sdk/hello-world",children:"complete example"})," from the Oasis SDK repository."]})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>a});var o=t(6540);const s={},r=o.createContext(s);function i(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4c52944b.9d7e2641.js b/assets/js/4c52944b.9d7e2641.js new file mode 100644 index 0000000000..f109e968af --- /dev/null +++ b/assets/js/4c52944b.9d7e2641.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2792],{647:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>r,default:()=>c,frontMatter:()=>o,metadata:()=>l,toc:()=>h});var i=t(4848),n=t(8453);const o={description:"How to build your first runtime"},r="Prerequisites",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/prerequisites.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"How to build your first runtime"},sidebar:"paratime",previous:{title:"Overview",permalink:"/paratime/"},next:{title:"Minimal Runtime",permalink:"/paratime/minimal-runtime"}},a={},h=[{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) 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}];function d(e){const s={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.h1,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(s.p,{children:"This chapter will show 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!"}),"\n",(0,i.jsxs)(s.p,{children:["If you already have everything set up, feel free to skip to the ",(0,i.jsx)(s.a,{href:"/paratime/minimal-runtime",children:"next chapter"}),"."]}),"\n",(0,i.jsx)(s.h2,{id:"environment-setup",children:"Environment Setup"}),"\n",(0,i.jsx)(s.p,{children:"The following is a list of prerequisites required to start developing using the\nOasis SDK:"}),"\n",(0,i.jsx)(s.h3,{id:"rust",children:(0,i.jsx)(s.a,{href:"https://www.rust-lang.org/",children:"Rust"})}),"\n",(0,i.jsxs)(s.p,{children:["We follow ",(0,i.jsx)(s.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust upstream's recommendation"})," on using\n",(0,i.jsx)(s.a,{href:"https://rustup.rs/",children:"rustup"})," to install and manage Rust versions."]}),"\n",(0,i.jsx)(s.admonition,{type:"info",children:(0,i.jsx)(s.p,{children:"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."})}),"\n",(0,i.jsx)(s.p,{children:"Install it by running:"}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{className:"language-bash",children:"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n"})}),"\n",(0,i.jsx)(s.admonition,{type:"info",children:(0,i.jsxs)(s.p,{children:["If you want to avoid directly executing a shell script fetched the\ninternet, you can also ",(0,i.jsxs)(s.a,{href:"https://rust-lang.github.io/rustup/installation/other.html",children:["download ",(0,i.jsx)(s.code,{children:"rustup-init"})," executable for your platform"]}),"\nand run it manually."]})}),"\n",(0,i.jsxs)(s.p,{children:["This will run ",(0,i.jsx)(s.code,{children:"rustup-init"})," which will download and install the latest stable\nversion of Rust on your system."]}),"\n",(0,i.jsx)(s.h4,{id:"rust-toolchain-version",children:"Rust Toolchain Version"}),"\n",(0,i.jsxs)(s.p,{children:["The version of the Rust toolchain we use in the Oasis SDK is specified in the\n",(0,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,i.jsx)(s.code,{children:"rust-toolchain.toml"})})," file."]}),"\n",(0,i.jsxs)(s.p,{children:["The rustup-installed versions of ",(0,i.jsx)(s.code,{children:"cargo"}),", ",(0,i.jsx)(s.code,{children:"rustc"})," and other tools will\n",(0,i.jsx)(s.a,{href:"https://github.com/rust-lang/rustup/blob/master/README.md#override-precedence",children:"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,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/rust-toolchain.toml",children:(0,i.jsx)(s.code,{children:"rust-toolchain.toml"})}),"\nfile to your project's top-level directory as well."]}),"\n",(0,i.jsx)(s.p,{children:"To install the appropriate version of the Rust toolchain, make sure you are\nin the project directory and run:"}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{children:"rustup show\n"})}),"\n",(0,i.jsx)(s.p,{children:"This will automatically install the appropriate Rust toolchain (if not\npresent) and output something similar to:"}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{children:"...\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"})}),"\n",(0,i.jsxs)(s.h3,{id:"optional-go",children:["(OPTIONAL) ",(0,i.jsx)(s.a,{href:"https://golang.org",children:"Go"})]}),"\n",(0,i.jsx)(s.p,{children:(0,i.jsx)(s.em,{children:"Required if you want to use the Go Client SDK."})}),"\n",(0,i.jsxs)(s.p,{children:["At least version ",(0,i.jsx)(s.strong,{children:"1.22.5"})," is required. If your distribution provides a\nnew-enough version of Go, just use that."]}),"\n",(0,i.jsx)(s.p,{children:"Otherwise:"}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsxs)(s.li,{children:["\n",(0,i.jsx)(s.p,{children:"install the Go version provided by your distribution,"}),"\n"]}),"\n",(0,i.jsxs)(s.li,{children:["\n",(0,i.jsxs)(s.p,{children:[(0,i.jsxs)(s.a,{href:"https://tip.golang.org/doc/code.html#GOPATH",children:["ensure ",(0,i.jsx)(s.code,{children:"$GOPATH/bin"})," is in your ",(0,i.jsx)(s.code,{children:"PATH"})]}),","]}),"\n"]}),"\n",(0,i.jsxs)(s.li,{children:["\n",(0,i.jsxs)(s.p,{children:[(0,i.jsx)(s.a,{href:"https://golang.org/doc/install#extra_versions",children:"install the desired version of Go"}),", e.g. 1.22.5, with:"]}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{children:"go get golang.org/dl/go1.22.5\ngo1.22.5 download\n"})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(s.h2,{id:"oasis-core-installation",children:"Oasis Core Installation"}),"\n",(0,i.jsxs)(s.p,{children:["The SDK requires utilities provided by ",(0,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"Oasis Core"})," in order to be able to run\na local test network for development purposes."]}),"\n",(0,i.jsxs)(s.p,{children:["The recommended way is to download a pre-built release (at least version\n24.2) from the ",(0,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases",children:"Oasis Core releases"})," page. After downloading the binary\nrelease (e.g. into ",(0,i.jsx)(s.code,{children:"~/Downloads/oasis_core_24.2_linux_amd64.tar.gz"}),"), unpack\nit as follows:"]}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{className:"language-bash",children:"cd ~/Downloads\ntar xf ~/Downloads/oasis_core_24.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_24.2_linux_amd64\n"})}),"\n",(0,i.jsx)(s.h2,{id:"oasis-cli-installation",children:"Oasis CLI Installation"}),"\n",(0,i.jsxs)(s.p,{children:["The rest of the guide uses the Oasis CLI as an easy way to interact with the\nParaTime. You can use ",(0,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/cli/releases",children:"one of the binary releases"})," or ",(0,i.jsx)(s.a,{href:"https://github.com/oasisprotocol/cli/blob/master/README.md",children:"compile it yourself"}),"."]})]})}function c(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>r,x:()=>l});var i=t(6540);const n={},o=i.createContext(n);function r(e){const s=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),i.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4c58f4a9.755b5ccb.js b/assets/js/4c58f4a9.755b5ccb.js new file mode 100644 index 0000000000..65bd8f6ddb --- /dev/null +++ b/assets/js/4c58f4a9.755b5ccb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1139],{2945:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var a=t(4848),r=t(8453),s=t(1470),o=t(9365);const i={description:"Secure dApps: Recipes for Confidentiality"},l="Security",c={id:"dapp/sapphire/security",title:"Security",description:"Secure dApps: Recipes for Confidentiality",source:"@site/docs/dapp/sapphire/security.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/security",permalink:"/dapp/sapphire/security",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/security.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Secure dApps: Recipes for Confidentiality"},sidebar:"developers",previous:{title:"Deployment Patterns",permalink:"/dapp/sapphire/deployment"},next:{title:"Oasis Privacy Layer",permalink:"/dapp/opl/"}},u={},d=[{value:"Storage Access Patterns",id:"storage-access-patterns",level:2},{value:"Order of Operations",id:"order-of-operations",level:2},{value:"Speed Bump",id:"speed-bump",level:2},{value:"Gas Padding",id:"gas-padding",level:2}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"security",children:"Security"}),"\n",(0,a.jsx)(n.p,{children:"This page is an ongoing work in progress to support confidential smart contract\ndevelopment. At the moment we address safeguarding storage variable access\npatterns and provide best practices for more secure orderings of error checking\nto prevent leaking contract state."}),"\n",(0,a.jsx)(n.h2,{id:"storage-access-patterns",children:"Storage Access Patterns"}),"\n",(0,a.jsxs)(n.p,{children:["You can use a tool such as ",(0,a.jsx)(n.a,{href:"https://www.npmjs.com/package/hardhat-tracer",children:"hardhat-tracer"})," to examine the base EVM state\ntransitions under the hood."]}),"\n",(0,a.jsxs)(s.A,{groupId:"npm2yarn",children:[(0,a.jsx)(o.A,{value:"npm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npm install -D hardhat-tracer\n"})})}),(0,a.jsx)(o.A,{value:"pnpm",label:"pnpm",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"pnpm add -D hardhat-tracer\n"})})}),(0,a.jsx)(o.A,{value:"yarn",label:"Yarn",children:(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"yarn add --dev hardhat-tracer\n"})})})]}),"\n",(0,a.jsxs)(n.p,{children:["and add ",(0,a.jsx)(n.code,{children:"hardhat-tracer"})," to your ",(0,a.jsx)(n.code,{children:"config.ts"})," file,"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-typescript",children:'import "hardhat-tracer"\n'})}),"\n",(0,a.jsx)(n.p,{children:"in order to test and show call traces."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npx hardhat test --vvv --opcodes SSTORE,SLOAD\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can also trace a particular transaction, once you know its hash."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"npx hardhat trace --hash 0xTransactionHash\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For both ",(0,a.jsx)(n.a,{href:"https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html",children:"gas"})," usage and confidentiality purposes, we ",(0,a.jsx)(n.strong,{children:"recommend using\nnon-unique data size"}),". E.g. 64-byte value will still be distinct from a\n128-byte value."]}),"\n",(0,a.jsx)(n.admonition,{title:"Inference based on access patterns",type:"caution",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"SSTORE"})," keys from one transaction may be linked to ",(0,a.jsx)(n.code,{children:"SLOAD"})," keys of another\ntransaction."]})}),"\n",(0,a.jsx)(n.h2,{id:"order-of-operations",children:"Order of Operations"}),"\n",(0,a.jsxs)(n.p,{children:["When handling errors, gas usage patterns not only can reveal the code path\ntaken, ",(0,a.jsx)(n.strong,{children:"but sometimes the balance of a user as well"})," (in the case of a diligent\nattacker using binary search)."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-solidity",children:"function transferFrom(address who, address to, uint amount)\n external\n{\n require( balances[who] >= amount );\n require( allowances[who][msg.sender] >= amount );\n // ...\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Modifying the order of error checking can prevent the accidental disclosure of\nbalance information in the example above."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-solidity",children:"function transferFrom(address who, address to, uint amount)\n external\n{\n require( allowances[who][msg.sender] >= amount );\n require( balances[who] >= amount );\n // ...\n}\n"})}),"\n",(0,a.jsx)(n.h2,{id:"speed-bump",children:"Speed Bump"}),"\n",(0,a.jsx)(n.p,{children:"If we would like to prevent off-chain calls from being chained together, we can\nensure that the block has been finalized."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-solidity",children:'contract Secret {\n uint256 private _height;\n bytes private _secret;\n address private _buyer;\n\n constructor(bytes memory _text) {\n _secret = _text;\n }\n\n function recordPayment() external payable {\n require(msg.value == 1 ether);\n // set and lock buyer\n _height = block.number;\n _buyer = msg.sender;\n }\n\n /// @notice Reveals the secret.\n function revealSecret() view external returns (bytes memory) {\n require(block.number > _height, "not settled");\n require(_buyer != address(0), "no recorded buyer");\n // TODO: optionally authenticate call from buyer\n return _secret;\n }\n}\n'})}),"\n",(0,a.jsx)(n.h2,{id:"gas-padding",children:"Gas Padding"}),"\n",(0,a.jsxs)(n.p,{children:["To prevent leaking information about a particular transaction, Sapphire\nprovides a ",(0,a.jsx)(n.a,{href:"https://api.docs.oasis.io/sol/sapphire-contracts/contracts/Sapphire.sol/library.Sapphire.html#padgas",children:"precompile"})," for dApp developers to ",(0,a.jsx)(n.strong,{children:"pad the amount of gas used\nin a transaction"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-solidity",children:"contract GasExample {\n bytes32 tmp;\n\n function constantMath(bool doMath, uint128 padGasAmount) external {\n if (doMath) {\n bytes32 x;\n\n for (uint256 i = 0; i < 100; i++) {\n x = keccak256(abi.encodePacked(x, tmp));\n }\n\n tmp = x;\n }\n\n Sapphire.padGas(padGasAmount);\n }\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Both contract calls below should use the same amount of gas. Sapphire also\nprovides the precompile to return the gas ",(0,a.jsx)(n.a,{href:"https://api.docs.oasis.io/sol/sapphire-contracts/contracts/Sapphire.sol/library.Sapphire.html#gasused",children:"used"})," by the current transaction."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-typescript",children:"await contract.constantMath(true, 100000);\nawait contract.constantMath(false, 100000);\n"})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>o});t(6540);var a=t(4164);const r={tabItem:"tabItem_Ymn6"};var s=t(4848);function o(e){let{children:n,hidden:t,className:o}=e;return(0,s.jsx)("div",{role:"tabpanel",className:(0,a.A)(r.tabItem,o),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>w});var a=t(6540),r=t(4164),s=t(3104),o=t(6347),i=t(205),l=t(7485),c=t(1682),u=t(9466);function d(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function p(e){const{values:n,children:t}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:t,attributes:a,default:r}}=e;return{value:n,label:t,attributes:a,default:r}}))}(t);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[n,t])}function h(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const r=(0,o.W6)(),s=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,l.aZ)(s),(0,a.useCallback)((e=>{if(!s)return;const n=new URLSearchParams(r.location.search);n.set(s,e),r.replace({...r.location,search:n.toString()})}),[s,r])]}function f(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,s=p(e),[o,l]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(n){if(!h({value:n,tabValues:t}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=t.find((e=>e.default))??t[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:s}))),[c,d]=m({queryString:t,groupId:r}),[f,g]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[r,s]=(0,u.Dv)(t);return[r,(0,a.useCallback)((e=>{t&&s.set(e)}),[t,s])]}({groupId:r}),b=(()=>{const e=c??f;return h({value:e,tabValues:s})?e:null})();(0,i.A)((()=>{b&&l(b)}),[b]);return{selectedValue:o,selectValue:(0,a.useCallback)((e=>{if(!h({value:e,tabValues:s}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),g(e)}),[d,g,s]),tabValues:s}}var g=t(2303);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(4848);function v(e){let{className:n,block:t,selectedValue:a,selectValue:o,tabValues:i}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,s.a_)(),u=e=>{const n=e.currentTarget,t=l.indexOf(n),r=i[t].value;r!==a&&(c(n),o(r))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.A)("tabs",{"tabs--block":t},n),children:i.map((e=>{let{value:n,label:t,attributes:s}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...s,className:(0,r.A)("tabs__item",b.tabItem,s?.className,{"tabs__item--active":a===n}),children:t??n},n)}))})}function y(e){let{lazy:n,children:t,selectedValue:r}=e;const s=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=s.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:s.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==r})))})}function j(e){const n=f(e);return(0,x.jsxs)("div",{className:(0,r.A)("tabs-container",b.tabList),children:[(0,x.jsx)(v,{...n,...e}),(0,x.jsx)(y,{...n,...e})]})}function w(e){const n=(0,g.A)();return(0,x.jsx)(j,{...e,children:d(e.children)},String(n))}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>i});var a=t(6540);const r={},s=a.createContext(r);function o(e){const n=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4daae886.d552a7b3.js b/assets/js/4daae886.d552a7b3.js new file mode 100644 index 0000000000..40399a684b --- /dev/null +++ b/assets/js/4daae886.d552a7b3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5456],{1494:(e,i,s)=>{s.r(i),s.d(i,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>t,metadata:()=>d,toc:()=>o});var a=s(4848),n=s(8453);const t={},r="ADR 0008: Standard Account Key Generation",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0008-standard-account-key-generation.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},o=[{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}];function h(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.h1,{id:"adr-0008-standard-account-key-generation",children:"ADR 0008: Standard Account Key Generation"}),"\n",(0,a.jsx)(i.h2,{id:"component",children:"Component"}),"\n",(0,a.jsx)(i.p,{children:"Oasis Core"}),"\n",(0,a.jsx)(i.h2,{id:"changelog",children:"Changelog"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"2021-05-07: Add test vectors and reference implementation, extend Consequences\nsection"}),"\n",(0,a.jsx)(i.li,{children:"2021-04-19: Switch from BIP32-Ed25519 to SLIP-0010 for hierarchical key\nderivation scheme"}),"\n",(0,a.jsx)(i.li,{children:"2021-01-27: Initial draft"}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"status",children:"Status"}),"\n",(0,a.jsx)(i.p,{children:"Accepted"}),"\n",(0,a.jsx)(i.h2,{id:"context",children:"Context"}),"\n",(0,a.jsx)(i.p,{children:"Currently, each application interacting with the Oasis Network defines its own\nmethod of generating an account's private/public key pair."}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"/core/consensus/services/staking#accounts",children:"Account"}),"'s public key is in turn used to derive the account's address of the\nform ",(0,a.jsx)(i.code,{children:"oasis1 ... 40 characters ..."})," which is used to for a variety of operations\n(i.e. token transfers, delegations/undelegations, ...) on the network."]}),"\n",(0,a.jsx)(i.p,{children:"The blockchain ecosystem has developed many standards for generating keys which\nimprove key storage and interoperability between different applications."}),"\n",(0,a.jsx)(i.p,{children:"Adopting these standards will allow the Oasis ecosystem to:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"Make key derivation the same across different applications (i.e. wallets)."}),"\n",(0,a.jsx)(i.li,{children:"Allow users to hold keys in hardware wallets."}),"\n",(0,a.jsx)(i.li,{children:"Allow users to hold keys in cold storage more reliably (i.e. using the\nfamiliar 24 word mnemonics)."}),"\n",(0,a.jsx)(i.li,{children:"Define how users can generate multiple keys from a single seed (i.e.\nthe 24 or 12 word mnemonic)."}),"\n"]}),"\n",(0,a.jsx)(i.h2,{id:"decision",children:"Decision"}),"\n",(0,a.jsx)(i.h3,{id:"mnemonic-codes-for-master-key-derivation",children:"Mnemonic Codes for Master Key Derivation"}),"\n",(0,a.jsxs)(i.p,{children:["We use Bitcoin's ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",children:"BIP-0039"}),": ",(0,a.jsx)(i.em,{children:"Mnemonic code for generating deterministic keys"}),"\nto derivate a binary seed from a mnemonic code."]}),"\n",(0,a.jsxs)(i.p,{children:["The binary seed is in turn used to derive the ",(0,a.jsx)(i.em,{children:"master key"}),", the root key from\nwhich a hierarchy of deterministic keys is derived, as described in\n",(0,a.jsx)(i.a,{href:"#hierarchical-key-derivation-scheme",children:"Hierarchical Key Derivation Scheme"}),"."]}),"\n",(0,a.jsx)(i.p,{children:"We strongly recommend using 24 word mnemonics which correspond to 256 bits of\nentropy."}),"\n",(0,a.jsx)(i.h3,{id:"hierarchical-key-derivation-scheme",children:"Hierarchical Key Derivation Scheme"}),"\n",(0,a.jsxs)(i.p,{children:["We use Sathoshi Labs' ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"}),": ",(0,a.jsx)(i.em,{children:"Universal private key derivation from master\nprivate key"}),", which is a superset of\nBitcoin's ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"}),": ",(0,a.jsx)(i.em,{children:"Hierarchical Deterministic Wallets"})," derivation algorithm,\nextended to work on other curves."]}),"\n",(0,a.jsxs)(i.p,{children:["Account keys use the ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"})," from the Ed25519 signature scheme\nspecified in ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032",children:"RFC 8032"}),"."]}),"\n",(0,a.jsx)(i.h3,{id:"key-derivation-paths",children:"Key Derivation Paths"}),"\n",(0,a.jsxs)(i.p,{children:["We adapt ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki",children:"BIP-0044"}),": ",(0,a.jsx)(i.em,{children:"Multi-Account Hierarchy for Deterministic Wallets"})," for\ngenerating deterministic keys where ",(0,a.jsx)(i.code,{children:"coin_type"})," equals 474, as assigned to the\nOasis Network by ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0044.md",children:"SLIP-0044"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["The following ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"})," path should be used to generate keys:"]}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{children:"m/44'/474'/x'\n"})}),"\n",(0,a.jsxs)(i.p,{children:["where ",(0,a.jsx)(i.code,{children:"x"})," represents the key number."]}),"\n",(0,a.jsxs)(i.p,{children:["Note that all path levels are ",(0,a.jsx)(i.em,{children:"hardened"}),", e.g. ",(0,a.jsx)(i.code,{children:"44'"})," is ",(0,a.jsx)(i.code,{children:"44 | 0x8000000"})," or\n",(0,a.jsx)(i.code,{children:"44 + 2^31"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["The key corresponding to key number 0 (i.e. ",(0,a.jsx)(i.code,{children:"m/44'/474'/0'"}),") is called the\n",(0,a.jsx)(i.em,{children:"primary key"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["The account corresponding to the ",(0,a.jsx)(i.em,{children:"primary key"})," is called the ",(0,a.jsx)(i.em,{children:"primary account"}),".\nApplications (i.e. wallets) should use this account as a user's default Oasis\naccount."]}),"\n",(0,a.jsx)(i.h2,{id:"rationale",children:"Rationale"}),"\n",(0,a.jsx)(i.p,{children:"BIPs and SLIPs are industry standards used by a majority of blockchain projects\nand software/hardware wallets."}),"\n",(0,a.jsx)(i.h3,{id:"slip-0010-for-hierarchical-key-derivation-scheme",children:"SLIP-0010 for Hierarchical Key Derivation Scheme"}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"})," defines a hierarchical key derivation scheme which is a superset of\n",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"})," derivation algorithm extended to work on other curves."]}),"\n",(0,a.jsxs)(i.p,{children:["In particular, we use their adaptation for the ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"}),"."]}),"\n",(0,a.jsx)(i.h4,{id:"adoption",children:"Adoption"}),"\n",(0,a.jsxs)(i.p,{children:["It is used by Stellar (",(0,a.jsx)(i.a,{href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md",children:"SEP-0005"}),")."]}),"\n",(0,a.jsxs)(i.p,{children:["It is supported by ",(0,a.jsx)(i.a,{href:"https://www.ledger.com/",children:"Ledger"})," and ",(0,a.jsx)(i.a,{href:"https://trezor.io/",children:"Trezor"})," hardware wallets."]}),"\n",(0,a.jsx)(i.p,{children:"It is commonly used by Ledger applications, including:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-stellar/blob/fc4ec38d9abcae9bd47c95ef93feb5e1ff25961f/src/stellar.c#L42-L49",children:"Stellar's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-solana/blob/1c72216edf4e5358f719b164a8d1b6100988b34d/src/utils.c#L42-L51",children:"Solana's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-near/blob/40ea52a0de81d65b993a49ac705e7edad8efff0e/workdir/app-near/src/crypto/ledger_crypto.c#L24",children:"NEAR Protocol's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-sia/blob/d4dbb5a9cae2e2389d6b6a44701069e234f0f392/src/sia.c#L14",children:"Siacoin's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-hedera/blob/47066dcfa02379a48a65c33efb1484bb744a30a5/src/hedera.c#L21-L30",children:"Hedera Hashgraph's Ledger app"}),"."]}),"\n"]}),"\n",(0,a.jsx)(i.h4,{id:"difficulties-in-adapting-bip-0032-to-edwards25519-curve",children:"Difficulties in Adapting BIP-0032 to edwards25519 Curve"}),"\n",(0,a.jsxs)(i.p,{children:["Creating a hierarchical key derivation scheme for the ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"}),'\nproved to be very challenging due to edwards25519\'s small cofactor and bit\n"clamping".']}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"})," was designed for the ",(0,a.jsx)(i.a,{href:"https://en.bitcoin.it/wiki/Secp256k1",children:"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,a.jsx)(i.em,{children:"h"})," * ",(0,a.jsx)(i.em,{children:"l"})," instead, where ",(0,a.jsx)(i.em,{children:"h"})," is a small co-factor\n(8) and ",(0,a.jsx)(i.em,{children:"l"})," is a 252-bit prime."]}),"\n",(0,a.jsxs)(i.p,{children:["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,a.jsx)(i.a,{href:"https://ristretto.group/why_ristretto.html#pitfalls-of-a-cofactor",children:"described by Risretto authors"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:['Additionally, edwards25519 curve employs bit "clamping". As ',(0,a.jsx)(i.a,{href:"https://moderncrypto.org/mail-archive/curves/2017/000874.html",children:"described by Trevor\nPerrin"}),', low bits are "clamped" to deal with\nsmall-subgroup attacks and high bits are "clamped" so that:']}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:"the scalar is smaller than the subgroup order, and"}),"\n",(0,a.jsx)(i.li,{children:"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."}),"\n"]}),"\n",(0,a.jsxs)(i.p,{children:["These issues were discussed on ",(0,a.jsx)(i.a,{href:"https://moderncrypto.org/",children:"modern crypto"}),"'s mailing list ",(0,a.jsx)(i.a,{href:"https://moderncrypto.org/mail-archive/curves/2017/000858.html",children:"[1]"}),", ",(0,a.jsx)(i.a,{href:"https://moderncrypto.org/mail-archive/curves/2017/000866.html",children:"[2]"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"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."]}),"\n",(0,a.jsx)(i.h3,{id:"shorter-key-derivation-paths",children:"Shorter Key Derivation Paths"}),"\n",(0,a.jsxs)(i.p,{children:["Similar to Stellar's ",(0,a.jsx)(i.a,{href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md",children:"SEP-0005"}),", we decided not to use the full ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"}),"\nderivation path specified by ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki",children:"BIP-0044"})," because ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"}),"'s scheme for\n",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"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,a.jsx)(i.a,{href:"https://en.wikipedia.org/wiki/Unspent_transaction_output",children:"UTXO"}),"-based."]}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://trezor.io/",children:"Trezor"})," follows the same scheme for account-based blockchain networks as\ndescribed in their ",(0,a.jsx)(i.a,{href:"https://github.com/trezor/trezor-firmware/blob/master/docs/misc/coins-bip44-paths.md",children:"BIP-44 derivation paths"})," document."]}),"\n",(0,a.jsx)(i.h2,{id:"test-vectors",children:"Test Vectors"}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{className:"language-json",children:'[\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'})}),"\n",(0,a.jsx)(i.p,{children:"To generate these test vectors yourself, run:"}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{children:"make -C go staking/gen_account_vectors\n"})}),"\n",(0,a.jsx)(i.p,{children:"We also provide more extensive test vectors. To generate them, run:"}),"\n",(0,a.jsx)(i.pre,{children:(0,a.jsx)(i.code,{children:"make -C go staking/gen_account_vectors_extended\n"})}),"\n",(0,a.jsx)(i.h2,{id:"implementation",children:"Implementation"}),"\n",(0,a.jsxs)(i.p,{children:["Reference implementation is in Oasis Core's ",(0,a.jsxs)(i.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/sakg",children:[(0,a.jsx)(i.code,{children:"go/common/crypto/sakg"})," package"]}),"."]}),"\n",(0,a.jsx)(i.h2,{id:"alternatives",children:"Alternatives"}),"\n",(0,a.jsx)(i.h3,{id:"bip32-ed25519-for-hierarchical-key-derivation",children:"BIP32-Ed25519 for Hierarchical Key Derivation"}),"\n",(0,a.jsxs)(i.p,{children:["The ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"})," (also sometimes referred to as ",(0,a.jsxs)(i.em,{children:["Ed25519 and BIP32\nbased on ",(0,a.jsx)(i.a,{href:"https://en.wikipedia.org/wiki/Dmitry_Khovratovich",children:"Khovratovich"})]}),") is a key derivation scheme that also adapts\n",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"}),"'s hierarchical derivation scheme for the ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"})," from\nthe Ed25519 signature scheme specified in ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032",children:"RFC 8032"}),"."]}),"\n",(0,a.jsx)(i.h4,{id:"adoption-1",children:"Adoption"}),"\n",(0,a.jsxs)(i.p,{children:["It is used by Cardano (",(0,a.jsx)(i.a,{href:"https://cips.cardano.org/cips/cip3/",children:"CIP 3"}),") and Tezos (dubbed ",(0,a.jsx)(i.a,{href:"https://medium.com/@obsidian.systems/v2-2-0-of-tezos-ledger-apps-babylon-support-and-more-e8df0e4ea161",children:"bip25519 derivation scheme"}),")."]}),"\n",(0,a.jsxs)(i.p,{children:["It is supported by ",(0,a.jsx)(i.a,{href:"https://www.ledger.com/",children:"Ledger"})," and ",(0,a.jsx)(i.a,{href:"https://trezor.io/",children:"Trezor"})," hardware wallets."]}),"\n",(0,a.jsx)(i.p,{children:"It is commonly used by Ledger applications, including:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/Zondax/ledger-polkadot/blob/7c3841a96caa5af6b78d49aac52b1373f10e3773/app/src/crypto.c#L44-L52",children:"Polkadot's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/Zondax/ledger-kusama/blob/90593207558ed82ad97123b730b07bcc33aeabf2/app/src/crypto.c#L44-L52",children:"Kusama's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/Zondax/ledger-zcash/blob/61fe324e567af59d39c609b84b591e28997c1a61/app/src/crypto.c#L173-L178",children:"Zcash's Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/Zondax/ledger-polymesh/blob/6228950a76c945fb0b5d7fc19fa475eccdf4160d/app/src/crypto.c#L44-L52",children:"Polymath's Ledger app"}),"."]}),"\n"]}),"\n",(0,a.jsx)(i.h4,{id:"security-concerns",children:"Security Concerns"}),"\n",(0,a.jsxs)(i.p,{children:["Its advantage is that it supports non-hardened parent public key to child public\nkey derivation which enables certain use cases described in ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#use-cases",children:"BIP-0032"})," (i.e. audits, insecure money receiver, ...)."]}),"\n",(0,a.jsxs)(i.p,{children:["At the same time, allowing non-hardened parent public key to child public key\nderivation presents a serious security concern due to ",(0,a.jsx)(i.a,{href:"#difficulties-in-adapting-bip-0032-to-edwards25519-curve",children:"edwards25519's co-factor\nissues"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/burdges",children:"Jeff Burdges (Web3 Foundation)"})," warned about a potential ",(0,a.jsx)(i.a,{href:"https://web.archive.org/web/20210513183118/https://forum.w3f.community/t/key-recovery-attack-on-bip32-ed25519/44",children:"key recovery attack\non the BIP32-Ed25519 scheme"})," which could occur under the\nfollowing two assumptions:"]}),"\n",(0,a.jsxs)(i.ol,{children:["\n",(0,a.jsx)(i.li,{children:"The Ed25519 library used in BIP-Ed25519 derivation scheme does clamping\nimmediately before signing."}),"\n",(0,a.jsx)(i.li,{children:"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."}),"\n"]}),"\n",(0,a.jsxs)(i.p,{children:["The first assumption is very reasonable since the ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"})," paper makes\nsupporting this part of their specification."]}),"\n",(0,a.jsxs)(i.p,{children:["The second assumption is a bit more controversial.\nThe ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"})," paper's specification limits the ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"})," path length\n(i.e. the number of levels in the tree) to 2",(0,a.jsx)("sup",{children:"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,a.jsx)("sup",{children:"20"})," path length limit."]}),"\n",(0,a.jsx)(i.h4,{id:"implementation-issues",children:"Implementation Issues"}),"\n",(0,a.jsxs)(i.p,{children:["One practical issue with ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"})," is that its authors didn't provide a\nreference implementation and accompanying test vectors."]}),"\n",(0,a.jsx)(i.p,{children:"This has led to a number of incompatible BIP32-Ed25519 implementations."}),"\n",(0,a.jsxs)(i.p,{children:["For example, ",(0,a.jsx)(i.a,{href:"https://github.com/vbmithr/ocaml-bip32-ed25519",children:"Vincent Bernardoff's OCaml implementation"}),"\nand ",(0,a.jsx)(i.a,{href:"https://github.com/islishude/bip32",children:"Shude Li's Go implementation"})," follow ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"}),"'s\noriginal master (i.e. root) key derivation specification and use SHA512 and\nSHA256 for deriving the private key ",(0,a.jsx)(i.em,{children:"k"})," and chain code ",(0,a.jsx)(i.em,{children:"c"})," (respectively) from\nthe seed (i.e. master secret)."]}),"\n",(0,a.jsxs)(i.p,{children:["On the other hand, Ledger's ",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/orakolo/blob/0b2d5e669ec61df9a824df9fa1a363060116b490/src/python/orakolo/HDEd25519.py",children:"Python implementation in orakolo repository"})," and ",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/speculos/blob/dce04843ad7d4edbcd399391b3c39d30b37de3cd/src/bolos/os_bip32.c",children:"C implementation for their Speculos emulator"})," (variant with ",(0,a.jsx)(i.code,{children:"curve"})," equal to ",(0,a.jsx)(i.code,{children:"CX_CURVE_Ed25519"})," and\n",(0,a.jsx)(i.code,{children:"mode"})," equal to ",(0,a.jsx)(i.code,{children:"HDW_NORMAL"}),") use HMAC-SHA512 and HMAC-SHA256 for deriving the\nprivate key ",(0,a.jsx)(i.em,{children:"k"})," and chain code ",(0,a.jsx)(i.em,{children:"c"})," (respectively) from the seed."]}),"\n",(0,a.jsxs)(i.p,{children:["Furthermore, ",(0,a.jsx)(i.a,{href:"https://github.com/vbmithr/ocaml-bip32-ed25519/blob/461e6a301996d41755acd35d82cd7ab6e30a8437/src/bip32_ed25519.ml#L120-L128",children:"Vincent Bernardoff's OCaml implementation"})," follows ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"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,a.jsxs)(i.em,{children:["k",(0,a.jsx)("sub",{children:"L"})]})," is not zero."]}),"\n",(0,a.jsxs)(i.p,{children:["On the other hand, ",(0,a.jsx)(i.a,{href:"https://github.com/islishude/bip32/blob/72b7efc571fdb69a3f0ce4caf7078e5466b9273d/xprv.go#L51-L53",children:"Shude Li's Go implementation"}),"\njust clears the master key's third highest bit\nand ",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/orakolo/blob/0b2d5e669ec61df9a824df9fa1a363060116b490/src/python/orakolo/HDEd25519.py#L130-L133",children:"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."]}),"\n",(0,a.jsxs)(i.p,{children:["Cardano uses its own variants of ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"})," described in ",(0,a.jsx)(i.a,{href:"https://cips.cardano.org/cips/cip3/",children:"CIP 3"}),". In\nparticular, they define different variants of master key derivation from the\nseed described in ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0023.md",children:"SLIP-0023"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["Lastly, some implementations, notably ",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-oasis",children:"Oasis' Ledger app"}),",\ndon't use use ",(0,a.jsx)(i.a,{href:"https://github.com/WebOfTrustInfo/rwot3-sf/blob/master/topics-and-advance-readings/HDKeys-Ed25519.pdf",children:"BIP32-Ed25519"}),"'s private and public key directly but use the\nobtained ",(0,a.jsxs)(i.em,{children:["k",(0,a.jsx)("sub",{children:"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,a.jsx)(i.a,{href:"https://github.com/Zondax/ledger-oasis/issues/84#issuecomment-827017112",children:"Zondax/ledger-oasis#84"}),"."]}),"\n",(0,a.jsx)(i.h3,{id:"tors-next-generation-hidden-service-keys-for-hierarchical-key-derivation",children:"Tor's Next Generation Hidden Service Keys for Hierarchical Key Derivation"}),"\n",(0,a.jsxs)(i.p,{children:["The ",(0,a.jsx)(i.a,{href:"https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt",children:"Next-Generation Hidden Services in Tor"})," specification defines a\n",(0,a.jsx)(i.a,{href:"https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt#n2135",children:"hierarchical key derivation scheme for Tor's keys"})," which employs\nmultiplicative blinding instead of an additive one use by ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"BIP-0032"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/burdges",children:"Jeff Burdges (Web3 Foundation)"}),"'s post on potential ",(0,a.jsx)(i.a,{href:"https://web.archive.org/web/20210513183118/https://forum.w3f.community/t/key-recovery-attack-on-bip32-ed25519/44",children:"key recovery\nattack on the BIP32-Ed25519 scheme"})," mentions there is\nnothing wrong with this proposed scheme.\nLikewise, ",(0,a.jsx)(i.a,{href:"https://github.com/jstarry",children:"Justin Starry (Solana)"}),"'s ",(0,a.jsx)(i.a,{href:"https://github.com/solana-labs/solana/issues/6301#issuecomment-551184457",children:"summary of approaches to adopting BIP-0032\nfor Ed25519"})," recommends this scheme as one of the possible\napproaches to adapt BIP-0032 for ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["One practical issue with using this scheme would be the absence of support by\nthe ",(0,a.jsx)(i.a,{href:"https://www.ledger.com/",children:"Ledger"})," and ",(0,a.jsx)(i.a,{href:"https://trezor.io/",children:"Trezor"})," hardware wallets."]}),"\n",(0,a.jsx)(i.h2,{id:"consequences",children:"Consequences"}),"\n",(0,a.jsx)(i.h3,{id:"positive",children:"Positive"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:["\n",(0,a.jsxs)(i.p,{children:["Different applications interacting with the Oasis Network will use a\n",(0,a.jsx)(i.em,{children:"standards-compliant"})," (",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",children:"BIP-0039"}),", ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"}),", ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki",children:"BIP-0044"}),") and\n",(0,a.jsx)(i.em,{children:"interoperable"})," account key generation process."]}),"\n",(0,a.jsx)(i.p,{children:"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)."}),"\n"]}),"\n",(0,a.jsxs)(i.li,{children:["\n",(0,a.jsxs)(i.p,{children:["Using ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"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,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"}),".\nNon-hardened key derivation is practically impossible to implement securely\ndue to ",(0,a.jsx)(i.a,{href:"#difficulties-in-adapting-bip-0032-to-edwards25519-curve",children:"edwards25519 curve's co-factor issues"}),"."]}),"\n",(0,a.jsxs)(i.p,{children:["This is achieved by ",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"})," explicitly disallowing non-hardened public\nparent key to public child key derivation with the edwards25519 curve."]}),"\n"]}),"\n",(0,a.jsxs)(i.li,{children:["\n",(0,a.jsxs)(i.p,{children:["Using a ",(0,a.jsx)(i.a,{href:"#key-derivation-paths",children:"3-level BIP-0032 path"})," (i.e. ",(0,a.jsx)(i.code,{children:"m/44'/474'/x'"}),")\nallows ",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-oasis",children:"Oasis' Ledger app"})," to implement automatic switching\nbetween existing (legacy) account key generation and the standard account key\ngeneration proposed in this ADR."]}),"\n",(0,a.jsxs)(i.p,{children:["Since the existing (legacy) account key generation used in\n",(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-oasis",children:"Oasis' Ledger app"})," uses a 5-level ",(0,a.jsx)(i.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",children:"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."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(i.h3,{id:"negative",children:"Negative"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:["\n",(0,a.jsx)(i.p,{children:"The account key generation proposed in this ADR is incompatible with two\nexisting account key generation schemes deployed in the field:"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/LedgerHQ/app-oasis",children:"Oasis' Ledger app"}),","]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"/general/manage-tokens/faq",children:"Bitpie mobile wallet"}),"."]}),"\n"]}),"\n",(0,a.jsx)(i.p,{children:"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."}),"\n"]}),"\n",(0,a.jsxs)(i.li,{children:["\n",(0,a.jsxs)(i.p,{children:[(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"}),"'s scheme for ",(0,a.jsx)(i.a,{href:"https://tools.ietf.org/html/rfc8032#section-5",children:"edwards25519 curve"})," only supports hardened private\nparent key to private child key derivation."]}),"\n",(0,a.jsx)(i.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(i.h3,{id:"neutral",children:"Neutral"}),"\n",(0,a.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,a.jsxs)(i.ul,{children:["\n",(0,a.jsx)(i.li,{children:(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/blob/master/slip-0010.md",children:"SLIP-0010"})}),"\n",(0,a.jsxs)(i.li,{children:["Stellar's ",(0,a.jsx)(i.a,{href:"https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md",children:"SEP-0005"})]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/jstarry",children:"Justin Starry (Solana)"}),"'s ",(0,a.jsx)(i.a,{href:"https://github.com/solana-labs/solana/issues/6301#issuecomment-551184457",children:"summary of approaches to adopting BIP-0032 for\nEd25519"})]}),"\n",(0,a.jsxs)(i.li,{children:[(0,a.jsx)(i.a,{href:"https://github.com/andrewkozlik",children:"Andrew Kozlik (SatoshiLabs)"}),"'s\n",(0,a.jsx)(i.a,{href:"https://github.com/satoshilabs/slips/issues/703#issuecomment-515213584",children:"comments on BIP32-Ed25519, SLIP-0010 and SLIP-0023"})]}),"\n"]})]})}function l(e={}){const{wrapper:i}={...(0,n.R)(),...e.components};return i?(0,a.jsx)(i,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},8453:(e,i,s)=>{s.d(i,{R:()=>r,x:()=>d});var a=s(6540);const n={},t=a.createContext(n);function r(e){const i=a.useContext(t);return a.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function d(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),a.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/527e04fa.9e57a7e4.js b/assets/js/527e04fa.9e57a7e4.js new file mode 100644 index 0000000000..bed970deea --- /dev/null +++ b/assets/js/527e04fa.9e57a7e4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8905],{3963:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var s=n(4848),i=n(8453);const r={},o="Runtime IDs",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/identifiers.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime Host Protocol",permalink:"/core/runtime/runtime-host-protocol"},next:{title:"Runtime Messages",permalink:"/core/runtime/messages"}},a={},d=[];function u(e){const t={a:"a",code:"code",h1:"h1",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"runtime-ids",children:"Runtime IDs"}),"\n",(0,s.jsxs)(t.p,{children:["Identifiers for runtimes are represented by the ",(0,s.jsx)(t.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common?tab=doc#Namespace",children:(0,s.jsx)(t.code,{children:"common.Namespace"})})," type."]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"Currently the following flags are defined (bit positions assume the flags\nvector is interpreted as an unsigned 64 bit big endian integer):"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Bit 63: The runtime is a test runtime and not for production networks."}),"\n",(0,s.jsx)(t.li,{children:"Bit 62: The runtime is a key manager runtime."}),"\n",(0,s.jsx)(t.li,{children:"Bits 61-0: Reserved for future expansion and MUST be set to 0."}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["Note: Unless the registry consensus parameter ",(0,s.jsx)(t.code,{children:"DebugAllowTestRuntimes"})," is\nset, attempts to register a test runtime will be rejected."]})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>c});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/52c9072e.e69f3274.js b/assets/js/52c9072e.e69f3274.js new file mode 100644 index 0000000000..7a670f9f71 --- /dev/null +++ b/assets/js/52c9072e.e69f3274.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4166],{9250:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Build Environment Setup and Building","slug":"core/development-setup/build-environment-setup-and-building","permalink":"/core/development-setup/build-environment-setup-and-building","sidebar":"oasisCore","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/5334ec61.0ffd7d74.js b/assets/js/5334ec61.0ffd7d74.js new file mode 100644 index 0000000000..7bc79f9bcc --- /dev/null +++ b/assets/js/5334ec61.0ffd7d74.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8025],{8316:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>a});var t=i(4848),s=i(8453);const r={},o="Building",l={id:"core/development-setup/building",title:"Building",description:"This chapter 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/building.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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"}},d={},a=[{value:"Unsafe Non-SGX Environment",id:"unsafe-non-sgx-environment",level:2},{value:"SGX Environment",id:"sgx-environment",level:2}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"building",children:"Building"}),"\n",(0,t.jsxs)(n.p,{children:["This chapter contains a description of steps required to build Oasis Core.\nBefore proceeding, make sure to look at the ",(0,t.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"prerequisites"})," required for running\nan Oasis Core environment."]}),"\n",(0,t.jsx)(n.h2,{id:"unsafe-non-sgx-environment",children:"Unsafe Non-SGX Environment"}),"\n",(0,t.jsx)(n.p,{children:"To build everything required for running an Oasis node locally, simply execute\nthe following in the top-level directory:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'export OASIS_UNSAFE_SKIP_AVR_VERIFY="1"\nexport OASIS_UNSAFE_SKIP_KM_POLICY="1"\nexport OASIS_UNSAFE_ALLOW_DEBUG_ENCLAVES="1"\nmake\n'})}),"\n",(0,t.jsxs)(n.p,{children:["To build BadgerDB without ",(0,t.jsx)(n.code,{children:"jemalloc"})," support (and avoid installing ",(0,t.jsx)(n.code,{children:"jemalloc"}),"\non your system), set"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'export OASIS_BADGER_NO_JEMALLOC="1"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Not using ",(0,t.jsx)(n.code,{children:"jemalloc"})," is fine for development purposes."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"sgx-environment",children:"SGX Environment"}),"\n",(0,t.jsx)(n.p,{children:"Compilation procedure under SGX environment is similar to the non-SGX with\nslightly different environmental variables set:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'export OASIS_UNSAFE_SKIP_AVR_VERIFY="1"\nexport OASIS_UNSAFE_ALLOW_DEBUG_ENCLAVES="1"\nmake\n'})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"To run an Oasis node under SGX make sure:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Your hardware has SGX support."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["You either explicitly enabled SGX in BIOS or made a\n",(0,t.jsx)(n.code,{children:"sgx_cap_enable_device()"})," system call, if SGX is in software controlled state."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["You installed ",(0,t.jsx)(n.a,{href:"https://github.com/intel/linux-sgx-driver",children:"Intel's SGX driver"})," (check that ",(0,t.jsx)(n.code,{children:"/dev/isgx"})," exists)."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Run ",(0,t.jsx)(n.code,{children:"sgx-detect"})," (part of fortanix rust tools) to verify that everything is\nconfigured correctly."]})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>l});var t=i(6540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/533aa3d4.1cbac429.js b/assets/js/533aa3d4.1cbac429.js new file mode 100644 index 0000000000..a0119d6819 --- /dev/null +++ b/assets/js/533aa3d4.1cbac429.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[319],{3010:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=s(4848),r=s(8453);const o={},t="Damask Upgrade",a={id:"node/mainnet/previous-upgrades/damask-upgrade",title:"Damask Upgrade",description:"This document provides an overview of the changes for the Damask Mainnet",source:"@site/docs/node/mainnet/previous-upgrades/damask-upgrade.md",sourceDirName:"node/mainnet/previous-upgrades",slug:"/node/mainnet/previous-upgrades/damask-upgrade",permalink:"/node/mainnet/previous-upgrades/damask-upgrade",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/previous-upgrades/damask-upgrade.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Previous Upgrades",permalink:"/node/mainnet/previous-upgrades"},next:{title:"Cobalt Upgrade",permalink:"/node/mainnet/previous-upgrades/cobalt-upgrade"}},d={},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:"proposed-state-changes",level:2},{value:"<strong>General</strong>",id:"general",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:"Launch Support",id:"launch-support",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"damask-upgrade",children:"Damask Upgrade"}),"\n",(0,i.jsx)(n.p,{children:"This document provides an overview of the changes for the Damask Mainnet\nupgrade."}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["The Damask upgrade on Mainnet is scheduled at epoch ",(0,i.jsx)(n.strong,{children:"13402"})," which will happen\naround ",(0,i.jsx)(n.strong,{children:"Apr 11, 2022 at 8:30 UTC"}),"."]})}),"\n",(0,i.jsx)(n.h2,{id:"major-features",children:"Major Features"}),"\n",(0,i.jsxs)(n.p,{children:["All features for the Damask upgrade are implemented as part of\n",(0,i.jsx)(n.strong,{children:"Oasis Core 22.1.x"})," release series which is a consensus protocol-breaking\nrelease."]}),"\n",(0,i.jsx)(n.p,{children:"Summary of the major features is as follows:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/adrs/0010-vrf-elections",children:"ADR 0010"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.em,{children:"yes"})," votes in terms of total\nvoting power for a governance proposal to pass."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/adrs/0013-runtime-upgrades",children:"ADR 0013"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/adrs/0011-incoming-runtime-messages",children:"ADR 0011"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/adrs/0012-runtime-message-results",children:"ADR 0012"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["In addition to the specified additional features, we also propose the\n",(0,i.jsx)(n.strong,{children:"validator set size"})," to be ",(0,i.jsx)(n.strong,{children:"increased from"})," the current ",(0,i.jsx)(n.strong,{children:"110 to 120"})," as\ndiscussed in the\n",(0,i.jsx)(n.a,{href:"https://oasiscommunity.slack.com/archives/CMUSJCRFA/p1647881564057319?thread_ts=1647448573.197229&cid=CMUSJCRFA",children:"Oasis Community Slack #nodeoperators channel"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This upgrade marks an important milestone for the Oasis Network, as it sets the\nfoundation for unlocking the network's full capabilities."}),"\n",(0,i.jsx)(n.h2,{id:"mechanics-of-the-upgrade",children:"Mechanics of the Upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["On Mar 24, 2022, the Oasis Protocol Foundation submitted the upgrade governance\nproposal with id of ",(0,i.jsx)(n.code,{children:"2"})," which proposed upgrading the network at epoch 13402."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["In addition to submitting the actual governance proposal to the network, Oasis\nProtocol Foundation also published the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/community/discussions/30",children:"Damask Upgrade Proposal discussion"})," to\nthe ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/community",children:"Oasis Community Forum on GitHub"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Node operators which had an active validator node in the validator set had 1\nweek to cast their vote."}),"\n",(0,i.jsxs)(n.p,{children:["Validators representing more than 88% of the total stake in the consensus\ncommittee participated in the vote, and 100% of them voted ",(0,i.jsx)(n.em,{children:"yes"})," for the proposal."]}),"\n",(0,i.jsxs)(n.p,{children:["The upgrade will be performed by exporting the network's state at the upgrade\nepoch, updating the ",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"genesis document"}),", upgrading the Oasis Node\nand the ParaTime binaries and starting a new network from the new genesis file."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Once enough nodes (representing 2/3+ of stake) have taken this step, the\nupgraded network will start."}),"\n",(0,i.jsxs)(n.p,{children:["For the actual steps that node operators need to make on their nodes, see the\n",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#damask-upgrade",children:"Upgrade Log"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"proposed-state-changes",children:"Proposed State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"This section will be updated with the exact details as we get closer to the\nupgrade."})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsx)(n.h3,{id:"general",children:(0,i.jsx)(n.strong,{children:"General"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"height"})})," will be set to the height of the Mainnet state dump + 1,\n",(0,i.jsx)(n.code,{children:"8048956"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"genesis_time"})})," will be set to",(0,i.jsx)(n.code,{children:"2022-04-11T09:30:00Z"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"oasis-3"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be bumped by ",(0,i.jsx)(n.code,{children:"10000"})," (a little more than a year) to\n",(0,i.jsx)(n.code,{children:"23807"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"registry",children:(0,i.jsx)(n.strong,{children:"Registry"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes"})})," list contains the registered runtimes' descriptors.\nIn this upgrade, all runtime descriptors will be migrated from version ",(0,i.jsx)(n.code,{children:"2"})," to\nversion ",(0,i.jsx)(n.code,{children:"3"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The migration will be done automatically with the\n",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes.[id=000000000000000000000000000000000000000000000000e2eaa99fc008f87f].deployments.version"})}),"\nspecifies Emerald ParaTime's version on Mainnet."]}),"\n",(0,i.jsx)(n.p,{children:"It will be upgraded from version 7.1.0 to 8.2.0 and hence the configuration\nneeds to be manually updated to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"version": {\n "major": 8,\n "minor": 2\n},\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes.[id=000000000000000000000000000000000000000000000000e199119c992377cb].deployments"})}),"\nspecifies Cipher ParaTime's version and TEE identity on Mainnet."]}),"\n",(0,i.jsx)(n.p,{children:"It will be upgraded from version 1.0.0 to 1.1.0 and hence the configuration\nneeds to be manually updated to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"version": {\n "major": 1,\n "minor": 1\n},\n"valid_from": 0,\n"tee": "oWhlbmNsYXZlc4GiaW1yX3NpZ25lclggQCXat+vaH77MTjY3YG4CEhTQ9BxtBCL9N4sqi4iBhFlqbXJfZW5jbGF2ZVggoiJgre0cDF5arUk9wh0X9eGWr5cHb8LY0A3/msmznHc="\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"2"})," to version ",(0,i.jsx)(n.code,{children:"3"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The migration will be done automatically with the\n",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Inactive registered entities in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.entities"})})," (and their\ncorresponding nodes in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.nodes"})}),") that don't pass the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"minimum staking thresholds"})," will be removed."]}),"\n",(0,i.jsxs)(n.p,{children:["The removal will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"root-hash",children:(0,i.jsx)(n.strong,{children:"Root Hash"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"1000"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"128"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.runtime_state"})})," contains the state roots of the runtimes.\nEmpty fields will be omitted."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"staking",children:(0,i.jsx)(n.strong,{children:"Staking"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"node-storage"})," key is removed since Oasis Core 22.0+ removes separate\nstorage nodes.\nFor more details, see: ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/pull/4308",children:"Oasis Core #4308"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"committee-scheduler",children:(0,i.jsx)(n.strong,{children:"Committee Scheduler"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.min_validators"})})," is the minimum size of the consensus\ncommittee (i.e. the validator set). It will be increased from ",(0,i.jsx)(n.code,{children:"15"})," to ",(0,i.jsx)(n.code,{children:"30"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.max_validators"})})," is the maximum size of the consensus\ncommittee (i.e. the validator set). It will be increased from ",(0,i.jsx)(n.code,{children:"110"})," to ",(0,i.jsx)(n.code,{children:"120"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"random-beacon",children:(0,i.jsx)(n.strong,{children:"Random Beacon"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon"})})," object contains parameters controlling the new\n",(0,i.jsx)(n.a,{href:"/adrs/0010-vrf-elections",children:"improved VRF-based random beacon"})," introduced in the Damask upgrade."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the epoch\nof Mainnet's state dump + 1, ",(0,i.jsx)(n.code,{children:"13402"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.backend"})})," configures the random beacon backend to use.\nIt will be set to ",(0,i.jsx)(n.code,{children:'"vrf"'})," indicating that the beacon implementing\n",(0,i.jsx)(n.a,{href:"/adrs/0010-vrf-elections",children:"VRF-based random beacon"})," should be used."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.vrf_parameters"})})," control the behavior of the new\n",(0,i.jsx)(n.a,{href:"/adrs/0010-vrf-elections",children:"VRF-based random beacon"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"20"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.vrf_parameters.interval"})})," is the duration of an epoch.\nIt will be set to ",(0,i.jsx)(n.code,{children:"600"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"400"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.vrf_parameters.gas_costs.vrf_prove"})})," specifies the cost for\na VRF prove transaction.\nIt will be set to ",(0,i.jsx)(n.code,{children:"1000"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.pvss_parameters"})})," control the behavior of the\n",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"previous random beacon implementing a PVSS scheme"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Since PVSS is no longer supported, all its configuration options are removed\nas well."}),"\n",(0,i.jsx)(n.h3,{id:"governance",children:(0,i.jsx)(n.strong,{children:"Governance"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.stake_threshold"})})," is a new parameter specifying the\nsingle unified stake threshold representing the percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes\nin terms of total voting power for a governance proposal to pass.\nIt will be set to ",(0,i.jsx)(n.code,{children:"68"})," (i.e. 68%)."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.quorum"})})," is the minimum percentage of voting power that\nneeds to be cast on a proposal for the result to be valid."]}),"\n",(0,i.jsxs)(n.p,{children:["It will be removed since it is being replaced by the single\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.staking_threshold"})})," parameter."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.threshold"})})," is the minimum percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes\nin order for a proposal to be accepted."]}),"\n",(0,i.jsxs)(n.p,{children:["It will be removed since it is being replaced by the single\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.staking_threshold"})})," parameter."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"consensus",children:(0,i.jsx)(n.strong,{children:"Consensus"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_interval"})})," parameter controls the\ninterval (in blocks) on which state checkpoints should be taken. It will be\nincreased from ",(0,i.jsx)(n.code,{children:"10000"})," to ",(0,i.jsx)(n.code,{children:"100000"})," to improve nodes' performance since\ncomputing checkpoints is I/O intensive."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"other",children:"Other"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"Mainnet genesis file"}),"\nto include the Oasis Network's genesis quote:"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"launch-support",children:"Launch Support"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["For any additional support, please reach out via the\n",(0,i.jsxs)(n.a,{href:"/get-involved/",children:[(0,i.jsx)(n.strong,{children:"#nodeoperators"})," Oasis Community Slack channel"]})," with\nyour questions, comments, and feedback related to Damask upgrade."]}),"\n",(0,i.jsxs)(n.p,{children:["To follow the network, please use one of the many\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards",children:"community block explorers"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>a});var i=s(6540);const r={},o=i.createContext(r);function t(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:t(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5583c17b.466febe7.js b/assets/js/5583c17b.466febe7.js new file mode 100644 index 0000000000..fe11552347 --- /dev/null +++ b/assets/js/5583c17b.466febe7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7513],{2991:(e,q,n)=>{n.r(q),n.d(q,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>A,metadata:()=>o,toc:()=>c});var t=n(4848),a=n(8453),r=n(1470),s=n(9365);const A={description:"Writing Sapphire dApp for browser and Metamask"},i="Browser Support",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/browser.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Writing Sapphire dApp for browser and Metamask"},sidebar:"developers",previous:{title:"Guide",permalink:"/dapp/sapphire/guide"},next:{title:"View-Call Authentication",permalink:"/dapp/sapphire/authentication"}},l={},c=[{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}];function d(e){const q={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(q.h1,{id:"browser-support",children:"Browser Support"}),"\n",(0,t.jsx)(q.p,{children:"Confidential Sapphire dApps work in web browsers by wrapping the\nEthereum provider such as Metamask to enable signing and encrypting\ncalls and transactions."}),"\n",(0,t.jsxs)(q.p,{children:["Let's begin with the ",(0,t.jsx)(q.a,{href:"https://hardhat.org/tutorial/boilerplate-project",children:"Hardhat boilerplate"}),". As mentioned on their website\nthe boilerplate provides the following:"]}),"\n",(0,t.jsxs)(q.ul,{children:["\n",(0,t.jsx)(q.li,{children:"The Solidity contract implementing an ERC-20 token"}),"\n",(0,t.jsx)(q.li,{children:"Tests for the entire functionality of the contract"}),"\n",(0,t.jsx)(q.li,{children:"A minimal React front-end to interact with the contract using ethers.js"}),"\n"]}),"\n",(0,t.jsxs)(q.p,{children:["Go ahead and clone the original ",(0,t.jsx)(q.a,{href:"https://github.com/NomicFoundation/hardhat-boilerplate",children:"Hardhat boilerplate repo"}),". Move to the checked\nout folder and ",(0,t.jsx)(q.strong,{children:"apply the Sapphire-specific changes"})," to ",(0,t.jsx)(q.code,{children:"hardhat.config.js"}),"\nas ",(0,t.jsx)(q.a,{href:"/dapp/sapphire/quickstart#add-the-sapphire-testnet-to-hardhat",children:"described in the quickstart"}),"."]}),"\n",(0,t.jsxs)(q.p,{children:["Next, install dependencies. The boilerplate project uses\n",(0,t.jsx)(q.a,{href:"https://pnpm.io",children:"pnpm"}),", but ",(0,t.jsx)(q.code,{children:"yarn"})," and ",(0,t.jsx)(q.code,{children:"npm"})," will also work with some modifications\naround workspaces:"]}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"npm install\nnpm install -D @oasisprotocol/sapphire-paratime\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"pnpm install\npnpm add -D @oasisprotocol/sapphire-paratime\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"yarn install\nyarn add --dev @oasisprotocol/sapphire-paratime\n"})})})]}),"\n",(0,t.jsxs)(q.p,{children:["Now, you can deploy the contract on the Testnet with the private key of the\naccount holding some ",(0,t.jsx)(q.a,{href:"/dapp/sapphire/quickstart#get-some-sapphire-testnet-tokens",children:"TEST tokens"}),":"]}),"\n",(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:'PRIVATE_KEY="0x..." npx hardhat run scripts/deploy.js --network sapphire-testnet\n'})}),"\n",(0,t.jsxs)(q.p,{children:["This will compile the contract and deploy it on the Testnet. In addition\nto the quickstart steps, ",(0,t.jsxs)(q.strong,{children:["the contract address and ABI will also automatically\nbe copied over to the ",(0,t.jsx)(q.code,{children:"frontend/src/contracts"})," folder so that the frontend can\naccess them!"]})]}),"\n",(0,t.jsx)(q.admonition,{type:"warning",children:(0,t.jsxs)(q.p,{children:["The contract in the Hardhat boilerplate is ERC-20-compatible and emits the\n",(0,t.jsx)(q.code,{children:"transfer"})," event. If your wish to preserve confidentiality, you can comment\nout ",(0,t.jsx)(q.a,{href:"https://github.com/NomicFoundation/hardhat-boilerplate/blob/13bd712c1285b2de572f14d20e6a750ae08565c0/contracts/Token.sol#L66",children:"line 66"}),". Read ",(0,t.jsx)(q.a,{href:"/dapp/sapphire/guide#contract-logs",children:"the guide"})," to learn more."]})}),"\n",(0,t.jsx)(q.h2,{id:"signing-sapphire-calls-and-transactions-in-browser",children:"Signing Sapphire Calls and Transactions in Browser"}),"\n",(0,t.jsxs)(q.p,{children:["Now, let's explore the frontend of our dApp. Begin by moving into the\n",(0,t.jsx)(q.code,{children:"frontend"})," folder and install dependencies:"]}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"npm install\nnpm install -D @oasisprotocol/sapphire-paratime\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"pnpm install\npnpm add -D @oasisprotocol/sapphire-paratime\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"yarn install\nyarn add --dev @oasisprotocol/sapphire-paratime\n"})})})]}),"\n",(0,t.jsxs)(q.p,{children:["The main frontend logic is stored in ",(0,t.jsx)(q.code,{children:"frontend/src/components/Dapp.js"}),". Apply\nthe following changes:"]}),"\n",(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-diff",metastring:'title="frontend/src/components/Dapp.js"',children:"--- 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+ this._provider.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"})}),"\n",(0,t.jsxs)(q.p,{children:["Beside the obvious change to the chain ID and wrapping ethers.js objects with the\nSapphire wrapper you can notice that we initialized ",(0,t.jsx)(q.strong,{children:"two"})," contract\ninstances:"]}),"\n",(0,t.jsxs)(q.ul,{children:["\n",(0,t.jsxs)(q.li,{children:[(0,t.jsx)(q.code,{children:"this._token"})," object will be used for unsigned eth calls. This is the\nHardhat method of ",(0,t.jsxs)(q.a,{href:"/dapp/sapphire/guide#transactions--calls",children:["setting ",(0,t.jsx)(q.code,{children:"from"})," transaction field to all\nzeros"]})," in order to avoid Metamask signature popups.\nAlthough the call is unsigned, ",(0,t.jsx)(q.strong,{children:"it is still encrypted"})," with the\ncorresponding runtime key to preserve confidentiality."]}),"\n",(0,t.jsxs)(q.li,{children:[(0,t.jsx)(q.code,{children:"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."]}),"\n"]}),"\n",(0,t.jsx)(q.h2,{id:"trying-it",children:"Trying it"}),"\n",(0,t.jsx)(q.p,{children:"Start the frontend by typing:"}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"npm run start\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"pnpm run start\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(q.pre,{children:(0,t.jsx)(q.code,{className:"language-shell",children:"yarn run start\n"})})})]}),"\n",(0,t.jsxs)(q.p,{children:["If all goes well the web server will spin up and your browser should\nautomatically open ",(0,t.jsx)(q.code,{children:"http://localhost:3000"}),"."]}),"\n",(0,t.jsx)(q.p,{children:(0,t.jsx)(q.img,{alt:"Hardhat boilerplate frontend",src:n(8496).A+"",width:"1489",height:"979"})}),"\n",(0,t.jsxs)(q.p,{children:["Go ahead and connect the wallet. If you haven't done it yet, you will have\nto add the ",(0,t.jsx)(q.a,{href:"/dapp/sapphire/#testnet",children:"Sapphire ParaTime Testnet network to your\nMetamask"}),". Once connected, the frontend will make an unsigned\ncall to the ",(0,t.jsx)(q.code,{children:"balanceOf"})," view and show you the amount of ",(0,t.jsx)(q.code,{children:"MHT"}),"s in your selected\nMetamask account."]}),"\n",(0,t.jsx)(q.p,{children:(0,t.jsx)(q.img,{alt:"MHT balance of your account",src:n(3899).A+"",width:"1489",height:"979"})}),"\n",(0,t.jsxs)(q.p,{children:["Next, let's transfer some ",(0,t.jsx)(q.code,{children:"MHT"}),"s. Fill in the amount, the address and hit the\n",(0,t.jsx)(q.em,{children:"Transfer"})," button. Metamask will show you the popup to sign and submit the\ntransfer transaction. Once confirmed, Metamask will both ",(0,t.jsx)(q.strong,{children:"sign and encrypt"})," the transaction."]}),"\n",(0,t.jsx)(q.p,{children:(0,t.jsx)(q.img,{alt:"Sign and encrypt the transfer transaction",src:n(242).A+"",width:"360",height:"635"})}),"\n",(0,t.jsx)(q.p,{children:"Once the transaction is processed, you will get a notification from Metamask\nand the balance in the dApp will be updated."}),"\n",(0,t.jsx)(q.admonition,{type:"tip",children:(0,t.jsxs)(q.p,{children:["If you commented out ",(0,t.jsx)(q.code,{children:"emit Transfer(...)"}),", the transfer of ",(0,t.jsx)(q.code,{children:"MHT"}),"s would have\nbeen completely confidential. In the example above, the ",(0,t.jsx)(q.a,{href:"https://explorer.oasis.io/testnet/sapphire/tx/0x3303dea5d48291d1564cad573f21fc71fcbdc2b862e17e056287fd9207e3bc53",children:"following\ntransaction"})," was generated. Go ahead and check your transaction\non the block explorer too, to make sure no sensitive data was leaked!"]})}),"\n",(0,t.jsx)(q.p,{children:"Congratulations, you successfully implemented your first truly confidential\ndApp which runs in the browser and wraps Metamask to both sign and encrypt the\ntransactions!"}),"\n",(0,t.jsxs)(q.p,{children:["Should you have any questions or ideas to share, feel free to reach out to us\non ",(0,t.jsx)(q.a,{href:"/get-involved/#social-media-channels",children:"discord and other social media channels"}),"."]}),"\n",(0,t.jsx)(q.admonition,{title:"Example",type:"info",children:(0,t.jsxs)(q.p,{children:["You can download a full working example from the ",(0,t.jsx)(q.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/hardhat-boilerplate",children:"Sapphire ParaTime examples"}),"\nrepository."]})}),"\n",(0,t.jsx)(q.admonition,{title:"Example",type:"info",children:(0,t.jsxs)(q.p,{children:["If your project involves building both a contract backend and a web frontend,\nwe recommend that you check out the official ",(0,t.jsx)(q.a,{href:"https://github.com/oasisprotocol/demo-starter",children:"Oasis starter"})," files."]})})]})}function h(e={}){const{wrapper:q}={...(0,a.R)(),...e.components};return q?(0,t.jsx)(q,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},9365:(e,q,n)=>{n.d(q,{A:()=>s});n(6540);var t=n(4164);const a={tabItem:"tabItem_Ymn6"};var r=n(4848);function s(e){let{children:q,hidden:n,className:s}=e;return(0,r.jsx)("div",{role:"tabpanel",className:(0,t.A)(a.tabItem,s),hidden:n,children:q})}},1470:(e,q,n)=>{n.d(q,{A:()=>v});var t=n(6540),a=n(4164),r=n(3104),s=n(6347),A=n(205),i=n(7485),o=n(1682),l=n(9466);function c(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:q}=e;return!!q&&"object"==typeof q&&"value"in q}(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)??[]}function d(e){const{values:q,children:n}=e;return(0,t.useMemo)((()=>{const e=q??function(e){return c(e).map((e=>{let{props:{value:q,label:n,attributes:t,default:a}}=e;return{value:q,label:n,attributes:t,default:a}}))}(n);return function(e){const q=(0,o.X)(e,((e,q)=>e.value===q.value));if(q.length>0)throw new Error(`Docusaurus error: Duplicate values "${q.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[q,n])}function h(e){let{value:q,tabValues:n}=e;return n.some((e=>e.value===q))}function p(e){let{queryString:q=!1,groupId:n}=e;const a=(0,s.W6)(),r=function(e){let{queryString:q=!1,groupId:n}=e;if("string"==typeof q)return q;if(!1===q)return null;if(!0===q&&!n)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 n??null}({queryString:q,groupId:n});return[(0,i.aZ)(r),(0,t.useCallback)((e=>{if(!r)return;const q=new URLSearchParams(a.location.search);q.set(r,e),a.replace({...a.location,search:q.toString()})}),[r,a])]}function u(e){const{defaultValue:q,queryString:n=!1,groupId:a}=e,r=d(e),[s,i]=(0,t.useState)((()=>function(e){let{defaultValue:q,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(q){if(!h({value:q,tabValues:n}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${q}" 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 q}const t=n.find((e=>e.default))??n[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:q,tabValues:r}))),[o,c]=p({queryString:n,groupId:a}),[u,m]=function(e){let{groupId:q}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(q),[a,r]=(0,l.Dv)(n);return[a,(0,t.useCallback)((e=>{n&&r.set(e)}),[n,r])]}({groupId:a}),f=(()=>{const e=o??u;return h({value:e,tabValues:r})?e:null})();(0,A.A)((()=>{f&&i(f)}),[f]);return{selectedValue:s,selectValue:(0,t.useCallback)((e=>{if(!h({value:e,tabValues:r}))throw new Error(`Can't select invalid tab value=${e}`);i(e),c(e),m(e)}),[c,m,r]),tabValues:r}}var m=n(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=n(4848);function g(e){let{className:q,block:n,selectedValue:t,selectValue:s,tabValues:A}=e;const i=[],{blockElementScrollPositionUntilNextRender:o}=(0,r.a_)(),l=e=>{const q=e.currentTarget,n=i.indexOf(q),a=A[n].value;a!==t&&(o(q),s(a))},c=e=>{let q=null;switch(e.key){case"Enter":l(e);break;case"ArrowRight":{const n=i.indexOf(e.currentTarget)+1;q=i[n]??i[0];break}case"ArrowLeft":{const n=i.indexOf(e.currentTarget)-1;q=i[n]??i[i.length-1];break}}q?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.A)("tabs",{"tabs--block":n},q),children:A.map((e=>{let{value:q,label:n,attributes:r}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:t===q?0:-1,"aria-selected":t===q,ref:e=>i.push(e),onKeyDown:c,onClick:l,...r,className:(0,a.A)("tabs__item",f.tabItem,r?.className,{"tabs__item--active":t===q}),children:n??q},q)}))})}function x(e){let{lazy:q,children:n,selectedValue:a}=e;const r=(Array.isArray(n)?n:[n]).filter(Boolean);if(q){const e=r.find((e=>e.props.value===a));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:r.map(((e,q)=>(0,t.cloneElement)(e,{key:q,hidden:e.props.value!==a})))})}function j(e){const q=u(e);return(0,b.jsxs)("div",{className:(0,a.A)("tabs-container",f.tabList),children:[(0,b.jsx)(g,{...q,...e}),(0,b.jsx)(x,{...q,...e})]})}function v(e){const q=(0,m.A)();return(0,b.jsx)(j,{...e,children:c(e.children)},String(q))}},8496:(e,q,n)=>{n.d(q,{A:()=>t});const t="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"},3899:(e,q,n)=>{n.d(q,{A:()=>t});const t=n.p+"assets/images/hardhat-boilerplate-frontend2-6d2fe4701649136e7c90270f572a86be.png"},242:(e,q,n)=>{n.d(q,{A:()=>t});const t=n.p+"assets/images/hardhat-boilerplate-frontend3-727893cadf6a2874b868f655cb84d059.png"},8453:(e,q,n)=>{n.d(q,{R:()=>s,x:()=>A});var t=n(6540);const a={},r=t.createContext(a);function s(e){const q=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(q):{...q,...e}}),[q,e])}function A(e){let q;return q=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(r.Provider,{value:q},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/562f786c.adfd2990.js b/assets/js/562f786c.adfd2990.js new file mode 100644 index 0000000000..e2ad9d69d3 --- /dev/null +++ b/assets/js/562f786c.adfd2990.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7386],{4753:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var n=o(4848),s=o(8453);const r={},i="Consensus Trust Root",a={id:"rofl/trust-root",title:"Consensus Trust Root",description:"The [ROFL app example] already contains an embedded root of trust called the",source:"@site/docs/rofl/trust-root.md",sourceDirName:"rofl",slug:"/rofl/trust-root",permalink:"/rofl/trust-root",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/rofl/trust-root.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"rofl",previous:{title:"Application",permalink:"/rofl/app"}},c={},d=[{value:"The Root of Trust",id:"the-root-of-trust",level:2},{value:"Embedding the Root",id:"embedding-the-root",level:2}];function u(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"consensus-trust-root",children:"Consensus Trust Root"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.a,{href:"/rofl/app",children:"ROFL app example"})," already contains an embedded root of trust called the\n",(0,n.jsx)(t.em,{children:"consensus trust root"}),". The preconfigured trust root is valid for the current\ndeployment of Sapphire Testnet. This chapter briefly describes what the trust\nroot is, how it can be securely derived and configured in your ROFL app."]}),"\n",(0,n.jsx)(t.h2,{id:"the-root-of-trust",children:"The Root of Trust"}),"\n",(0,n.jsx)(t.p,{children:"In order to ensure that the ROFL app can securely authenticate it is talking to\nthe actual consensus layer and not a fork, you need to configure it with a\nsuitable consensus trust root. The trust root is a well-known consensus block\nheader that is used to bootstrap the light client which verifies everything\nelse."}),"\n",(0,n.jsx)(t.p,{children:"Having a correct trust root configured makes it impossible even for the node\noperator who is running your ROFL app to forge any queries as integrity of all\nresults is verified against the consensus layer trust root. One should try to\nuse a somewhat recent trust root which can be refreshed during application\nupgrades."}),"\n",(0,n.jsx)(t.admonition,{type:"caution",children:(0,n.jsx)(t.p,{children:"The consensus trust root represents the root of security for the ROFL app. Not\nconfiguring it makes your application vulnerable to man-in-the-middle attacks by\nthe node operator."})}),"\n",(0,n.jsx)(t.h2,{id:"embedding-the-root",children:"Embedding the Root"}),"\n",(0,n.jsxs)(t.p,{children:["In order to obtain a suitable consensus trust root you can leverage the Oasis\nCLI as follows (note the correct ",(0,n.jsx)(t.em,{children:"network"})," and ",(0,n.jsx)(t.em,{children:"paratime"}),"). Note that you should\nuse a node you trust to query this information (the example below uses the\ndefault public gRPC endpoints)."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"oasis rofl trust-root --network testnet --paratime sapphire\n"})}),"\n",(0,n.jsx)(t.p,{children:"Which should output something like the following:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-rust",children:'TrustRoot {\n height: 22110615,\n hash: "95d1501f9cb88619050a5b422270929164ce739c5d803ed9500285b3b040985e".into(),\n runtime_id: "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c".into(),\n chain_context: "0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76".to_string(),\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["You can then use this in your ROFL app definition by adding the following method\nto your ",(0,n.jsx)(t.code,{children:"App"})," trait implementation."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-rust",children:'fn consensus_trust_root() -> Option<TrustRoot> {\n Some(TrustRoot {\n height: 22110615,\n hash: "95d1501f9cb88619050a5b422270929164ce739c5d803ed9500285b3b040985e".into(),\n runtime_id: "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c".into(),\n chain_context: "0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76"\n .to_string(),\n })\n}\n'})})]})}function l(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>a});var n=o(6540);const s={},r=n.createContext(s);function i(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5741.8206d17e.js b/assets/js/5741.8206d17e.js new file mode 100644 index 0000000000..088bde4311 --- /dev/null +++ b/assets/js/5741.8206d17e.js @@ -0,0 +1 @@ +(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5741],{5741:()=>{}}]); \ No newline at end of file diff --git a/assets/js/59b1a96c.827e3a10.js b/assets/js/59b1a96c.827e3a10.js new file mode 100644 index 0000000000..5bc5cc35a7 --- /dev/null +++ b/assets/js/59b1a96c.827e3a10.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4485],{3398:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>l,metadata:()=>d,toc:()=>h});var s=n(4848),r=n(8453),o=n(5965),i=n(2550),a=n(6116);const l={},c="Getting Started",d={id:"README",title:"Getting Started",description:"Use Oasis",source:"@site/docs/README.mdx",sourceDirName:".",slug:"/",permalink:"/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{}},u={},h=[{value:"Use Oasis",id:"use-oasis",level:2},{value:"Create dApp",id:"create-dapp",level:2},{value:"Build ROFL",id:"build-rofl",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}];function p(e){const t={a:"a",h1:"h1",h2:"h2",p:"p",strong:"strong",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"getting-started",children:"Getting Started"}),"\n",(0,s.jsx)(t.h2,{id:"use-oasis",children:"Use Oasis"}),"\n",(0,s.jsx)(t.p,{children:"This introductory part 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."}),"\n",(0,s.jsx)(i.A,{items:[(0,a.$)("/general/oasis-network/"),(0,a.$)("/general/manage-tokens/"),(0,a.$)("/general/manage-tokens/cli/")]}),"\n",(0,s.jsx)(t.h2,{id:"create-dapp",children:"Create dApp"}),"\n",(0,s.jsxs)(t.p,{children:["Contains learning material for the smart contract developers. Since the Oasis\nplatform is best known for confidentiality, the most notable ParaTime is\n",(0,s.jsx)(t.a,{href:"/dapp/sapphire/",children:"Oasis Sapphire"}),", an ",(0,s.jsx)(t.strong,{children:"EVM-compatible"})," ParaTime with ",(0,s.jsx)(t.strong,{children:"built-in contract state\nencryption"}),". The Oasis team also prepared a set of libraries called the\n",(0,s.jsx)(t.a,{href:"/dapp/opl/",children:"Oasis Privacy Layer"})," to ",(0,s.jsx)(t.strong,{children:"bridge existing dApps running on other chains"})," to\nuse the unique Sapphire's confidentiality."]}),"\n",(0,s.jsxs)(t.p,{children:["The part also covers other ParaTimes such as the non-confidential\n",(0,s.jsx)(t.a,{href:"/dapp/emerald/",children:"Oasis Emerald"})," and Wasm-compatible, confidential ",(0,s.jsx)(t.a,{href:"/dapp/emerald/",children:"Oasis Cipher"}),"."]}),"\n",(0,s.jsx)(i.A,{items:[(0,a.$)("/dapp/sapphire/"),(0,a.$)("/dapp/opl/"),(0,a.$)("/dapp/emerald/"),(0,a.$)("/dapp/cipher/")]}),"\n",(0,s.jsx)(t.h2,{id:"build-rofl",children:"Build ROFL"}),"\n",(0,s.jsx)(t.p,{children:"Runtime OFfchain Logic (ROFL) enables you to build secure applications running\noffchain in a trusted environment (TEE) and that seamlessly communicate with\nOasis Sapphire. This is ideal for trusted oracles, compute-expensive tasks\nin AI or as a backend for interactive games."}),"\n",(0,s.jsx)(o.A,{item:(0,a.$)("/rofl/")}),"\n",(0,s.jsx)(t.h2,{id:"get-involved",children:"Get Involved"}),"\n",(0,s.jsx)(t.p,{children:"Contains information on official channels to get in touch with the Oasis Network\ndevelopers and how to contribute to the network."}),"\n",(0,s.jsx)(i.A,{items:[(0,a.$)("/get-involved/"),(0,a.$)("https://oasisrose.garden"),(0,a.$)("/get-involved/run-node"),(0,a.$)("/get-involved/oasis-core")]}),"\n",(0,s.jsx)(t.h2,{id:"run-node",children:"Run Node"}),"\n",(0,s.jsx)(t.p,{children:"If you want to run your own Oasis node, this part 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."}),"\n",(0,s.jsx)(i.A,{items:[(0,a.$)("/node/"),(0,a.$)("/node/mainnet/"),(0,a.$)("/node/testnet/"),(0,a.$)("/node/run-your-node/")]}),"\n",(0,s.jsx)(t.h2,{id:"build-paratimes",children:"Build ParaTimes"}),"\n",(0,s.jsx)(t.p,{children:"Apart from the Sapphire, Emerald, Cipher and the Key manager ParaTimes,\nyou can also write, compile, sign and deploy your own ParaTime on the Oasis\nNetwork. This part describes the knobs you need to use to do so."}),"\n",(0,s.jsx)(o.A,{item:(0,a.$)("/paratime/")}),"\n",(0,s.jsx)(t.h2,{id:"develop-core",children:"Develop Core"}),"\n",(0,s.jsx)(t.p,{children:"Whether you want to contribute your code to the core components of the Oasis\nNetwork or just learn more about the Oasis consensus layer and other core\ncomponents, this is the part for you."}),"\n",(0,s.jsx)(o.A,{item:(0,a.$)("/core/")}),"\n",(0,s.jsx)(t.p,{children:"Additions or changes to the interoperable Oasis network components are always\nmade with consensus. Similar to the Ethereum's ERC/EIP mechanism Oasis follows\nformal Architectural Decision Records (ADRs) which are first proposed, voted on\nand finally implemented, if accepted."}),"\n",(0,s.jsx)(o.A,{item:(0,a.$)("/adrs")})]})}function m(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(p,{...e})}):p(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var s=n(4164),r=n(8774),o=n(4142),i=n(5846),a=n(6654),l=n(1312),c=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=n(4848);function h(e){let{href:t,children:n}=e;return(0,u.jsx)(r.A,{href:t,className:(0,s.A)("card padding--lg",d.cardContainer),children:n})}function p(e){let{href:t,icon:n,title:r,description:o}=e;return(0,u.jsxs)(h,{href:t,children:[(0,u.jsxs)(c.A,{as:"h2",className:(0,s.A)("text--truncate",d.cardTitle),title:r,children:[n," ",r]}),o&&(0,u.jsx)("p",{className:(0,s.A)("text--truncate",d.cardDescription),title:o,children:o})]})}function m(e){let{item:t}=e;const n=(0,o.Nr)(t),s=function(){const{selectMessage:e}=(0,i.W)();return t=>e(t,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,u.jsx)(p,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??s(t.items.length)}):null}function f(e){let{item:t}=e;const n=(0,a.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",s=(0,o.cC)(t.docId??void 0);return(0,u.jsx)(p,{href:t.href,icon:n,title:t.label,description:t.description??s?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,u.jsx)(f,{item:t});case"category":return(0,u.jsx)(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,n)=>{n.d(t,{A:()=>l});n(6540);var s=n(4164),r=n(4142),o=n(5965),i=n(4848);function a(e){let{className:t}=e;const n=(0,r.$S)();return(0,i.jsx)(l,{items:n.items,className:t})}function l(e){const{items:t,className:n}=e;if(!t)return(0,i.jsx)(a,{...e});const l=(0,r.d1)(t);return(0,i.jsx)("section",{className:(0,s.A)("row",n),children:l.map(((e,t)=>(0,i.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,i.jsx)(o.A,{item:e})},t)))})}},5846:(e,t,n)=>{n.d(t,{W:()=>c});var s=n(6540),r=n(4586);const o=["zero","one","two","few","many","other"];function i(e){return o.filter((t=>e.includes(t)))}const a={locale:"en",pluralForms:i(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,r.A)();return(0,s.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:i(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`),a}}),[e])}function c(){const e=l();return{selectMessage:(t,n)=>function(e,t,n){const s=e.split("|");if(1===s.length)return s[0];s.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${s.length}: ${e}`);const r=n.select(t),o=n.pluralForms.indexOf(r);return s[Math.min(o,s.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>o});var s=n(2252);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,s.r)();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]}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>a});var s=n(6540);const r={},o=s.createContext(r);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5a14fd4c.4416ac9f.js b/assets/js/5a14fd4c.4416ac9f.js new file mode 100644 index 0000000000..e472224173 --- /dev/null +++ b/assets/js/5a14fd4c.4416ac9f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9555],{9138:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var i=t(4848),s=t(8453);const o={},r="ADR 0010: VRF-based Committee Elections",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0010-vrf-elections.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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={},h=[{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}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-0010-vrf-based-committee-elections",children:"ADR 0010: VRF-based Committee Elections"}),"\n",(0,i.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,i.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2021-05-10: Initial version"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"cryptographic-primitives",children:"Cryptographic Primitives"}),"\n",(0,i.jsxs)(n.p,{children:["Let the VRF to be used across the system be ECVRF-EDWARDS25519-SHA512-ELL2\nfrom the ",(0,i.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/",children:"Verifiable Random Functions (VRFs) draft (v10)"}),", with the\nfollowing additions and extra clarifications:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:'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).'}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"When decoding s in the ECVRF_verify routine, the s scalar MUST fall\nwithin the range 0 \u2264 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."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"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)."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Let the tuple oriented cryptographic hash function be TupleHash256 from\n",(0,i.jsx)(n.a,{href:"https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf",children:"NIST SP 800-185"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"node-descriptor-changes",children:"Node Descriptor Changes"}),"\n",(0,i.jsx)(n.p,{children:"The node descriptor of each node will be extended to include the following\ndatastructure."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["The existing ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,i.jsx)(n.p,{children:"The scheduler module will have the following additional consensus parameters\nthat control behavior."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.h3,{id:"consensus-state-events-and-transactions",children:"Consensus State, Events, and Transactions"}),"\n",(0,i.jsx)(n.p,{children:"The scheduler component will maintain and make available the following additonal\nconsensus state."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Upon epoch transition, the scheduler will emit the following event."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.h3,{id:"vrf-operation",children:"VRF Operation"}),"\n",(0,i.jsx)(n.p,{children:"For the genesis epoch, let the VRF alpha_string input be derived as:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:'TupleHash256((chain_context, I2OSP(epoch,8)), 256, "oasis-core:vrf/alpha")'})}),"\n",(0,i.jsx)(n.p,{children:"For every subsequent epoch, let alpha_string be derived as:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:'TupleHash256((chain_context, I2OSP(epoch, 8), beta_0, ... beta_n), 256, "oasis-core:vrf/alpha")'})}),"\n",(0,i.jsx)(n.p,{children:'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.'}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"ECVRF_prove(VRFKey_private, alpha_string)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Upon receiving a VRFProve transaction, the scheduler does the following:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Rejects the transaction if less than ProofSubmissionDelay blocks\nhave elapsed since the transition into the current epoch."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Checks to see if the node tentatively eligible to be included in\nthe next election according to the following criteria:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Not frozen."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Has registered the VRF.ID used to generate the proof prior\nto the transition into the current epoch (May slash)."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Has not already submitted a proof for the current epoch\n(May slash if proof is different)."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Validates the proof, and if valid, stores the VRF.ID + pi_string\nin the consensus state."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"vrf-committee-elections",children:"VRF Committee Elections"}),"\n",(0,i.jsx)(n.p,{children:"The following changes are made to the committee election process."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"If the alpha value is considered weak, no commitee elections are allowed."}),"\n",(0,i.jsx)(n.p,{children:"For each committee:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Filter the node list based on the current stake/eligibility criteria,\nand additionally filter out nodes that have not submitted a valid\nVRF proof."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"For each eligible (node, commitee kind, committe role) tuple, derive\na sortition string as:"}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:'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,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Sort s_0 ... s_n in ascending lexographical order."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Select the requisite nodes that produced the sortition strings\nstarting from the head of the sorted list as the committee."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"vrf-validator-elections",children:"VRF Validator Elections"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"When this situation occurs the validator is selected as follows:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"For all validator-eligible nodes controlled by the given entity,\nderive a sortition string as:"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:'s_n = TupleHash256((chain_context, I2OSP(epoch, 8), beta_n), 256, "oasis-core:vrf/validator")'})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Sort s_0 ... s_n, in ascending lexographic order."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Select the node that produced the 0th sortition string in the sorted\nlist as the validator."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"timekeeping-changes",children:"Timekeeping Changes"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"This is significantly simpler from a design standpoint."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"This is significantly faster and scales significantly better."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"It is possible to go back to fixed-length epochs again."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The system loses a way to generate entropy at the consensus layer."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The simple design involves an additional 1-epoch period after network\ninitialization where elections are not available."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"I need to implement TupleHash256."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5da91464.fb8e830b.js b/assets/js/5da91464.fb8e830b.js new file mode 100644 index 0000000000..a7e5095282 --- /dev/null +++ b/assets/js/5da91464.fb8e830b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4839],{4129:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var i=o(4848),s=o(8453);const r={description:"This page describes how to run an archive node on the Oasis Network."},t="Archive Node",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/archive-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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 (Oasis Core 23 and later)",id:"configuration-oasis-core-23-and-later",level:2},{value:"Configuration (Oasis Core 22 and earlier)",id:"configuration-oasis-core-22-and-earlier",level:2},{value:"Damask",id:"damask",level:4},{value:"Cobalt",id:"cobalt",level:4},{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",div:"div",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"archive-node",children:"Archive Node"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsxs)(n.p,{children:["Running an archive node requires a pre-existing ",(0,i.jsx)(n.code,{children:"oasis-node"})," state. If you don't have one,\nyou can download a snapshot of a specific network state ",(0,i.jsx)(n.a,{href:"https://snapshots.oasis.io",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"configuration-oasis-core-23-and-later",children:"Configuration (Oasis Core 23 and later)"}),"\n",(0,i.jsxs)(n.p,{children:["Starting from the Oasis Core version 23, the configuration for enabling archive mode has changed.\nUse the ",(0,i.jsx)(n.code,{children:"mode"})," setting:"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"This setting configures the node to act as an archive node."})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"mode: archive\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: info\n cometbft/context: error\n default: info\ngenesis:\n file: /node/etc/genesis.json\nruntime:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n paths:\n - {{ runtime_orc_path }}\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"Keep all other settings the same as those for a full client node. For example, to serve archived runtime\nstate, the node needs to have the runtime configured and the state present."})}),"\n",(0,i.jsx)(n.h2,{id:"configuration-oasis-core-22-and-earlier",children:"Configuration (Oasis Core 22 and earlier)"}),"\n",(0,i.jsxs)(n.p,{children:["For all pre-Eden networks, such as Damask, the configuration remains the same but requires the\nappropriate version of ",(0,i.jsx)(n.code,{children:"oasis-node"})," and the node state."]}),"\n",(0,i.jsx)(n.h4,{id:"damask",children:"Damask"}),"\n",(0,i.jsxs)(n.p,{children:["To run an archive node for Damask, use ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.2.12",children:"Oasis Core v22.2.12"})," and the following\nconfiguration:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'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: archive\n\nruntime:\n mode: client\n paths:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n - "{{ runtime_orc_path }}"\n'})}),"\n",(0,i.jsx)(n.h4,{id:"cobalt",children:"Cobalt"}),"\n",(0,i.jsxs)(n.p,{children:["To run an archive node for Cobalt, use ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.3.14",children:"Oasis Core v21.3.14"})," and the following configuration:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'log:\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: archive\n\nruntime:\n supported:\n - "{{ runtime_id }}"\n\n paths:\n "{{ runtime_id }}": {{ paratime_binary_path }}\n\nworker:\n storage:\n enabled: true\n'})}),"\n",(0,i.jsx)(n.div,{children:(0,i.jsx)(n.p,{children:"Ensure you are using the correct version of oasis-node and the pre-existing state for your specific pre-Eden network."})}),"\n",(0,i.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,i.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,i.jsx)(n.h3,{id:"archive-node-status",children:"Archive node status"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The mode field is currently unavailable in the control status output. It will\nbe included in an upcoming release."})}),"\n",(0,i.jsx)(n.p,{children:"To ensure the node is running in archive mode, run the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Output should report ",(0,i.jsx)(n.code,{children:"archive"})," consensus mode status:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n // other fields omitted ...\n "mode": "archive",\n // ...\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"/node/web3#archive-web3-gateway",children:"Archive Web3 Gateway"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>t,x:()=>a});var i=o(6540);const s={},r=i.createContext(s);function t(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5e95c892.f27fa3ac.js b/assets/js/5e95c892.f27fa3ac.js new file mode 100644 index 0000000000..bfcd74cad4 --- /dev/null +++ b/assets/js/5e95c892.f27fa3ac.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9647],{7121:(s,e,r)=>{r.r(e),r.d(e,{default:()=>n});r(6540);var a=r(4164),c=r(1003),o=r(7559),u=r(2831),i=r(5476),d=r(4848);function n(s){return(0,d.jsx)(c.e3,{className:(0,a.A)(o.G.wrapper.docsPages),children:(0,d.jsx)(i.A,{children:(0,u.v)(s.route.routes)})})}}}]); \ No newline at end of file diff --git a/assets/js/60d875af.68802beb.js b/assets/js/60d875af.68802beb.js new file mode 100644 index 0000000000..9ea2201d84 --- /dev/null +++ b/assets/js/60d875af.68802beb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[436],{6502:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>u,frontMatter:()=>a,metadata:()=>d,toc:()=>h});var i=t(4848),s=t(8453),r=t(6116),o=t(2550);const a={},c="Run your node",d={id:"node/run-your-node/README",title:"Run your node",description:"The Oasis Network consists of several types of nodes, each serving distinct",source:"@site/docs/node/run-your-node/README.mdx",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/",permalink:"/node/run-your-node/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Genesis Document",permalink:"/node/genesis-doc"},next:{title:"Prerequisites",permalink:"/node/run-your-node/prerequisites"}},l={},h=[{value:"Validator Node",id:"validator-node",level:2},{value:"Compute Nodes",id:"compute-nodes",level:2},{value:"Client Nodes",id:"client-nodes",level:2},{value:"Archive Node",id:"archive-node",level:2},{value:"Seed Node",id:"seed-node",level:2},{value:"Key Manager Node",id:"key-manager-node",level:2},{value:"Services",id:"services",level:2},{value:"Rosetta Gateway",id:"rosetta-gateway",level:3},{value:"Public gRPC",id:"public-grpc",level:3},{value:"Web3 Gateway",id:"web3-gateway",level:3},{value:"See also",id:"see-also",level:2}];function p(e){const n={a:"a",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"run-your-node",children:"Run your node"}),"\n",(0,i.jsx)(n.p,{children:"The Oasis Network consists of several types of nodes, each serving distinct\nroles to maintain the functionality, security, and decentralization of the\nnetwork. In this section you can find descriptions of the main types of nodes\nwithin the Oasis Network."}),"\n",(0,i.jsx)(n.h2,{id:"validator-node",children:"Validator Node"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"Validator Node"})," is an essential component, as Oasis Network uses\nproof-of-stake (PoS) consensus mechanisms. It is responsible for verifying transactions and proposing new blocks to be added to the blockchain. Validator\nnodes operate on the consensus layer by staking the network's tokens, which\ngrants them the right to participate in the consensus process. This process\ninvolves validating transactions, signing blocks, and ensuring the integrity of\nthe blockchain."]}),"\n",(0,i.jsx)(n.h2,{id:"compute-nodes",children:"Compute Nodes"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"Compute Nodes"})," are responsible for executing smart contracts and processing\ntransactions within a specific ParaTime (Parallel Runtime). These nodes handle\nthe actual computation tasks, such as running decentralized applications\n(dApps), performing data processing, and executing privacy-preserving smart\ncontracts."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Sapphire Compute Node"})," is responsible for executing EVM-compatible\nprivacy-preserving smart contracts and processing transactions within the\nSapphire ParaTime. These nodes validate and execute transactions while\nmaintaining the confidentiality of sensitive data, which is a crucial aspect\nof applications that handle private information or require enhanced security.\nThis is achieved through trusted execution environments (TEEs) that ensure\ndata remains encrypted and confidential, even while being processed."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Cipher Compute Node"})," is responsible for executing privacy-preserving smart\ncontracts written in Oasis Wasm and processing transactions within the Cipher\nParaTime. These nodes validate and execute transactions while maintaining the\nconfidentiality of sensitive data, which is a crucial aspect of applications\nthat handle private information or require enhanced security. This is achieved\nthrough trusted execution environments (TEEs) that ensure data remains\nencrypted and confidential, even while being processed."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Emerald Compute Node"})," is responsible for executing EVM-compatible smart\ncontracts and processing transactions within the Emerald ParaTime. It performs\ntasks such as validating transactions, running EVM-based smart contracts, and\nensuring that the operations within the Emerald ParaTime are carried out\nefficiently."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"client-nodes",children:"Client Nodes"}),"\n",(0,i.jsx)(n.p,{children:"A Client Node is a type of node within the Oasis Network that serves as\nan interface for users or other applications to interact with the blockchain.\nUnlike compute nodes, which handle transaction processing and smart contract\nexecution, client nodes are primarily responsible for tasks such as querying\nthe blockchain, submitting transactions, and retrieving other data from the\nnetwork."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Non-Validator Node"})})," is a type of node in the Oasis Network that does not\nparticipate in the consensus process of validating and proposing new blocks.\nInstead, it has client node functions that support the network's operations and\ndecentralization."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node",children:"Sapphire Client Node"})})," is a specific type of client node within the Oasis\nNetwork that interacts with the Sapphire ParaTime. The Sapphire ParaTime is\ndesigned to support EVM-compatible confidential smart contracts and\nprivacy-preserving decentralized applications (dApps) with strong privacy\nfeatures and high performance."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node",children:"Cipher Client Node"})})," is a type of node within the Oasis Network designed\nto interact specifically with the Cipher ParaTime. The Cipher ParaTime is known\nfor its strong privacy features, allowing for the execution of confidential\nsmart contracts and the development of privacy-preserving decentralized\napplications (dApps)."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node",children:"Emerald Client Node"})})," is a specific type of client node within the Oasis\nNetwork, designed to interact with the Emerald ParaTime. The Emerald ParaTime is\nan Ethereum-compatible environment on the Oasis Network, allowing developers\nto deploy and manage decentralized applications (dApps) that utilize the\nEthereum Virtual Machine (EVM)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"archive-node",children:"Archive Node"}),"\n",(0,i.jsxs)(n.p,{children:["An ",(0,i.jsx)(n.a,{href:"/node/run-your-node/archive-node",children:"Archive Node"})," is a specialized node within the Oasis Network that stores the\nentire blockchain history, making it a crucial tool for in-depth analysis,\ndevelopment, and ensuring that the network's past states remain accessible."]}),"\n",(0,i.jsx)(n.h2,{id:"seed-node",children:"Seed Node"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"/node/run-your-node/seed-node",children:"Seed Node"})," is a type of node in the Oasis Network that serves a critical role\nin helping other nodes discover peers and join the network (",(0,i.jsx)(n.em,{children:"address book"}),").\nUnlike validator nodes, which participate in the consensus process, Seed Nodes\ndo not play a direct role in consensus."]}),"\n",(0,i.jsx)(n.h2,{id:"key-manager-node",children:"Key Manager Node"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"/node/run-your-node/keymanager-node/",children:"Key Manager Node"})," is a specialized node in the Oasis Network responsible for\nsecurely managing cryptographic keys used in confidential computing. These nodes\nare crucial for the network's privacy-preserving features, enabling secure\nencryption and decryption of data processed within Trusted Execution\nEnvironments (TEEs). They play a vital role in enabling the Oasis Network's\nsecure, decentralized, and privacy-focused operations."]}),"\n",(0,i.jsx)(n.h2,{id:"services",children:"Services"}),"\n",(0,i.jsx)(n.h3,{id:"rosetta-gateway",children:"Rosetta Gateway"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway",children:"Rosetta Gateway"})," service is a specialized service within the Oasis Network\nthat implements the ",(0,i.jsx)(n.a,{href:"https://docs.cdp.coinbase.com/mesh/docs/api-reference",children:"Rosetta API"})," to provide a standardized and simplified\ninterface for interacting with the blockchain. This service is crucial for\nenabling seamless integration between the Oasis Network and various external\nplatforms, such as exchanges, wallets, custodians, and blockchain-based\napplications. The Rosetta Gateway connects to a ",(0,i.jsx)(n.a,{href:"#client-nodes",children:"non-validator"}),"\nnode."]}),"\n",(0,i.jsx)(n.h3,{id:"public-grpc",children:"Public gRPC"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"/node/grpc",children:"Oasis gRPC protocol"})," is an efficient, real-time, and cross-platform\ncommunication protocol that allows developers to both manage the Oasis node and communicate with the Oasis network. While each Oasis node opens a gRPC socket,\nthe public endpoints run a proxy and expose only a small, safe subset of the\nAPI calls publicly."]}),"\n",(0,i.jsx)(n.h3,{id:"web3-gateway",children:"Web3 Gateway"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"/node/web3",children:"Web3 Gateway"})," enables interaction with the Oasis Network using standard\nWeb3 protocol, which is widely used in the Ethereum ecosystem. It acts as a\nbridge between Web3-based applications and the Oasis Network, allowing\ndevelopers to leverage the tools, libraries, and practices familiar in\nEthereum development while benefiting from the unique features of the Oasis\nNetwork, such as privacy and confidentiality. The Web3 gateway connects to a\n",(0,i.jsx)(n.a,{href:"#compute-nodes",children:"compute"})," or a ",(0,i.jsx)(n.a,{href:"#client-nodes",children:"client"})," Sapphire or Emerald node."]}),"\n",(0,i.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,i.jsx)(o.A,{items:[(0,r.$)("/node/run-your-node/maintenance"),(0,r.$)("/node/run-your-node/advanced"),(0,r.$)("/node/run-your-node/troubleshooting")]})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>g});t(6540);var i=t(4164),s=t(8774),r=t(4142),o=t(5846),a=t(6654),c=t(1312),d=t(1107);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:n,children:t}=e;return(0,h.jsx)(s.A,{href:n,className:(0,i.A)("card padding--lg",l.cardContainer),children:t})}function u(e){let{href:n,icon:t,title:s,description:r}=e;return(0,h.jsxs)(p,{href:n,children:[(0,h.jsxs)(d.A,{as:"h2",className:(0,i.A)("text--truncate",l.cardTitle),title:s,children:[t," ",s]}),r&&(0,h.jsx)("p",{className:(0,i.A)("text--truncate",l.cardDescription),title:r,children:r})]})}function m(e){let{item:n}=e;const t=(0,r.Nr)(n),i=function(){const{selectMessage:e}=(0,o.W)();return n=>e(n,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,h.jsx)(u,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??i(n.items.length)}):null}function f(e){let{item:n}=e;const t=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",i=(0,r.cC)(n.docId??void 0);return(0,h.jsx)(u,{href:n.href,icon:t,title:n.label,description:n.description??i?.description})}function g(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(f,{item:n});case"category":return(0,h.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},2550:(e,n,t)=>{t.d(n,{A:()=>c});t(6540);var i=t(4164),s=t(4142),r=t(5965),o=t(4848);function a(e){let{className:n}=e;const t=(0,s.$S)();return(0,o.jsx)(c,{items:t.items,className:n})}function c(e){const{items:n,className:t}=e;if(!n)return(0,o.jsx)(a,{...e});const c=(0,s.d1)(n);return(0,o.jsx)("section",{className:(0,i.A)("row",t),children:c.map(((e,n)=>(0,o.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,o.jsx)(r.A,{item:e})},n)))})}},5846:(e,n,t)=>{t.d(n,{W:()=>d});var i=t(6540),s=t(4586);const r=["zero","one","two","few","many","other"];function o(e){return r.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,i.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:o(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function d(){const e=c();return{selectMessage:(n,t)=>function(e,n,t){const i=e.split("|");if(1===i.length)return i[0];i.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${i.length}: ${e}`);const s=t.select(n),r=t.pluralForms.indexOf(s);return i[Math.min(r,i.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>r});var i=t(2252);function s(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&s(n.items)}}function r(e){const n=(0,i.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)s(n.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]}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>a});var i=t(6540);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6602e166.d3e7dc73.js b/assets/js/6602e166.d3e7dc73.js new file mode 100644 index 0000000000..6132ec36b2 --- /dev/null +++ b/assets/js/6602e166.d3e7dc73.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8063],{7435:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Run a Node","slug":"get-involved/run-node","permalink":"/get-involved/run-node","sidebar":"getInvolved","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/6629c45f.f05c5041.js b/assets/js/6629c45f.f05c5041.js new file mode 100644 index 0000000000..54216d60d5 --- /dev/null +++ b/assets/js/6629c45f.f05c5041.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5820],{7691:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"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","unlisted":false},{"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","unlisted":false},{"type":"link","label":"ADR 0003: Consensus/Runtime Token Transfer","href":"/adrs/0003-consensus-runtime-token-transfer","docId":"adrs/0003-consensus-runtime-token-transfer","unlisted":false},{"type":"link","label":"ADR 0004: Runtime Governance","href":"/adrs/0004-runtime-governance","docId":"adrs/0004-runtime-governance","unlisted":false},{"type":"link","label":"ADR 0005: Runtime Compute Node Slashing","href":"/adrs/0005-runtime-compute-slashing","docId":"adrs/0005-runtime-compute-slashing","unlisted":false},{"type":"link","label":"ADR 0006: Consensus Governance","href":"/adrs/0006-consensus-governance","docId":"adrs/0006-consensus-governance","unlisted":false},{"type":"link","label":"ADR 0007: Improved Random Beacon","href":"/adrs/0007-improved-random-beacon","docId":"adrs/0007-improved-random-beacon","unlisted":false},{"type":"link","label":"ADR 0008: Standard Account Key Generation","href":"/adrs/0008-standard-account-key-generation","docId":"adrs/0008-standard-account-key-generation","unlisted":false},{"type":"link","label":"ADR 0009: Ed25519 Signature Verification Semantics","href":"/adrs/0009-ed25519-semantics","docId":"adrs/0009-ed25519-semantics","unlisted":false},{"type":"link","label":"ADR 0010: VRF-based Committee Elections","href":"/adrs/0010-vrf-elections","docId":"adrs/0010-vrf-elections","unlisted":false},{"type":"link","label":"ADR 0011: Incoming Runtime Messages","href":"/adrs/0011-incoming-runtime-messages","docId":"adrs/0011-incoming-runtime-messages","unlisted":false},{"type":"link","label":"ADR 0012: Runtime Message Results","href":"/adrs/0012-runtime-message-results","docId":"adrs/0012-runtime-message-results","unlisted":false},{"type":"link","label":"ADR 0013: Runtime Upgrade Improvements","href":"/adrs/0013-runtime-upgrades","docId":"adrs/0013-runtime-upgrades","unlisted":false},{"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","unlisted":false},{"type":"link","label":"ADR 0015: Randomized Paratime Proposer Selection","href":"/adrs/0015-vrf-per-block-entropy","docId":"adrs/0015-vrf-per-block-entropy","unlisted":false},{"type":"link","label":"ADR 0016: Consensus Parameters Change Proposal","href":"/adrs/0016-consensus-parameters-change-proposal","docId":"adrs/0016-consensus-parameters-change-proposal","unlisted":false},{"type":"link","label":"ADR 0017: ParaTime Application Standard Proposal Process","href":"/adrs/0017-app-standards","docId":"adrs/0017-app-standards","unlisted":false},{"type":"link","label":"ADR 0020: Governance Support for Delegator Votes","href":"/adrs/0020-governance-delegator-votes","docId":"adrs/0020-governance-delegator-votes","unlisted":false},{"type":"link","label":"ADR 0021: Forward-Secret Ephemeral Secrets","href":"/adrs/0021-keymanager-ephemeral-secrets","docId":"adrs/0021-keymanager-ephemeral-secrets","unlisted":false},{"type":"link","label":"ADR 0022: Forward-Secret Master Secrets","href":"/adrs/0022-keymanager-master-secrets","docId":"adrs/0022-keymanager-master-secrets","unlisted":false},{"type":"link","label":"ADR 0024: Runtime Off-chain Logic (ROFL)","href":"/adrs/0024-off-chain-runtime-logic","docId":"adrs/0024-off-chain-runtime-logic","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/adrs"}],"oasisCore":[{"type":"link","label":"Overview","href":"/core/","docId":"core/README","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Building","href":"/core/development-setup/building","docId":"core/development-setup/building","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Local Network Runner","href":"/core/development-setup/oasis-net-runner","docId":"core/development-setup/oasis-net-runner","unlisted":false},{"type":"link","label":"Single Validator Node Network","href":"/core/development-setup/single-validator-node-network","docId":"core/development-setup/single-validator-node-network","unlisted":false},{"type":"link","label":"Deploying a Runtime","href":"/core/development-setup/deploying-a-runtime","docId":"core/development-setup/deploying-a-runtime","unlisted":false}],"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","unlisted":false},{"type":"category","label":"Services","items":[{"type":"link","label":"Epoch Time","href":"/core/consensus/services/epochtime","docId":"core/consensus/services/epochtime","unlisted":false},{"type":"link","label":"Random Beacon","href":"/core/consensus/services/beacon","docId":"core/consensus/services/beacon","unlisted":false},{"type":"link","label":"Staking","href":"/core/consensus/services/staking","docId":"core/consensus/services/staking","unlisted":false},{"type":"link","label":"Registry","href":"/core/consensus/services/registry","docId":"core/consensus/services/registry","unlisted":false},{"type":"link","label":"Committee Scheduler","href":"/core/consensus/services/scheduler","docId":"core/consensus/services/scheduler","unlisted":false},{"type":"link","label":"Governance","href":"/core/consensus/services/governance","docId":"core/consensus/services/governance","unlisted":false},{"type":"link","label":"Root Hash","href":"/core/consensus/services/roothash","docId":"core/consensus/services/roothash","unlisted":false},{"type":"link","label":"Key Manager","href":"/core/consensus/services/keymanager","docId":"core/consensus/services/keymanager","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/core/consensus/services"},{"type":"link","label":"Genesis Document","href":"/core/consensus/genesis","docId":"core/consensus/genesis","unlisted":false},{"type":"link","label":"Transaction Test Vectors","href":"/core/consensus/test-vectors","docId":"core/consensus/test-vectors","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Runtime IDs","href":"/core/runtime/identifiers","docId":"core/runtime/identifiers","unlisted":false},{"type":"link","label":"Runtime Messages","href":"/core/runtime/messages","docId":"core/runtime/messages","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Metrics","href":"/core/oasis-node/metrics","docId":"core/oasis-node/metrics","unlisted":false},{"type":"link","label":"oasis-node CLI","href":"/core/oasis-node/cli","docId":"core/oasis-node/cli","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Cryptography","href":"/core/crypto","docId":"core/crypto","unlisted":false},{"type":"category","label":"Protocols","items":[{"type":"link","label":"Authenticated gRPC","href":"/core/authenticated-grpc","docId":"core/authenticated-grpc","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Merklized Key-Value Store (MKVS)","href":"/core/mkvs","docId":"core/mkvs","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Versioning","href":"/core/versioning","docId":"core/versioning","unlisted":false},{"type":"link","label":"Security","href":"/core/SECURITY","docId":"core/SECURITY","unlisted":false}],"collapsed":false,"href":"/core/processes"},{"type":"link","label":"ADRs","href":"/adrs"},{"type":"link","label":"Core Client TypeScript API","href":"https://api.docs.oasis.io/js/client"},{"type":"link","label":"Core Client Go API","href":"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go"}],"developers":[{"type":"link","label":"Overview","href":"/dapp/","docId":"dapp/README","unlisted":false},{"type":"category","label":"Sapphire","items":[{"type":"link","label":"Quickstart","href":"/dapp/sapphire/quickstart","docId":"dapp/sapphire/quickstart","unlisted":false},{"type":"link","label":"Guide","href":"/dapp/sapphire/guide","docId":"dapp/sapphire/guide","unlisted":false},{"type":"link","label":"Browser Support","href":"/dapp/sapphire/browser","docId":"dapp/sapphire/browser","unlisted":false},{"type":"link","label":"View-Call Authentication","href":"/dapp/sapphire/authentication","docId":"dapp/sapphire/authentication","unlisted":false},{"type":"link","label":"Gasless Transactions","href":"/dapp/sapphire/gasless","docId":"dapp/sapphire/gasless","unlisted":false},{"type":"link","label":"Contract Addresses and Deployments","href":"/dapp/sapphire/addresses","docId":"dapp/sapphire/addresses","unlisted":false},{"type":"link","label":"Deployment Patterns","href":"/dapp/sapphire/deployment","docId":"dapp/sapphire/deployment","unlisted":false},{"type":"link","label":"Security","href":"/dapp/sapphire/security","docId":"dapp/sapphire/security","unlisted":false},{"type":"link","label":"TypeScript API","href":"https://api.docs.oasis.io/js/sapphire-paratime"},{"type":"link","label":"Solidity API","href":"https://api.docs.oasis.io/sol/sapphire-contracts"}],"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","unlisted":false},{"type":"link","label":"Setup","href":"/dapp/opl/setup","docId":"dapp/opl/setup","unlisted":false},{"type":"link","label":"DAO Contract","href":"/dapp/opl/host","docId":"dapp/opl/host","unlisted":false},{"type":"link","label":"Ballot Contract","href":"/dapp/opl/enclave","docId":"dapp/opl/enclave","unlisted":false},{"type":"link","label":"Build","href":"/dapp/opl/build","docId":"dapp/opl/build","unlisted":false},{"type":"link","label":"Frontend Application","href":"/dapp/opl/frontend","docId":"dapp/opl/frontend","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/dapp/opl/"},{"type":"category","label":"Cipher","items":[{"type":"link","label":"Prerequisites","href":"/dapp/cipher/prerequisites","docId":"dapp/cipher/prerequisites","unlisted":false},{"type":"link","label":"Hello World","href":"/dapp/cipher/hello-world","docId":"dapp/cipher/hello-world","unlisted":false},{"type":"link","label":"Confidential Hello World","href":"/dapp/cipher/confidential-smart-contract","docId":"dapp/cipher/confidential-smart-contract","unlisted":false},{"type":"link","label":"Rust API","href":"https://api.docs.oasis.io/rust/oasis_contract_sdk"}],"collapsed":true,"collapsible":true,"href":"/dapp/cipher/"},{"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","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/dapp/emerald/"},{"type":"category","label":"Tools & Services","items":[{"type":"link","label":"Integrating BAND Oracle","href":"/dapp/tools/band","docId":"dapp/tools/band","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/dapp/tools/"}],"general":[{"type":"link","label":"Overview","href":"/general/","docId":"general/README","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Token Metrics and Distribution","href":"/general/oasis-network/token-metrics-and-distribution","docId":"general/oasis-network/token-metrics-and-distribution","unlisted":false},{"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","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Staking and Delegating","href":"/general/manage-tokens/staking-and-delegating","docId":"general/manage-tokens/staking-and-delegating","unlisted":false},{"type":"category","label":"ROSE Wallet","items":[{"type":"link","label":"Web","href":"/general/manage-tokens/oasis-wallets/web","docId":"general/manage-tokens/oasis-wallets/web","unlisted":false},{"type":"link","label":"Browser Extension","href":"/general/manage-tokens/oasis-wallets/browser-extension","docId":"general/manage-tokens/oasis-wallets/browser-extension","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/general/manage-tokens/oasis-wallets"},{"type":"category","label":"3rd Party Wallets and Services","items":[{"type":"link","label":"Custody Providers & Protocols","href":"/general/manage-tokens/holding-rose-tokens/custody-providers","docId":"general/manage-tokens/holding-rose-tokens/custody-providers","unlisted":false},{"type":"link","label":"Ledger Hardware Wallet","href":"/general/manage-tokens/holding-rose-tokens/ledger-wallet","docId":"general/manage-tokens/holding-rose-tokens/ledger-wallet","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/general/manage-tokens/holding-rose-tokens"},{"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","unlisted":false},{"type":"category","label":"Oasis CLI","items":[{"type":"link","label":"Setup","href":"/general/manage-tokens/cli/setup","docId":"general/manage-tokens/cli/setup","unlisted":false},{"type":"link","label":"Network","href":"/general/manage-tokens/cli/network","docId":"general/manage-tokens/cli/network","unlisted":false},{"type":"link","label":"ParaTime","href":"/general/manage-tokens/cli/paratime","docId":"general/manage-tokens/cli/paratime","unlisted":false},{"type":"link","label":"Wallet","href":"/general/manage-tokens/cli/wallet","docId":"general/manage-tokens/cli/wallet","unlisted":false},{"type":"link","label":"Account","href":"/general/manage-tokens/cli/account","docId":"general/manage-tokens/cli/account","unlisted":false},{"type":"link","label":"Transaction","href":"/general/manage-tokens/cli/transaction","docId":"general/manage-tokens/cli/transaction","unlisted":false},{"type":"link","label":"Address book","href":"/general/manage-tokens/cli/addressbook","docId":"general/manage-tokens/cli/addressbook","unlisted":false}],"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","unlisted":false}],"collapsed":false,"href":"/general/manage-tokens/"}],"getInvolved":[{"type":"link","label":"Join our Community","href":"/get-involved/","docId":"get-involved/README","unlisted":false},{"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","unlisted":false},{"type":"link","label":"ParaTime Node","href":"/get-involved/run-node/paratime-node","docId":"get-involved/run-node/paratime-node","unlisted":false}],"collapsed":false,"href":"/get-involved/run-node"},{"type":"link","label":"Develop Oasis Core","href":"/get-involved/oasis-core","docId":"get-involved/oasis-core","unlisted":false},{"type":"link","label":"Network Governance","href":"/get-involved/network-governance","docId":"get-involved/network-governance","unlisted":false},{"type":"link","label":"Delegation Policy","href":"/get-involved/delegation-policy","docId":"get-involved/delegation-policy","unlisted":false},{"type":"link","label":"Token Delivery & KYC Guide","href":"/get-involved/token-delivery-and-kyc","docId":"get-involved/token-delivery-and-kyc","unlisted":false}],"operators":[{"type":"link","label":"Overview","href":"/node/","docId":"node/README","unlisted":false},{"type":"category","label":"Mainnet","collapsible":false,"items":[{"type":"link","label":"Eden Upgrade","href":"/node/mainnet/eden-upgrade","docId":"node/mainnet/eden-upgrade","unlisted":false},{"type":"category","label":"Previous Upgrades","items":[{"type":"link","label":"Damask Upgrade","href":"/node/mainnet/previous-upgrades/damask-upgrade","docId":"node/mainnet/previous-upgrades/damask-upgrade","unlisted":false},{"type":"link","label":"Cobalt Upgrade","href":"/node/mainnet/previous-upgrades/cobalt-upgrade","docId":"node/mainnet/previous-upgrades/cobalt-upgrade","unlisted":false},{"type":"link","label":"Upgrade to Mainnet","href":"/node/mainnet/previous-upgrades/mainnet-upgrade","docId":"node/mainnet/previous-upgrades/mainnet-upgrade","unlisted":false}],"collapsed":true,"collapsible":true,"href":"/node/mainnet/previous-upgrades"},{"type":"link","label":"Upgrade Log","href":"/node/mainnet/upgrade-log","docId":"node/mainnet/upgrade-log","unlisted":false}],"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","unlisted":false}],"collapsed":false,"href":"/node/testnet/"},{"type":"link","label":"Genesis Document","href":"/node/genesis-doc","docId":"node/genesis-doc","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Stake Requirements","href":"/node/run-your-node/prerequisites/stake-requirements","docId":"node/run-your-node/prerequisites/stake-requirements","unlisted":false},{"type":"link","label":"Install the Oasis Node","href":"/node/run-your-node/prerequisites/oasis-node","docId":"node/run-your-node/prerequisites/oasis-node","unlisted":false},{"type":"link","label":"System Configuration","href":"/node/run-your-node/prerequisites/system-configuration","docId":"node/run-your-node/prerequisites/system-configuration","unlisted":false},{"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","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Non-validator Node","href":"/node/run-your-node/non-validator-node","docId":"node/run-your-node/non-validator-node","unlisted":false},{"type":"link","label":"Seed Node","href":"/node/run-your-node/seed-node","docId":"node/run-your-node/seed-node","unlisted":false},{"type":"link","label":"Archive Node","href":"/node/run-your-node/archive-node","docId":"node/run-your-node/archive-node","unlisted":false},{"type":"link","label":"ParaTime Node","href":"/node/run-your-node/paratime-node","docId":"node/run-your-node/paratime-node","unlisted":false},{"type":"link","label":"ParaTime Client Node","href":"/node/run-your-node/paratime-client-node","docId":"node/run-your-node/paratime-client-node","unlisted":false},{"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","unlisted":false},{"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","unlisted":false}],"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","unlisted":false},{"type":"link","label":"Sentry Node","href":"/node/run-your-node/sentry-node","docId":"node/run-your-node/sentry-node","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Handling Network Upgrades","href":"/node/run-your-node/maintenance/handling-network-upgrades","docId":"node/run-your-node/maintenance/handling-network-upgrades","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Refreshing Node Certificates","href":"/node/run-your-node/maintenance/refreshing-certificates","docId":"node/run-your-node/maintenance/refreshing-certificates","unlisted":false},{"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","unlisted":false}],"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","unlisted":false},{"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","unlisted":false},{"type":"link","label":"Remote Signer for Oasis Node Keys","href":"/node/run-your-node/advanced/remote-signer","docId":"node/run-your-node/advanced/remote-signer","unlisted":false}],"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","unlisted":false}],"collapsed":false,"href":"/node/run-your-node/"},{"type":"link","label":"Web3 Gateway","href":"/node/web3","docId":"node/web3","unlisted":false},{"type":"link","label":"gRPC Proxy","href":"/node/grpc","docId":"node/grpc","unlisted":false}],"paratime":[{"type":"link","label":"Overview","href":"/paratime/","docId":"paratime/README","unlisted":false},{"type":"link","label":"Prerequisites","href":"/paratime/prerequisites","docId":"paratime/prerequisites","unlisted":false},{"type":"link","label":"Minimal Runtime","href":"/paratime/minimal-runtime","docId":"paratime/minimal-runtime","unlisted":false},{"type":"link","label":"Modules","href":"/paratime/modules","docId":"paratime/modules","unlisted":false},{"type":"link","label":"Reproducibility","href":"/paratime/reproducibility","docId":"paratime/reproducibility","unlisted":false},{"type":"link","label":"ParaTime Client TypeScript API","href":"https://api.docs.oasis.io/js/client-rt"},{"type":"link","label":"ParaTime Client Go API","href":"https://pkg.go.dev/github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"},{"type":"link","label":"ParaTime SDK Rust API","href":"https://api.docs.oasis.io/rust/oasis_runtime_sdk"}],"rofl":[{"type":"link","label":"Overview","href":"/rofl/","docId":"rofl/README","unlisted":false},{"type":"link","label":"Prerequisites","href":"/rofl/prerequisites","docId":"rofl/prerequisites","unlisted":false},{"type":"link","label":"Application","href":"/rofl/app","docId":"rofl/app","unlisted":false},{"type":"link","label":"Consensus Trust Root","href":"/rofl/trust-root","docId":"rofl/trust-root","unlisted":false}]},"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"},"adrs/0024-off-chain-runtime-logic":{"id":"adrs/0024-off-chain-runtime-logic","title":"ADR 0024: Runtime Off-chain Logic (ROFL)","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 chapter 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 chapter 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":"Cipher is a confidential ParaTime for executing Wasm smart contracts.","sidebar":"developers"},"dapp/emerald/README":{"id":"dapp/emerald/README","title":"Emerald ParaTime","description":"Emerald is our official ParaTime which executes smart contracts inside the","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":"Contract Addresses and Deployments","description":"List of Standard Contract Addresses","sidebar":"developers"},"dapp/sapphire/authentication":{"id":"dapp/sapphire/authentication","title":"View-Call Authentication","description":"Authenticate users with your confidential contracts","sidebar":"developers"},"dapp/sapphire/browser":{"id":"dapp/sapphire/browser","title":"Browser Support","description":"Writing Sapphire dApp for browser and Metamask","sidebar":"developers"},"dapp/sapphire/deployment":{"id":"dapp/sapphire/deployment","title":"Deployment Patterns","description":"Deploying upgradable and deterministic contracts","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/quickstart":{"id":"dapp/sapphire/quickstart","title":"Quickstart","description":"In this tutorial, you will build and deploy a unique dApp that requires","sidebar":"developers"},"dapp/sapphire/README":{"id":"dapp/sapphire/README","title":"Sapphire ParaTime","description":"Sapphire is our official confidential ParaTime providing a smart contract","sidebar":"developers"},"dapp/sapphire/security":{"id":"dapp/sapphire/security","title":"Security","description":"Secure dApps: Recipes for Confidentiality","sidebar":"developers"},"dapp/tools/band":{"id":"dapp/tools/band","title":"Integrating BAND Oracle","description":"This guide will explain how to query the Band Protocol reference data smart","sidebar":"developers"},"dapp/tools/README":{"id":"dapp/tools/README","title":"Tools & Services","description":"Oasis integrates with a number of services and provides tooling support for","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 networks, 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":"Use CLI to decode, verify, sign and submit 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 the official Oasis and","sidebar":"general"},"general/manage-tokens/holding-rose-tokens/custody-providers":{"id":"general/manage-tokens/holding-rose-tokens/custody-providers","title":"Custody Providers & Protocols","description":"Not comfortable keeping the keys on your own?","sidebar":"general"},"general/manage-tokens/holding-rose-tokens/ledger-wallet":{"id":"general/manage-tokens/holding-rose-tokens/ledger-wallet","title":"Ledger Hardware Wallet","description":"How to setup your Ledger hardware wallet","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/oasis-wallets/browser-extension":{"id":"general/manage-tokens/oasis-wallets/browser-extension","title":"ROSE Wallet - Browser Extension","description":"The Oasis Foundation-managed non-custodial browser extension wallet","sidebar":"general"},"general/manage-tokens/oasis-wallets/web":{"id":"general/manage-tokens/oasis-wallets/web","title":"ROSE Wallet - Web","description":"The Oasis Foundation-managed non-custodial web wallet","sidebar":"general"},"general/manage-tokens/README":{"id":"general/manage-tokens/README","title":"Manage your Tokens","description":"Transfer, deposit, withdraw and delegate your ROSE","sidebar":"general"},"general/manage-tokens/staking-and-delegating":{"id":"general/manage-tokens/staking-and-delegating","title":"Staking and Delegating","description":"The Oasis Network is a proof-of-stake network. This means that the voting","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 the initial state of an Oasis Network, and all the","sidebar":"operators"},"node/grpc":{"id":"node/grpc","title":"gRPC proxy for your Oasis node","description":"gRPC proxy for Oasis node","sidebar":"operators"},"node/mainnet/eden-upgrade":{"id":"node/mainnet/eden-upgrade","title":"Eden Upgrade","description":"This document provides an overview of the changes for the Eden Mainnet","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/damask-upgrade":{"id":"node/mainnet/previous-upgrades/damask-upgrade","title":"Damask Upgrade","description":"This document provides an overview of the changes for the Damask Mainnet","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":"Network Parameters","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":"Welcome! This documentation is designed to provide you with a comprehensive","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","sidebar":"operators"},"node/run-your-node/advanced/remote-signer":{"id":"node/run-your-node/advanced/remote-signer","title":"Remote Signer for Oasis Node Keys","description":"The Oasis remote signer is an application that","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","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 certain situations, you may need to do a complete node redeployment with a","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 the Oasis Node","description":"The Oasis node is a binary that is created from the [Oasis Core] repository\'s","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 outlines the modifications necessary that should be made to the","sidebar":"operators"},"node/run-your-node/README":{"id":"node/run-your-node/README","title":"Run your node","description":"The Oasis Network consists of several types of nodes, each serving distinct","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","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"},"paratime/minimal-runtime":{"id":"paratime/minimal-runtime","title":"Minimal Runtime","description":"This chapter 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"},"rofl/app":{"id":"rofl/app","title":"Application","description":"This chapter will show you how to quickly create, build and test a minimal","sidebar":"rofl"},"rofl/prerequisites":{"id":"rofl/prerequisites","title":"Prerequisites","description":"How to build your first ROFL app","sidebar":"rofl"},"rofl/README":{"id":"rofl/README","title":"Build ROFL App","description":"Build your own ROFL app","sidebar":"rofl"},"rofl/trust-root":{"id":"rofl/trust-root","title":"Consensus Trust Root","description":"The [ROFL app example] already contains an embedded root of trust called the","sidebar":"rofl"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/6ac8b2ab.8af26dc9.js b/assets/js/6ac8b2ab.8af26dc9.js new file mode 100644 index 0000000000..1183581108 --- /dev/null +++ b/assets/js/6ac8b2ab.8af26dc9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3132],{2082:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var t=i(4848),s=i(8453);const o={},r="ADR 0009: Ed25519 Signature Verification Semantics",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0009-ed25519-semantics.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},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:"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}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0009-ed25519-signature-verification-semantics",children:"ADR 0009: Ed25519 Signature Verification Semantics"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2021-05-10: Initial version"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Informative"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsx)(n.p,{children:"In programming, it's often the buts in the specification that kill you."}),"\n",(0,t.jsx)(n.p,{children:"-- Boris Beizer"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:'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.'}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"The Oasis Core consensus layer (and all of the Go components) currently uses\nthe following Ed25519 verification semantics."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Non-canonical s is rejected (MUST enforce ",(0,t.jsx)(n.code,{children:"s < L"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"Small order A/R are rejected"}),"\n",(0,t.jsx)(n.li,{children:"Non-canonical A/R are accepted"}),"\n",(0,t.jsxs)(n.li,{children:["The cofactored verification equation MUST be used (",(0,t.jsx)(n.code,{children:"[8][S]B = [8]R + [8][k]A"}),")"]}),"\n",(0,t.jsx)(n.li,{children:"A/R may have a non-zero torsion component."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"reject-non-canonical-s",children:"Reject Non-canonical s"}),"\n",(0,t.jsxs)(n.p,{children:["Ed25519 signatures are trivially malleable unless the scalar component is\nconstrained to ",(0,t.jsx)(n.code,{children:"0 <= s < L"}),", as is possible to create valid signatures\nfrom an existing public key/message/signature tuple by adding L to s."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["Note: Only asserting that ",(0,t.jsx)(n.code,{children:"s[31] & 224 == 0"})," as done in older implementations\nis insufficient."]}),"\n",(0,t.jsx)(n.h3,{id:"reject-small-order-ar",children:"Reject Small Order A/R"}),"\n",(0,t.jsx)(n.p,{children:"Rejecting small order A is required to make the signature scheme strongly\nbinding (resilience to key/message substitution attacks)."}),"\n",(0,t.jsx)(n.p,{children:"Rejecting (or accepting) small order R is not believed to have a security\nimpact."}),"\n",(0,t.jsx)(n.h3,{id:"accept-non-canonical-ar",children:"Accept Non-canonical A/R"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"Note: RFC 8032 and FIPS 186-5 require rejecting non-canonically encoded\npoints."}),"\n",(0,t.jsx)(n.h3,{id:"cofactored-verification-equation",children:"Cofactored Verification Equation"}),"\n",(0,t.jsxs)(n.p,{children:["There are two forms of the Ed25519 verification equation commonly in use,\n",(0,t.jsx)(n.code,{children:"[S]B = R + [k]A"})," (cofactor-less), and ",(0,t.jsx)(n.code,{children:"[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."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"accept-ar-with-non-zero-torsion",children:"Accept A/R With Non-zero Torsion"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsx)(n.p,{children:"The verification semantics in use by Oasis Core provides the following\nproperties:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"SUF-CMA security"}),"\n",(0,t.jsx)(n.li,{children:"Non-repudiation (strong binding)"}),"\n",(0,t.jsx)(n.li,{children:"Compatibility with batch and lattice reduction based verification."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsx)(n.p,{children:'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.'}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsx)(n.h3,{id:"future-improvements",children:"Future Improvements"}),"\n",(0,t.jsx)(n.p,{children:"WARNING: Any changes to verification semantics are consensus breaking."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:'Consider switching to the "Algorithm 2" definition, for ease of testing\nand because it is the default behavior provided by curve25519-voi.'}),"\n",(0,t.jsx)(n.li,{children:"Consider switching to ZIP-215 semantics, to be inline with other projects,\nmore library support (Give up on strong binding)."}),"\n",(0,t.jsx)(n.li,{children:"Switching to ristretto255 (sr25519) eliminates these problems entirely."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"recomendations-for-future-projects",children:"Recomendations For Future Projects"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://eprint.iacr.org/2020/1244.pdf",children:"Taming the many EdDSAs"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://zips.z.cash/zip-0215",children:"Explicitly Defining and Modifying Ed25519 Validation Rules"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>a});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6b19e4d7.7c8b354c.js b/assets/js/6b19e4d7.7c8b354c.js new file mode 100644 index 0000000000..55630899b4 --- /dev/null +++ b/assets/js/6b19e4d7.7c8b354c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9589],{3076:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>h,contentTitle:()=>d,default:()=>m,frontMatter:()=>c,metadata:()=>l,toc:()=>p});var n=t(4848),i=t(8453),r=t(2550),a=t(6116),o=t(1766);const c={},d="Sapphire ParaTime",l={id:"dapp/sapphire/README",title:"Sapphire ParaTime",description:"Sapphire is our official confidential ParaTime providing a smart contract",source:"@site/docs/dapp/sapphire/README.mdx",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/",permalink:"/dapp/sapphire/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/sapphire/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Overview",permalink:"/dapp/"},next:{title:"Quickstart",permalink:"/dapp/sapphire/quickstart"}},h={},p=[{value:"Chain Information",id:"chain-information",level:2},{value:"Mainnet",id:"mainnet",level:3},{value:"Testnet",id:"testnet",level:3},{value:"RPC Endpoints",id:"rpc-endpoints",level:2},{value:"Block Explorers",id:"block-explorers",level:2},{value:"Indexers",id:"indexers",level:2},{value:"See also",id:"see-also",level:2}];function x(e){const s={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"sapphire-paratime",children:"Sapphire ParaTime"}),"\n",(0,n.jsxs)(s.p,{children:["Sapphire is our official confidential ParaTime providing a smart contract\ndevelopment environment with ",(0,n.jsx)(s.a,{href:"https://ethereum.org/en/developers/docs/evm/",children:"Ethereum Virtual Machine (EVM)"})," compatibility."]}),"\n",(0,n.jsx)(s.p,{children:"As the official confidential EVM-compatible ParaTime on the Oasis Network,\nSapphire allows for:"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsx)(s.li,{children:"Confidential state, end-to-end encryption, confidential randomness"}),"\n",(0,n.jsx)(s.li,{children:"EVM compatibility"}),"\n",(0,n.jsx)(s.li,{children:"Easy integration with EVM-based dApps, such as DeFi, NFT, Metaverse and\ncrypto gaming"}),"\n",(0,n.jsx)(s.li,{children:"Scalability: increased throughput of transactions"}),"\n",(0,n.jsx)(s.li,{children:"Low-cost: 99%+ lower fees than Ethereum"}),"\n",(0,n.jsx)(s.li,{children:"6 second finality (1 block)"}),"\n",(0,n.jsx)(s.li,{children:"Cross-chain bridge to enable cross-chain interoperability (upcoming)"}),"\n"]}),"\n",(0,n.jsxs)(s.p,{children:["If you are not bound to EVM and you wish to develop dApps with more\nfine-grained confidentiality, check out the\n",(0,n.jsx)(s.a,{href:"/dapp/cipher/",children:"Cipher ParaTime"}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"chain-information",children:"Chain Information"}),"\n",(0,n.jsx)(s.h3,{id:"mainnet",children:"Mainnet"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Network name: ",(0,n.jsx)(s.code,{children:"sapphire"})]}),"\n",(0,n.jsxs)(s.li,{children:["Long network name: ",(0,n.jsx)(s.code,{children:"Oasis Sapphire"})]}),"\n",(0,n.jsxs)(s.li,{children:["Chain ID:","\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Hex: ",(0,n.jsx)(s.code,{children:"0x5afe"})]}),"\n",(0,n.jsxs)(s.li,{children:["Decimal: ",(0,n.jsx)(s.code,{children:"23294"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"testnet",children:"Testnet"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Network name: ",(0,n.jsx)(s.code,{children:"sapphire-testnet"})]}),"\n",(0,n.jsxs)(s.li,{children:["Long network name: ",(0,n.jsx)(s.code,{children:"Oasis Sapphire Testnet"})]}),"\n",(0,n.jsxs)(s.li,{children:["Chain ID:","\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Hex: ",(0,n.jsx)(s.code,{children:"0x5aff"})]}),"\n",(0,n.jsxs)(s.li,{children:["Decimal: ",(0,n.jsx)(s.code,{children:"23295"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"rpc-endpoints",children:"RPC Endpoints"}),"\n",(0,n.jsx)(s.admonition,{type:"danger",children:(0,n.jsxs)(s.p,{children:["The RPC endpoint is a ",(0,n.jsx)(s.em,{children:"point of trust"}),". Beside traffic rate limiting, it can\nalso perform censorship or even a man-in-the-middle attack. If you have security\nconsiderations, we strongly recommend that you set up your own ",(0,n.jsx)(s.a,{href:"/node/run-your-node/paratime-client-node",children:"ParaTime client\nnode"})," and the ",(0,n.jsx)(s.a,{href:"/node/web3",children:"Web3-compatible gateway"}),"."]})}),"\n",(0,n.jsx)(s.p,{children:"You can connect to one of the public Web3 gateways below (in alphabetic order):"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Provider"}),(0,n.jsx)(s.th,{children:"Mainnet RPC URLs"}),(0,n.jsx)(s.th,{children:"Testnet RPC URLs"}),(0,n.jsx)(s.th,{children:"Supports Confidential Queries"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/",children:"1RPC"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.KT,{rpcs:["https://1rpc.io/oasis/sapphire"]})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:"Yes"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.KT,{rpcs:["https://sapphire.oasis.io","wss://sapphire.oasis.io/ws"]})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.XV,{rpcs:["https://testnet.sapphire.oasis.io","wss://testnet.sapphire.oasis.io/ws"]})}),(0,n.jsx)(s.td,{children:"Yes"})]})]})]}),"\n",(0,n.jsx)(s.p,{children:"Public RPCs may have rate limits or traffic restrictions. For professional,\ndedicated RPC endpoints, consider the following providers (in alphabetic order):"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Provider"}),(0,n.jsx)(s.th,{children:"Instructions"}),(0,n.jsx)(s.th,{children:"Pricing"}),(0,n.jsx)(s.th,{children:"Supports Confidential Queries"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/",children:"1RPC"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://docs.1rpc.io/guide/how-to-use-1rpc",children:"docs.1rpc.io"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/#pricing",children:"Pricing"})}),(0,n.jsx)(s.td,{children:"Yes"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://chainstack.com/build-better-with-oasis-sapphire/",children:"Chainstack"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://docs.chainstack.com/docs/oasis-sapphire-tooling",children:"docs.chainstack.com"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://chainstack.com/pricing/",children:"Pricing"})}),(0,n.jsx)(s.td,{children:"Yes"})]})]})]}),"\n",(0,n.jsx)(s.h2,{id:"block-explorers",children:"Block Explorers"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Name (Provider)"}),(0,n.jsx)(s.th,{children:"Mainnet URL"}),(0,n.jsx)(s.th,{children:"Testnet URL"}),(0,n.jsx)(s.th,{children:"EIP-3091 compatible"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Explorer (",(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire",children:"https://explorer.oasis.io/mainnet/sapphire"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/sapphire",children:"https://explorer.oasis.io/testnet/sapphire"})}),(0,n.jsx)(s.td,{children:"Yes"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Scan (",(0,n.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000f80306c9858e7279",children:"https://www.oasisscan.com/paratimes/000\u2026279"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://testnet.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c",children:"https://testnet.oasisscan.com/paratimes/000\u2026f6c"})}),(0,n.jsx)(s.td,{children:"No"})]})]})]}),"\n",(0,n.jsx)(s.h2,{id:"indexers",children:"Indexers"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Name (Provider)"}),(0,n.jsx)(s.th,{children:"Mainnet URL"}),(0,n.jsx)(s.th,{children:"Testnet URL"}),(0,n.jsx)(s.th,{children:"Documentation"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.covalenthq.com/",children:"Covalent"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.covalenthq.com/v1/oasis-sapphire-mainnet"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.covalenthq.com/v1/oasis-sapphire-testnet"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.covalenthq.com/docs/unified-api/",children:"Unified API docs"})})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://goldsky.com",children:"Goldsky Subgraph"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://docs.goldsky.com/subgraphs/deploying-subgraphs",children:"Documentation site"})})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Nexus (",(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://nexus.oasis.io/v1/"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://testnet.nexus.oasis.io/v1/"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://nexus.oasis.io/v1/spec/v1.html",children:"API"})})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Scan (",(0,n.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.oasisscan.com/mainnet/v2"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.oasisscan.com/testnet/v2"})}),(0,n.jsxs)(s.td,{children:[(0,n.jsx)(s.a,{href:"https://api.oasisscan.com/mainnet/swagger-ui/#/runtime-controller",children:"Mainnet Runtime API"}),", ",(0,n.jsx)(s.a,{href:"https://api.oasisscan.com/testnet/swagger-ui/#/runtime-controller",children:"Testnet Runtime API"})]})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://subquery.network",children:"SubQuery Network"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsxs)(s.td,{children:[(0,n.jsx)(s.a,{href:"https://academy.subquery.network/",children:"SubQuery Academy"}),", ",(0,n.jsx)(s.a,{href:"https://academy.subquery.network/quickstart/quickstart.html",children:"QuickStart"}),", ",(0,n.jsx)(s.a,{href:"https://github.com/subquery/ethereum-subql-starter/tree/main/Oasis/oasis-sapphire-starter",children:"Starter project"})]})]})]})]}),"\n",(0,n.jsx)(s.admonition,{type:"note",children:(0,n.jsxs)(s.p,{children:["If you are running your own Sapphire endpoint, a block explorer, or an indexer\nand wish to be added to these docs, open an issue at\n",(0,n.jsx)(s.a,{href:"https://github.com/oasisprotocol/docs",children:"github.com/oasisprotocol/docs"}),"."]})}),"\n",(0,n.jsx)(s.h2,{id:"see-also",children:"See also"}),"\n",(0,n.jsx)(r.A,{items:[(0,a.$)("/general/manage-tokens/"),(0,a.$)("/node/run-your-node/paratime-node"),(0,a.$)("/node/run-your-node/paratime-client-node"),(0,a.$)("/node/web3"),(0,a.$)("/dapp/emerald/"),(0,a.$)("/dapp/cipher/")]})]})}function m(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(x,{...e})}):x(e)}},5965:(e,s,t)=>{t.d(s,{A:()=>j});t(6540);var n=t(4164),i=t(8774),r=t(4142),a=t(5846),o=t(6654),c=t(1312),d=t(1107);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:s,children:t}=e;return(0,h.jsx)(i.A,{href:s,className:(0,n.A)("card padding--lg",l.cardContainer),children:t})}function x(e){let{href:s,icon:t,title:i,description:r}=e;return(0,h.jsxs)(p,{href:s,children:[(0,h.jsxs)(d.A,{as:"h2",className:(0,n.A)("text--truncate",l.cardTitle),title:i,children:[t," ",i]}),r&&(0,h.jsx)("p",{className:(0,n.A)("text--truncate",l.cardDescription),title:r,children:r})]})}function m(e){let{item:s}=e;const t=(0,r.Nr)(s),n=function(){const{selectMessage:e}=(0,a.W)();return s=>e(s,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:s}))}();return t?(0,h.jsx)(x,{href:t,icon:"\ud83d\uddc3\ufe0f",title:s.label,description:s.description??n(s.items.length)}):null}function u(e){let{item:s}=e;const t=(0,o.A)(s.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,r.cC)(s.docId??void 0);return(0,h.jsx)(x,{href:s.href,icon:t,title:s.label,description:s.description??n?.description})}function j(e){let{item:s}=e;switch(s.type){case"link":return(0,h.jsx)(u,{item:s});case"category":return(0,h.jsx)(m,{item:s});default:throw new Error(`unknown item type ${JSON.stringify(s)}`)}}},2550:(e,s,t)=>{t.d(s,{A:()=>c});t(6540);var n=t(4164),i=t(4142),r=t(5965),a=t(4848);function o(e){let{className:s}=e;const t=(0,i.$S)();return(0,a.jsx)(c,{items:t.items,className:s})}function c(e){const{items:s,className:t}=e;if(!s)return(0,a.jsx)(o,{...e});const c=(0,i.d1)(s);return(0,a.jsx)("section",{className:(0,n.A)("row",t),children:c.map(((e,s)=>(0,a.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,a.jsx)(r.A,{item:e})},s)))})}},5846:(e,s,t)=>{t.d(s,{W:()=>d});var n=t(6540),i=t(4586);const r=["zero","one","two","few","many","other"];function a(e){return r.filter((s=>e.includes(s)))}const o={locale:"en",pluralForms:a(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,i.A)();return(0,n.useMemo)((()=>{try{return function(e){const s=new Intl.PluralRules(e);return{locale:e,pluralForms:a(s.resolvedOptions().pluralCategories),select:e=>s.select(e)}}(e)}catch(s){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${s.message}\n`),o}}),[e])}function d(){const e=c();return{selectMessage:(s,t)=>function(e,s,t){const n=e.split("|");if(1===n.length)return n[0];n.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${n.length}: ${e}`);const i=t.select(s),r=t.pluralForms.indexOf(i);return n[Math.min(r,n.length-1)]}(t,s,e)}}},1766:(e,s,t)=>{t.d(s,{KT:()=>r,XV:()=>a,YH:()=>o,fm:()=>c});t(6540);var n=t(4848);const i=e=>(0,n.jsxs)("span",{children:[e.rpcs.map((e=>(0,n.jsxs)("code",{children:[e,(0,n.jsx)("br",{})]},e))),(0,n.jsx)("button",{className:"button button--primary margin-top--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.");const s=Date.now();window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:e.chainId,chainName:e.name,nativeCurrency:{name:e.token,symbol:e.token,decimals:18},rpcUrls:e.rpcs,blockExplorerUrls:e.be}]}).then((t=>{const n=Date.now()-s<100;null===t&&n&&alert(`The ${e.name} RPC already added.`)}))},children:"Add to MetaMask"})]}),r=e=>i({name:"Oasis Sapphire",chainId:"0x5afe",token:"ROSE",rpcs:e.rpcs,be:["https://explorer.oasis.io/mainnet/sapphire"]}),a=e=>i({name:"Oasis Sapphire Testnet",chainId:"0x5aff",token:"TEST",rpcs:e.rpcs,be:["https://explorer.oasis.io/testnet/sapphire"]}),o=e=>i({name:"Oasis Emerald",chainId:"0xa516",token:"ROSE",rpcs:e.rpcs,be:["https://explorer.oasis.io/mainnet/emerald"]}),c=e=>i({name:"Oasis Emerald Testnet",chainId:"0xa515",token:"TEST",rpcs:e.rpcs,be:["https://explorer.oasis.io/testnet/emerald"]})},6116:(e,s,t)=>{t.d(s,{$:()=>r});var n=t(2252);function i(e){for(const s of e){const e=s.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=s),"category"===s.type&&i(s.items)}}function r(e){const s=(0,n.r)();if(!s)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in s.docsSidebars)i(s.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]}},8453:(e,s,t)=>{t.d(s,{R:()=>a,x:()=>o});var n=t(6540);const i={},r=n.createContext(i);function a(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function o(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6de7ad9b.f0b69df3.js b/assets/js/6de7ad9b.f0b69df3.js new file mode 100644 index 0000000000..92616be16e --- /dev/null +++ b/assets/js/6de7ad9b.f0b69df3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[87],{9972:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var t=a(4848),l=a(8453),r=a(1470),s=a(9365);const o={},i="Frontend Application",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/frontend.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Build",permalink:"/dapp/opl/build"},next:{title:"Cipher ParaTime",permalink:"/dapp/cipher/"}},d={},u=[{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}];function p(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,l.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"frontend-application",children:"Frontend Application"}),"\n",(0,t.jsxs)(n.p,{children:["We will need a ",(0,t.jsx)(n.a,{href:"https://www.pinata.cloud",children:"Pinata"})," development API\n",(0,t.jsx)(n.a,{href:"https://docs.pinata.cloud/docs/getting-started#2-generate-your-api-keys",children:"key"}),"\nand JWT with the ",(0,t.jsx)(n.code,{children:"pinFileToIPFS"})," permission. Let's obtain that first."]}),"\n",(0,t.jsx)(n.h3,{id:"vuejs",children:"VueJS"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"opl-secret-ballot"})," directory run:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"git init .\ngit remote add -f demo-opl-secret-ballot https://github.com/oasisprotocol/demo-opl-secret-ballot\ngit checkout demo-opl-secret-ballot/main frontend\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, update the ",(0,t.jsx)(n.code,{children:"@oasislabs/secret-ballot-backend"})," package name in\n",(0,t.jsx)(n.code,{children:"frontend/package.json"})," to match your ",(0,t.jsx)(n.code,{children:"backend/package.json"})," project name."]}),"\n",(0,t.jsxs)(n.p,{children:["We recommend using ",(0,t.jsx)(n.a,{href:"https://pnpm.io",children:"pnpm"})," to install dependencies, but ",(0,t.jsx)(n.code,{children:"yarn"}),"\nand ",(0,t.jsx)(n.code,{children:"npm"})," will work with some modifications around workspaces."]}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm install\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm install\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn install\n"})})})]}),"\n",(0,t.jsx)(n.p,{children:"Compile and Hot-Reload for Development"}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm run dev\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm run dev\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn dev\n"})})})]}),"\n",(0,t.jsx)(n.p,{children:"Build assets for deployment"}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm run build\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm run build\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn build\n"})})})]}),"\n",(0,t.jsx)(n.p,{children:"We can now reference the deployed contracts in our frontend Vue app."}),"\n",(0,t.jsxs)(n.p,{children:["Modify the ",(0,t.jsx)(n.code,{children:".env.development"})," file with the appropriate addresses:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"VITE_BALLOT_BOX_V1_ADDR=0xFb40591a8df155da291A4B52E4Df9901a95b7C06\n"})}),"\n",(0,t.jsx)(n.p,{children:"and"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"VITE_DAO_V1_ADDR=0xFBcb580DD6D64fbF7caF57FB0439502412324179\n"})}),"\n",(0,t.jsx)(n.h3,{id:"pinata",children:"Pinata"}),"\n",(0,t.jsxs)(n.p,{children:["Additionally, we will need a ",(0,t.jsx)(n.a,{href:"https://www.pinata.cloud",children:"Pinata"})," JWT\n",(0,t.jsx)(n.a,{href:"https://docs.pinata.cloud/reference/datatestauthentication",children:"key"})," to access the\npinning service with which we store our ballots as JSON."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"VITE_PINATA_JWT=\n"})}),"\n",(0,t.jsx)(n.h3,{id:"start",children:"Start"}),"\n",(0,t.jsx)(n.p,{children:"Start Vue app"}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(s.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm run dev\n"})})}),(0,t.jsx)(s.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm run dev\n"})})}),(0,t.jsx)(s.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn dev\n"})})})]}),"\n",(0,t.jsx)(n.h3,{id:"metamask",children:"MetaMask"}),"\n",(0,t.jsxs)(n.p,{children:["You can use one of the deployed test accounts and associated private key with\n",(0,t.jsx)(n.a,{href:"https://metamask.io",children:"MetaMask"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"If you have not added a local network to MetaMask already, you can use this\nconfiguration."}),"\n",(0,t.jsx)(n.h4,{id:"localhost",children:"Localhost"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["RPC HTTP endpoint: ",(0,t.jsx)(n.code,{children:"http://127.0.0.1:8545/"})]}),"\n",(0,t.jsxs)(n.li,{children:["Chain ID:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Decimal: 1337"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsxs)(n.p,{children:["You should be able to navigate to\n",(0,t.jsx)(n.a,{href:"http://localhost:5173",children:"http://localhost:5173"})," and create a new poll."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Create a poll",src:a(8661).A+"",width:"2880",height:"1800"})}),"\n",(0,t.jsx)(n.p,{children:"Confirm and sign a transaction to create a new poll (issues a request against\nthe Host contract)."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Confirm new poll",src:a(8342).A+"",width:"2880",height:"1800"})}),"\n",(0,t.jsxs)(n.p,{children:["Voting on a ballot issues a request to the ",(0,t.jsx)(n.em,{children:"enclave"})," contract."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Vote on ballot",src:a(5730).A+"",width:"2880",height:"1800"})}),"\n",(0,t.jsx)(n.p,{children:"You should be able to see results from past polls."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"See past proposals",src:a(6274).A+"",width:"2880",height:"1800"})}),"\n",(0,t.jsx)(n.p,{children:"If you were able to get to this point, congrats! You have created an OPL dApp!"}),"\n",(0,t.jsx)(n.admonition,{title:"Example",type:"info",children:(0,t.jsxs)(n.p,{children:["You can try out and download a frontend of the secret ballot Dapp from the\n",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/demo-opl-secret-ballot/tree/main/frontend",children:"Oasis Playground repository"}),"."]})})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},9365:(e,n,a)=>{a.d(n,{A:()=>s});a(6540);var t=a(4164);const l={tabItem:"tabItem_Ymn6"};var r=a(4848);function s(e){let{children:n,hidden:a,className:s}=e;return(0,r.jsx)("div",{role:"tabpanel",className:(0,t.A)(l.tabItem,s),hidden:a,children:n})}},1470:(e,n,a)=>{a.d(n,{A:()=>w});var t=a(6540),l=a(4164),r=a(3104),s=a(6347),o=a(205),i=a(7485),c=a(1682),d=a(9466);function u(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function p(e){const{values:n,children:a}=e;return(0,t.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:a,attributes:t,default:l}}=e;return{value:n,label:a,attributes:t,default:l}}))}(a);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[n,a])}function h(e){let{value:n,tabValues:a}=e;return a.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:a}=e;const l=(0,s.W6)(),r=function(e){let{queryString:n=!1,groupId:a}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!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:n,groupId:a});return[(0,i.aZ)(r),(0,t.useCallback)((e=>{if(!r)return;const n=new URLSearchParams(l.location.search);n.set(r,e),l.replace({...l.location,search:n.toString()})}),[r,l])]}function x(e){const{defaultValue:n,queryString:a=!1,groupId:l}=e,r=p(e),[s,i]=(0,t.useState)((()=>function(e){let{defaultValue:n,tabValues:a}=e;if(0===a.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(n){if(!h({value:n,tabValues:a}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${n}" 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 n}const t=a.find((e=>e.default))??a[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:r}))),[c,u]=m({queryString:a,groupId:l}),[x,j]=function(e){let{groupId:n}=e;const a=function(e){return e?`docusaurus.tab.${e}`:null}(n),[l,r]=(0,d.Dv)(a);return[l,(0,t.useCallback)((e=>{a&&r.set(e)}),[a,r])]}({groupId:l}),f=(()=>{const e=c??x;return h({value:e,tabValues:r})?e:null})();(0,o.A)((()=>{f&&i(f)}),[f]);return{selectedValue:s,selectValue:(0,t.useCallback)((e=>{if(!h({value:e,tabValues:r}))throw new Error(`Can't select invalid tab value=${e}`);i(e),u(e),j(e)}),[u,j,r]),tabValues:r}}var j=a(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=a(4848);function g(e){let{className:n,block:a,selectedValue:t,selectValue:s,tabValues:o}=e;const i=[],{blockElementScrollPositionUntilNextRender:c}=(0,r.a_)(),d=e=>{const n=e.currentTarget,a=i.indexOf(n),l=o[a].value;l!==t&&(c(n),s(l))},u=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const a=i.indexOf(e.currentTarget)+1;n=i[a]??i[0];break}case"ArrowLeft":{const a=i.indexOf(e.currentTarget)-1;n=i[a]??i[i.length-1];break}}n?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,l.A)("tabs",{"tabs--block":a},n),children:o.map((e=>{let{value:n,label:a,attributes:r}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:t===n?0:-1,"aria-selected":t===n,ref:e=>i.push(e),onKeyDown:u,onClick:d,...r,className:(0,l.A)("tabs__item",f.tabItem,r?.className,{"tabs__item--active":t===n}),children:a??n},n)}))})}function v(e){let{lazy:n,children:a,selectedValue:l}=e;const r=(Array.isArray(a)?a:[a]).filter(Boolean);if(n){const e=r.find((e=>e.props.value===l));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:r.map(((e,n)=>(0,t.cloneElement)(e,{key:n,hidden:e.props.value!==l})))})}function y(e){const n=x(e);return(0,b.jsxs)("div",{className:(0,l.A)("tabs-container",f.tabList),children:[(0,b.jsx)(g,{...n,...e}),(0,b.jsx)(v,{...n,...e})]})}function w(e){const n=(0,j.A)();return(0,b.jsx)(y,{...e,children:u(e.children)},String(n))}},8342:(e,n,a)=>{a.d(n,{A:()=>t});const t=a.p+"assets/images/confirm-new-poll-44de684bfe667f9b7c51358f6e374bc9.png"},8661:(e,n,a)=>{a.d(n,{A:()=>t});const t=a.p+"assets/images/create-poll-07bde4932eab22772d5d7e193cbc0255.png"},6274:(e,n,a)=>{a.d(n,{A:()=>t});const t=a.p+"assets/images/past-dao-proposals-fd0f3f96be29751307e0850e034593c3.png"},5730:(e,n,a)=>{a.d(n,{A:()=>t});const t=a.p+"assets/images/vote-on-ballot-1a35d67b60f5531fd4b91a1633030ee2.png"},8453:(e,n,a)=>{a.d(n,{R:()=>s,x:()=>o});var t=a(6540);const l={},r=t.createContext(l);function s(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:s(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6e63ac1c.385d397a.js b/assets/js/6e63ac1c.385d397a.js new file mode 100644 index 0000000000..f35745d148 --- /dev/null +++ b/assets/js/6e63ac1c.385d397a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7189],{536:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>d});var a=n(4848),s=n(8453);const i={description:"Deploying upgradable and deterministic contracts"},r="Deployment Patterns",o={id:"dapp/sapphire/deployment",title:"Deployment Patterns",description:"Deploying upgradable and deterministic contracts",source:"@site/docs/dapp/sapphire/deployment.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/deployment",permalink:"/dapp/sapphire/deployment",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/deployment.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Deploying upgradable and deterministic contracts"},sidebar:"developers",previous:{title:"Contract Addresses and Deployments",permalink:"/dapp/sapphire/addresses"},next:{title:"Security",permalink:"/dapp/sapphire/security"}},c={},d=[{value:"Implementing Proxy contracts on Oasis Sapphire",id:"implementing-proxy-contracts-on-oasis-sapphire",level:2},{value:"What are Upgradable Contracts?",id:"what-are-upgradable-contracts",level:3},{value:"EIP-1822: Universal Upgradeable Proxy Standard (UUPS)",id:"eip-1822-universal-upgradeable-proxy-standard-uups",level:4},{value:"EIP-1967: Standard Proxy Storage Slots",id:"eip-1967-standard-proxy-storage-slots",level:4},{value:"The Impact of Confidential EVM on Tooling Compatibility",id:"the-impact-of-confidential-evm-on-tooling-compatibility",level:3},{value:"Solutions for Using UUPS Proxies on Oasis Sapphire",id:"solutions-for-using-uups-proxies-on-oasis-sapphire",level:3},{value:"1. Directly Implement EIP-1822",id:"1-directly-implement-eip-1822",level:4},{value:"2. Modify Deployment Scripts",id:"2-modify-deployment-scripts",level:4},{value:"Solution for Using Deterministic Proxies on Oasis Sapphire",id:"solution-for-using-deterministic-proxies-on-oasis-sapphire",level:3},{value:"Caution Against Using <code>eth_getStorageAt</code>",id:"caution-against-using-eth_getstorageat",level:3},{value:"EIP-7201: Namespaced Storage for Delegatecall Contracts",id:"eip-7201-namespaced-storage-for-delegatecall-contracts",level:3},{value:"Benefits of Namespacing over Direct Storage Access",id:"benefits-of-namespacing-over-direct-storage-access",level:3}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"deployment-patterns",children:"Deployment Patterns"}),"\n",(0,a.jsx)(t.h2,{id:"implementing-proxy-contracts-on-oasis-sapphire",children:"Implementing Proxy contracts on Oasis Sapphire"}),"\n",(0,a.jsx)(t.p,{children:"As a confidential Ethereum Virtual Machine (EVM), Oasis prevents external\naccess to contract storage or runtime states in order to keep your secrets\nprivate. This unique feature affects how developers interact with and manage\nsmart contracts, particularly when using common Ethereum development tools."}),"\n",(0,a.jsx)(t.h3,{id:"what-are-upgradable-contracts",children:"What are Upgradable Contracts?"}),"\n",(0,a.jsx)(t.p,{children:"Upgradable contracts are smart contracts designed to allow developers to update\nfunctionality even after being deployed to a blockchain. This is particularly\nuseful for fixing bugs or adding new features without losing the existing state\nor having to deploy a new contract. Upgradability is achieved through proxy\npatterns, where a proxy contract directs calls to an underlying logic contract\nwhich developers can swap out without affecting the state stored in the proxy."}),"\n",(0,a.jsxs)(t.h4,{id:"eip-1822-universal-upgradeable-proxy-standard-uups",children:[(0,a.jsx)(t.a,{href:"https://eips.ethereum.org/EIPS/eip-1822",children:"EIP-1822"}),": Universal Upgradeable Proxy Standard (UUPS)"]}),"\n",(0,a.jsx)(t.p,{children:"EIP-1822 introduces a method for creating upgradable contracts using a proxy\npattern and specifies a mechanism where the proxy contract itself contains the\nupgrade logic. This design reduces the complexity and potential for errors\ncompared to other proxy patterns because it consolidates upgrade functionality\nwithin the proxy and eliminates the need for additional external management."}),"\n",(0,a.jsxs)(t.h4,{id:"eip-1967-standard-proxy-storage-slots",children:[(0,a.jsx)(t.a,{href:"https://eips.ethereum.org/EIPS/eip-1967",children:"EIP-1967"}),": Standard Proxy Storage Slots"]}),"\n",(0,a.jsx)(t.p,{children:"EIP-1967 defines standard storage slots to be used by all proxy contracts for\nconsistent and predictable storage access. This standard helps prevent storage\ncollisions and enhances security by outlining specific locations in a proxy\ncontract for storing the address of the logic contract and other administrative\ninformation. Using these predetermined slots makes managing and auditing proxy\ncontracts easier."}),"\n",(0,a.jsx)(t.h3,{id:"the-impact-of-confidential-evm-on-tooling-compatibility",children:"The Impact of Confidential EVM on Tooling Compatibility"}),"\n",(0,a.jsxs)(t.p,{children:["While the underlying proxy implementations in EIP-1822 work perfectly in\nfacilitating smart contract upgrades, the tools typically used to manage these\nproxies may not function as expected on Oasis Sapphire.\nFor example, the ",(0,a.jsx)(t.a,{href:"https://github.com/OpenZeppelin/openzeppelin-upgrades",children:"openzeppelin-upgrades"})," library, which relies on the EIP-1967\nstandard, uses ",(0,a.jsx)(t.a,{href:"https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat",children:"eth_getStorageAt"})," to access contract storage. This function\ndoes not work in a confidential environment which forbids direct storage\naccess."]}),"\n",(0,a.jsxs)(t.p,{children:["Additionally, Sapphire natively protects against replay and currently does not\nallow an empty chain ID \xe0 la pre ",(0,a.jsx)(t.a,{href:"https://eips.ethereum.org/EIPS/eip-155",children:"EIP-155"})," transactions."]}),"\n",(0,a.jsx)(t.h3,{id:"solutions-for-using-uups-proxies-on-oasis-sapphire",children:"Solutions for Using UUPS Proxies on Oasis Sapphire"}),"\n",(0,a.jsx)(t.p,{children:"Developers looking to use UUPS proxies on Oasis Sapphire have two primary\noptions:"}),"\n",(0,a.jsx)(t.h4,{id:"1-directly-implement-eip-1822",children:"1. Directly Implement EIP-1822"}),"\n",(0,a.jsxs)(t.p,{children:["Avoid using ",(0,a.jsx)(t.a,{href:"https://github.com/OpenZeppelin/openzeppelin-upgrades",children:"openzeppelin-upgrades"})," and manually handle the proxy setup and\nupgrades with your own scripts, such as by calling the ",(0,a.jsx)(t.code,{children:"updateCodeAddress"}),"\nmethod directly."]}),"\n",(0,a.jsx)(t.h4,{id:"2-modify-deployment-scripts",children:"2. Modify Deployment Scripts"}),"\n",(0,a.jsxs)(t.p,{children:["Change deployment scripts to avoid ",(0,a.jsx)(t.code,{children:"eth_getStorageAt"}),". Alternative methods\nlike calling ",(0,a.jsx)(t.code,{children:"owner()"})," which do not require direct storage access.\n",(0,a.jsx)(t.a,{href:"https://github.com/wighawag/hardhat-deploy",children:"hardhat-deploy"})," as of ",(0,a.jsx)(t.code,{children:"0.12.4"})," supports this approach with a default proxy\nthat includes an ",(0,a.jsx)(t.code,{children:"owner()"})," function when deploying with a configuration that\nspecifies ",(0,a.jsx)(t.code,{children:"proxy: true"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-typescript",children:"module.exports = async ({getNamedAccounts, deployments, getChainId}) => {\n const {deploy} = deployments;\n const {deployer} = await getNamedAccounts();\n await deploy('Greeter', {\n from: deployer,\n proxy: true,\n });\n};\n"})}),"\n",(0,a.jsx)(t.h3,{id:"solution-for-using-deterministic-proxies-on-oasis-sapphire",children:"Solution for Using Deterministic Proxies on Oasis Sapphire"}),"\n",(0,a.jsx)(t.p,{children:"We suggest that developers interested in deterministic proxies on Oasis\nSapphire use a contract that supports replay protection."}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.code,{children:"hardhat-deploy"})," supports using the ",(0,a.jsx)(t.a,{href:"https://github.com/safe-global/safe-singleton-factory",children:"Safe Singleton factory"})," deployed on\nthe Sapphire ",(0,a.jsx)(t.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",children:"Mainnet"})," and ",(0,a.jsx)(t.a,{href:"https://explorer.oasis.io/testnet/sapphire/address/0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",children:"Testnet"})," when ",(0,a.jsx)(t.code,{children:"deterministicDeployment"})," is ",(0,a.jsx)(t.code,{children:"true"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-typescript",children:"module.exports = async ({getNamedAccounts, deployments, getChainId}) => {\n const {deploy} = deployments;\n const {deployer} = await getNamedAccounts();\n await deploy('Greeter', {\n from: deployer,\n deterministicDeployment: true,\n });\n};\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Next, in your ",(0,a.jsx)(t.code,{children:"hardhat.config.ts"})," file, specify the address of the Safe\nSingleton factory:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-typescript",children:" deterministicDeployment: {\n \"97\": {\n factory: '0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7',\n deployer: '0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37',\n funding: '2000000',\n signedTx: '',\n },\n \"23295\": {\n factory: '0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7',\n deployer: '0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37',\n funding: '2000000',\n signedTx: '',\n }\n },\n"})}),"\n",(0,a.jsxs)(t.h3,{id:"caution-against-using-eth_getstorageat",children:["Caution Against Using ",(0,a.jsx)(t.code,{children:"eth_getStorageAt"})]}),"\n",(0,a.jsxs)(t.p,{children:["Direct storage access, such as with ",(0,a.jsx)(t.code,{children:"eth_getStorageAt"}),", is generally\ndiscouraged. It reduces contract flexibility and deviates from common practice\nwhich advocates for a standardized Solidity compatible API to both facilitate\ninteractions between contracts and allow popular libraries such as ",(0,a.jsx)(t.a,{href:"https://abitype.dev/",children:"ABIType"}),"\nand ",(0,a.jsx)(t.a,{href:"https://www.npmjs.com/package/typechain",children:"TypeChain"})," to automatically generate client bindings. Direct storage\naccess makes contracts less adaptable and complicates on-chain automation; it\ncan even complicate the use of multisig wallets.\nFor contracts aiming to maintain a standard interface and ensure future\nupgradeability, we advise sticking to ERC-defined Solidity compatible APIs and\navoiding directly interacting with contract storage."]}),"\n",(0,a.jsxs)(t.h3,{id:"eip-7201-namespaced-storage-for-delegatecall-contracts",children:[(0,a.jsx)(t.a,{href:"https://eips.ethereum.org/EIPS/eip-7201",children:"EIP-7201"}),": Namespaced Storage for Delegatecall Contracts"]}),"\n",(0,a.jsxs)(t.p,{children:["ERC-7201 proposes a structured approach to storage in smart contracts that\nutilize ",(0,a.jsx)(t.code,{children:"delegatecall"})," which is often employed in proxy contracts for\nupgradability. This standard recommends namespacing storage to mitigate the\nrisk of storage collisions \u2014 a common issue when multiple contracts share the\nsame storage space in a ",(0,a.jsx)(t.code,{children:"delegatecall"})," context."]}),"\n",(0,a.jsx)(t.h3,{id:"benefits-of-namespacing-over-direct-storage-access",children:"Benefits of Namespacing over Direct Storage Access"}),"\n",(0,a.jsxs)(t.p,{children:["Contracts using ",(0,a.jsx)(t.code,{children:"delegatecall"}),", such as upgradable proxies, can benefit from\nnamespacing their storage through more efficient data organization which\nenhances security. This approach isolates different variables and sections of\na contract\u2019s storage under distinct namespaces, ensuring that each segment is\ndistinct and does not interfere with others. Namespacing is generally more\nrobust and preferable to using ",(0,a.jsx)(t.code,{children:"eth_getStorageAt"}),"."]}),"\n",(0,a.jsxs)(t.p,{children:["See example ERC-7201 implementation and usage:\n",(0,a.jsx)(t.a,{href:"https://gist.github.com/CedarMist/4cfb8f967714aa6862dd062742acbc7b",children:"https://gist.github.com/CedarMist/4cfb8f967714aa6862dd062742acbc7b"})]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-solidity",children:'// SPDX-License-Identifier: Apache-2.0\n\npragma solidity ^0.8.0;\n\ncontract Example7201 {\n /// @custom:storage-location erc7201:Example7201.state\n struct State {\n uint256 counter;\n }\n\n function _stateStorageSlot()\n private pure\n returns (bytes32)\n {\n return keccak256(abi.encode(uint256(keccak256("Example7201.state")) - 1)) & ~bytes32(uint256(0xff));\n }\n\n function _getState()\n private pure\n returns (State storage state)\n {\n bytes32 slot = _stateStorageSlot();\n assembly {\n state.slot := slot\n }\n }\n\n function increment()\n public\n {\n State storage state = _getState();\n\n state.counter += 1;\n }\n\n function get()\n public view\n returns (uint256)\n {\n State storage state = _getState();\n\n return state.counter;\n }\n}\n\ncontract ExampleCaller {\n Example7201 private example;\n\n constructor () {\n example = new Example7201();\n }\n function get()\n external\n returns (uint256 counter)\n {\n (bool success, bytes memory result ) = address(example).delegatecall(abi.encodeCall(example.get, ()));\n require(success);\n counter = abi.decode(result, (uint256));\n }\n\n function increment()\n external\n {\n (bool success, ) = address(example).delegatecall(abi.encodeCall(example.increment, ()));\n require(success);\n }\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var a=n(6540);const s={},i=a.createContext(s);function r(e){const t=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6ea13540.c7c72dc1.js b/assets/js/6ea13540.c7c72dc1.js new file mode 100644 index 0000000000..ba212da6ac --- /dev/null +++ b/assets/js/6ea13540.c7c72dc1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8186],{6743:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>c,frontMatter:()=>o,metadata:()=>r,toc:()=>a});var i=t(4848),s=t(8453);const o={},l="ADR 0001: Multiple Roots Under the Tendermint Application Hash",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0001-tm-multi-root-apphash.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},d={},a=[{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}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-0001-multiple-roots-under-the-tendermint-application-hash",children:"ADR 0001: Multiple Roots Under the Tendermint Application Hash"}),"\n",(0,i.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,i.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2020-08-06: Added consequence for state checkpoints"}),"\n",(0,i.jsx)(n.li,{children:"2020-07-28: Initial version"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.p,{children:"The proposed design is to derive the Tendermint ABCI application hash by hashing\nall the different roots as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"AppHash := H(Context || Root_0 || ... || Root_n)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Where:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"H"})," is the SHA-512/256 hash function."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Context"})," is the string ",(0,i.jsx)(n.code,{children:"oasis-core/tendermint: roots"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Root_i"})," is the fixed-size SHA-512/256 root hash of the specified root."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Currently, the only root would be the existing consensus state root at index 0."}),"\n",(0,i.jsx)(n.p,{children:"To implement this change the following modifications would be required:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Update the ABCI multiplexer's ",(0,i.jsx)(n.code,{children:"Commit"})," method to calculate and return the\napplication hash using the scheme specified above."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Update the consensus API ",(0,i.jsx)(n.code,{children:"SignedHeader"})," response to include the\n",(0,i.jsx)(n.code,{children:"UntrustedStateRoot"})," (the untrusted prefix denotes that the user must verify\nthat the state root corresponds to ",(0,i.jsx)(n.code,{children:"AppHash"})," provided in the signed header in\n",(0,i.jsx)(n.code,{children:"Meta"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:["When new roots will be added in the future, both ",(0,i.jsx)(n.code,{children:"Block"})," and ",(0,i.jsx)(n.code,{children:"SignedHeader"}),"\nwill need to include them all."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"alternatives",children:"Alternatives"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"As this changes the application hash, this would be a breaking change for the\nconsensus layer."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Since we are simply hashing all the roots together, all of them need to be\nincluded in the signed headers returned to light clients."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Consensus state checkpoints will need to contain data for multiple roots."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/tendermint/tendermint/pull/5134",children:"tendermint#5134"})}),"\n"]})]})}function c(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>r});var i=t(6540);const s={},o=i.createContext(s);function l(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/714fd338.c767d0fe.js b/assets/js/714fd338.c767d0fe.js new file mode 100644 index 0000000000..7386145137 --- /dev/null +++ b/assets/js/714fd338.c767d0fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3343],{5416:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var t=s(4848),i=s(8453);const o={},r="Set up Trusted Execution Environment (TEE)",l={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,unlisted:!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:172612742e4,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"}},a={},d=[{value:"BIOS Configuration",id:"bios-configuration",level:2},{value:"Ensure Clock Synchronization",id:"ensure-clock-synchronization",level:2},{value:"Ensure Proper SGX Device Permissions",id:"ensure-proper-sgx-device-permissions",level:2},{value:"AESM Service",id:"aesm-service",level:2},{value:"DCAP Attestation",id:"dcap-attestation",level:2},{value:"Ubuntu 22.04",id:"ubuntu-2204",level:3},{value:"Configuring the Quote Provider",id:"configuring-the-quote-provider",level:3},{value:"Intel PCS",id:"intel-pcs",level:4},{value:"Cloud Service Provider's PCCS",id:"cloud-service-providers-pccs",level:4},{value:"Own PCCS",id:"own-pccs",level:4},{value:"DCAP Attestation Docker",id:"dcap-attestation-docker",level:3},{value:"Multi-socket Systems",id:"multi-socket-systems",level:3},{value:"Ubuntu 22.04",id:"ubuntu-2204-1",level:4},{value:"VMware vSphere 8.0+",id:"vmware-vsphere-80",level:4},{value:"Migrate from EPID Attestation to DCAP Attestation",id:"migrate-from-epid-attestation-to-dcap-attestation",level:2},{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:"Oasis Attestation tool",id:"oasis-attestation-tool",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"AESM could not be contacted",id:"aesm-could-not-be-contacted",level:3},{value:"AESM: error 30",id:"aesm-error-30",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:"Ensure <code>/dev</code> is NOT Mounted with the <code>noexec</code> Option",id:"ensure-dev-is-not-mounted-with-the-noexec-option",level:4},{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},{value:"Couldn't find the platform library",id:"couldnt-find-the-platform-library",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"set-up-trusted-execution-environment-tee",children:"Set up Trusted Execution Environment (TEE)"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"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."})}),"\n",(0,t.jsxs)(n.p,{children:["If the ParaTime is configured to run in a TEE (currently only ",(0,t.jsx)(n.a,{href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html",children:"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."]}),"\n",(0,t.jsx)(n.h2,{id:"bios-configuration",children:"BIOS Configuration"}),"\n",(0,t.jsxs)(n.p,{children:["To enable Intel SGX on your hardware, you also need to configure the BIOS.\nFirst, ",(0,t.jsx)(n.strong,{children:"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:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"SGX"}),": ENABLE"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Hyper-Threading"}),": DISABLE"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Intel SpeedStep"}),": DISABLE"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"SecureBoot"}),": DISABLE (not necessary for recent kernels)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"All Internal Graphics"}),": DISABLE"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Turbo Mode"}),": DISABLE"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"CPU AES"}),": ENABLE"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"ensure-clock-synchronization",children:"Ensure Clock Synchronization"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"ensure-proper-sgx-device-permissions",children:"Ensure Proper SGX Device Permissions"}),"\n",(0,t.jsxs)(n.p,{children:["Make sure that the user that is running the Oasis Node binary has access to the\nSGX device (e.g. ",(0,t.jsx)(n.code,{children:"/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:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"crw-rw---- 1 root sgx 10, 125 Oct 28 09:28 /dev/sgx_enclave\n"})}),"\n",(0,t.jsxs)(n.p,{children:["and the user running Oasis Node is ",(0,t.jsx)(n.code,{children:"oasis"}),", you can do:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo adduser oasis sgx\n"})}),"\n",(0,t.jsx)(n.p,{children:"Failure to do so may result in permission denied errors during runtime startup."}),"\n",(0,t.jsx)(n.h2,{id:"aesm-service",children:"AESM Service"}),"\n",(0,t.jsxs)(n.p,{children:["To allow execution of SGX enclaves, several ",(0,t.jsx)(n.strong,{children:"Architectural Enclaves (AE)"})," are\ninvolved (i.e. Launch Enclave, Provisioning Enclave, Provisioning Certificate\nEnclave, Quoting Enclave, Platform Services Enclaves)."]}),"\n",(0,t.jsxs)(n.p,{children:["Communication between application-spawned SGX enclaves and Intel-provided\nArchitectural Enclaves is through ",(0,t.jsx)(n.strong,{children:"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."]}),"\n",(0,t.jsx)(n.p,{children:"Oasis node requires the use of DCAP attestation. To see if your system supports\nit, run the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:' cpuid -1 | grep "SGX"\n'})}),"\n",(0,t.jsx)(n.p,{children:"and look for the following line:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:" SGX_LC: SGX launch config supported = true\n"})}),"\n",(0,t.jsx)(n.h2,{id:"dcap-attestation",children:"DCAP Attestation"}),"\n",(0,t.jsx)(n.h3,{id:"ubuntu-2204",children:"Ubuntu 22.04"}),"\n",(0,t.jsxs)(n.p,{children:["A convenient way to install the AESM service on Ubuntu 22.04 systems\nis to use the Intel's ",(0,t.jsx)(n.a,{href:"https://download.01.org/intel-sgx/sgx_repo/",children:"official Intel SGX APT repository"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"First add Intel SGX APT repository to your system:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'curl -fsSL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo gpg --dearmor -o /usr/share/keyrings/intel-sgx-deb.gpg\necho "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx-deb.gpg] 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\n'})}),"\n",(0,t.jsxs)(n.p,{children:["And then install the ",(0,t.jsx)(n.code,{children:"sgx-aesm-service"}),", ",(0,t.jsx)(n.code,{children:"libsgx-aesm-ecdsa-plugin"}),", ",(0,t.jsx)(n.code,{children:"libsgx-aesm-quote-ex-plugin"})," and ",(0,t.jsx)(n.code,{children:"libsgx-dcap-default-qpl"})," packages:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo apt update\nsudo apt install sgx-aesm-service libsgx-aesm-ecdsa-plugin libsgx-aesm-quote-ex-plugin libsgx-dcap-default-qpl\n"})}),"\n",(0,t.jsx)(n.p,{children:"The AESM service should be up and running. To confirm that, use:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo systemctl status aesmd.service\n"})}),"\n",(0,t.jsx)(n.h3,{id:"configuring-the-quote-provider",children:"Configuring the Quote Provider"}),"\n",(0,t.jsxs)(n.p,{children:["The Intel Quote Provider (",(0,t.jsx)(n.code,{children:"libsgx-dcap-default-qpl"}),") needs to be configured in\norder to use either the Intel PCS, the PCCS of your cloud service provider, or\nyour own PCCS. The configuration file is located at ",(0,t.jsx)(n.code,{children:"/etc/sgx_default_qcnl.conf"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Make sure to always restart the ",(0,t.jsx)(n.code,{children:"aesmd.service"})," after updating the\nconfiguration, via:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo systemctl restart aesmd.service\n"})}),"\n",(0,t.jsx)(n.h4,{id:"intel-pcs",children:"Intel PCS"}),"\n",(0,t.jsxs)(n.p,{children:["Using the Intel PCS is the simplest and most generic way, but it may be less\nreliable than using your own PCCS. Some cloud providers (see the ",(0,t.jsx)(n.a,{href:"#cloud-service-providers-pccs",children:"following section"}),")\nalso require you to use their PCCS."]}),"\n",(0,t.jsxs)(n.p,{children:["To use Intel PCS update the ",(0,t.jsx)(n.code,{children:"pccs_url"})," value in ",(0,t.jsx)(n.code,{children:"/etc/sgx_default_qcnl.conf"}),"\nto the Intel PCS API URL:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:' //PCCS server address\n "pccs_url": "https://api.trustedservices.intel.com/sgx/certification/v4/"\n'})}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsx)(n.p,{children:"In case there is an error in the QPL configuration file, attestation will refuse\nto work and the AESM service may produce unhelpful errors like the following:"}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Couldn't find the platform library. (null)\n"})}),(0,t.jsxs)(n.p,{children:["The only thing that needs to be changed is the ",(0,t.jsx)(n.code,{children:"pccs_url"})," value above. ",(0,t.jsx)(n.strong,{children:"Do not\nadd any comments and/or modify punctuation as these could make the configuration\nfile invalid."})]})]}),"\n",(0,t.jsx)(n.h4,{id:"cloud-service-providers-pccs",children:"Cloud Service Provider's PCCS"}),"\n",(0,t.jsx)(n.p,{children:"Some cloud providers require you to use their PCCS."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Azure: See the ",(0,t.jsx)(n.a,{href:"https://learn.microsoft.com/en-us/azure/security/fundamentals/trusted-hardware-identity-management#how-do-i-use-intel-qpl-with-trusted-hardware-identity-management",children:"Azure documentation"})," for details on configuring the quote provider. The documentation\ncontains an example of an Intel QPL configuration file that can be used."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Alibaba Cloud: See the ",(0,t.jsx)(n.a,{href:"https://www.alibabacloud.com/help/en/ecs/user-guide/build-an-sgx-encrypted-computing-environment",children:"Alibaba Cloud documentation"})," for details on configuring the quote provider. The\ndocumentation shows the required ",(0,t.jsx)(n.code,{children:"sgx_default_qcnl.conf"})," changes."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Other cloud providers: If you are using a different cloud service provider, consult their\nspecific documentation for the appropriate PCCS configuration and guidance on configuring the quote provider, or\nuse one of the other PCCS options."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"own-pccs",children:"Own PCCS"}),"\n",(0,t.jsxs)(n.p,{children:["It is also possible to run PCCS yourself. Follow ",(0,t.jsx)(n.a,{href:"https://www.intel.com/content/www/us/en/developer/articles/guide/intel-software-guard-extensions-data-center-attestation-primitives-quick-install-guide.html",children:"official Intel instructions"})," on how to setup your own PCCS."]}),"\n",(0,t.jsx)(n.h3,{id:"dcap-attestation-docker",children:"DCAP Attestation Docker"}),"\n",(0,t.jsxs)(n.p,{children:["Alternatively, an easy way to install and run the AESM service on a ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/engine/",children:"Docker"}),"-enabled\nsystem is to use ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/pkgs/container/aesmd",children:"our AESM container image"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Executing the following command should (always) pull the latest version of our\nAESMD Docker container, map the SGX devices and ",(0,t.jsx)(n.code,{children:"/var/run/aesmd"})," directory\nand ensure AESM is running in the background (also automatically started on boot):"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"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-dcap:master\n"})}),"\n",(0,t.jsxs)(n.p,{children:["By default, the Intel Quote Provider in the docker container is configured to use the Intel PCS endpoint.\nTo override the Intel Quote Provider configuration within the container mount your own custom configuration using\nthe ",(0,t.jsx)(n.code,{children:"volume"})," flag."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"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 --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf \\\n --name aesmd \\\n ghcr.io/oasisprotocol/aesmd-dcap:master\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The default Intel Quote Provider config is available in ",(0,t.jsx)(n.a,{href:"https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf",children:"Intel SGX Github repository"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"multi-socket-systems",children:"Multi-socket Systems"}),"\n",(0,t.jsx)(n.p,{children:"Note that platform provisioning for multi-socket systems (e.g. systems with\nmultiple CPUs) is more complex, especially if one is using a hypervisor and\nrunning SGX workloads inside guest VMs. In this case additional provisioning may\nbe required to be performed on the host."}),"\n",(0,t.jsx)(n.p,{children:"Note that the system must be booted in UEFI mode for provisioning to work as the\nprovisioning process uses UEFI variables to communicate with the BIOS."}),"\n",(0,t.jsx)(n.h4,{id:"ubuntu-2204-1",children:"Ubuntu 22.04"}),"\n",(0,t.jsx)(n.p,{children:"To provision and register your multi-socket system you need to install the Intel\nSGX Multi-Package Registration Agent Service as follows (assuming Intel's SGX\napt repository has been added as discussed above):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"sudo apt install sgx-ra-service\n"})}),"\n",(0,t.jsx)(n.h4,{id:"vmware-vsphere-80",children:"VMware vSphere 8.0+"}),"\n",(0,t.jsxs)(n.p,{children:["In order to enable SGX remote attestation on VMware vSphere-based systems,\nplease follow ",(0,t.jsx)(n.a,{href:"https://docs.vmware.com/en/VMware-vSphere/8.0/vsphere-vcenter-esxi-management/GUID-F16476FD-3B66-462F-B7FB-A456BEDC3549.html",children:"the vSphere guide"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"migrate-from-epid-attestation-to-dcap-attestation",children:"Migrate from EPID Attestation to DCAP Attestation"}),"\n",(0,t.jsx)(n.p,{children:"EPID attestation will be discontinued in 2025 and will no longer be available on\nany processors. All nodes using EPID attestation must migrate to DCAP\nattestation."}),"\n",(0,t.jsx)(n.p,{children:"For transitioning to the DCAP attestation, follow these steps:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["See if your system ",(0,t.jsx)(n.a,{href:"#aesm-service",children:"supports DCAP attestation"}),". If your hardware does not\nsupport DCAP attestation, you'll need to migrate your node to newer hardware."]}),"\n",(0,t.jsx)(n.li,{children:"Transition to DCAP attestation:"}),"\n"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["In case you are running AESM service on Docker follow ",(0,t.jsx)(n.a,{href:"#dcap-attestation-docker",children:"these instructions"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Otherwise manually configure AESM service to use DCAP attestation:","\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Remove any leftover EPID attestation packages. If running on Ubuntu 22.04 run\nthe following command:"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:" sudo apt remove libsgx-aesm-launch-plugin libsgx-aesm-epid-plugin\n"})}),"\n",(0,t.jsxs)(n.ol,{start:"2",children:["\n",(0,t.jsxs)(n.li,{children:["Configure AESM service to use ",(0,t.jsx)(n.a,{href:"#dcap-attestation",children:"DCAP attestation"})]}),"\n",(0,t.jsx)(n.li,{children:"Restart the AESM service. If running on Ubuntu 22.04 run the following\ncommand:"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo systemctl restart aesmd.service\n"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.ol,{start:"3",children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"#configuring-the-quote-provider",children:"Configure the Quote Provider"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Use the ",(0,t.jsx)(n.a,{href:"#oasis-attestation-tool",children:"attestation tool"})," to test if your settings are correct."]}),"\n",(0,t.jsxs)(n.li,{children:["Restart your compute node and verify that node is ",(0,t.jsx)(n.code,{children:"ready"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"check-sgx-setup",children:"Check SGX Setup"}),"\n",(0,t.jsxs)(n.p,{children:["In order to make sure that your SGX setup is working, you can use the\n",(0,t.jsx)(n.code,{children:"sgx-detect"})," tool from the ",(0,t.jsx)(n.a,{href:"https://lib.rs/crates/sgxs-tools",children:"sgxs-tools"})," Rust\npackage."]}),"\n",(0,t.jsx)(n.p,{children:"There are no pre-built packages for it, so you will need to compile it yourself."}),"\n",(0,t.jsx)(n.h3,{id:"install-dependencies",children:"Install Dependencies"}),"\n",(0,t.jsx)(n.p,{children:"Make sure you have the following installed on your system:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://gcc.gnu.org",children:"GCC"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/protocolbuffers/protobuf",children:"Protobuf"})," compiler."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://www.freedesktop.org/wiki/Software/pkg-config",children:"pkg-config"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://www.openssl.org",children:"OpenSSL"})," development package."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"On Fedora, you can install all the above with:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sudo dnf install gcc protobuf-compiler pkg-config openssl-devel\n"})}),"\n",(0,t.jsx)(n.p,{children:"On Ubuntu, you can install all the above with:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sudo apt install gcc protobuf-compiler pkg-config libssl-dev\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"install-rust",children:["Install ",(0,t.jsx)(n.a,{href:"https://www.rust-lang.org",children:"Rust"})]}),"\n",(0,t.jsxs)(n.p,{children:["We follow ",(0,t.jsx)(n.a,{href:"https://www.rust-lang.org/tools/install",children:"Rust upstream's recommendation"}),"\non using ",(0,t.jsx)(n.a,{href:"https://rustup.rs",children:"rustup"})," to install and manage Rust versions."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsx)(n.p,{children:"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."})}),"\n",(0,t.jsx)(n.p,{children:"Install rustup by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you want to avoid directly executing a shell script fetched the internet, you\ncan also ",(0,t.jsxs)(n.a,{href:"https://rust-lang.github.io/rustup/installation/other.html",children:["download ",(0,t.jsx)(n.code,{children:"rustup-init"})," executable for your platform"]}),"\nand run it manually. This will run ",(0,t.jsx)(n.code,{children:"rustup-init"})," which will download and install\nthe latest stable version of Rust on your system."]})}),"\n",(0,t.jsx)(n.h3,{id:"build-and-install-sgxs-tools",children:"Build and Install sgxs-tools"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"cargo install sgxs-tools\n"})}),"\n",(0,t.jsxs)(n.h3,{id:"run-sgx-detect-tool",children:["Run ",(0,t.jsx)(n.code,{children:"sgx-detect"})," Tool"]}),"\n",(0,t.jsxs)(n.p,{children:["After the installation completes, run ",(0,t.jsx)(n.code,{children:"sgx-detect"})," to make sure that everything\nis set up correctly:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sudo $(which sgx-detect)\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you don't run the ",(0,t.jsx)(n.code,{children:"sgx-detect"})," tool as ",(0,t.jsx)(n.code,{children:"root"}),", it might not have the\nnecessary permissions to access the SGX kernel device."]})}),"\n",(0,t.jsx)(n.p,{children:"When everything works, you should get output similar to the following (some\nthings depend on hardware features so your output may differ):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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/sgx_enclave)\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"})}),"\n",(0,t.jsxs)(n.p,{children:["The important part is the checkbox under ",(0,t.jsx)(n.em,{children:"Able to launch enclaves"})," in both\n",(0,t.jsx)(n.em,{children:"Debug mode"})," and ",(0,t.jsx)(n.em,{children:"Production mode (Intel whitelisted)"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["In case you encounter errors, see the ",(0,t.jsx)(n.a,{href:"https://edp.fortanix.com/docs/installation/help/",children:"list of common SGX installation issues"}),"\nfor help."]}),"\n",(0,t.jsx)(n.h3,{id:"oasis-attestation-tool",children:"Oasis Attestation tool"}),"\n",(0,t.jsxs)(n.p,{children:["To test if your settings are correct, you may use the ",(0,t.jsx)(n.a,{href:"#oasis-attestation-tool",children:"attestation tool"}),"\n(",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/releases",children:"binary"}),") for testing remote attestation against Intel SGX's\ndevelopment server."]}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["See ",(0,t.jsx)(n.a,{href:"/node/run-your-node/troubleshooting",children:"the general troubleshooting section"}),", before\nproceeding with ParaTime node-specific troubleshooting."]}),"\n",(0,t.jsx)(n.h3,{id:"aesm-could-not-be-contacted",children:"AESM could not be contacted"}),"\n",(0,t.jsxs)(n.p,{children:["If running ",(0,t.jsx)(n.code,{children:"sgx-detect --verbose"})," reports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"\ud83d\udd6e SGX system software > AESM service\nAESM could not be contacted. AESM is needed for launching enclaves and generating attestations.\n\nPlease check your AESM installation.\n\ndebug: error communicating with aesm\ndebug: cause: Connection refused (os error 111)\n\nMore information: https://edp.fortanix.com/docs/installation/help/#aesm-service\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Ensure you have completed all the necessary installation steps outlined in\n",(0,t.jsx)(n.a,{href:"#dcap-attestation",children:"DCAP Attestation"})," section."]}),"\n",(0,t.jsx)(n.h3,{id:"aesm-error-30",children:"AESM: error 30"}),"\n",(0,t.jsx)(n.p,{children:"If you are encountering the following error message in your node's logs:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"failed to initialize TEE: error while getting quote info from AESMD: aesm: error 30\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Ensure you have all required SGX driver libraries installed as listed in\n",(0,t.jsx)(n.a,{href:"#dcap-attestation",children:"DCAP Attestation"})," section."]}),"\n",(0,t.jsx)(n.h3,{id:"permission-denied-when-accessing-sgx-kernel-device",children:"Permission Denied When Accessing SGX Kernel Device"}),"\n",(0,t.jsxs)(n.p,{children:["If running ",(0,t.jsx)(n.code,{children:"sgx-detect --verbose"})," reports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"\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"})}),"\n",(0,t.jsxs)(n.p,{children:["Ensure you are running the ",(0,t.jsx)(n.code,{children:"sgx-detect"})," tool as ",(0,t.jsx)(n.code,{children:"root"})," via:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sudo $(which sgx-detect) --verbose\n"})}),"\n",(0,t.jsx)(n.h3,{id:"error-opening-sgx-kernel-device",children:"Error Opening SGX Kernel Device"}),"\n",(0,t.jsxs)(n.p,{children:["If running ",(0,t.jsx)(n.code,{children:"sgx-detect --verbose"})," reports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'\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'})}),"\n",(0,t.jsxs)(n.h4,{id:"ensure-dev-is-not-mounted-with-the-noexec-option",children:["Ensure ",(0,t.jsx)(n.code,{children:"/dev"})," is NOT Mounted with the ",(0,t.jsx)(n.code,{children:"noexec"})," Option"]}),"\n",(0,t.jsxs)(n.p,{children:["Some Linux distributions mount ",(0,t.jsx)(n.code,{children:"/dev"})," with the ",(0,t.jsx)(n.code,{children:"noexec"})," mount option. If that is\nthe case, it will prevent the enclave loader from mapping executable pages."]}),"\n",(0,t.jsxs)(n.p,{children:["Ensure your ",(0,t.jsx)(n.code,{children:"/dev"})," (i.e. ",(0,t.jsx)(n.code,{children:"devtmpfs"}),") is not mounted with the ",(0,t.jsx)(n.code,{children:"noexec"})," option.\nTo check that, use:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"cat /proc/mounts | grep devtmpfs\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To temporarily remove the ",(0,t.jsx)(n.code,{children:"noexec"})," mount option for ",(0,t.jsx)(n.code,{children:"/dev"}),", run:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sudo mount -o remount,exec /dev\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To permanently remove the ",(0,t.jsx)(n.code,{children:"noexec"})," mount option for ",(0,t.jsx)(n.code,{children:"/dev"}),", add the following to\nthe system's ",(0,t.jsx)(n.code,{children:"/etc/fstab"})," file:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"devtmpfs /dev devtmpfs defaults,exec 0 0\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["This is the recommended way to modify mount options for virtual (i.e. API) file\nsystem as described in ",(0,t.jsx)(n.a,{href:"https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems/",children:"systemd's API File Systems"}),"\ndocumentation."]})}),"\n",(0,t.jsx)(n.h3,{id:"unable-to-launch-enclaves-operation-not-permitted",children:"Unable to Launch Enclaves: Operation not permitted"}),"\n",(0,t.jsxs)(n.p,{children:["If running ",(0,t.jsx)(n.code,{children:"sgx-detect --verbose"})," reports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"\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"})}),"\n",(0,t.jsxs)(n.p,{children:["Ensure your system's ",(0,t.jsxs)(n.a,{href:"#ensure-dev-is-not-mounted-with-the-noexec-option",children:[(0,t.jsx)(n.code,{children:"/dev"})," is NOT mounted with the ",(0,t.jsx)(n.code,{children:"noexec"})," mount option"]}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"unable-to-launch-enclaves-invalid-argument",children:"Unable to Launch Enclaves: Invalid argument"}),"\n",(0,t.jsxs)(n.p,{children:["If running ",(0,t.jsx)(n.code,{children:"sgx-detect --verbose"})," reports:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"\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"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"couldnt-find-the-platform-library",children:"Couldn't find the platform library"}),"\n",(0,t.jsx)(n.p,{children:"If AESMD service log reports:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"[read_persistent_data ../qe_logic.cpp:1084] Couldn't find the platform library. (null)\n[get_platform_quote_cert_data ../qe_logic.cpp:438] Couldn't load the platform library. (null)\n"})}),"\n",(0,t.jsxs)(n.p,{children:["It may be that the ",(0,t.jsx)(n.a,{href:"#configuring-the-quote-provider",children:"DCAP quote provider"})," is misconfigured or the configuration\nfile is not a valid JSON file but is malformed. Double-check that its\nconfiguration file (e.g. ",(0,t.jsx)(n.code,{children:"/etc/sgx_default_qcnl.conf"}),") is correct."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>l});var t=s(6540);const i={},o=t.createContext(i);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/71d6bec9.bebaaf63.js b/assets/js/71d6bec9.bebaaf63.js new file mode 100644 index 0000000000..3a3e70eb51 --- /dev/null +++ b/assets/js/71d6bec9.bebaaf63.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1894],{5381:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>c,default:()=>s,frontMatter:()=>a,metadata:()=>i,toc:()=>g});var d=n(4848),l=n(8453);const a={},c="Integrating BAND Oracle",i={id:"dapp/tools/band",title:"Integrating BAND Oracle",description:"This guide will explain how to query the Band Protocol reference data smart",source:"@site/docs/dapp/tools/band.md",sourceDirName:"dapp/tools",slug:"/dapp/tools/band",permalink:"/dapp/tools/band",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/tools/band.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Tools & Services",permalink:"/dapp/tools/"}},r={},g=[{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}];function o(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",...(0,l.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(t.h1,{id:"integrating-band-oracle",children:"Integrating BAND Oracle"}),"\n",(0,d.jsx)("p",{style:{width:"100%"},children:(0,d.jsx)("iframe",{style:{margin:"auto",display:"block"},width:"560",height:"315",src:"https://www.youtube.com/embed/cwe6P5MvIfk?si=4QFRA8yJ2PCZB5fq",title:"YouTube video player",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:!0})}),"\n",(0,d.jsxs)(t.p,{children:["This guide will explain how to query the Band Protocol reference data smart\ncontract from another Solidity smart contract on Oasis Sapphire, a confidential\nEVM-compatible ",(0,d.jsx)(t.a,{href:"/general/oasis-network/faq#how-is-a-paratime-different-from-a-parachain",children:"Paratime"}),"."]}),"\n",(0,d.jsx)(t.admonition,{type:"tip",children:(0,d.jsxs)(t.p,{children:["You can follow the same steps to integrate with Band on Oasis ",(0,d.jsx)(t.a,{href:"/dapp/emerald",children:"Emerald"}),"\n, a non-confidential EVM. See Band ",(0,d.jsx)(t.a,{href:"https://docs.bandchain.org/develop/supported-blockchains",children:"documentation"}),"\nfor full list of deployed contract addresses."]})}),"\n",(0,d.jsx)(t.h3,{id:"what-is-the-band-protocol",children:"What is the Band Protocol?"}),"\n",(0,d.jsxs)(t.p,{children:[(0,d.jsx)(t.a,{href:"https://bandprotocol.com",children:"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 details of the protocol\n",(0,d.jsx)(t.a,{href:"https://docs.bandchain.org",children:"here"}),"."]}),"\n",(0,d.jsx)(t.h3,{id:"deploy-oracle",children:"Deploy Oracle"}),"\n",(0,d.jsxs)(t.ol,{children:["\n",(0,d.jsxs)(t.li,{children:["Follow ",(0,d.jsx)(t.a,{href:"https://remix.ethereum.org/?#code=cHJhZ21hIHNvbGlkaXR5IDAuNi4xMTsKcHJhZ21hIGV4cGVyaW1lbnRhbCBBQklFbmNvZGVyVjI7CgppbnRlcmZhY2UgSVN0ZFJlZmVyZW5jZSB7CiAgICAvLy8gQSBzdHJ1Y3R1cmUgcmV0dXJuZWQgd2hlbmV2ZXIgc29tZW9uZSByZXF1ZXN0cyBmb3Igc3RhbmRhcmQgcmVmZXJlbmNlIGRhdGEuCiAgICBzdHJ1Y3QgUmVmZXJlbmNlRGF0YSB7CiAgICAgICAgdWludDI1NiByYXRlOyAvLyBiYXNlL3F1b3RlIGV4Y2hhbmdlIHJhdGUsIG11bHRpcGxpZWQgYnkgMWUxOC4KICAgICAgICB1aW50MjU2IGxhc3RVcGRhdGVkQmFzZTsgLy8gVU5JWCBlcG9jaCBvZiB0aGUgbGFzdCB0aW1lIHdoZW4gYmFzZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICAgICAgdWludDI1NiBsYXN0VXBkYXRlZFF1b3RlOyAvLyBVTklYIGVwb2NoIG9mIHRoZSBsYXN0IHRpbWUgd2hlbiBxdW90ZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICB9CgogICAgLy8vIFJldHVybnMgdGhlIHByaWNlIGRhdGEgZm9yIHRoZSBnaXZlbiBiYXNlL3F1b3RlIHBhaXIuIFJldmVydCBpZiBub3QgYXZhaWxhYmxlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YShzdHJpbmcgbWVtb3J5IF9iYXNlLCBzdHJpbmcgbWVtb3J5IF9xdW90ZSkKICAgICAgICBleHRlcm5hbAogICAgICAgIHZpZXcKICAgICAgICByZXR1cm5zIChSZWZlcmVuY2VEYXRhIG1lbW9yeSk7CgogICAgLy8vIFNpbWlsYXIgdG8gZ2V0UmVmZXJlbmNlRGF0YSwgYnV0IHdpdGggbXVsdGlwbGUgYmFzZS9xdW90ZSBwYWlycyBhdCBvbmNlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoc3RyaW5nW10gbWVtb3J5IF9iYXNlcywgc3RyaW5nW10gbWVtb3J5IF9xdW90ZXMpCiAgICAgICAgZXh0ZXJuYWwKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAoUmVmZXJlbmNlRGF0YVtdIG1lbW9yeSk7Cn0KCmNvbnRyYWN0IERlbW9PcmFjbGUgewogICAgSVN0ZFJlZmVyZW5jZSByZWY7CgogICAgdWludDI1NiBwdWJsaWMgcHJpY2U7CgogICAgY29uc3RydWN0b3IoSVN0ZFJlZmVyZW5jZSBfcmVmKSBwdWJsaWMgewogICAgICAgIHJlZiA9IF9yZWY7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UHJpY2UoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKCJXQlRDIiwiVVNEIik7CiAgICAgICAgcmV0dXJuIGRhdGEucmF0ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRNdWx0aVByaWNlcygpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludDI1NltdIG1lbW9yeSl7CiAgICAgICAgc3RyaW5nW10gbWVtb3J5IGJhc2VTeW1ib2xzID0gbmV3IHN0cmluZ1tdKDIpOwogICAgICAgIGJhc2VTeW1ib2xzWzBdID0gIldCVEMiOwogICAgICAgIGJhc2VTeW1ib2xzWzFdID0gIkVUSCI7CgogICAgICAgIHN0cmluZ1tdIG1lbW9yeSBxdW90ZVN5bWJvbHMgPSBuZXcgc3RyaW5nW10oMik7CiAgICAgICAgcXVvdGVTeW1ib2xzWzBdID0gIlVTRCI7CiAgICAgICAgcXVvdGVTeW1ib2xzWzFdID0gIlVTRCI7CiAgICAgICAgSVN0ZFJlZmVyZW5jZS5SZWZlcmVuY2VEYXRhW10gbWVtb3J5IGRhdGEgPSByZWYuZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoYmFzZVN5bWJvbHMscXVvdGVTeW1ib2xzKTsKCiAgICAgICAgdWludDI1NltdIG1lbW9yeSBwcmljZXMgPSBuZXcgdWludDI1NltdKDIpOwogICAgICAgIHByaWNlc1swXSA9IGRhdGFbMF0ucmF0ZTsKICAgICAgICBwcmljZXNbMV0gPSBkYXRhWzFdLnJhdGU7CgogICAgICAgIHJldHVybiBwcmljZXM7CiAgICB9CgogICAgZnVuY3Rpb24gc2F2ZVByaWNlKHN0cmluZyBtZW1vcnkgYmFzZSwgc3RyaW5nIG1lbW9yeSBxdW90ZSkgZXh0ZXJuYWwgewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKGJhc2UscXVvdGUpOwogICAgICAgIHByaWNlID0gZGF0YS5yYXRlOwogICAgfQp9Cg==",children:"this link"})," to Remix. The link contains an encoded\nexample ",(0,d.jsx)(t.code,{children:"DemoOracle.sol"})," contract."]}),"\n",(0,d.jsxs)(t.li,{children:["Compile the contract with compiler version ",(0,d.jsx)(t.code,{children:"0.6.11"}),"."]}),"\n",(0,d.jsxs)(t.li,{children:["Switch to the Deploy tab of Remix.","\n",(0,d.jsxs)(t.ol,{children:["\n",(0,d.jsx)(t.li,{children:'Select "Injected Web3" in the Environment dropdown in the top left to\nconnect Metamask.'}),"\n",(0,d.jsxs)(t.li,{children:["Make sure that Metamask is connected to the Sapphire Paratime\n(Testnet/Mainnet) network. You can read about adding a network to Metamask ",(0,d.jsx)(t.a,{href:"../../general/manage-tokens/#metamask",children:"here"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,d.jsx)(t.p,{children:(0,d.jsx)(t.img,{alt:"Setting up the environment in Remix",src:n(1078).A+"",width:"756",height:"558"})}),"\n",(0,d.jsxs)(t.ol,{start:"4",children:["\n",(0,d.jsxs)(t.li,{children:["Enter the Testnet Band reference data aggregator contract address\n(",(0,d.jsx)(t.code,{children:"0x61704EFB8b8120c03C210cAC5f5193BF8c80852a"}),") to the ",(0,d.jsx)(t.code,{children:"DemoOracle"})," constructor\nand deploy the contract. You can access the reference data aggregator contract\non the Sapphire Mainnet at ",(0,d.jsx)(t.code,{children:"0xDA7a001b254CD22e46d3eAB04d937489c93174C3"}),"."]}),"\n"]}),"\n",(0,d.jsx)(t.p,{children:(0,d.jsx)(t.img,{alt:"Deploying DemoOracle",src:n(766).A+"",width:"1314",height:"1439"})}),"\n",(0,d.jsx)(t.p,{children:"An interface to interact with the contract will appear in the bottom left\ncorner of Remix."}),"\n",(0,d.jsx)(t.h3,{id:"get-rates",children:"Get Rates"}),"\n",(0,d.jsxs)(t.p,{children:["Clicking the ",(0,d.jsx)(t.code,{children:"getPrice"})," button will return the current price of WBTC in USD.\nThis function calls ",(0,d.jsx)(t.code,{children:"getReferenceData(string memory _base, string memory _quote)"}),'\non the Band reference data contract, passing "WBTC" and "USD", indicating WBTC\nas the base and USD as the quote. The rate returned is base/quote multiplied by\n1e18.']}),"\n",(0,d.jsx)(t.p,{children:(0,d.jsx)(t.img,{alt:"Get Rates",src:n(4841).A+"",width:"1690",height:"1234"})}),"\n",(0,d.jsxs)(t.p,{children:["Note that the ",(0,d.jsx)(t.code,{children:"DemoOracle"})," contract only returns the latest rate, but the\nreference contract also returns values of the last time the base and quote\nreferences were updated."]}),"\n",(0,d.jsxs)(t.p,{children:["The price is offset by 1e18. The returned value at the time of testing is\n",(0,d.jsx)(t.code,{children:"39567000000000000000000"}),". Multiplying by 1e-18 gives the current USD price\ngiven by the reference contract, 39567.00 WBTC/USD."]}),"\n",(0,d.jsxs)(t.p,{children:["Clicking the ",(0,d.jsx)(t.code,{children:"getMultiPrices"})," button returns multiple quotes in the same call,\nWBTC/USD and ETH/USD in this case. This function calls\n",(0,d.jsx)(t.code,{children:"getReferenceDataBulk(string[] memory _bases, string[] memory _quotes)"}),' on the\nBand reference data contract, passing "WBTC" and "ETH" as the base and "USD"\nfor the quote. This will return the current WBTC and ETH prices in USD, as an\narray of integers. The call also returns just the exchange rates (multipilied\nby 1e18), but can be modified to return the last updated times for the bases\nand quotes.']}),"\n",(0,d.jsxs)(t.p,{children:["The ",(0,d.jsx)(t.code,{children:"savePrice"})," function will save any base/quote rate that is passed to it in\nthe storage variable named ",(0,d.jsx)(t.code,{children:"price"}),". This storage data will only be updated when\nthe \u201csavePrice\u201d function is called, so the saved ",(0,d.jsx)(t.code,{children:"price"})," value will go stale\nunless this function is called repeatedly."]}),"\n",(0,d.jsx)(t.p,{children:(0,d.jsx)(t.img,{alt:"Save Price",src:n(6211).A+"",width:"343",height:"447"})}),"\n",(0,d.jsx)(t.h3,{id:"mainnet-reference-data-contract",children:"Mainnet Reference Data Contract"}),"\n",(0,d.jsxs)(t.p,{children:["You can access the reference data aggregator contract on the Sapphire Mainnet\nat ",(0,d.jsx)(t.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xDA7a001b254CD22e46d3eAB04d937489c93174C3",children:"0xDA7a001b254CD22e46d3eAB04d937489c93174C3"}),"."]}),"\n",(0,d.jsx)(t.h3,{id:"available-reference-data",children:"Available Reference Data"}),"\n",(0,d.jsxs)(t.p,{children:["You can view the available reference data on the ",(0,d.jsx)(t.a,{href:"https://data.bandprotocol.com/",children:"Band Standard Dataset site here"}),"."]}),"\n",(0,d.jsx)(t.h3,{id:"example-of-demooraclesol-contract",children:"Example of DemoOracle.sol contract"}),"\n",(0,d.jsx)(t.p,{children:(0,d.jsx)(t.a,{href:"https://remix.ethereum.org/?#code=cHJhZ21hIHNvbGlkaXR5IDAuNi4xMTsKcHJhZ21hIGV4cGVyaW1lbnRhbCBBQklFbmNvZGVyVjI7CgppbnRlcmZhY2UgSVN0ZFJlZmVyZW5jZSB7CiAgICAvLy8gQSBzdHJ1Y3R1cmUgcmV0dXJuZWQgd2hlbmV2ZXIgc29tZW9uZSByZXF1ZXN0cyBmb3Igc3RhbmRhcmQgcmVmZXJlbmNlIGRhdGEuCiAgICBzdHJ1Y3QgUmVmZXJlbmNlRGF0YSB7CiAgICAgICAgdWludDI1NiByYXRlOyAvLyBiYXNlL3F1b3RlIGV4Y2hhbmdlIHJhdGUsIG11bHRpcGxpZWQgYnkgMWUxOC4KICAgICAgICB1aW50MjU2IGxhc3RVcGRhdGVkQmFzZTsgLy8gVU5JWCBlcG9jaCBvZiB0aGUgbGFzdCB0aW1lIHdoZW4gYmFzZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICAgICAgdWludDI1NiBsYXN0VXBkYXRlZFF1b3RlOyAvLyBVTklYIGVwb2NoIG9mIHRoZSBsYXN0IHRpbWUgd2hlbiBxdW90ZSBwcmljZSBnZXRzIHVwZGF0ZWQuCiAgICB9CgogICAgLy8vIFJldHVybnMgdGhlIHByaWNlIGRhdGEgZm9yIHRoZSBnaXZlbiBiYXNlL3F1b3RlIHBhaXIuIFJldmVydCBpZiBub3QgYXZhaWxhYmxlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YShzdHJpbmcgbWVtb3J5IF9iYXNlLCBzdHJpbmcgbWVtb3J5IF9xdW90ZSkKICAgICAgICBleHRlcm5hbAogICAgICAgIHZpZXcKICAgICAgICByZXR1cm5zIChSZWZlcmVuY2VEYXRhIG1lbW9yeSk7CgogICAgLy8vIFNpbWlsYXIgdG8gZ2V0UmVmZXJlbmNlRGF0YSwgYnV0IHdpdGggbXVsdGlwbGUgYmFzZS9xdW90ZSBwYWlycyBhdCBvbmNlLgogICAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoc3RyaW5nW10gbWVtb3J5IF9iYXNlcywgc3RyaW5nW10gbWVtb3J5IF9xdW90ZXMpCiAgICAgICAgZXh0ZXJuYWwKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAoUmVmZXJlbmNlRGF0YVtdIG1lbW9yeSk7Cn0KCmNvbnRyYWN0IERlbW9PcmFjbGUgewogICAgSVN0ZFJlZmVyZW5jZSByZWY7CgogICAgdWludDI1NiBwdWJsaWMgcHJpY2U7CgogICAgY29uc3RydWN0b3IoSVN0ZFJlZmVyZW5jZSBfcmVmKSBwdWJsaWMgewogICAgICAgIHJlZiA9IF9yZWY7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UHJpY2UoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKCJXQlRDIiwiVVNEIik7CiAgICAgICAgcmV0dXJuIGRhdGEucmF0ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRNdWx0aVByaWNlcygpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludDI1NltdIG1lbW9yeSl7CiAgICAgICAgc3RyaW5nW10gbWVtb3J5IGJhc2VTeW1ib2xzID0gbmV3IHN0cmluZ1tdKDIpOwogICAgICAgIGJhc2VTeW1ib2xzWzBdID0gIldCVEMiOwogICAgICAgIGJhc2VTeW1ib2xzWzFdID0gIkVUSCI7CgogICAgICAgIHN0cmluZ1tdIG1lbW9yeSBxdW90ZVN5bWJvbHMgPSBuZXcgc3RyaW5nW10oMik7CiAgICAgICAgcXVvdGVTeW1ib2xzWzBdID0gIlVTRCI7CiAgICAgICAgcXVvdGVTeW1ib2xzWzFdID0gIlVTRCI7CiAgICAgICAgSVN0ZFJlZmVyZW5jZS5SZWZlcmVuY2VEYXRhW10gbWVtb3J5IGRhdGEgPSByZWYuZ2V0UmVmZXJlbmNlRGF0YUJ1bGsoYmFzZVN5bWJvbHMscXVvdGVTeW1ib2xzKTsKCiAgICAgICAgdWludDI1NltdIG1lbW9yeSBwcmljZXMgPSBuZXcgdWludDI1NltdKDIpOwogICAgICAgIHByaWNlc1swXSA9IGRhdGFbMF0ucmF0ZTsKICAgICAgICBwcmljZXNbMV0gPSBkYXRhWzFdLnJhdGU7CgogICAgICAgIHJldHVybiBwcmljZXM7CiAgICB9CgogICAgZnVuY3Rpb24gc2F2ZVByaWNlKHN0cmluZyBtZW1vcnkgYmFzZSwgc3RyaW5nIG1lbW9yeSBxdW90ZSkgZXh0ZXJuYWwgewogICAgICAgIElTdGRSZWZlcmVuY2UuUmVmZXJlbmNlRGF0YSBtZW1vcnkgZGF0YSA9IHJlZi5nZXRSZWZlcmVuY2VEYXRhKGJhc2UscXVvdGUpOwogICAgICAgIHByaWNlID0gZGF0YS5yYXRlOwogICAgfQp9Cg==",children:"DemoOracle.sol contract example in Remix"})}),"\n",(0,d.jsx)(t.h3,{id:"bandchain",children:"Bandchain.js"}),"\n",(0,d.jsxs)(t.p,{children:["Band also has a JavaScript library that makes it easy to interact with BandChain\ndirectly from JavaScript or TypeScript applications. The library provides\nclasses and methods for convenient to send transactions, query data,\nOBI encoding, and wallet management. You can read more about it ",(0,d.jsx)(t.a,{href:"https://docs.bandchain.org/develop/developer-tools/bandchain.js/getting-started",children:"here"}),"."]})]})}function s(e={}){const{wrapper:t}={...(0,l.R)(),...e.components};return t?(0,d.jsx)(t,{...e,children:(0,d.jsx)(o,{...e})}):o(e)}},1078:(e,t,n)=>{n.d(t,{A:()=>d});const d=n.p+"assets/images/band_demooracle_smartcontract-33de5c1550770b2f65357831fc13c6e1.png"},766:(e,t,n)=>{n.d(t,{A:()=>d});const d=n.p+"assets/images/band_deploy_demooracle_smartcontact-bcfd8510f590412a0eb3af8025b8a9dc.png"},4841:(e,t,n)=>{n.d(t,{A:()=>d});const d=n.p+"assets/images/band_get_rates-1172d264b2dcff4f0841da0e3f8a9d53.png"},6211:(e,t,n)=>{n.d(t,{A:()=>d});const d="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"},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>i});var d=n(6540);const l={},a=d.createContext(l);function c(e){const t=d.useContext(a);return d.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:c(e.components),d.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/72e396cc.6d65511b.js b/assets/js/72e396cc.6d65511b.js new file mode 100644 index 0000000000..e9b4da7560 --- /dev/null +++ b/assets/js/72e396cc.6d65511b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9743],{5700:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var i=s(4848),o=s(8453);const t={},r="Sentry Node",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/sentry-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"IAS Proxy",permalink:"/node/run-your-node/ias-proxy"},next:{title:"Maintenance",permalink:"/node/run-your-node/maintenance"}},a={},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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"sentry-node",children:"Sentry Node"}),"\n",(0,i.jsx)(n.p,{children:"This guide provides instructions for a deployment using the Sentry node architecture to protect validator nodes from being directly exposed on the public network."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://forum.cosmos.network/t/sentry-node-architecture-overview/454",children:"Tendermint's Sentry Node architecture"})," is assumed as well."]}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsxs)(n.p,{children:["Before following this guide, make sure you've read the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Prerequisites"})," and ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"Running a Node on the Network"})," guides and created your Entity."]}),"\n",(0,i.jsx)(n.h2,{id:"configuring-the-oasis-sentry-node",children:"Configuring the Oasis Sentry Node"}),"\n",(0,i.jsx)(n.h3,{id:"initializing-sentry-node",children:"Initializing Sentry Node"}),"\n",(0,i.jsx)(n.p,{children:"Sentry node identity keys can be initialized with:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node identity init --datadir /node/data\n"})}),"\n",(0,i.jsx)(n.h3,{id:"configuring-sentry-node",children:"Configuring Sentry Node"}),"\n",(0,i.jsxs)(n.p,{children:["An Oasis node can be configured to run as a sentry node by setting the ",(0,i.jsx)(n.code,{children:"worker.sentry.enabled"})," flag. The ",(0,i.jsx)(n.code,{children:"tendermint.sentry.upstream_address"})," flag can be used to configure a list of nodes that will be protected by the sentry node."]}),"\n",(0,i.jsxs)(n.p,{children:["An example of full ",(0,i.jsx)(n.code,{children:"YAML"})," configuration of a sentry node is below."]}),"\n",(0,i.jsx)(n.p,{children:"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ external_address }}"}),": This is the external IP on which sentry node will be reachable."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ seed_node_address }}"}),": This the seed node address of the form ",(0,i.jsx)(n.code,{children:"ID@IP:port"}),". You can find the current Oasis Seed Node address in the Network Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ 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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node identity tendermint show-node-address --datadir /node/data\n"})}),"\n",(0,i.jsx)(n.p,{children:"on the validator node."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ validator_private_address }}"}),": This is the (presumably) private address on which validator should be reachable from the sentry node."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ 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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:" oasis-node identity show-sentry-client-pubkey --datadir /node/data\n"})}),"\n",(0,i.jsxs)(n.p,{children:["on the validator node. Note that the above command is only available in ",(0,i.jsx)(n.code,{children:"oasis-node"})," from version 20.8.1 onward."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'mode: client\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: warn\n cometbft/context: error\n # Per-module log levels. Longest prefix match will be taken. Fallback to\n # "default", if no match.\n default: debug\n # By default logs are output to stdout. If you\'re running this in docker \n # keep the default\n #file: /var/log/oasis-node.log\nconsensus:\n external_address: tcp://{{ external_address }}:26656\n listen_address: tcp://0.0.0.0:26656\n sentry_upstream_addresses:\n - {{ validator_tendermint_id }}@{{ validator_private_address }}:26656\ngenesis:\n # Path to the genesis file for the current version of the network.\n file: /node/etc/genesis.json\np2p:\n seeds:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n - {{ seed_node_address }}\nsentry:\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 authorized_pubkeys:\n - {{ validator_sentry_client_grpc_public_key }}\n port: 9009\n enabled: true\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Multiple sentry nodes can be provisioned following the above steps."})}),"\n",(0,i.jsx)(n.h2,{id:"configuring-the-oasis-validator-node",children:"Configuring the Oasis Validator Node"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"initializing-validator-node",children:"Initializing Validator Node"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsxs)(n.p,{children:["When you are ",(0,i.jsx)(n.a,{href:"/node/run-your-node/validator-node#configuration",children:"initializing a validator node"}),", you should use the sentry node's external address and Consensus ID in the ",(0,i.jsx)(n.code,{children:"node.consensus_address"})," flag. If you are running multiple sentry nodes, you can specify the ",(0,i.jsx)(n.code,{children:"node.consensus_address"})," flag multiple times."]}),"\n",(0,i.jsxs)(n.p,{children:["To initialize a validator node with 2 sentry nodes, run the following commands from the ",(0,i.jsx)(n.code,{children:"/localhostdir/node"})," directory:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"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"})}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"SENTRY_CONSENSUS_ID"}),": This is the Consensus ID of the sentry node in base64 format. This ID can be obtained from ",(0,i.jsx)(n.code,{children:"consensus_pub.pem"}),":"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sed -n 2p /node/data/consensus_pub.pem\n"})}),(0,i.jsx)(n.p,{children:"on the sentry node."})]}),"\n",(0,i.jsx)(n.h3,{id:"configuring-the-validator-node",children:"Configuring the Validator Node"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["Since the validator node will not have an external address, the ",(0,i.jsx)(n.code,{children:"consensus.tendermint.core.external_address"})," flag should be skipped. Similarly, the ",(0,i.jsx)(n.code,{children:"consensus.tendermint.p2p.seed"})," flag can be skipped, as the ",(0,i.jsx)(n.code,{children:"oasis-node"})," won't be directly connecting to any of the seed nodes."]}),"\n",(0,i.jsxs)(n.p,{children:["Tendermint Peer Exchange should be disabled on the validator with the ",(0,i.jsx)(n.code,{children:"consensus.tendermint.p2p.disable_peer_exchange"})," flag."]}),"\n",(0,i.jsxs)(n.p,{children:["Sentry nodes can also be configured as Tendermint Persistent-Peers with the ",(0,i.jsx)(n.code,{children:"consensus.tendermint.p2p.persistent_peer"})," flag."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"worker.sentry.address"})," flag."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"worker.sentry.address"})," flag is of format: ",(0,i.jsx)(n.code,{children:"<pubkey>@ip:port"})," where:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"<pubkey>"}),": Is the sentry node's TLS public key."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"ip:port"}),": Is the (private) address of the sentry node's control endpoint."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Putting it all together, an example configuration of a validator node in the sentry node architecture is given below."}),"\n",(0,i.jsxs)(n.p,{children:["Before using this configuration you should collect the following information to replace the ",(0,i.jsx)(n.code,{children:"{{ var_name }}"})," variables present in the configuration file:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ sentry_node_private_ip }}"}),": This is the private IP address of the sentry node over which sentry node should be accessible to the validator."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ sentry_node_grpc_public_key }}"}),": This is the sentry node's control endpoint TLS public key. This ID can be obtained by running:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:" oasis-node identity show-tls-pubkey --datadir /node/data\n"})}),"\n",(0,i.jsxs)(n.p,{children:["on the sentry node. Note that the above command is only available in ",(0,i.jsx)(n.code,{children:"oasis-node"})," from version 20.8.1 onward."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ 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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node identity tendermint show-node-address --datadir /node/data\n"})}),"\n",(0,i.jsx)(n.p,{children:"on the sentry node."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'mode: validator\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: warn\n cometbft/context: error\n # Per-module log levels. Longest prefix match will be taken.\n # Fallback to "default", if no match.\n default: debug\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\nconsensus:\n listen_address: tcp://0.0.0.0:26656\n p2p:\n disable_peer_exchange: true\n persistent_peers:\n - {{ sentry_node_tendermint_id }}@{{ sentry_node_private_ip }}:26656\n\ngenesis:\n # Path to the genesis file for the current version of the network.\n file: /node/etc/genesis.json\n\nregistration:\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\nsentry:\n address:\n - {{ sentry_node_grpc_public_key }}@{{ sentry_node_private_ip }}:9009\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["Make sure the ",(0,i.jsx)(n.code,{children:"consensus"})," port (default: ",(0,i.jsx)(n.code,{children:"26656"}),") and ",(0,i.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,i.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,i.jsx)(n.code,{children:"TCP"})," and ",(0,i.jsx)(n.code,{children:"UDP"})," traffic)."]})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>d});var i=s(6540);const o={},t=i.createContext(o);function r(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/72efe815.dd30683c.js b/assets/js/72efe815.dd30683c.js new file mode 100644 index 0000000000..694a220046 --- /dev/null +++ b/assets/js/72efe815.dd30683c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5028],{7004:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var o=i(4848),r=i(8453);const t={},s="IAS Proxy",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/ias-proxy.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},d={},l=[{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></a>",id:"share-ias-proxy-address-",level:3}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"ias-proxy",children:"IAS Proxy"}),"\n",(0,o.jsxs)(n.p,{children:["This guide will cover setting up an ",(0,o.jsx)(n.a,{href:"https://software.intel.com/content/www/us/en/develop/download/intel-sgx-intel-epid-provisioning-and-attestation-services.html",children:"Intel Attestation Service (IAS)"}),"\nProxy node for the Oasis Network. This guide assumes some basic knowledge on the\nuse of command line tools."]}),"\n",(0,o.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,o.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the\n",(0,o.jsx)(n.a,{href:"prerequisites",children:"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.jsx)(n.a,{href:"/node/run-your-node/non-validator-node#configuration",children:"Run a Non-validator Node"}),"."]}),"\n",(0,o.jsx)(n.h3,{id:"obtaining-ias-service-provider-id-spid-and-api-key",children:"Obtaining IAS Service Provider ID (SPID) and API Key"}),"\n",(0,o.jsxs)(n.p,{children:["Running the ",(0,o.jsx)(n.a,{href:"https://software.intel.com/content/www/us/en/develop/download/intel-sgx-intel-epid-provisioning-and-attestation-services.html",children:"Intel Attestation Service (IAS)"}),"\nProxy requires access to the IAS API. Go to ",(0,o.jsx)(n.a,{href:"https://api.portal.trustedservices.intel.com/EPID-attestation",children:"IAS Enhanced Privacy ID (EPID) attestation"}),"\npage and signup for the ",(0,o.jsx)(n.em,{children:"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."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["Basic understanding of SGX Remote attestation is recommended. See Intel's\n",(0,o.jsx)(n.a,{href:"https://software.intel.com/content/www/us/en/develop/articles/code-sample-intel-software-guard-extensions-remote-attestation-end-to-end-example.html",children:"Remote Attestation End-to-End Example"}),"\nfor a short practical introduction."]})}),"\n",(0,o.jsx)(n.h3,{id:"creating-a-working-directory",children:"Creating a Working Directory"}),"\n",(0,o.jsxs)(n.p,{children:["We will be using the following working directory ",(0,o.jsx)(n.code,{children:"/node/ias"})," (feel free to name\nyour directory however you wish)."]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["The directory permissions should be ",(0,o.jsx)(n.code,{children:"rwx------"}),"."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"To create the directory, use the following command:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-text",children:"mkdir -m700 -p /node/ias\n"})}),"\n",(0,o.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,o.jsx)(n.p,{children:"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:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-text",children:'OASIS_IAS_SPID="<your-SPID>"\nOASIS_IAS_APIKEY="<your-API-key>"\n'})}),"\n",(0,o.jsxs)(n.p,{children:["In order to configure the IAS proxy create the ",(0,o.jsx)(n.code,{children:"/node/ias/config.yml"})," file with\nthe following content:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"common:\n data_dir: /node/ias\n log:\n format: JSON\n level:\n default: info\n"})}),"\n",(0,o.jsx)(n.h2,{id:"starting-the-ias-proxy",children:"Starting the IAS Proxy"}),"\n",(0,o.jsx)(n.p,{children:"You can start the IAS Proxy using the following command:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"oasis-node ias proxy \\\n --config /node/ias/config.yml \\\n --address unix:{{ oasis_node_socket }} \\\n --ias.production true \\\n --grpc.port 8650\n"})}),"\n",(0,o.jsx)(n.p,{children:"Before using this configuration you should collect the following information to\nreplace the variables present in the invocation command:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"{{ oasis_node_socket }}"}),": Path to a running client Oasis Node socket."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"ias-proxy-public-key",children:"IAS Proxy Public Key"}),"\n",(0,o.jsx)(n.p,{children:"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:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'{"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'})}),"\n",(0,o.jsxs)(n.p,{children:["The relevant item is the ",(0,o.jsx)(n.code,{children:"public_key"})," which in the above case is\n",(0,o.jsx)(n.code,{children:"tnTwXvGbbxqlFoirBDj63xWtZHS20Lb3fCURv0YDtYw="}),"."]}),"\n",(0,o.jsxs)(n.h3,{id:"share-ias-proxy-address-",children:["Share IAS Proxy address ",(0,o.jsx)("a",{id:"share-seed-node-address"})]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"ParaTime nodes"})," can now use your IAS Proxy by specifying it\nin configuration, e.g.:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:'ias:\n proxy:\n address:\n - "<IAS_PROXY_PUBLIC_KEY>@<EXTERNAL_IP>:8650"\n'})}),"\n",(0,o.jsx)(n.p,{children:"Note that you can list multiple IAS proxy addresses."})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>a});var o=i(6540);const r={},t=o.createContext(r);function s(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/72f44a45.57701f10.js b/assets/js/72f44a45.57701f10.js new file mode 100644 index 0000000000..636e0cbd7d --- /dev/null +++ b/assets/js/72f44a45.57701f10.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3902],{8700:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>h,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>r,toc:()=>c});var i=t(4848),s=t(8453);const a={},o="Frequently Asked Questions",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/faq.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Token Metrics and Distribution",permalink:"/general/oasis-network/token-metrics-and-distribution"},next:{title:"Manage your Tokens",permalink:"/general/manage-tokens/"}},h={},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}];function l(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"frequently-asked-questions",children:"Frequently Asked Questions"}),"\n",(0,i.jsx)(n.p,{children:"This page tries to answer some of the most frequently asked questions about the\nOasis Network."}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"This page will constantly be updated with new questions and responses."})}),"\n",(0,i.jsx)(n.h2,{id:"overview",children:(0,i.jsx)(n.strong,{children:"Overview"})}),"\n",(0,i.jsx)(n.h3,{id:"why-oasis",children:(0,i.jsx)(n.strong,{children:"Why Oasis?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"First to Enable Data Tokenization:"})," The Oasis Network can ",(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsx)(n.h3,{id:"is-the-oasis-protocol-foundation-still-taking-grant-applications-for-projects-that-are-building-new-dapps",children:(0,i.jsx)(n.strong,{children:"Is the Oasis Protocol Foundation still taking grant applications for projects that are building new dApps?"})}),"\n",(0,i.jsxs)(n.p,{children:["Yes! We are still taking grant applications. You can apply any time ",(0,i.jsx)(n.a,{href:"https://medium.com/oasis-protocol-project/oasis-foundation-grant-wishlist-3ad73b723d7",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"architecture",children:(0,i.jsx)(n.strong,{children:"Architecture"})}),"\n",(0,i.jsx)(n.h3,{id:"what-kind-of-blockchain-is-the-oasis-network-does-it-use-sidechains",children:(0,i.jsx)(n.strong,{children:"What kind of blockchain is the Oasis Network? Does it use sidechains?"})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://docsend.com/view/aq86q2pckrut2yvq",children:"platform whitepaper"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"what-does-the-oasis-networks-architecture-look-like",children:(0,i.jsx)(n.strong,{children:"What does the Oasis Network\u2019s architecture look like?"})}),"\n",(0,i.jsx)(n.p,{children:"The Oasis Network is a Layer 1, proof-of-stake, decentralized network. It has two main components, the consensus layer and the ParaTime layer."}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.strong,{children:"consensus layer"})," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."]}),"\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.strong,{children:"ParaTime layer"})," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Paratime Communication",src:t(3048).A+"",width:"1600",height:"940"})}),"\n",(0,i.jsx)(n.h3,{id:"how-is-a-paratime-different-from-a-parachain",children:(0,i.jsx)(n.strong,{children:"How is a ParaTime different from a Parachain?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"who-will-be-running-all-of-these-paratimes-can-anyone-run-a-paratime",children:(0,i.jsx)(n.strong,{children:"Who will be running all of these ParaTimes? Can anyone run a ParaTime?"})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://medium.com/oasis-protocol-project/ethereum-support-on-the-oasis-blockchain-3add9e13556?source=collection_home---4------0-----------------------",children:"Second State Virtual Machine"}),", an EVM compatible Runtime."]}),"\n",(0,i.jsx)(n.h3,{id:"what-consensus-mechanism-are-you-running-is-it-bft",children:(0,i.jsx)(n.strong,{children:"What consensus mechanism are you running? Is it BFT?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"why-doesnt-the-oasis-network-do-sharding-does-that-mean-its-slow",children:(0,i.jsx)(n.strong,{children:"Why doesn\u2019t the Oasis Network do sharding? Does that mean it\u2019s slow?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"how-does-storage-work-on-the-oasis-network-do-you-use-ipfs",children:(0,i.jsx)(n.strong,{children:"How does storage work on the Oasis Network? Do you use IPFS?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"open-finance--defi",children:(0,i.jsx)(n.strong,{children:"Open Finance & DeFi"})}),"\n",(0,i.jsx)(n.h3,{id:"does-the-oasis-network-have-a-vision-for-defi-is-it-different-from-the-mainstream-view-of-defi",children:(0,i.jsx)(n.strong,{children:"Does the Oasis Network have a vision for DeFi? Is it different from the mainstream view of DeFi?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"ive-seen-oasis-use-both-the-terms-open-finance-and-defi-whats-the-difference",children:(0,i.jsx)(n.strong,{children:"I\u2019ve seen Oasis use both the terms \u201cOpen Finance\u201d and \u201cDeFi\u201d? What\u2019s the difference?"})}),"\n",(0,i.jsx)(n.p,{children:"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**.**"}),"\n",(0,i.jsx)(n.h3,{id:"will-oasis-provide-oracle-solutions-for-use-in-defi-applications",children:(0,i.jsx)(n.strong,{children:"Will Oasis provide oracle solutions for use in DeFi applications?"})}),"\n",(0,i.jsxs)(n.p,{children:["Oasis recently announced a partnership with ",(0,i.jsx)(n.a,{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-----------------------",children:"Chainlink"})," as the preferred oracle provider of the Oasis Network. This integration is ongoing."]}),"\n",(0,i.jsx)(n.h3,{id:"what-aspects-of-defi-require-privacy-how-can-the-oasis-networks-focus-on-privacy-help-with-defi-applications",children:(0,i.jsx)(n.strong,{children:"What aspects of DeFi require privacy? How can the Oasis Network\u2019s focus on privacy help with DeFi applications?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"how-does-privacy-help-create-a-new-system-of-open-finance",children:(0,i.jsx)(n.strong,{children:"How does privacy help create a new system of Open Finance?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"why-would-anyone-choose-to-build-a-defi-project-on-oasis-over-ethereum",children:(0,i.jsx)(n.strong,{children:"Why would anyone choose to build a DeFi project on Oasis over Ethereum?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"token",children:(0,i.jsx)(n.strong,{children:"Token"})}),"\n",(0,i.jsx)(n.h3,{id:"how-will-the-oasis-networks-token-be-used-in-the-network-when-it-launches",children:(0,i.jsx)(n.strong,{children:"How will the Oasis Network\u2019s token be used in the network when it launches?"})}),"\n",(0,i.jsx)(n.p,{children:"The ROSE token will be used for transaction fees, staking, and delegation at the consensus layer."}),"\n",(0,i.jsx)(n.h2,{id:"privacy",children:(0,i.jsx)(n.strong,{children:"Privacy"})}),"\n",(0,i.jsx)(n.h3,{id:"how-does-the-oasis-network-achieve-privacy-and-confidentiality-is-it-through-homomorphic-encryption",children:(0,i.jsx)(n.strong,{children:"How does the Oasis Network achieve privacy and confidentiality? Is it through homomorphic encryption?"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"interoperability",children:(0,i.jsx)(n.strong,{children:"Interoperability"})}),"\n",(0,i.jsx)(n.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",children:(0,i.jsx)(n.strong,{children:"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?"})}),"\n",(0,i.jsx)(n.p,{children:"In short, yes! The Oasis Network supports EVM-compatible ParaTimes which will support a wide range of applications."})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},3048:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/consensus_paratime_communication-9e496f13908c8e30ad6e63e6da9f5fa3.png"},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>r});var i=t(6540);const s={},a=i.createContext(s);function o(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7327d54c.87942bc5.js b/assets/js/7327d54c.87942bc5.js new file mode 100644 index 0000000000..98fce211d3 --- /dev/null +++ b/assets/js/7327d54c.87942bc5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[622],{5330:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var t=n(4848),s=n(8453);const i={},r="Network Governance",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/network-governance.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"getInvolved",previous:{title:"Develop Oasis Core",permalink:"/get-involved/oasis-core"},next:{title:"Delegation Policy",permalink:"/get-involved/delegation-policy"}},c={},l=[{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}];function d(e){const o={a:"a",admonition:"admonition",h1:"h1",h3:"h3",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.h1,{id:"network-governance",children:"Network Governance"}),"\n",(0,t.jsxs)(o.admonition,{type:"info",children:[(0,t.jsxs)(o.p,{children:["If you have a general question on how to use and deploy our software, please\nread our ",(0,t.jsx)(o.a,{href:"/node/",children:"Run a Node"})," section or join our\n",(0,t.jsx)(o.a,{href:"/get-involved/",children:"community Discord"}),"."]}),(0,t.jsxs)(o.p,{children:["All community members are welcome and encouraged to commit code, documentation\nand enhancement proposals to the platform. Contribution guidelines can be found\n",(0,t.jsx)(o.a,{href:"/get-involved/oasis-core",children:"here"}),"."]})]}),"\n",(0,t.jsx)(o.h3,{id:"governance-model-overview",children:"Governance Model Overview"}),"\n",(0,t.jsx)(o.p,{children:"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."}),"\n",(0,t.jsx)(o.p,{children:"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:"}),"\n",(0,t.jsxs)(o.ol,{children:["\n",(0,t.jsx)(o.li,{children:"Minor Feature Requests"}),"\n",(0,t.jsx)(o.li,{children:"Major Feature Requests"}),"\n",(0,t.jsx)(o.li,{children:"Bug Fixes"}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"decision-making-process",children:"Decision Making Process"}),"\n",(0,t.jsx)(o.p,{children:"Moving forward, our proposed process for reviewing and approving major protocol\nupdates is:"}),"\n",(0,t.jsxs)(o.ul,{children:["\n",(0,t.jsxs)(o.li,{children:["\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.strong,{children:"Proposals."})," for features and roadmap updates can come from anyone in the\ncommunity in the form of issues\n(",(0,t.jsx)(o.a,{href:"/get-involved/network-governance#minor-feature-requests",children:"for minor features"}),") or\n",(0,t.jsx)(o.a,{href:"../../adrs",children:"Architectural Decision Records"})," (ADRs,\n",(0,t.jsx)(o.a,{href:"/get-involved/network-governance#major-feature-requests",children:"for major features"}),")."]}),"\n"]}),"\n",(0,t.jsxs)(o.li,{children:["\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.strong,{children:"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,t.jsx)(o.a,{href:"/get-involved/network-governance#minor-feature-requests",children:"for minor features"}),") and ADRs\n(",(0,t.jsx)(o.a,{href:"/get-involved/network-governance#major-feature-requests",children:"for major features"}),")."]}),"\n"]}),"\n",(0,t.jsxs)(o.li,{children:["\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.strong,{children:"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."]}),"\n",(0,t.jsx)(o.p,{children:"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."}),"\n",(0,t.jsxs)(o.p,{children:["In case consensus is not reached through discussion, the\n",(0,t.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/master/GOVERNANCE.md#committers",children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(o.li,{children:["\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.strong,{children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(o.li,{children:["\n",(0,t.jsxs)(o.p,{children:[(0,t.jsx)(o.strong,{children:"Upgrade."})," Node operators autonomously upgrade their system to run the new\nversion of the software."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"minor-feature-requests",children:"Minor Feature Requests"}),"\n",(0,t.jsx)(o.p,{children:"To request new functionality, there are two primary approaches that will be\nmost effective at receiving input and making progress."}),"\n",(0,t.jsxs)(o.p,{children:["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,t.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/new?template=feature_request.md",children:"propose it is as a new feature request"}),"\nin the Oasis Core repository."]}),"\n",(0,t.jsx)(o.h3,{id:"major-feature-requests",children:"Major Feature Requests"}),"\n",(0,t.jsxs)(o.p,{children:["If the feature is more complicated, involves protocol changes, or has potential\nsafety or performance implications, then consider\n",(0,t.jsx)(o.a,{href:"../../adrs",children:"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."]}),"\n",(0,t.jsx)(o.admonition,{type:"info",children:(0,t.jsx)(o.p,{children:"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."})}),"\n",(0,t.jsx)(o.h3,{id:"urgent-bug-fixes",children:"Urgent Bug Fixes"}),"\n",(0,t.jsx)(o.p,{children:"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."}),"\n",(0,t.jsx)(o.p,{children:"Bugs are a reality for any software project. We can't fix what we don't know\nabout!"}),"\n",(0,t.jsxs)(o.p,{children:["If you believe a bug report presents a security risk, please follow\n",(0,t.jsx)(o.a,{href:"https://en.wikipedia.org/wiki/Responsible_disclosure",children:"responsible disclosure"}),"\nand report it by following the\n",(0,t.jsx)(o.a,{href:"https://oasisprotocol.org/security",children:"security disclosure information"})," instead\nof filing a public issue or posting it to a public forum."]}),"\n",(0,t.jsx)(o.p,{children:"We will get back to you promptly."}),"\n",(0,t.jsxs)(o.p,{children:["Otherwise, please, first search between\n",(0,t.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/issues",children:"existing issues in our repository"}),"\nand if the issue is not reported yet,\n",(0,t.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/new?template=bug_report.md",children:"file a new one"}),"."]}),"\n",(0,t.jsx)(o.h3,{id:"contributing-to-the-network",children:"Contributing to the Network"}),"\n",(0,t.jsxs)(o.p,{children:["If you are interested in contributing to the Oasis Network's codebase or\ndocumentation, please\n",(0,t.jsx)(o.a,{href:"/get-involved/oasis-core",children:"review our contribution guidelines here."}),"."]})]})}function h(e={}){const{wrapper:o}={...(0,s.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>r,x:()=>a});var t=n(6540);const s={},i=t.createContext(s);function r(e){const o=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/736ce571.e13e5850.js b/assets/js/736ce571.e13e5850.js new file mode 100644 index 0000000000..f9130f5748 --- /dev/null +++ b/assets/js/736ce571.e13e5850.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[210],{9817:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var r=i(4848),s=i(8453);const t={},o="Hardware Requirements",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/hardware-recommendations.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Prerequisites",permalink:"/node/run-your-node/prerequisites"},next:{title:"Stake Requirements",permalink:"/node/run-your-node/prerequisites/stake-requirements"}},d={},c=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"hardware-requirements",children:"Hardware Requirements"}),"\n",(0,r.jsx)(n.p,{children:"The Oasis Network is composed of multiple classes of nodes and services such\nas:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Consensus validator or non-validator node"}),"\n",(0,r.jsx)(n.li,{children:"Sapphire ParaTime compute or client node"}),"\n",(0,r.jsx)(n.li,{children:"Emerald ParaTime compute or client node"}),"\n",(0,r.jsx)(n.li,{children:"Cipher ParaTime compute or client node"}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["Hardware requirements for running the Oasis Web3 gateway can be found\n",(0,r.jsx)(n.a,{href:"/node/web3#hardware",children:"here"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This page describes the ",(0,r.jsx)(n.strong,{children:"minimum"})," and ",(0,r.jsx)(n.strong,{children:"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."]}),"\n",(0,r.jsxs)(n.admonition,{type:"caution",children:[(0,r.jsx)(n.p,{children:"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.jsx)(n.p,{children:"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."})]}),"\n",(0,r.jsx)(n.h3,{id:"suggested-minimum-configurations",children:"CPU"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Consensus validator or non-validator node:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Minimum: 2.0 GHz x86-64 CPU with ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," support"]}),"\n",(0,r.jsxs)(n.li,{children:["Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs with\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," and ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2",children:"AVX2"})," support"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Emerald ParaTime compute node and all ParaTime client nodes:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Minimum: 2.0 GHz x86-64 CPU with ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," support"]}),"\n",(0,r.jsxs)(n.li,{children:["Recommended: 2.0 GHz x86-64 CPU with 4 cores/vCPUs with\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," and ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2",children:"AVX2"})," support"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Sapphire and Cipher ParaTime compute node:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Minimum: 2.0 GHz x86-64 CPU with ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," and ",(0,r.jsx)(n.a,{href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html",children:"Intel SGX"})," support"]}),"\n",(0,r.jsxs)(n.li,{children:["Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs with\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"}),", ",(0,r.jsx)(n.a,{href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html",children:"Intel SGX"})," and ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2",children:"AVX2"})," support"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.admonition,{type:"info",children:[(0,r.jsx)(n.p,{children:"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.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/AES_instruction_set",children:"AES instruction set"})," support is required by ",(0,r.jsx)(n.a,{href:"https://sites.google.com/view/deoxyscipher",children:"Deoxys-II-256-128"}),", a\nMisuse-Resistant Authenticated Encryption (MRAE) algorithm, which is used for\nencrypting ParaTime's state."]}),(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2",children:"Advanced Vector Extensions 2 (AVX2)"})," support enables faster Ed25519\nsignature verification which in turn makes a node sync faster."]}),(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.a,{href:"https://www.intel.com/content/www/us/en/architecture-and-technology/software-guard-extensions.html",children:"Intel SGX"})," support is required if you want to run Paratime compute nodes\nthat use a trusted execution environment (TEE)."]})]}),"\n",(0,r.jsx)(n.h3,{id:"memory",children:"Memory"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Consensus validator or non-validator node:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 6 GB of ECC RAM"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 8 GB of ECC RAM"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Each Emerald, Sapphire, Cipher compute or client node:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 12 GB of ECC RAM"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 20 GB of ECC RAM"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsx)(n.p,{children:"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..."})}),"\n",(0,r.jsx)(n.h3,{id:"storage",children:"Storage"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Consensus validator or non-validator node:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 400 GB of SSD or NVMe fast storage"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 700 GB of SSD or NVMe fast storage"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Emerald ParaTime compute or client node (in addition to the consensus storage requirements):"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 400 GB of SSD or NVMe fast storage"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 700 GB of SSD or NVMe fast storage"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"Sapphire and Cipher ParaTime compute or client node (in addition to the consensus storage requirements):"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 200 GB of SSD or NVMe fast storage"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 300 GB of SSD or NVMe fast storage"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsxs)(n.p,{children:["Consensus and ParaTime state is stored in an embedded ",(0,r.jsx)(n.a,{href:"https://dgraph.io/docs/badger/",children:"BadgerDB"})," database which\nwas ",(0,r.jsx)(n.a,{href:"https://dgraph.io/docs/badger/design/",children:"designed to run on SSDs"}),". Hence, we ",(0,r.jsx)(n.strong,{children:"strongly discourage"}),"\ntrying to run a node that stores data ",(0,r.jsx)(n.strong,{children:"on classical HDDs"}),"."]})}),"\n",(0,r.jsxs)(n.admonition,{type:"info",children:[(0,r.jsx)(n.p,{children:"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.jsx)(n.p,{children:"For example, a consensus non-validator node on the Mainnet accumulated:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["280 GB of consensus state in ~1 year between Apr 28, 2021 and Apr 11, 2022 (since the ",(0,r.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt upgrade"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["32 GB of consensus state in ~1 month since the ",(0,r.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/damask-upgrade",children:"Damask upgrade"})]}),"\n"]}),(0,r.jsx)(n.p,{children:"For example, an Emerald client node on the Mainnet additionally accumulated:"}),(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["260 GB of Emerald ParaTime state in ~5 months between Nov 18, 2021 and Apr 11, 2022 (since the ",(0,r.jsx)(n.a,{href:"https://medium.com/oasis-protocol-project/oasis-emerald-evm-paratime-is-live-on-mainnet-13afe953a4c9",children:"Emerald Mainnet launch"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:["25 GB of Emerald ParaTime state in ~1 month since the ",(0,r.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/damask-upgrade",children:"Damask upgrade"})]}),"\n"]})]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["Dump & restore upgrades (e.g. ",(0,r.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/damask-upgrade",children:"Damask upgrade"}),", ",(0,r.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt upgrade"}),") include state\nwipes which will free the node storage. Historical state can be accessed by\nrunning a separate archive node."]})}),"\n",(0,r.jsxs)(n.admonition,{type:"info",children:[(0,r.jsxs)(n.p,{children:["You can configure your node ",(0,r.jsx)(n.em,{children:"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.jsxs)(n.p,{children:["To enable pruning of the consensus state set the\n",(0,r.jsx)(n.code,{children:"consensus.prune.strategy"})," and\n",(0,r.jsx)(n.code,{children:"consensus.prune.num_kept"})," parameters appropriately in your\n",(0,r.jsx)(n.a,{href:"/node/run-your-node/validator-node#configuration",children:"node's configuration"}),"."]}),(0,r.jsxs)(n.p,{children:["To enable pruning of the ParaTime state set the\n",(0,r.jsx)(n.code,{children:"runtime.prune.strategy"})," and ",(0,r.jsx)(n.code,{children:"runtime.prune.num_kept"}),"\nparameters appropriately in your ",(0,r.jsx)(n.a,{href:"/node/run-your-node/validator-node#configuration",children:"node's configuration"}),"."]})]}),"\n",(0,r.jsx)(n.h3,{id:"network",children:"Network"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Consensus validator node and all ParaTime compute nodes:","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Minimum: 200 Mbps internet connection with low latency"}),"\n",(0,r.jsx)(n.li,{children:"Recommended: 1 Gbps internet connection with low latency"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsx)(n.p,{children:"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."})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>a});var r=i(6540);const s={},t=r.createContext(s);function o(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/74cc02ce.bcf65a71.js b/assets/js/74cc02ce.bcf65a71.js new file mode 100644 index 0000000000..d9c8c6f915 --- /dev/null +++ b/assets/js/74cc02ce.bcf65a71.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6350],{7725:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var r=n(4848),s=n(8453),o=n(2550),i=n(6116);const a={},c="Use Oasis",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",next:{title:"Oasis Network",permalink:"/general/oasis-network/"}},d={},u=[];function m(e){const t={h1:"h1",p:"p",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"use-oasis",children:"Use Oasis"}),"\n",(0,r.jsx)(t.p,{children:"This chapter provides general overview of the Oasis Network and introduces\nbasic tools for you to get started."}),"\n",(0,r.jsx)(o.A,{items:[(0,i.$)("/general/oasis-network/"),(0,i.$)("/general/manage-tokens/"),(0,i.$)("/general/manage-tokens/cli/")]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(m,{...e})}):m(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var r=n(4164),s=n(8774),o=n(4142),i=n(5846),a=n(6654),c=n(1312),l=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=n(4848);function m(e){let{href:t,children:n}=e;return(0,u.jsx)(s.A,{href:t,className:(0,r.A)("card padding--lg",d.cardContainer),children:n})}function h(e){let{href:t,icon:n,title:s,description:o}=e;return(0,u.jsxs)(m,{href:t,children:[(0,u.jsxs)(l.A,{as:"h2",className:(0,r.A)("text--truncate",d.cardTitle),title:s,children:[n," ",s]}),o&&(0,u.jsx)("p",{className:(0,r.A)("text--truncate",d.cardDescription),title:o,children:o})]})}function p(e){let{item:t}=e;const n=(0,o.Nr)(t),r=function(){const{selectMessage:e}=(0,i.W)();return t=>e(t,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,u.jsx)(h,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??r(t.items.length)}):null}function f(e){let{item:t}=e;const n=(0,a.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,o.cC)(t.docId??void 0);return(0,u.jsx)(h,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,u.jsx)(f,{item:t});case"category":return(0,u.jsx)(p,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,n)=>{n.d(t,{A:()=>c});n(6540);var r=n(4164),s=n(4142),o=n(5965),i=n(4848);function a(e){let{className:t}=e;const n=(0,s.$S)();return(0,i.jsx)(c,{items:n.items,className:t})}function c(e){const{items:t,className:n}=e;if(!t)return(0,i.jsx)(a,{...e});const c=(0,s.d1)(t);return(0,i.jsx)("section",{className:(0,r.A)("row",n),children:c.map(((e,t)=>(0,i.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,i.jsx)(o.A,{item:e})},t)))})}},5846:(e,t,n)=>{n.d(t,{W:()=>l});var r=n(6540),s=n(4586);const o=["zero","one","two","few","many","other"];function i(e){return o.filter((t=>e.includes(t)))}const a={locale:"en",pluralForms:i(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,r.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:i(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`),a}}),[e])}function l(){const e=c();return{selectMessage:(t,n)=>function(e,t,n){const r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const s=n.select(t),o=n.pluralForms.indexOf(s);return r[Math.min(o,r.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>o});var r=n(2252);function s(e){for(const t of e){const e=t.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=t),"category"===t.type&&s(t.items)}}function o(e){const t=(0,r.r)();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)s(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]}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>a});var r=n(6540);const s={},o=r.createContext(s);function i(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/767aa429.5de976b1.js b/assets/js/767aa429.5de976b1.js new file mode 100644 index 0000000000..89a842b291 --- /dev/null +++ b/assets/js/767aa429.5de976b1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[472],{7978:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>t,metadata:()=>i,toc:()=>o});var a=s(4848),r=s(8453);const t={title:"Wallet",description:"Manage accounts in your CLI wallet"},l="Managing Accounts in Your Wallet",i={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/wallet.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,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"}},c={},o=[{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:"Import an Existing Keypair from PEM file",id:"import-file",level:3},{value:"Remote Signer for <code>oasis-node</code>",id:"remote-signer",level:3},{value:"Test Accounts",id:"test-accounts",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"managing-accounts-in-your-wallet",children:"Managing Accounts in Your Wallet"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.p,{children:"The following encryption algorithms and derivation paths are supported by the\nOasis CLI for your accounts:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"ed25519-adr8"}),": ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/EdDSA",children:"Ed25519"})," keypair using the ",(0,a.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"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."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"secp256k1-bip44"}),": ",(0,a.jsx)(n.a,{href:"https://en.bitcoin.it/wiki/Secp256k1",children:"Secp256k1"})," Ethereum-compatible keypair using ",(0,a.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki",children:"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."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"ed25519-raw"}),": ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/EdDSA",children:"Ed25519"})," keypair imported directly from the Base64-encoded\nprivate key. No key derivation is involved. This setting is primarily used by\nthe network validators to sign the governance and other consensus-layer\ntransactions."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"ed25519-legacy"}),": ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/EdDSA",children:"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,a.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8"})," was standardized."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"sr25519-adr8"}),": ",(0,a.jsx)(n.a,{href:"https://wiki.polkadot.network/docs/learn-cryptography",children:"Sr25519"})," keypair using the ",(0,a.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8"})," derivation path. This is\nan alternative signature scheme for signing ParaTime transactions."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"secp256k1-raw"})," and ",(0,a.jsx)(n.code,{children:"sr25519-raw"}),": Respective Secp256k1 and Sr25519 keypairs\nimported directly from the Hex- or Base64-encoded private key. No key\nderivation is involved."]}),"\n"]}),"\n",(0,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsxs)(n.p,{children:["For compatibility with Ethereum, each ",(0,a.jsx)(n.code,{children:"secp256k1"})," account corresponds to two\naddresses:"]}),(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["20-byte hex-encoded Ethereum-compatible address, e.g.\n",(0,a.jsx)(n.code,{children:"0xDCbF59bbcC0B297F1729adB23d7a5D721B481BA9"})]}),"\n",(0,a.jsxs)(n.li,{children:["Bech32-encoded Oasis native address, e.g.\n",(0,a.jsx)(n.code,{children:"oasis1qq3agel5x07pxz08ns3d2y7sjrr3xf9paquhhhzl"}),"."]}),"\n"]}),(0,a.jsxs)(n.p,{children:["There exists a ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/types/address.go#L135-L142",children:"mapping"})," from the Ethereum address\nto the native Oasis address as in the example above, but ",(0,a.jsx)(n.strong,{children:"there is no reverse\nmapping"}),"."]})]}),"\n",(0,a.jsx)(n.h2,{id:"create",children:"Create an Account"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"wallet create <name>"})," command is used add a new account into your Oasis\nCLI wallet by:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"generating a new mnemonic and storing it into a file-based wallet, or"}),"\n",(0,a.jsx)(n.li,{children:"creating a reference to an account stored on your hardware wallet."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet create oscar\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"? Choose a new passphrase:\n? Repeat passphrase:\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["The first account you create or import will become your ",(0,a.jsx)(n.strong,{children:"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,a.jsx)(n.code,{children:"--account <name>"}),"\nflag. You can always ",(0,a.jsx)(n.a,{href:"#set-default",children:"change the default account"})," later."]})}),"\n",(0,a.jsxs)(n.p,{children:["To use your hardware wallet, add ",(0,a.jsx)(n.code,{children:"--kind ledger"})," parameter and Oasis CLI will\nstore a reference to an account on your hardware wallet:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet create logan --kind ledger\n"})}),"\n",(0,a.jsxs)(n.p,{children:["A specific account kind (",(0,a.jsx)(n.code,{children:"ed25519-adr8"}),", ",(0,a.jsx)(n.code,{children:"secp256k1-bip44"}),") and the derivation\npath number can be passed with ",(0,a.jsx)(n.code,{children:"--file.algorithm"})," and ",(0,a.jsx)(n.code,{children:"--file.number"})," or\n",(0,a.jsx)(n.code,{children:"--ledger.algorithm"})," and ",(0,a.jsx)(n.code,{children:"--ledger.number"})," respectively. For example:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet create logan --kind ledger\n"})}),"\n",(0,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsx)(n.p,{children:"When creating a hardware wallet account, Oasis CLI will:"}),(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"obtain the public key of the account from your hardware wallet,"}),"\n",(0,a.jsx)(n.li,{children:"compute the corresponding native address, and"}),"\n",(0,a.jsx)(n.li,{children:"store the Oasis native address into the Oasis CLI."}),"\n"]}),(0,a.jsx)(n.p,{children:"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,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet show logan\n"})}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Error: address mismatch after loading account (expected: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl got: oasis1qzdyu09x7hs5nqa0sjgy5jtmz3j5f99ccq0aezjk)\n"})})]}),"\n",(0,a.jsx)(n.h2,{id:"import",children:"Import an Existing Keypair or a Mnemonic"}),"\n",(0,a.jsxs)(n.p,{children:["If you already have a mnemonic or a raw private key, you can import it\nas a new account by invoking ",(0,a.jsx)(n.code,{children:"wallet import"}),". You will be asked\ninteractively to select an account kind (",(0,a.jsx)(n.code,{children:"mnemonic"})," or ",(0,a.jsx)(n.code,{children:"private key"}),"),\nencryption algorithm (",(0,a.jsx)(n.code,{children:"ed25519"})," or ",(0,a.jsx)(n.code,{children:"secp256k1"}),") and then provide either the\nmnemonic with the derivation number, or the raw private key in the corresponding\nformat."]}),"\n",(0,a.jsx)(n.p,{children:"Importing an account with a mnemonic looks like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet import eugene\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"? 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"})}),"\n",(0,a.jsx)(n.p,{children:"Let's make another Secp256k1 account and entering a hex-encoded raw private key:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet import emma\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.h2,{id:"list",children:"List Accounts Stored in Your Wallet"}),"\n",(0,a.jsxs)(n.p,{children:["You can list all available accounts in your wallet with ",(0,a.jsx)(n.code,{children:"wallet list"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlenny \tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar (*)\tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Above, you can see the native Oasis addresses of all local accounts. The\n",(0,a.jsx)(n.a,{href:"#set-default",children:"default account"})," has a special ",(0,a.jsx)(n.code,{children:"(*)"})," sign next to its name."]}),"\n",(0,a.jsx)(n.h2,{id:"show",children:"Show Account Configuration Details"}),"\n",(0,a.jsxs)(n.p,{children:["To verify whether an account exists in your wallet, use ",(0,a.jsx)(n.code,{children:"wallet show <name>"}),".\nThis will print the account's native address and the public key which requires\nentering your account's password."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet show oscar\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Unlock your account.\n? Passphrase:\nName: oscar\nKind: file (ed25519-adr8:0)\nPublic Key: Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=\nNative address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For ",(0,a.jsx)(n.code,{children:"secp256k1"})," accounts Ethereum's hex-encoded address will also be printed."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet show eugene\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Unlock your account.\n? Passphrase:\nName: eugene\nKind: file (secp256k1-bip44:0)\nPublic Key: ArEjDxsPfDvfeLlity4mjGzy8E/nI4umiC8vYQh+eh/c\nEthereum address: 0xBd16C6bF701a01DF1B5C11B14860b6bDbE776669\nNative address: oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\n"})}),"\n",(0,a.jsx)(n.p,{children:"Showing an account stored on your hardware wallet will require connecting it to\nyour computer:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet show logan\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"Name: logan\nKind: ledger (ed25519-legacy:0)\nPublic Key: l+cuboPsOeuY1+kYlROrpmKgiiELmXSw9xl0WEg8cWE=\nNative address: oasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\n"})}),"\n",(0,a.jsx)(n.h2,{id:"export",children:"Export the Account's Secret"}),"\n",(0,a.jsxs)(n.p,{children:["You can obtain the secret material of a file-based account such as the mnemonic\nor the private key by running ",(0,a.jsx)(n.code,{children:"wallet export <name>"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"For example:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet export oscar\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase:\nName: oscar\nKind: file (ed25519-adr8:0)\nPublic Key: Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=\nNative address: oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\nSecret mnemonic:\npromote easily runway junior saddle gold flip believe wet example amount believe habit mixed pistol lemon increase moon rail mail fiction miss clip asset\nDerived secret key for account number 0:\nLHOUUJgVquTdi/3DVsS4caW4jQcvuFgl1Oag6BwlNvwHHqA6LGfHLXm0KzT25rkNwrJf26jYWitvfY7ofKOhzw==\n"})}),"\n",(0,a.jsx)(n.p,{children:"The same goes for your Secp256k1 accounts:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet export eugene\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase:\nName: eugene\nKind: file (secp256k1-bip44:0)\nPublic Key: ArEjDxsPfDvfeLlity4mjGzy8E/nI4umiC8vYQh+eh/c\nEthereum address: 0xBd16C6bF701a01DF1B5C11B14860b6bDbE776669\nNative address: oasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\nSecret mnemonic:\nman ankle mystery favorite tone number ice west spare marriage control lucky life together neither\nDerived secret key for account number 0:\nc559cad1e71e0db1b3a657f47ca7a618bfb6a51a7294df72bcfca57aded5377e\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet export emma\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"WARNING: Exporting the account will expose secret key material!\nUnlock your account.\n? Passphrase:\nName: emma\nKind: file (secp256k1-raw)\nPublic Key: Az8B2UpSUET0E3n9XMzr+HBvviQKcRvz6C6bJtRFWNYG\nEthereum address: 0xeEbE22411f579682F6f9D68f4C19B3581bCb576b\nNative address: oasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\nSecret key:\n4811ebbe4f29f32a758f6f7bad39deb97ea67f07350637e31c75795dc679262a\n"})}),"\n",(0,a.jsx)(n.p,{children:"Trying to export an account stored on your hardware wallet will only\nexport its public key:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet export lenny\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"WARNING: Exporting the account will expose secret key material!\nName: lenny\nKind: ledger (secp256k1-bip44:3)\nPublic Key: AhhT2TUkEZ7rMasLBvHcsGj4SUO7Iw36ELEpL0evZDV1\nEthereum address: 0x95e5e3C1BDD92cd4A0c14c62480DB5867946281D\nNative address: oasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\n"})}),"\n",(0,a.jsx)(n.h2,{id:"rename",children:"Renaming the Account"}),"\n",(0,a.jsxs)(n.p,{children:["To rename an account, run ",(0,a.jsx)(n.code,{children:"wallet rename <old_name> <new_name>"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"For example:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlenny \tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar (*)\tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet rename lenny lester\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlester \tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar (*)\tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsx)(n.h2,{id:"remove",children:"Deleting an Account"}),"\n",(0,a.jsxs)(n.p,{children:["To irreversibly delete the accounts from your wallet use\n",(0,a.jsx)(n.code,{children:"wallet remove [names]"}),". For file-based accounts this will delete the file\ncontaining the private key from your disk. For hardware wallet accounts this\nwill delete the Oasis CLI reference, but the private keys will remain intact on\nyour hardware wallet."]}),"\n",(0,a.jsxs)(n.p,{children:["For example, let's delete ",(0,a.jsx)(n.code,{children:"lenny"})," account:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlenny \tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar (*)\tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet remove lenny\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT 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"})}),"\n",(0,a.jsxs)(n.p,{children:["You can also delete accounct in non-interactive mode format by passing the\n",(0,a.jsx)(n.code,{children:"-y"})," parameter:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet remove lenny -y\n"})}),"\n",(0,a.jsx)(n.h2,{id:"set-default",children:"Set Default Account"}),"\n",(0,a.jsxs)(n.p,{children:["To change your default account, use ",(0,a.jsx)(n.code,{children:"wallet set-default <name>"})," and the\nname of the desired default account."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlenny \tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar (*)\tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet set-default lenny\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT \tKIND \tADDRESS \nemma \tfile (secp256k1-raw) \toasis1qph93wnfw8shu04pqyarvtjy4lytz3hp0c7tqnqh\t\neugene \tfile (secp256k1-bip44:0) \toasis1qrvzxld9rz83wv92lvnkpmr30c77kj2tvg0pednz\t\nlenny (*)\tledger (secp256k1-bip44:3)\toasis1qrmw4rhvp8ksj3yx6p2ftnkz864muc3re5jlgall\t\nlogan \tledger (ed25519-legacy:0) \toasis1qpl4axynedmdrrgrg7dpw3yxc4a8crevr5dkuksl\t\noscar \tfile (ed25519-adr8:0) \toasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\t\n"})}),"\n",(0,a.jsx)(n.h2,{id:"advanced",children:"Advanced"}),"\n",(0,a.jsx)(n.h3,{id:"import-file",children:"Import an Existing Keypair from PEM file"}),"\n",(0,a.jsxs)(n.p,{children:["Existing node operators may already use their Ed25519 private key for running\ntheir nodes stored in a PEM-encoded file typically named ",(0,a.jsx)(n.code,{children:"entity.pem"}),". In order\nto submit their governance transaction, for example to vote on the network\nupgrade using the Oasis CLI, they need to import the key into the Oasis CLI\nwallet:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet import-file my_entity entity.pem\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"? Choose a new passphrase:\n? Repeat passphrase:\n"})}),"\n",(0,a.jsx)(n.p,{children:"The key is now safely stored and encrypted inside the Oasis CLI."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"ACCOUNT KIND ADDRESS \nmy_entity file (ed25519-raw) oasis1qpe0vnm0ahczgc353vytvtz9r829le4pjux8lc5z\n"})}),"\n",(0,a.jsxs)(n.h3,{id:"remote-signer",children:["Remote Signer for ",(0,a.jsx)(n.code,{children:"oasis-node"})]}),"\n",(0,a.jsxs)(n.p,{children:["You can bind the account in your Oasis CLI wallet with a local instance of\n",(0,a.jsx)(n.code,{children:"oasis-node"}),". To do this, use\n",(0,a.jsx)(n.code,{children:"wallet remote-signer <account_name> <socket_path>"}),", pick the account you wish\nto expose and provide a path to the new unix socket:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis wallet remote-signer oscar /datadir/oasis-oscar.socket\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"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"})}),"\n",(0,a.jsx)(n.h3,{id:"test-accounts",children:"Test Accounts"}),"\n",(0,a.jsx)(n.p,{children:"Oasis CLI comes with the following hardcoded test accounts:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:alice"}),": Ed25519 test account used by Oasis core tests"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:bob"}),": Ed25519 test account used by Oasis core tests"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:charlie"}),": Secp256k1 test account"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:cory"}),": Ed25519 account used by ",(0,a.jsx)(n.code,{children:"oasis-net-runner"})]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:dave"}),": Secp256k1 test account"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:erin"}),": Sr25519 test account"]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test:frank"}),": Sr25519 test account"]}),"\n"]}),"\n",(0,a.jsx)(n.admonition,{title:"Do not use these accounts on public networks",type:"danger",children:(0,a.jsx)(n.p,{children:"Private keys for these accounts are well-known. Do not fund them on public\nnetworks, because anyone can drain them!"})}),"\n",(0,a.jsxs)(n.p,{children:["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 invoking the ",(0,a.jsx)(n.a,{href:"#export",children:(0,a.jsx)(n.code,{children:"oasis wallet export"})})," command."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>i});var a=s(6540);const r={},t=a.createContext(r);function l(e){const n=a.useContext(t);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),a.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7687a514.1e7aebe8.js b/assets/js/7687a514.1e7aebe8.js new file mode 100644 index 0000000000..4448c4135a --- /dev/null +++ b/assets/js/7687a514.1e7aebe8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1538],{8542:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>h,contentTitle:()=>l,default:()=>u,frontMatter:()=>c,metadata:()=>d,toc:()=>p});var r=n(4848),i=n(8453),s=n(5965),o=n(2550),a=n(6116);const c={},l="Cipher ParaTime",d={id:"dapp/cipher/README",title:"Cipher ParaTime",description:"Cipher 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/cipher/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Frontend Application",permalink:"/dapp/opl/frontend"},next:{title:"Prerequisites",permalink:"/dapp/cipher/prerequisites"}},h={},p=[{value:"Smart Contract Development",id:"smart-contract-development",level:2},{value:"RPC Endpoints",id:"rpc-endpoints",level:2},{value:"Block Explorers",id:"block-explorers",level:2},{value:"Indexers",id:"indexers",level:2},{value:"See also",id:"see-also",level:2}];function m(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"cipher-paratime",children:"Cipher ParaTime"}),"\n",(0,r.jsx)(t.p,{children:"Cipher is a confidential ParaTime for executing Wasm smart contracts."}),"\n",(0,r.jsx)(t.p,{children:"As the officially supported ParaTime by the Oasis Protocol Foundation, Cipher\nallows for:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsx)(t.li,{children:"Flexibility: developer can define which data to store in a public\nand which data in the (more expensive) confidential storage"}),"\n",(0,r.jsxs)(t.li,{children:["Security: the ",(0,r.jsx)(t.a,{href:"https://www.rust-lang.org/",children:"rust language"})," primarily used for writing Wasm smart contracts\nis known for its strict memory management and was developed specifically to\navoid memory leaks"]}),"\n",(0,r.jsx)(t.li,{children:"Scalability: increased throughput of transactions"}),"\n",(0,r.jsx)(t.li,{children:"Low-cost: 99%+ lower fees than Ethereum"}),"\n",(0,r.jsx)(t.li,{children:"6 second finality (1 block)"}),"\n",(0,r.jsx)(t.li,{children:"Cross-chain bridge to enable cross-chain interoperability (upcoming)"}),"\n"]}),"\n",(0,r.jsxs)(t.p,{children:["If you're looking for EVM-compatible ParaTimes, check out the\n",(0,r.jsx)(t.a,{href:"/dapp/emerald/",children:"Emerald"})," and the confidential\n",(0,r.jsx)(t.a,{href:"/dapp/sapphire/",children:"Sapphire"})," paratimes."]}),"\n",(0,r.jsx)(t.h2,{id:"smart-contract-development",children:"Smart Contract Development"}),"\n",(0,r.jsxs)(t.p,{children:["Cipher implements the ",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/contract-sdk",children:"Oasis Contract SDK"})," API. To learn how to write a\nconfidential smart contract in Rust and deploy it on Cipher, read the related\nOasis Contract SDK chapters:"]}),"\n",(0,r.jsx)(s.A,{item:(0,a.$)("/dapp/cipher/prerequisites")}),"\n",(0,r.jsx)(s.A,{item:(0,a.$)("/dapp/cipher/hello-world")}),"\n",(0,r.jsx)(s.A,{item:(0,a.$)("/dapp/cipher/confidential-smart-contract")}),"\n",(0,r.jsx)(t.h2,{id:"rpc-endpoints",children:"RPC Endpoints"}),"\n",(0,r.jsx)(t.admonition,{type:"danger",children:(0,r.jsxs)(t.p,{children:["The RPC endpoint is a ",(0,r.jsx)(t.em,{children:"point of trust"}),". Beside traffic rate limiting, it can\nalso perform censorship or even a man-in-the-middle attack. If you have security\nconsiderations, we strongly recommend that you set up your own ",(0,r.jsx)(t.a,{href:"/node/run-your-node/paratime-client-node",children:"ParaTime client\nnode"}),"."]})}),"\n",(0,r.jsx)(t.p,{children:"Cipher endpoints share the gRPC protocol with the Oasis Core. You can connect to\none of the public endpoints below (in alphabetic order):"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Provider"}),(0,r.jsx)(t.th,{children:"Mainnet RPC URLs"}),(0,r.jsx)(t.th,{children:"Testnet RPC URLs"})]})}),(0,r.jsx)(t.tbody,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"})}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"grpc.oasis.io:443"})}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"testnet.grpc.oasis.io:443"})})]})})]}),"\n",(0,r.jsx)(t.h2,{id:"block-explorers",children:"Block Explorers"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Name/Provider"}),(0,r.jsx)(t.th,{children:"Mainnet URL"}),(0,r.jsx)(t.th,{children:"Testnet URL"}),(0,r.jsx)(t.th,{children:"EIP-3091 compatible"})]})}),(0,r.jsx)(t.tbody,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsxs)(t.td,{children:["Oasis Scan (",(0,r.jsx)(t.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://www.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000e199119c992377cb",children:"https://www.oasisscan.com/paratimes/000\u20267cb"})}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"https://testnet.oasisscan.com/paratimes/0000000000000000000000000000000000000000000000000000000000000000",children:"https://testnet.oasisscan.com/paratimes/000\u2026000"})}),(0,r.jsx)(t.td,{children:"No"})]})})]}),"\n",(0,r.jsx)(t.admonition,{type:"tip",children:(0,r.jsxs)(t.p,{children:["Only rudimentary block explorer features exist for Cipher. Consider debugging\nthe Cipher transactions using the ",(0,r.jsx)(t.a,{href:"/general/manage-tokens/cli/paratime#show",children:(0,r.jsx)(t.code,{children:"oasis paratime show"})})," command part of the\n",(0,r.jsx)(t.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"}),"."]})}),"\n",(0,r.jsx)(t.h2,{id:"indexers",children:"Indexers"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Name (Provider)"}),(0,r.jsx)(t.th,{children:"Mainnet URL"}),(0,r.jsx)(t.th,{children:"Testnet URL"}),(0,r.jsx)(t.th,{children:"Documentation"})]})}),(0,r.jsx)(t.tbody,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsxs)(t.td,{children:["Oasis Scan (",(0,r.jsx)(t.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"https://api.oasisscan.com/mainnet/v2"})}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"https://api.oasisscan.com/testnet/v2"})}),(0,r.jsxs)(t.td,{children:[(0,r.jsx)(t.a,{href:"https://api.oasisscan.com/mainnet/swagger-ui/#/runtime-controller",children:"Mainnet Runtime API"}),", ",(0,r.jsx)(t.a,{href:"https://api.oasisscan.com/testnet/swagger-ui/#/runtime-controller",children:"Testnet Runtime API"})]})]})})]}),"\n",(0,r.jsx)(t.admonition,{type:"note",children:(0,r.jsxs)(t.p,{children:["If you are running your own Cipher endpoint, a block explorer, or an indexer\nand wish to be added to these docs, open an issue at\n",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/docs",children:"github.com/oasisprotocol/docs"}),"."]})}),"\n",(0,r.jsx)(t.h2,{id:"see-also",children:"See also"}),"\n",(0,r.jsx)(o.A,{items:[(0,a.$)("/general/manage-tokens/"),(0,a.$)("/node/run-your-node/paratime-node"),(0,a.$)("/node/run-your-node/paratime-client-node"),(0,a.$)("/dapp/emerald/"),(0,a.$)("/dapp/sapphire/")]})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(m,{...e})}):m(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>f});n(6540);var r=n(4164),i=n(8774),s=n(4142),o=n(5846),a=n(6654),c=n(1312),l=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=n(4848);function p(e){let{href:t,children:n}=e;return(0,h.jsx)(i.A,{href:t,className:(0,r.A)("card padding--lg",d.cardContainer),children:n})}function m(e){let{href:t,icon:n,title:i,description:s}=e;return(0,h.jsxs)(p,{href:t,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,r.A)("text--truncate",d.cardTitle),title:i,children:[n," ",i]}),s&&(0,h.jsx)("p",{className:(0,r.A)("text--truncate",d.cardDescription),title:s,children:s})]})}function u(e){let{item:t}=e;const n=(0,s.Nr)(t),r=function(){const{selectMessage:e}=(0,o.W)();return t=>e(t,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,h.jsx)(m,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??r(t.items.length)}):null}function x(e){let{item:t}=e;const n=(0,a.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,s.cC)(t.docId??void 0);return(0,h.jsx)(m,{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(0,h.jsx)(x,{item:t});case"category":return(0,h.jsx)(u,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,n)=>{n.d(t,{A:()=>c});n(6540);var r=n(4164),i=n(4142),s=n(5965),o=n(4848);function a(e){let{className:t}=e;const n=(0,i.$S)();return(0,o.jsx)(c,{items:n.items,className:t})}function c(e){const{items:t,className:n}=e;if(!t)return(0,o.jsx)(a,{...e});const c=(0,i.d1)(t);return(0,o.jsx)("section",{className:(0,r.A)("row",n),children:c.map(((e,t)=>(0,o.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,o.jsx)(s.A,{item:e})},t)))})}},5846:(e,t,n)=>{n.d(t,{W:()=>l});var r=n(6540),i=n(4586);const s=["zero","one","two","few","many","other"];function o(e){return s.filter((t=>e.includes(t)))}const a={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,i.A)();return(0,r.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:o(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`),a}}),[e])}function l(){const e=c();return{selectMessage:(t,n)=>function(e,t,n){const r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const i=n.select(t),s=n.pluralForms.indexOf(i);return r[Math.min(s,r.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>s});var r=n(2252);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 s(e){const t=(0,r.r)();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]}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var r=n(6540);const i={},s=r.createContext(i);function o(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/777245c5.bb091a8d.js b/assets/js/777245c5.bb091a8d.js new file mode 100644 index 0000000000..a600881b9b --- /dev/null +++ b/assets/js/777245c5.bb091a8d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4551],{6661:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>t,metadata:()=>c,toc:()=>l});var o=s(4848),r=s(8453);const t={},i="Governance",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/governance.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Committee Scheduler",permalink:"/core/consensus/services/scheduler"},next:{title:"Root Hash",permalink:"/core/consensus/services/roothash"}},a={},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}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"governance",children:"Governance"}),"\n",(0,o.jsx)(n.p,{children:"The governance service is responsible for providing an on-chain governance\nmechanism."}),"\n",(0,o.jsxs)(n.p,{children:["The service interface definition lives in ",(0,o.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/governance/api",children:(0,o.jsx)(n.code,{children:"go/governance/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,o.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/governance/api?tab=doc",children:"consensus service API documentation"})," and the ",(0,o.jsx)(n.a,{href:"/adrs/0006-consensus-governance",children:"governance ADR\nspecification"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,o.jsx)(n.p,{children:"The following sections describe the methods supported by the consensus\ngovernance service."}),"\n",(0,o.jsx)(n.h3,{id:"submit-proposal",children:"Submit Proposal"}),"\n",(0,o.jsx)(n.p,{children:"Proposal submission enables a new consensus layer governance proposal to be\ncreated."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"governance.SubmitProposal\n"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"upgrade"})," (optional) specifies an upgrade proposal."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"cancel_upgrade"})," (optional) specifies an upgrade cancellation proposal."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Exactly one of the proposal kind fields needs to be non-nil, otherwise the\nproposal is considered malformed."}),"\n",(0,o.jsx)(n.h3,{id:"vote",children:"Vote"}),"\n",(0,o.jsx)(n.p,{children:"Voting for submitted consensus layer governance proposals."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"governance.CastVote\n"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.h2,{id:"events",children:"Events"}),"\n",(0,o.jsx)(n.h3,{id:"proposal-submitted-event",children:"Proposal Submitted Event"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.p,{children:"Emitted for every submitted proposal."}),"\n",(0,o.jsx)(n.h3,{id:"proposal-finalized-event",children:"Proposal Finalized Event"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.p,{children:"Emitted when a proposal is finalized."}),"\n",(0,o.jsx)(n.h3,{id:"proposal-executed-event",children:"Proposal Executed Event"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'type ProposalExecutedEvent {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Emitted when a passed proposal is executed."}),"\n",(0,o.jsx)(n.h3,{id:"vote-event",children:"Vote Event"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.p,{children:"Emitted when a vote is cast."}),"\n",(0,o.jsx)(n.h2,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"gas_costs"})," (transaction.Costs) are the governance transaction gas costs."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"min_proposal_deposit"})," (base units) specifies the number of base units that\nare deposited when creating a new proposal."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"voting_period"})," (epochs) specifies the number of epochs after which the voting\nfor a proposal is closed and the votes are tallied."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"threshold"})," (uint8: [0,100]) specifies the minimum percentage of ",(0,o.jsx)(n.code,{children:"VoteYes"}),"\nvotes in order for a proposal to be accepted."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"test-vectors",children:"Test Vectors"}),"\n",(0,o.jsxs)(n.p,{children:["To generate test vectors for various governance ",(0,o.jsx)(n.a,{href:"/core/consensus/transactions",children:"transactions"}),", run:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"make -C go governance/gen_vectors\n"})}),"\n",(0,o.jsxs)(n.p,{children:["For more information about the structure of the test vectors see the section\non ",(0,o.jsx)(n.a,{href:"/core/consensus/test-vectors",children:"Transaction Test Vectors"}),"."]})]})}function p(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>c});var o=s(6540);const r={},t=o.createContext(r);function i(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/79102774.aa997a44.js b/assets/js/79102774.aa997a44.js new file mode 100644 index 0000000000..6433e2dd80 --- /dev/null +++ b/assets/js/79102774.aa997a44.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3684],{2383:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>h});var i=t(4848),s=t(8453),o=t(2550),r=t(6116);const a={},d="Validator Node",l={id:"node/run-your-node/validator-node",title:"Validator Node",description:"This guide will walk you through the process of setting up your validator",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/validator-node.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},c={},h=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Initialize Entity",id:"initialize-entity",level:2},{value:"Add Entity Account to Oasis CLI",id:"add-entity-account-to-oasis-cli",level:3},{value:"Write the Entity Descriptor File",id:"write-the-entity-descriptor-file",level:3},{value:"Copy the Public Entity File Descriptor to <code>server</code>",id:"copy-the-public-entity-file-descriptor-to-server",level:3},{value:"Configuration",id:"configuration",level:2},{value:"Starting the Oasis Node",id:"starting-the-oasis-node",level:2},{value:"Node Keys",id:"node-keys",level:3},{value:"Ensuring Proper Permissions",id:"ensuring-proper-permissions",level:3},{value:"Obtain the Node ID",id:"obtain-the-node-id",level:3},{value:"Check that your Node is Synced",id:"check-that-your-node-is-synced",level:3},{value:"Staking and Registering",id:"staking-and-registering",level:2},{value:"Staking (Escrow) Transaction",id:"staking-escrow-transaction",level:3},{value:"Add your Node ID to the Entity Descriptor",id:"add-your-node-id-to-the-entity-descriptor",level:3},{value:"Entity Registration",id:"entity-registration",level:3},{value:"Check that Your Node is Properly Registered",id:"check-that-your-node-is-properly-registered",level:3},{value:"Oasis Metadata Registry",id:"oasis-metadata-registry",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"validator-node",children:"Validator Node"}),"\n",(0,i.jsxs)(n.p,{children:["This guide will walk you through the process of setting up your ",(0,i.jsx)(n.strong,{children:"validator\nnode"})," for the Oasis Network either on Mainnet or Testnet. It is designed for\nindividuals who have basic understanding of the command line environment."]}),"\n",(0,i.jsx)(n.p,{children:"We will be using two separate physical machines for deployment:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["your local system, referred to as ",(0,i.jsx)(n.code,{children:"localhost"}),","]}),"\n",(0,i.jsxs)(n.li,{children:["a remote ",(0,i.jsx)(n.code,{children:"server"})," which will function as an Oasis node."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The guide consists of the following steps:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["On the ",(0,i.jsx)(n.code,{children:"localhost"}),", we will use ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," to ",(0,i.jsx)(n.a,{href:"#initialize-entity",children:"Initialize your\nEntity"})," which is essential for deploying nodes on the\nnetwork. To ensure the security of these private keys, we strongly recommend\nto either isolate the ",(0,i.jsx)(n.code,{children:"localhost"})," from any network or internet connectivity, or\nuse a ",(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Hardware_security_module",children:"hardware wallet"})," as a secure storage, such as ",(0,i.jsx)(n.a,{href:"../../../general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Ledger"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["After the entity has been created, we will move over to the ",(0,i.jsx)(n.code,{children:"server"})," and\n",(0,i.jsx)(n.a,{href:"#starting-the-oasis-node",children:"Start the Oasis Node"}),". The server needs to meet\nthe hardware requirements and have access to the internet."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Finally, we will ",(0,i.jsx)(n.a,{href:"#staking-and-registering",children:"stake assets to your entity, register it on the network,\nand attach the unique ID"})," of the\nOasis Node instance running on your server."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsxs)(n.p,{children:["Before proceeding with this guide, ensure that you have completed the steps\noutlined in the ",(0,i.jsx)(n.a,{href:"prerequisites/",children:"Prerequisites"})," chapter so that:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["your system meets the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/hardware-recommendations",children:"hardware requirements"}),","]}),"\n",(0,i.jsxs)(n.li,{children:["you have the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," installed on your ",(0,i.jsx)(n.code,{children:"localhost"}),","]}),"\n",(0,i.jsxs)(n.li,{children:["you have the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node binary"})," installed on your ",(0,i.jsx)(n.code,{children:"server"}),","]}),"\n",(0,i.jsxs)(n.li,{children:["you understand what are ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/stake-requirements",children:"Stake requirements"})," to become a validator on the\nOasis Network."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"initialize-entity",children:"Initialize Entity"}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsxs)(n.p,{children:["Everything in this section should be done on the ",(0,i.jsx)(n.code,{children:"localhost"})," as there are\nsensitive items that will be created."]})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"add-entity-account-to-oasis-cli",children:"Add Entity Account to Oasis CLI"}),"\n",(0,i.jsxs)(n.p,{children:["An entity is critical to operating nodes on the network as it controls the stake\nattached to a given individual or organization on the network. The entity is\nrepresented as a consensus-layer account using the Ed25519 signature scheme.\nTo protect your entity private key, we strongly recommend using a ",(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Hardware_security_module",children:"hardware\nwallet"})," such as ",(0,i.jsx)(n.a,{href:"../../../general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Ledger"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["We will be using ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," to initialize the entity and later stake our assets\nand register the entity on the network. If you haven't already, go ahead and\ninstall it."]}),"\n",(0,i.jsx)(n.p,{children:"Oasis CLI stores either your entity private key encrypted inside a file or a\nreference to an account whose keypair is stored on your hardware wallet."}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsxs)(n.p,{children:["If you really need to use the file-based wallet using another\n",(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Air_gap_(networking)",children:"offline/air-gapped machine"})," for this purpose is highly recommended. Gaining\naccess to the entity private key can compromise your tokens and the network\nsecurity through proposing and signing malicious governance transactions."]})}),"\n",(0,i.jsxs)(n.p,{children:["On the ",(0,i.jsx)(n.code,{children:"localhost"})," add a new entity account to Oasis CLI. This can be done in\none of the following ways:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Create an account entry in Oasis CLI, but use your Ledger device to store\nthe actual keypair to sign the transactions by executing\n",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#create",children:(0,i.jsx)(n.code,{children:"oasis wallet create"})})," and passing the ",(0,i.jsx)(n.code,{children:"--kind ledger"})," flag. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet create my_entity --kind ledger\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Import your existing ",(0,i.jsx)(n.code,{children:"entity.pem"})," into Oasis CLI by executing\n",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import-file",children:(0,i.jsx)(n.code,{children:"oasis wallet import-file"})})," command, for example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet import-file my_entity entity.pem\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Generate a new keypair and store the private key in the encrypted file by\nexecuting ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#create",children:(0,i.jsx)(n.code,{children:"oasis wallet create"})}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet create my_entity\n"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Similar to the examples above we will assume that you named your entity account\nas ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"my_entity"})})," in the remainder of this chapter."]}),"\n",(0,i.jsx)(n.h3,{id:"write-the-entity-descriptor-file",children:"Write the Entity Descriptor File"}),"\n",(0,i.jsxs)(n.p,{children:["On the ",(0,i.jsx)(n.code,{children:"localhost"})," we begin by creating a directory named ",(0,i.jsx)(n.code,{children:"/localhostdir"})," with\nthe ",(0,i.jsx)(n.code,{children:"entity"})," subdirectory that will contain the entity file descriptor."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"mkdir -p /localhostdir/entity\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Create a JSON file containing the ",(0,i.jsx)(n.strong,{children:"public key"})," of your entity by executing\n",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#entity-init",children:(0,i.jsx)(n.code,{children:"oasis account entity init"})})," and store it as ",(0,i.jsx)(n.code,{children:"entity.json"}),", for example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account entity init -o /localhostdir/entity/entity.json --account my_entity\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now, we can move on to configuring our Oasis node with the freshly generated\n",(0,i.jsx)(n.code,{children:"entity.json"}),"."]}),"\n",(0,i.jsxs)(n.h3,{id:"copy-the-public-entity-file-descriptor-to-server",children:["Copy the Public Entity File Descriptor to ",(0,i.jsx)(n.code,{children:"server"})]}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis node needs access to the public key of your entity. Copy your\n",(0,i.jsx)(n.code,{children:"entity.json"})," to ",(0,i.jsx)(n.code,{children:"/node/etc/entity.json"})," on the ",(0,i.jsx)(n.code,{children:"server"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsx)(n.p,{children:"There are a variety of options available when running an Oasis node. The\nfollowing YAML file is a basic configuration for a validator node on the\nnetwork."}),"\n",(0,i.jsx)(n.p,{children:"Before using this configuration you should collect the following information to\nreplace the variables present in the configuration file:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"{{ external_ip }}"}),": The external/public IP address you used when registering\nthis node."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["If you are using a ",(0,i.jsx)(n.a,{href:"/node/run-your-node/sentry-node",children:"Sentry Node"}),", you should use the public IP\nof that machine."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"{{ seed_node_address }}"}),": The seed node address in the form ",(0,i.jsx)(n.code,{children:"ID@IP:port"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["You can find the current Oasis Seed Node address in the Network Parameters\npage (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["To use this configuration, save it in the ",(0,i.jsx)(n.code,{children:"/node/etc/config.yml"})," file:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",metastring:'title="/node/etc/config.yml"',children:'mode: validator\ncommon:\n # Set this to where you wish to store node data. The node\'s artifacts\n # should also be located in this directory.\n data_dir: /node/data\n # Logging.\n #\n # Per-module log levels are defined below. If you prefer just one unified\n # log level, you can use:\n #\n # log:\n # level: debug\n log:\n level:\n cometbft: warn\n cometbft/context: error\n # Per-module log levels. Longest prefix match will be taken.\n # Fallback to "default", if no match.\n default: debug\n format: JSON\n # By default logs are output to stdout. If you would like to output\n # logs to a file, you can use:\n #\n # file: /var/log/oasis-node.log\n\nconsensus:\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_ip }}:26656\n listen_address: tcp://0.0.0.0:26656\n\ngenesis:\n # Path to the genesis file for the current version of the network.\n file: /node/etc/genesis.json\n\np2p:\n port: 9200\n registration:\n addresses:\n - {{ external_ip }}:9200\n seeds:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n - {{ seed_node_address }}\n\nregistration:\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",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["Make sure the ",(0,i.jsx)(n.code,{children:"consensus"})," port (default: ",(0,i.jsx)(n.code,{children:"26656"}),") and ",(0,i.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,i.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,i.jsx)(n.code,{children:"TCP"})," and ",(0,i.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,i.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,i.jsx)(n.p,{children:"You can start the node by simply running the command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"The Oasis node is configured to run in the foreground by default."}),(0,i.jsxs)(n.p,{children:["We recommend that you configure and use it with a process manager like\n",(0,i.jsx)(n.a,{href:"https://github.com/systemd/systemd",children:"systemd"})," or\n",(0,i.jsx)(n.a,{href:"http://supervisord.org",children:"Supervisor"}),". Check out the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#create-a-user",children:"System Configuration"}),"\npage for examples."]})]}),"\n",(0,i.jsx)(n.h3,{id:"node-keys",children:"Node Keys"}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis node requires ",(0,i.jsx)(n.strong,{children:"node keys"})," in order to register itself and to\nsecurely communicate with other nodes in the peer-to-peer network. The following\nkeys will automatically be generated and stored in your ",(0,i.jsx)(n.code,{children:"/node/data"})," folder\nas ",(0,i.jsx)(n.code,{children:".pem"})," files:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consensus.pem"}),": The node's consensus private key. ",(0,i.jsx)(n.strong,{children:"DO NOT SHARE"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consensus_pub.pem"}),": The node's consensus public key."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"identity.pem"}),": The node's identity private key. ",(0,i.jsx)(n.strong,{children:"DO NOT SHARE"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"identity_pub.pem"}),": The node's identity public key."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"p2p.pem"}),": The node's private key for libp2p. ",(0,i.jsx)(n.strong,{children:"DO NOT SHARE"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"p2p_pub.pem"}),": The node's public key for libp2p."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"sentry_client_tls_identity.pem"}),": The node's TLS private key for communicating\nwith sentry nodes. ",(0,i.jsx)(n.strong,{children:"DO NOT SHARE"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"sentry_client_tls_identity_cert.pem"}),": The node's TLS certificate for\ncommunicating with sentry nodes."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"If the node keys do not exist, they will be automatically generated when you\nlaunch the Oasis node. Otherwise, the existing ones will be used."})}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsxs)(n.p,{children:["You may have noticed that some files above are listed as ",(0,i.jsx)(n.strong,{children:"DO NOT SHARE"}),"."]}),(0,i.jsxs)(n.p,{children:["Ideally, the node keys should be stored on a separate device such as a\n",(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Hardware_security_module",children:"hardware wallet"})," or a ",(0,i.jsx)(n.a,{href:"/node/run-your-node/advanced/remote-signer",children:"remote signer"}),". However, until the support is\nfully implemented, keep the keys on the ",(0,i.jsx)(n.code,{children:"server"})," as secure as possible."]})]}),"\n",(0,i.jsx)(n.h3,{id:"ensuring-proper-permissions",children:"Ensuring Proper Permissions"}),"\n",(0,i.jsxs)(n.p,{children:["Only the owner of the process that runs the Oasis node should have access to the\nfiles in the ",(0,i.jsx)(n.code,{children:"/node/data"})," directory. The ",(0,i.jsx)(n.code,{children:"oasis-node"})," binary ensures that\nthe files used by the node are as least privileged as possible so that you don't\naccidentally shoot yourself in the foot while operating a node."]}),"\n",(0,i.jsxs)(n.p,{children:["If you followed the steps described in the\n",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Install the Oasis Node"})," chapter, then the proper permissions\nare already set:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"700"})," for the ",(0,i.jsx)(n.code,{children:"/node/data"})," directory"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"700"})," for the ",(0,i.jsx)(n.code,{children:"/node/etc"})," directory"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"700"})," for the ",(0,i.jsx)(n.code,{children:"/node/runtimes"})," directory"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"600"})," for all ",(0,i.jsx)(n.code,{children:"/node/data/*.pem"})," files"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Otherwise, run the following to remove all non-owner read/write/execute\npermissions:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"chmod -R go-r,go-w,go-x /node\n"})}),"\n",(0,i.jsx)(n.h3,{id:"obtain-the-node-id",children:"Obtain the Node ID"}),"\n",(0,i.jsx)(n.p,{children:"Now that the Oasis node is running, you can obtain your unique node ID which is\nneeded in order to associate your node with your entity in the network registry."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis-node control status -a unix:/node/data/internal.sock | jq .identity.node\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"5MsgQwijUlpH9+0Hbyors5jwmx7tTmKMA4c9leV3prI="\n'})}),"\n",(0,i.jsx)(n.h3,{id:"check-that-your-node-is-synced",children:"Check that your Node is Synced"}),"\n",(0,i.jsx)(n.p,{children:"Before you can become a validator, you will have to make sure that your node is\nsynced. To do so call this command on the server:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis-node control is-synced -a unix:/node/data/internal.sock\n"})}),"\n",(0,i.jsx)(n.p,{children:"If your node is synced, the above command should output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"ready"\n'})}),"\n",(0,i.jsx)(n.p,{children:"If your node is not yet synced, you will need to wait before you can move\nforward."}),"\n",(0,i.jsx)(n.h2,{id:"staking-and-registering",children:"Staking and Registering"}),"\n",(0,i.jsx)(n.p,{children:"Once you have been funded, you can complete the process of connecting your node\nto the network by registering both your entity and your node, as described\nbelow."}),"\n",(0,i.jsx)(n.h3,{id:"staking-escrow-transaction",children:"Staking (Escrow) Transaction"}),"\n",(0,i.jsxs)(n.p,{children:["The current minimum stake required to register an entity and register a node as\na validator is 200 tokens. We will submit the escrow transaction that\ndelegates 200 tokens from your entity account on the consensus layer to itself\nby invoking the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#delegate",children:(0,i.jsx)(n.code,{children:"oasis account delegate"})})," command."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account delegate 200 my_entity --no-paratime --account my_entity\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You can also fund your entity account from a different one. If you haven't yet\ninvoke the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import",children:(0,i.jsx)(n.code,{children:"oasis wallet import"})})," command to import the private key of the\nfunding account to the Oasis CLI and follow the instructions."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet import my_funding_account\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Then, invoke the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#delegate",children:(0,i.jsx)(n.code,{children:"oasis account delegate"})})," passing the new account name with\nthe ",(0,i.jsx)(n.code,{children:"--account"})," parameter. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account delegate 200 my_entity --no-paratime --account my_funding_account\n"})}),"\n",(0,i.jsx)(n.h3,{id:"add-your-node-id-to-the-entity-descriptor",children:"Add your Node ID to the Entity Descriptor"}),"\n",(0,i.jsxs)(n.p,{children:["Now we can register our entity on the network and associate it with the node ID\nobtained in the ",(0,i.jsx)(n.a,{href:"#obtain-the-node-id",children:"section above"}),". Open the ",(0,i.jsx)(n.code,{children:"entity.json"}),"\nfile we initially generated and add the ID inside the ",(0,i.jsx)(n.code,{children:"nodes"})," block. Your\nentity descriptor file should now look like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "id": "Bx6gOixnxy15tCs09ua5DcKyX9uo2Forb32O6Hyjoc8=",\n "nodes": [\n "5MsgQwijUlpH9+0Hbyors5jwmx7tTmKMA4c9leV3prI="\n ],\n "v": 2\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"entity-registration",children:"Entity Registration"}),"\n",(0,i.jsxs)(n.p,{children:["We can submit the fresh entity file descriptor by invoking the\n",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#entity-register",children:(0,i.jsx)(n.code,{children:"oasis account entity register"})})," command:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account entity register entity.json --account my_entity\n"})}),"\n",(0,i.jsx)(n.h3,{id:"check-that-your-node-is-properly-registered",children:"Check that Your Node is Properly Registered"}),"\n",(0,i.jsxs)(n.p,{children:["To ensure that your node is properly connected as a validator on the network,\ninvoke the following command on your ",(0,i.jsx)(n.code,{children:"server"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis-node control status -a unix:/node/data/internal.sock | jq .consensus.is_validator\n"})}),"\n",(0,i.jsx)(n.p,{children:"If your node is registered and became a validator, the above command should\noutput:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"true\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"Nodes are only elected into the validator set at epoch transitions, so you may\nneed to wait for up to an epoch before being considered."})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["In order to be elected in the validator set you ",(0,i.jsx)(n.strong,{children:"need to have enough\nstake to be in the top K entities"})," (where K is a network-specific parameter\nspecified by the ",(0,i.jsx)(n.a,{href:"/node/genesis-doc#consensus",children:(0,i.jsx)(n.code,{children:"scheduler.max_validators"})})," field in the genesis document)."]})}),"\n",(0,i.jsx)(n.p,{children:"Congratulations, if you made it this far, you've properly connected your node\nto the network and became a validator on the Oasis Network."}),"\n",(0,i.jsx)(n.h2,{id:"oasis-metadata-registry",children:"Oasis Metadata Registry"}),"\n",(0,i.jsxs)(n.p,{children:["For the final touch, you can add some metadata about your entity to the\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/metadata-registry",children:"Metadata Registry"}),". The Metadata Registry is the same for Mainnet and\nthe Testnet. The metadata consists of your entity name, email, Keybase handle,\nTwitter handle, etc. This information is also used by various applications.\nFor example the ",(0,i.jsx)(n.a,{href:"https://wallet.oasisprotocol.org",children:"ROSE Wallet - Web"})," and the ",(0,i.jsx)(n.a,{href:"https://www.oasisscan.com/validators",children:"Oasis Scan"})," will fetch and show\nthe node operator's name and the avatar."]}),"\n",(0,i.jsx)(n.h1,{id:"see-also",children:"See also"}),"\n",(0,i.jsx)(o.A,{items:[(0,r.$)("/general/manage-tokens/cli/"),(0,r.$)("/core/oasis-node/cli"),(0,r.$)("/node/grpc")]})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>x});t(6540);var i=t(4164),s=t(8774),o=t(4142),r=t(5846),a=t(6654),d=t(1312),l=t(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function u(e){let{href:n,children:t}=e;return(0,h.jsx)(s.A,{href:n,className:(0,i.A)("card padding--lg",c.cardContainer),children:t})}function p(e){let{href:n,icon:t,title:s,description:o}=e;return(0,h.jsxs)(u,{href:n,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,i.A)("text--truncate",c.cardTitle),title:s,children:[t," ",s]}),o&&(0,h.jsx)("p",{className:(0,i.A)("text--truncate",c.cardDescription),title:o,children:o})]})}function y(e){let{item:n}=e;const t=(0,o.Nr)(n),i=function(){const{selectMessage:e}=(0,r.W)();return n=>e(n,(0,d.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,h.jsx)(p,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??i(n.items.length)}):null}function g(e){let{item:n}=e;const t=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",i=(0,o.cC)(n.docId??void 0);return(0,h.jsx)(p,{href:n.href,icon:t,title:n.label,description:n.description??i?.description})}function x(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(g,{item:n});case"category":return(0,h.jsx)(y,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},2550:(e,n,t)=>{t.d(n,{A:()=>d});t(6540);var i=t(4164),s=t(4142),o=t(5965),r=t(4848);function a(e){let{className:n}=e;const t=(0,s.$S)();return(0,r.jsx)(d,{items:t.items,className:n})}function d(e){const{items:n,className:t}=e;if(!n)return(0,r.jsx)(a,{...e});const d=(0,s.d1)(n);return(0,r.jsx)("section",{className:(0,i.A)("row",t),children:d.map(((e,n)=>(0,r.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,r.jsx)(o.A,{item:e})},n)))})}},5846:(e,n,t)=>{t.d(n,{W:()=>l});var i=t(6540),s=t(4586);const o=["zero","one","two","few","many","other"];function r(e){return o.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:r(["one","other"]),select:e=>1===e?"one":"other"};function d(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,i.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:r(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function l(){const e=d();return{selectMessage:(n,t)=>function(e,n,t){const i=e.split("|");if(1===i.length)return i[0];i.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${i.length}: ${e}`);const s=t.select(n),o=t.pluralForms.indexOf(s);return i[Math.min(o,i.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>o});var i=t(2252);function s(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&s(n.items)}}function o(e){const n=(0,i.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)s(n.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]}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7b1f3817.f32ce934.js b/assets/js/7b1f3817.f32ce934.js new file mode 100644 index 0000000000..64d18924c6 --- /dev/null +++ b/assets/js/7b1f3817.f32ce934.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7532],{100:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>x,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var t=s(4848),i=s(8453);const r={},l="ADR 0002: Go Modules Compatible Git Tags",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0002-go-modules-compatible-git-tags.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},o={},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:"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}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0002-go-modules-compatible-git-tags",children:"ADR 0002: Go Modules Compatible Git Tags"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2020-09-04: Initial version"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Accepted"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsxs)(n.p,{children:["Projects that depend on ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/mod/github.com/oasisprotocol/oasis-core/go",children:"Oasis Core's Go module"}),", i.e.\n",(0,t.jsx)(n.code,{children:"github.com/oasisprotocol/oasis-core/go"}),", need a way to depend on its particular\nversion."]}),"\n",(0,t.jsxs)(n.p,{children:["Go Modules only allow ",(0,t.jsx)(n.a,{href:"https://semver.org/spec/v2.0.0.html",children:"Semantic Versioning 2.0.0"})," for\n",(0,t.jsx)(n.a,{href:"https://golang.org/ref/mod#versions",children:"versioning of the modules"})," which makes it hard to work\nwith ",(0,t.jsx)(n.a,{href:"/core/versioning",children:"Oasis Core's CalVer (calendar versioning) scheme"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"The currently used scheme for Go Modules compatible Git tags is:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"go/v0.YY.MINOR[.MICRO]\n"})}),"\n",(0,t.jsx)(n.p,{children:"where:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"YY"})," represents the short year (e.g. ",(0,t.jsx)(n.code,{children:"19"}),", ",(0,t.jsx)(n.code,{children:"20"}),", ",(0,t.jsx)(n.code,{children:"21"}),", ...),"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"MINOR"})," represents the minor version starting with zero (e.g. ",(0,t.jsx)(n.code,{children:"0"}),", ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"2"}),",\n",(0,t.jsx)(n.code,{children:"3"}),", ...),"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"MICRO"}),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,t.jsx)(n.code,{children:"0"}),", ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"2"}),", ",(0,t.jsx)(n.code,{children:"3"}),", ...)."]}),"\n",(0,t.jsxs)(n.p,{children:["If the ",(0,t.jsx)(n.code,{children:"MICRO"})," version is ",(0,t.jsx)(n.code,{children:"0"}),", it is omitted."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["It turns out this only works for Oasis Core versions with the ",(0,t.jsx)(n.code,{children:"MICRO"})," version\nof ",(0,t.jsx)(n.code,{children:"0"})," since the Go Modules compatible Git tag omits the ",(0,t.jsx)(n.code,{children:".MICRO"})," part and is\nthus compatible with ",(0,t.jsx)(n.a,{href:"https://golang.org/ref/mod#versions",children:"Go Modules versioning requirements"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"The proposed design is to tag Oasis Core releases with the following Go Modules\ncompatible Git tags (in addition to the ordinary Git tags):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"go/v0.YY0MINOR.MICRO\n"})}),"\n",(0,t.jsx)(n.p,{children:"where:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"YY"})," represents the short year (e.g. ",(0,t.jsx)(n.code,{children:"19"}),", ",(0,t.jsx)(n.code,{children:"20"}),", ",(0,t.jsx)(n.code,{children:"21"}),", ...),"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"0MINOR"})," represents the zero-padded minor version starting with zero (e.g.\n",(0,t.jsx)(n.code,{children:"00"}),", ",(0,t.jsx)(n.code,{children:"01"}),", ",(0,t.jsx)(n.code,{children:"02"}),", ..., ",(0,t.jsx)(n.code,{children:"10"}),", ",(0,t.jsx)(n.code,{children:"11"}),", ...),"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"MICRO"}),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,t.jsx)(n.code,{children:"0"}),", ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"2"}),", ",(0,t.jsx)(n.code,{children:"3"}),", ...)."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Here are some examples of how the ordinary and the corresponding Go Modules\ncompatible Git tags would look like:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{style:{textAlign:"center"},children:"Version"}),(0,t.jsx)(n.th,{style:{textAlign:"center"},children:"Ordinary Git tag"}),(0,t.jsx)(n.th,{style:{textAlign:"center"},children:"Go Modules compatible Git tag"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.9"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.9"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2009.0"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.9.1"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.9.1"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2009.1"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.9.2"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.9.2"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2009.2"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.10"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.10"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2010.0"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.10.1"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.10.1"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2010.1"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"20.10.2"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v20.10.2"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2010.2"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.0"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.0"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2100.0"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.0.1"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.0.1"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2100.1"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.0.2"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.0.2"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2100.2"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.1"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.1"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2101.0"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.1.1"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.1.1"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2101.1"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"21.1.2"}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"v21.1.2"})}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:(0,t.jsx)(n.code,{children:"go/v0.2101.2"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."}),(0,t.jsx)(n.td,{style:{textAlign:"center"},children:"..."})]})]})]}),"\n",(0,t.jsxs)(n.p,{children:["Using such a scheme makes the version of the Oasis Core Go module fully\ncompatible with the ",(0,t.jsx)(n.a,{href:"https://golang.org/ref/mod#versions",children:"Go Modules versioning requirements"})," and thus\nenables users to use the familiar Go tools to check for new module versions,\ni.e. ",(0,t.jsx)(n.code,{children:"go list -m -u all"}),", or to obtain and require a module, i.e.\n",(0,t.jsx)(n.code,{children:"go get github.com/oasisprotocol/oasis-core/go@latest"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"alternatives",children:"Alternatives"}),"\n",(0,t.jsx)(n.p,{children:"An alternative scheme would be to use the following Go Modules compatible Git\ntags:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"go/v0.YY.MINOR-MICRO\n"})}),"\n",(0,t.jsx)(n.p,{children:"where:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"YY"})," represents the short year (e.g. ",(0,t.jsx)(n.code,{children:"19"}),", ",(0,t.jsx)(n.code,{children:"20"}),", ",(0,t.jsx)(n.code,{children:"21"}),", ...),"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"MINOR"})," represents the minor version starting with zero (e.g. ",(0,t.jsx)(n.code,{children:"0"}),", ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"2"}),",\n",(0,t.jsx)(n.code,{children:"3"}),", ...),"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"MICRO"}),' represents the final number in the version (sometimes referred to as\nthe "patch" segment) (e.g. ',(0,t.jsx)(n.code,{children:"0"}),", ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"2"}),", ",(0,t.jsx)(n.code,{children:"3"}),", ...)."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Using the ",(0,t.jsx)(n.code,{children:"-MICRO"})," suffix would make Go treat all such versions as a\n",(0,t.jsx)(n.a,{href:"https://golang.org/ref/mod#glos-pre-release-version",children:"Go Modules pre-release version"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"The consequence of that would be that all Go tools would treat such versions as\npre-releases."}),"\n",(0,t.jsx)(n.p,{children:"For example, let's say the Oasis Core Go module would have the following Go\nversion tags:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"go/v0.20.9"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"go/v0.20.10-0"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"go/v0.20.10-1"})}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["and a module that depends on the Oasis Core Go module would currently require\nversion ",(0,t.jsx)(n.code,{children:"v0.20.9"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["One downside would be that the ",(0,t.jsx)(n.code,{children:"go list -m -u all"})," command would not notify a\nuser that an update, i.e. version ",(0,t.jsx)(n.code,{children:"v0.20.10-1"}),", is available."]}),"\n",(0,t.jsxs)(n.p,{children:["The second downside would be that using the\n",(0,t.jsx)(n.code,{children:"go get github.com/oasisprotocol/oasis-core/go@latest"})," command would treat\nversion ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"v0.20.10-1"})," in\nthis example."]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["This allow users to depend on a bugfix/patch release of the Oasis Core Go\nmodule in a ",(0,t.jsx)(n.a,{href:"https://golang.org/ref/mod#versions",children:"Go Modules versioning requirements"})," compatible way,\ni.e. without having to resort to pinning the requirement to a particular\nOasis Core commit."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The connection between an ordinary Git tag and a Go Modules compatible Git tag\nis not very obvious."}),"\n",(0,t.jsxs)(n.p,{children:["For example, it might not be immediately obvious that ",(0,t.jsx)(n.code,{children:"v21.0"})," and\n",(0,t.jsx)(n.code,{children:"go/v0.2100.0"})," refer to the same thing."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Using a zero-padded minor version fixed to two characters would limit the\nnumber of releases in a year to 100 releases."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/dgraph-io/badger",children:"BadgerDB"})," uses a ",(0,t.jsx)(n.a,{href:"https://github.com/dgraph-io/badger/releases",children:"similar scheme for tagging Go Modules compatible Git tags"}),"\nfor their CalVer versioning scheme."]}),"\n"]})]})}function x(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>d});var t=s(6540);const i={},r=t.createContext(i);function l(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7bee5ea1.88163222.js b/assets/js/7bee5ea1.88163222.js new file mode 100644 index 0000000000..9713ec79aa --- /dev/null +++ b/assets/js/7bee5ea1.88163222.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4938],{6557:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=s(4848),t=s(8453);const i={},r="Terminology",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/terminology.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Manage your Tokens",permalink:"/general/manage-tokens/"},next:{title:"Staking and Delegating",permalink:"/general/manage-tokens/staking-and-delegating"}},c={},d=[{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}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"terminology",children:"Terminology"}),"\n",(0,o.jsx)(n.h2,{id:"account",children:"Account"}),"\n",(0,o.jsxs)(n.p,{children:["A staking ",(0,o.jsx)(n.strong,{children:"account"})," is an entry in the staking ledger."]}),"\n",(0,o.jsx)(n.p,{children:"It has two (sub)accounts:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"General account"})}),"\n",(0,o.jsx)(n.p,{children:"It is used to keep the funds that are freely available to the account owner\nto transfer, delegate/stake, pay gas fees, etc."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Escrow account"})}),"\n",(0,o.jsx)(n.p,{children:"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, ...)."}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"address",children:"Address"}),"\n",(0,o.jsxs)(n.p,{children:["A staking account ",(0,o.jsx)(n.strong,{children:"address"})," is represented by a truncated hash of a\ncorresponding entity's public key, prefixed by a 1 byte address version."]}),"\n",(0,o.jsxs)(n.p,{children:["It uses ",(0,o.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32",children:"Bech32 encoding"})," for text serialization with ",(0,o.jsx)(n.code,{children:"oasis"})," as its human\nreadable part (HRP) prefix."]}),"\n",(0,o.jsxs)(n.p,{children:["EVM-compatible ParaTimes running on the Oasis compute layer ",(0,o.jsx)(n.strong,{children:"may use"}),"\nEVM-compatible 20-byte addresses in hex format (starting with ",(0,o.jsx)(n.code,{children:"0x"}),")."]}),"\n",(0,o.jsx)(n.h2,{id:"delegation",children:"Delegation"}),"\n",(0,o.jsxs)(n.p,{children:["You can ",(0,o.jsx)(n.strong,{children:"delegate"})," your tokens by submitting an ",(0,o.jsx)(n.strong,{children:"escrow"})," transaction that\ndeposits a specific number of tokens into someone else\u2019s escrow account (as\nopposed to ",(0,o.jsx)(n.strong,{children:"staking"})," tokens, which usually refers to depositing tokens into\nyour own escrow account)."]}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.h2,{id:"staking",children:"Staking"}),"\n",(0,o.jsxs)(n.p,{children:["You can stake your tokens by submitting an ",(0,o.jsx)(n.strong,{children:"escrow"})," transaction that deposits\na specific number of tokens into your escrow account."]}),"\n",(0,o.jsx)(n.h2,{id:"rewards",children:"Rewards"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.h2,{id:"commission",children:"Commission"}),"\n",(0,o.jsxs)(n.p,{children:["Node operators collect ",(0,o.jsx)(n.strong,{children:"commissions"})," when their node earns a\n",(0,o.jsx)(n.strong,{children:"staking reward"})," for delegators. A validator node earns a staking reward for\nparticipating in the consensus protocol each epoch. The ",(0,o.jsx)(n.strong,{children:"commission rate"})," is\na fraction of the staking reward."]}),"\n",(0,o.jsx)(n.p,{children:"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)."}),"\n",(0,o.jsx)(n.h2,{id:"slashing",children:"Slashing"}),"\n",(0,o.jsxs)(n.p,{children:["A portion of your delegated tokens can be ",(0,o.jsx)(n.strong,{children:"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."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>a});var o=s(6540);const t={},i=o.createContext(t);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7ca72da4.271d128a.js b/assets/js/7ca72da4.271d128a.js new file mode 100644 index 0000000000..cfdbb74072 --- /dev/null +++ b/assets/js/7ca72da4.271d128a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8660],{3873:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>p,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var i=n(4848),r=n(8453);const o={},s="Big Integer Quantities",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/bigint.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{}},d={},a=[{value:"Encoding",id:"encoding",level:2}];function u(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"big-integer-quantities",children:"Big Integer Quantities"}),"\n",(0,i.jsxs)(t.p,{children:["Arbitrary-precision positive integer quantities are represented by the\n",(0,i.jsx)(t.code,{children:"quantity.Quantity"})," type."]}),"\n",(0,i.jsx)(t.h2,{id:"encoding",children:"Encoding"}),"\n",(0,i.jsx)(t.p,{children:"When encoded it uses the big-endian byte order."})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var i=n(6540);const r={},o=i.createContext(r);function s(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7da689db.27e05283.js b/assets/js/7da689db.27e05283.js new file mode 100644 index 0000000000..e15b964b52 --- /dev/null +++ b/assets/js/7da689db.27e05283.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1420],{5754:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>o,metadata:()=>d,toc:()=>u});var t=r(4848),i=r(8453),a=r(1470),s=r(9365);const o={},l="ParaTime Node",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/run-node/paratime-node.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},c={},u=[{value:"About Oasis Network",id:"about-oasis-network",level:2},{value:"Operating ParaTimes",id:"operating-paratimes",level:2},{value:"Sapphire ParaTime",id:"sapphire-paratime",level:3},{value:"Overview",id:"overview",level:3},{value:"Features",id:"features",level:3},{value:"Mainnet Requirements",id:"mainnet-requirements",level:3},{value:"Cipher ParaTime",id:"cipher-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},{value:"Emerald ParaTime",id:"emerald-paratime",level:3},{value:"Overview",id:"overview-2",level:3},{value:"Features",id:"features-2",level:3},{value:"Mainnet Requirements",id:"mainnet-requirements-2",level:3}];function h(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"paratime-node",children:"ParaTime Node"}),"\n",(0,t.jsx)(n.p,{children:"This guide provides an overview of the requirements to become a compute node for\na ParaTime connected to the Oasis Network."}),"\n",(0,t.jsx)(n.h2,{id:"about-oasis-network",children:"About Oasis Network"}),"\n",(0,t.jsx)(n.p,{children:"The Oasis Network has two main components, the consensus layer and the ParaTime\nLayer."}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The ",(0,t.jsx)(n.strong,{children:"consensus layer"})," is a scalable, high-throughput, secure,\nproof-of-stake consensus run by a decentralized set of validator nodes."]}),"\n",(0,t.jsxs)(n.li,{children:["The ",(0,t.jsx)(n.strong,{children:"ParaTime layer"})," hosts many parallel runtimes (ParaTimes), each\nrepresenting a replicated compute environment with shared state."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Oasis architectural design including ParaTime and consensus layers",src:r(141).A+"",width:"1523",height:"718"})}),"\n",(0,t.jsx)(n.h2,{id:"operating-paratimes",children:"Operating ParaTimes"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"running a ParaTime node for node operators"}),"."]}),"\n",(0,t.jsxs)(a.A,{children:[(0,t.jsxs)(s.A,{value:"Sapphire ParaTime",children:[(0,t.jsx)(n.h3,{id:"sapphire-paratime",children:"Sapphire ParaTime"}),(0,t.jsx)(n.p,{children:"A confidential EVM-compatible Oasis Foundation developed ParaTime that enables\nthe use of EVM smart contracts on the Oasis network."}),(0,t.jsx)(n.h3,{id:"overview",children:"Overview"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Leading Developer:"})," ",(0,t.jsx)(n.a,{href:"http://oasisprotocol.org",children:"Oasis Protocol Foundation"}),", with contributions from\ncommunity developers"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Status:"})," Deployed on Mainnet and Testnet"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Testnet Launch Date:"})," July 2022"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Mainnet Launch Date:"})," Dec 2022"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Discord Channel:"})," ",(0,t.jsx)(n.a,{href:"/get-involved/",children:"#node-operators"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Requires SGX:"})," Yes"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Parameters:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/mainnet/#sapphire",children:"Mainnet"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/testnet/#sapphire",children:"Testnet"})}),"\n"]}),"\n"]}),"\n"]}),(0,t.jsx)(n.h3,{id:"features",children:"Features"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Fully decentralized with node operators distributed across the world."}),"\n",(0,t.jsxs)(n.li,{children:["Oasis ",(0,t.jsx)(n.strong,{children:"ROSE"})," tokens are the native token used in the ParaTime for gas fees."]}),"\n",(0,t.jsx)(n.li,{children:"Support for EVM smart contracts."}),"\n",(0,t.jsx)(n.li,{children:"Support for confidential compute."}),"\n"]}),(0,t.jsx)(n.h3,{id:"mainnet-requirements",children:"Mainnet Requirements"}),(0,t.jsx)(n.p,{children:"For your Sapphire ParaTime node to be eligible to be elected into the Sapphire\ncommittee on Mainnet, your entity needs to:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Have a validator in the ",(0,t.jsx)(n.strong,{children:"validator set"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Have at least ",(0,t.jsx)(n.strong,{children:"5,000,000.00 ROSE staked/delegated"})," to it."]}),"\n"]})]}),(0,t.jsxs)(s.A,{value:"Cipher ParaTime",children:[(0,t.jsx)(n.h3,{id:"cipher-paratime",children:"Cipher ParaTime"}),(0,t.jsx)(n.p,{children:"An Oasis Foundation developed ParaTime that enables WebAssembly-based\nconfidential smart contracts."}),(0,t.jsx)(n.h3,{id:"overview-1",children:"Overview"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Leading Developer:"})," ",(0,t.jsx)(n.a,{href:"http://oasisprotocol.org",children:"Oasis Protocol Foundation"}),", with contributions from\ncommunity developers"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Status:"})," Deployed on Mainnet and Testnet"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Testnet Launch Date:"})," June 2021"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Mainnet Launch Date:"})," October 2021"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Discord Channel:"})," ",(0,t.jsx)(n.a,{href:"/get-involved/",children:"#node-operators"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Requires SGX:"})," Yes"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Parameters:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/mainnet/#cipher",children:"Mainnet"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/testnet/#cipher",children:"Testnet"})}),"\n"]}),"\n"]}),"\n"]}),(0,t.jsx)(n.h3,{id:"features-1",children:"Features"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Fully decentralized with node operators distributed across the world."}),"\n",(0,t.jsxs)(n.li,{children:["Oasis ",(0,t.jsx)(n.strong,{children:"ROSE"})," tokens are the native token used in the ParaTime for gas fees."]}),"\n",(0,t.jsx)(n.li,{children:"Support for WebAssembly smart contracts."}),"\n",(0,t.jsx)(n.li,{children:"Support for confidential compute."}),"\n"]}),(0,t.jsx)(n.h3,{id:"mainnet-requirements-1",children:"Mainnet Requirements"}),(0,t.jsx)(n.p,{children:"For your Cipher ParaTime node to be eligible to be elected into the Cipher\ncommittee on Mainnet, your entity needs to:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Have a validator in the ",(0,t.jsx)(n.strong,{children:"validator set"}),"."]}),"\n"]})]}),(0,t.jsxs)(s.A,{value:"Emerald ParaTime",children:[(0,t.jsx)(n.h3,{id:"emerald-paratime",children:"Emerald ParaTime"}),(0,t.jsx)(n.p,{children:"An EVM-compatible Oasis Foundation developed ParaTime that enables the use of\nEVM smart contracts on the Oasis network."}),(0,t.jsx)(n.h3,{id:"overview-2",children:"Overview"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Leading Developer:"})," ",(0,t.jsx)(n.a,{href:"http://oasisprotocol.org",children:"Oasis Protocol Foundation"}),", with contributions from\ncommunity developers"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Status:"})," Deployed on Mainnet and Testnet"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Testnet Launch Date:"})," October 2021"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Mainnet Launch Date:"})," November 2021"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Discord Channel:"})," ",(0,t.jsx)(n.a,{href:"/get-involved/",children:"#node-operators"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Requires SGX:"})," No"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Parameters:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/mainnet/#emerald",children:"Mainnet"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/node/testnet/#emerald",children:"Testnet"})}),"\n"]}),"\n"]}),"\n"]}),(0,t.jsx)(n.h3,{id:"features-2",children:"Features"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Fully decentralized with node operators distributed across the world."}),"\n",(0,t.jsxs)(n.li,{children:["Oasis ",(0,t.jsx)(n.strong,{children:"ROSE"})," tokens are the native token used in the ParaTime for gas fees."]}),"\n"]}),(0,t.jsx)(n.h3,{id:"mainnet-requirements-2",children:"Mainnet Requirements"}),(0,t.jsx)(n.p,{children:"For your Emerald ParaTime node to be eligible to be elected into the Emerald\ncommittee on Mainnet, your entity needs to:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Have a validator in the ",(0,t.jsx)(n.strong,{children:"validator set"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Have at least ",(0,t.jsx)(n.strong,{children:"5,000,000.00 ROSE staked/delegated"})," to it."]}),"\n"]})]})]})]})}function m(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},9365:(e,n,r)=>{r.d(n,{A:()=>s});r(6540);var t=r(4164);const i={tabItem:"tabItem_Ymn6"};var a=r(4848);function s(e){let{children:n,hidden:r,className:s}=e;return(0,a.jsx)("div",{role:"tabpanel",className:(0,t.A)(i.tabItem,s),hidden:r,children:n})}},1470:(e,n,r)=>{r.d(n,{A:()=>T});var t=r(6540),i=r(4164),a=r(3104),s=r(6347),o=r(205),l=r(7485),d=r(1682),c=r(9466);function u(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function h(e){const{values:n,children:r}=e;return(0,t.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:r,attributes:t,default:i}}=e;return{value:n,label:r,attributes:t,default:i}}))}(r);return function(e){const n=(0,d.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`)}(e),e}),[n,r])}function m(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:r}=e;const i=(0,s.W6)(),a=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)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 r??null}({queryString:n,groupId:r});return[(0,l.aZ)(a),(0,t.useCallback)((e=>{if(!a)return;const n=new URLSearchParams(i.location.search);n.set(a,e),i.replace({...i.location,search:n.toString()})}),[a,i])]}function v(e){const{defaultValue:n,queryString:r=!1,groupId:i}=e,a=h(e),[s,l]=(0,t.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(n){if(!m({value:n,tabValues:r}))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const t=r.find((e=>e.default))??r[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:a}))),[d,u]=p({queryString:r,groupId:i}),[v,x]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[i,a]=(0,c.Dv)(r);return[i,(0,t.useCallback)((e=>{r&&a.set(e)}),[r,a])]}({groupId:i}),j=(()=>{const e=d??v;return m({value:e,tabValues:a})?e:null})();(0,o.A)((()=>{j&&l(j)}),[j]);return{selectedValue:s,selectValue:(0,t.useCallback)((e=>{if(!m({value:e,tabValues:a}))throw new Error(`Can't select invalid tab value=${e}`);l(e),u(e),x(e)}),[u,x,a]),tabValues:a}}var x=r(2303);const j={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=r(4848);function g(e){let{className:n,block:r,selectedValue:t,selectValue:s,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:d}=(0,a.a_)(),c=e=>{const n=e.currentTarget,r=l.indexOf(n),i=o[r].value;i!==t&&(d(n),s(i))},u=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const r=l.indexOf(e.currentTarget)+1;n=l[r]??l[0];break}case"ArrowLeft":{const r=l.indexOf(e.currentTarget)-1;n=l[r]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.A)("tabs",{"tabs--block":r},n),children:o.map((e=>{let{value:n,label:r,attributes:a}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:t===n?0:-1,"aria-selected":t===n,ref:e=>l.push(e),onKeyDown:u,onClick:c,...a,className:(0,i.A)("tabs__item",j.tabItem,a?.className,{"tabs__item--active":t===n}),children:r??n},n)}))})}function b(e){let{lazy:n,children:r,selectedValue:i}=e;const a=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===i));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,t.cloneElement)(e,{key:n,hidden:e.props.value!==i})))})}function y(e){const n=v(e);return(0,f.jsxs)("div",{className:(0,i.A)("tabs-container",j.tabList),children:[(0,f.jsx)(g,{...n,...e}),(0,f.jsx)(b,{...n,...e})]})}function T(e){const n=(0,x.A)();return(0,f.jsx)(y,{...e,children:u(e.children)},String(n))}},141:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"},8453:(e,n,r)=>{r.d(n,{R:()=>s,x:()=>o});var t=r(6540);const i={},a=t.createContext(i);function s(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/82c34158.6d656fb2.js b/assets/js/82c34158.6d656fb2.js new file mode 100644 index 0000000000..893708308d --- /dev/null +++ b/assets/js/82c34158.6d656fb2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9737],{4271:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var i=t(4848),a=t(8453);const s={description:"Authenticate users with your confidential contracts"},r="View-Call Authentication",c={id:"dapp/sapphire/authentication",title:"View-Call Authentication",description:"Authenticate users with your confidential contracts",source:"@site/docs/dapp/sapphire/authentication.md",sourceDirName:"dapp/sapphire",slug:"/dapp/sapphire/authentication",permalink:"/dapp/sapphire/authentication",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/authentication.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Authenticate users with your confidential contracts"},sidebar:"developers",previous:{title:"Browser Support",permalink:"/dapp/sapphire/browser"},next:{title:"Gasless Transactions",permalink:"/dapp/sapphire/gasless"}},o={},d=[{value:"Sapphire Wrapper",id:"sapphire-wrapper",level:2},{value:"Caching Signed Queries",id:"caching-signed-queries",level:2},{value:"Daily Sign-In with EIP-712",id:"daily-sign-in-with-eip-712",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"view-call-authentication",children:"View-Call Authentication"}),"\n",(0,i.jsxs)(n.p,{children:['User impersonation on Ethereum and other "Transparent EVMs" isn\'t a problem\nbecause ',(0,i.jsx)(n.strong,{children:"everybody"})," can see ",(0,i.jsx)(n.strong,{children:"all"})," data however the Sapphire confidential\nEVM prevents contracts from revealing confidential information to the wrong\nparty (account or contract) - for this reason we cannot allow arbitrary\nimpersonation of any ",(0,i.jsx)(n.code,{children:"msg.sender"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"In Sapphire, there are four types of contract calls:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Contract to contract calls (also known as ",(0,i.jsx)(n.em,{children:"internal calls"}),")"]}),"\n",(0,i.jsxs)(n.li,{children:["Unauthenticted view calls (queries using ",(0,i.jsx)(n.code,{children:"eth_call"}),")"]}),"\n",(0,i.jsx)(n.li,{children:"Authenticated view calls (signed queries)"}),"\n",(0,i.jsx)(n.li,{children:"Transactions (authenticated by signature)"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Intra-contract calls always set ",(0,i.jsx)(n.code,{children:"msg.sender"})," appropriately, if a contract calls\nanother contract in a way which could reveal sensitive information, the calling\ncontract must implement access control or authentication."]}),"\n",(0,i.jsxs)(n.p,{children:["By default all ",(0,i.jsx)(n.code,{children:"eth_call"})," queries used to invoke contract functions have the\n",(0,i.jsx)(n.code,{children:"msg.sender"})," parameter set to ",(0,i.jsx)(n.code,{children:"address(0x0)"}),". In contrast, authenticated calls are\nsigned by a keypair and will have the ",(0,i.jsx)(n.code,{children:"msg.sender"})," parameter correctly initialized\n(more on that later). Also, when a transaction is\nsubmitted it is signed by a keypair (thus costs gas and can make state updates)\nand the ",(0,i.jsx)(n.code,{children:"msg.sender"})," will be set to the signing account."]}),"\n",(0,i.jsx)(n.h2,{id:"sapphire-wrapper",children:"Sapphire Wrapper"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime",children:"@oasisprotocol/sapphire-paratime"})," Ethereum provider wrapper\n",(0,i.jsx)(n.code,{children:"sapphire.wrap"})," function will ",(0,i.jsx)(n.strong,{children:"automatically end-to-end encrypt calldata"})," when\ninteracting with contracts on Sapphire, this is an easy way to ensure the\ncalldata of your dApp transactions remain confidential - although the ",(0,i.jsx)(n.code,{children:"from"}),",\n",(0,i.jsx)(n.code,{children:"to"}),", and ",(0,i.jsx)(n.code,{children:"gasprice"})," parameters are not encrypted."]}),"\n",(0,i.jsx)(n.admonition,{title:"Unauthenticated calls and Encryption",type:"tip",children:(0,i.jsx)(n.p,{children:"Although the calls may be unauthenticated, they can still be encrypted!"})}),"\n",(0,i.jsxs)(n.p,{children:["However, if the Sapphire wrapper has been attached to a signer then subsequent\nview calls via ",(0,i.jsx)(n.code,{children:"eth_call"})," will request that the user sign them (e.g. a\nMetaMask popup), these are called ",(0,i.jsx)(n.strong,{children:"signed queries"})," meaning ",(0,i.jsx)(n.code,{children:"msg.sender"})," will be\nset to the signing account and can be used for authentication or to implement\naccess control. This may add friction to the end-user experience and can result\nin frequent pop-ups requesting they sign queries which wouldn't normally require\nany interaction on Transparent EVMs."]}),"\n",(0,i.jsx)(n.p,{children:"Let's see how Sapphire interprets different contract calls. Suppose the\nfollowing solidity code:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-solidity",children:"contract Example {\n address owner;\n constructor () {\n owner = msg.sender;\n }\n function isOwner () public view returns (bool) {\n return msg.sender == owner;\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In the sample above, assuming we're calling from the same contract or account\nwhich created the contract, calling ",(0,i.jsx)(n.code,{children:"isOwner"})," will return:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"false"}),", for ",(0,i.jsx)(n.code,{children:"eth_call"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"false"}),", with ",(0,i.jsx)(n.code,{children:"sapphire.wrap"})," but without an attached signer"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"true"}),", with ",(0,i.jsx)(n.code,{children:"sapphire.wrap"})," and an attached signer"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"true"}),", if called via the contract which created it"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"true"}),", if called via transaction"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"caching-signed-queries",children:"Caching Signed Queries"}),"\n",(0,i.jsx)(n.p,{children:"When using signed queries the blockchain will be queried each time, however\nthe Sapphire wrapper will cache signatures for signed queries with the same\nparameters to avoid asking the user to sign the same thing multiple times."}),"\n",(0,i.jsxs)(n.p,{children:['Behind the scenes the signed queries use a "leash" to specify validity conditions\nso the query can only be performed within a block and account ',(0,i.jsx)(n.code,{children:"nonce"})," range.\nThese parameters are visible in the EIP-712 popup signed by the user. Queries\nwith the same parameters will use the same leash."]}),"\n",(0,i.jsx)(n.h2,{id:"daily-sign-in-with-eip-712",children:"Daily Sign-In with EIP-712"}),"\n",(0,i.jsxs)(n.p,{children:["One strategy which can be used to reduce the number of transaction signing\nprompts when a user interacts with contracts via a dApp is to use\n",(0,i.jsx)(n.a,{href:"https://eips.ethereum.org/EIPS/eip-712",children:"EIP-712"}),' to "sign-in" once per day (or per-session), in combination\nwith using two wrapped providers:']}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Provider to perform encrypted but unauthenticated view calls"}),"\n",(0,i.jsxs)(n.li,{children:["Another provider to perform encrypted and authenticated transactions (or view calls)","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"The user will be prompted to sign each action."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The two-provider pattern, in conjunction with a daily EIP-712 sign-in prompt\nensures all transactions are end-to-end encrypted and the contract can\nauthenticate users in view calls without frequent annoying popups."}),"\n",(0,i.jsxs)(n.p,{children:["The code sample below uses an ",(0,i.jsx)(n.code,{children:"authenticated"})," modifier to verify the sign-in:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-solidity",children:'// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nstruct SignatureRSV {\n bytes32 r;\n bytes32 s;\n uint256 v;\n}\n\ncontract SignInExample {\n bytes32 public constant EIP712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");\n string public constant SIGNIN_TYPE = "SignIn(address user,uint32 time)";\n bytes32 public constant SIGNIN_TYPEHASH = keccak256(bytes(SIGNIN_TYPE));\n bytes32 public immutable DOMAIN_SEPARATOR;\n\n constructor () {\n DOMAIN_SEPARATOR = keccak256(abi.encode(\n EIP712_DOMAIN_TYPEHASH,\n keccak256("SignInExample.SignIn"),\n keccak256("1"),\n block.chainid,\n address(this)\n ));\n }\n\n struct SignIn {\n address user;\n uint32 time;\n SignatureRSV rsv;\n }\n\n modifier authenticated(SignIn calldata auth)\n {\n // Must be signed within 24 hours ago.\n require( auth.time > (block.timestamp - (60*60*24)) );\n\n // Validate EIP-712 sign-in authentication.\n bytes32 authdataDigest = keccak256(abi.encodePacked(\n "\\x19\\x01",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(\n SIGNIN_TYPEHASH,\n auth.user,\n auth.time\n ))\n ));\n\n address recovered_address = ecrecover(\n authdataDigest, uint8(auth.rsv.v), auth.rsv.r, auth.rsv.s);\n\n require( auth.user == recovered_address, "Invalid Sign-In" );\n\n _;\n }\n\n function authenticatedViewCall(\n SignIn calldata auth,\n ... args\n )\n external view\n authenticated(auth)\n returns (bytes memory output)\n {\n // Use `auth.user` instead of `msg.sender`!\n }\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"With the above contract code deployed, let's look at the frontend dApp and how\nit can request the user to sign-in using EIP-712. You may wish to add additional\nparameters which are authenticated such as the domain name. The following code\nexample uses Ethers:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:'const time = new Date().getTime();\nconst user = await eth.signer.getAddress();\n\n// Ask user to "Sign-In" every 24 hours.\nconst signature = await eth.signer.signTypedData({\n name: "SignInExample.SignIn",\n version: "1",\n chainId: import.meta.env.CHAINID,\n verifyingContract: await contract.getAddress()\n}, {\n SignIn: [\n { name: \'user\', type: "address" },\n { name: \'time\', type: \'uint32\' },\n ]\n}, {\n user,\n time: time\n});\nconst rsv = ethers.Signature.from(signature);\nconst auth = {user, time, rsv};\n// The `auth` variable can then be cached.\n\n// Then in the future, authenticated view calls can be performed by\n// passing auth without further user interaction authenticated data.\nawait contract.authenticatedViewCall(auth, ...args);\n'})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>c});var i=t(6540);const a={},s=i.createContext(a);function r(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/85011861.ba4e738a.js b/assets/js/85011861.ba4e738a.js new file mode 100644 index 0000000000..8d5b1ae8a9 --- /dev/null +++ b/assets/js/85011861.ba4e738a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5403],{6995:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>d});var s=t(4848),a=t(8453);const i={title:"Transaction",description:"Use CLI to decode, verify, sign and submit a transaction"},o="Transaction Tools",r={id:"general/manage-tokens/cli/transaction",title:"Transaction",description:"Use CLI to decode, verify, sign and submit 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/transaction.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,frontMatter:{title:"Transaction",description:"Use CLI to decode, verify, sign and submit a transaction"},sidebar:"general",previous:{title:"Account",permalink:"/general/manage-tokens/cli/account"},next:{title:"Address book",permalink:"/general/manage-tokens/cli/addressbook"}},c={},d=[{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}];function l(n){const e={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...n.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(e.h1,{id:"transaction-tools",children:"Transaction Tools"}),"\n",(0,s.jsxs)(e.p,{children:["The ",(0,s.jsx)(e.code,{children:"transaction"})," command offers convenient tools for processing raw\nconsensus or ParaTime transactions stored in a JSON file:"]}),"\n",(0,s.jsxs)(e.ul,{children:["\n",(0,s.jsx)(e.li,{children:"decoding and displaying the transaction,"}),"\n",(0,s.jsx)(e.li,{children:"verifying transaction's signature,"}),"\n",(0,s.jsx)(e.li,{children:"signing the transaction,"}),"\n",(0,s.jsx)(e.li,{children:"broadcasting the transaction."}),"\n"]}),"\n",(0,s.jsx)(e.h2,{id:"show",children:"Decode, Verify and Show a Transaction"}),"\n",(0,s.jsxs)(e.p,{children:["To show the transaction, invoke ",(0,s.jsx)(e.code,{children:"transaction show <filename.json>"})," and provide\na filename containing a previously generated transaction by ",(0,s.jsx)(e.code,{children:"oasis-node"})," or the\nOasis CLI's ",(0,s.jsx)(e.a,{href:"/general/manage-tokens/cli/account#output-file",children:(0,s.jsx)(e.code,{children:"--output-file"})})," parameter."]}),"\n",(0,s.jsxs)(e.p,{children:["For example, let's take the following transaction transferring ",(0,s.jsx)(e.code,{children:"1.0 TEST"})," from\n",(0,s.jsx)(e.code,{children:"test:alice"})," to ",(0,s.jsx)(e.code,{children:"test:bob"})," on Testnet consensus layer and store it to\n",(0,s.jsx)(e.code,{children:"testtx.json"}),":"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",metastring:'title="testtx.json"',children:'{\n "untrusted_raw_value": "pGNmZWWiY2dhcwFmYW1vdW50QGRib2R5omJ0b1UAyND0Wds45cwxynfmbSxEVty+tQJmYW1vdW50RDuaygBlbm9uY2UBZm1ldGhvZHBzdGFraW5nLlRyYW5zZmVy",\n "signature": {\n "public_key": "NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=",\n "signature": "ph5Sj29JFG8p0rCqAXjHm+yLwiXHybxah9C1cVTI01SDeJlyXT8dbp4BfI1hFxBomgi1hOrevTpShX0f9puTCQ=="\n }\n}\n'})}),"\n",(0,s.jsx)(e.p,{children:"We can decode and verify the transaction as follows:"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis transaction show testtx.json --network testnet\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"Hash: c996e9d17d652d5dc64589d10806c244a5ef0f650cc2ec8c810b28a85fef5705\nSigner: NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: ph5Sj29JFG8p0rCqAXjHm+yLwiXHybxah9C1cVTI01SDeJlyXT8dbp4BfI1hFxBomgi1hOrevTpShX0f9puTCQ==)\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"})}),"\n",(0,s.jsxs)(e.p,{children:["Since the signature depends on the ",(0,s.jsx)(e.a,{href:"/core/crypto#chain-domain-separation",children:"chain domain separation context"}),", the\ntransaction above will be invalid on other networks such as the Mainnet. In this\ncase the Oasis CLI will print the ",(0,s.jsx)(e.code,{children:"[INVALID SIGNATURE]"})," warning below the\nsignature:"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis transaction show testtx.json --network mainnet\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-text",metastring:"{4}",children:"Hash: c996e9d17d652d5dc64589d10806c244a5ef0f650cc2ec8c810b28a85fef5705\nSigner: NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: ph5Sj29JFG8p0rCqAXjHm+yLwiXHybxah9C1cVTI01SDeJlyXT8dbp4BfI1hFxBomgi1hOrevTpShX0f9puTCQ==)\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"})}),"\n",(0,s.jsxs)(e.p,{children:["The ",(0,s.jsx)(e.code,{children:"show"})," command is also compatible with ParaTime transactions. Take the\nfollowing transaction which transfers ",(0,s.jsx)(e.code,{children:"1.0 TEST"})," from ",(0,s.jsx)(e.code,{children:"test:alice"})," to ",(0,s.jsx)(e.code,{children:"test:bob"}),"\ninside Sapphire ParaTime on the Testnet:"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",metastring:'title="testtx2.json"',children:'{\n "Body": "o2F2AWJhaaJic2mBomVub25jZQFsYWRkcmVzc19zcGVjoWlzaWduYXR1cmWhZ2VkMjU1MTlYIDXD8zVt2FNk/roDVLVFraEJ0b2zi/XWEmgX24xyz9aRY2ZlZaJjZ2FzAWZhbW91bnSCQEBkY2FsbKJkYm9keaJidG9VAMjQ9FnbOOXMMcp35m0sRFbcvrUCZmFtb3VudIJIDeC2s6dkAABAZm1ldGhvZHFhY2NvdW50cy5UcmFuc2Zlcg==",\n "AuthProofs": [\n {\n "signature": "u71xOVJhRrUth5rNTAa2HuARYCsGLmvOCRE05fCbaQiSoQhXtKPVP9feoQSXmLVxISCHr/0aNnRLEoifJLMzBQ=="\n }\n ]\n}\n'})}),"\n",(0,s.jsxs)(e.p,{children:["The Oasis CLI will be able to verify a transaction only for the ",(0,s.jsx)(e.strong,{children:"exact network\nand ParaTime combination"})," since both are used to derive the chain domain\nseparation context for signing the transaction."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis transaction show testtx2.json --network testnet --paratime sapphire\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"Hash: 1558a5d6254a1b216a0885fa16114899e35b27622fd5af7c8b2eee7284dcad2e\nSigner(s):\n 1. NcPzNW3YU2T+ugNUtUWtoQnRvbOL9dYSaBfbjHLP1pE=\n (signature: u71xOVJhRrUth5rNTAa2HuARYCsGLmvOCRE05fCbaQiSoQhXtKPVP9feoQSXmLVxISCHr/0aNnRLEoifJLMzBQ==)\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"})}),"\n",(0,s.jsx)(e.h2,{id:"sign",children:"Sign a Transaction"}),"\n",(0,s.jsxs)(e.p,{children:["To sign a ",(0,s.jsx)(e.a,{href:"/general/manage-tokens/cli/account#unsigned",children:"previously unsigned transaction"})," transaction or to append\nanother signature to the transaction (",(0,s.jsx)(e.em,{children:"multisig"}),"), run\n",(0,s.jsx)(e.code,{children:"transaction sign <filename.json>"}),"."]}),"\n",(0,s.jsxs)(e.p,{children:["For example, let's transfer ",(0,s.jsx)(e.code,{children:"1.0 TEST"})," from ",(0,s.jsx)(e.code,{children:"test:alice"})," to ",(0,s.jsx)(e.code,{children:"test:bob"})," on\nTestnet consensus layer, but don't sign it and store it to\n",(0,s.jsx)(e.code,{children:"testtx_unsigned.json"}),":"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-json",metastring:'title="testtx_unsigned.json"',children:'{\n "nonce": 32,\n "fee": {\n "amount": "0",\n "gas": 1265\n },\n "method": "staking.Transfer",\n "body": "omJ0b1UAyND0Wds45cwxynfmbSxEVty+tQJmYW1vdW50RDuaygA="\n}\n'})}),"\n",(0,s.jsxs)(e.p,{children:["Comparing this transaction to ",(0,s.jsx)(e.a,{href:"#show",children:(0,s.jsx)(e.code,{children:"testtx.json"})})," which was signed, we can\nnotice that the transaction is not wrapped inside the ",(0,s.jsx)(e.code,{children:"untrusted_raw_value"}),"\nenvelope with the ",(0,s.jsx)(e.code,{children:"signature"})," field."]}),"\n",(0,s.jsx)(e.p,{children:"Decoding unsigned transaction gives us similar output:"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis transaction show testtx_unsigned.json --network testnet\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"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"})}),"\n",(0,s.jsx)(e.p,{children:"Finally, let's sign the transaction:"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis transaction sign testtx_unsigned.json --network testnet --account test:alice\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"You are about to sign the following transaction:\nMethod: staking.Transfer\nBody:\n To: oasis1qrydpazemvuwtnp3efm7vmfvg3tde044qg6cxwzx\n Amount: 1.0 TEST\nNonce: 47\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"})}),"\n",(0,s.jsxs)(e.p,{children:["We can also use ",(0,s.jsx)(e.a,{href:"/general/manage-tokens/cli/account#output-file",children:(0,s.jsx)(e.code,{children:"--output-file"})})," here and store the\nsigned transaction back to another file instead of showing it."]}),"\n",(0,s.jsx)(e.admonition,{type:"info",children:(0,s.jsxs)(e.p,{children:[(0,s.jsx)(e.a,{href:"/general/manage-tokens/cli/account#npa",children:"Network and Account"})," selectors are available for the ",(0,s.jsx)(e.code,{children:"transaction sign"}),"\ncommand."]})}),"\n",(0,s.jsx)(e.h2,{id:"submit",children:"Submit a Transaction"}),"\n",(0,s.jsxs)(e.p,{children:["Invoking ",(0,s.jsx)(e.code,{children:"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."]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis tx submit testtx.json --network testnet --no-paratime\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"Broadcasting transaction...\nTransaction executed successfully.\nTransaction hash: a81a1dcd203bba01761a55527f2c44251278110a247e63a12f064bf41e07f13a\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",children:"oasis tx submit testtx2.json --network testnet --paratime sapphire\n"})}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{children:"Broadcasting transaction...\nTransaction included in block successfully.\nRound: 946461\nTransaction hash: 25f0b2a92b6171969e9cd41d047bc20b4e2307c3a329ddef41af73df69d95b5d\n"})})]})}function h(n={}){const{wrapper:e}={...(0,a.R)(),...n.components};return e?(0,s.jsx)(e,{...n,children:(0,s.jsx)(l,{...n})}):l(n)}},8453:(n,e,t)=>{t.d(e,{R:()=>o,x:()=>r});var s=t(6540);const a={},i=s.createContext(a);function o(n){const e=s.useContext(i);return s.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function r(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(a):n.components||a:o(n.components),s.createElement(i.Provider,{value:e},n.children)}}}]); \ No newline at end of file diff --git a/assets/js/8509.15e604b0.js b/assets/js/8509.15e604b0.js new file mode 100644 index 0000000000..dbb6c1b0aa --- /dev/null +++ b/assets/js/8509.15e604b0.js @@ -0,0 +1,2 @@ +/*! For license information please see 8509.15e604b0.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8509],{8478:(e,t,r)=>{"use strict";r.d(t,{A:()=>i});r(6540);var n=r(2303),a=r(4848);function i(e){let{children:t,fallback:r}=e;return(0,n.A)()?(0,a.jsx)(a.Fragment,{children:t?.()}):r??null}},8157:e=>{var t;self,t=function(){return function(){var e={9288:function(e,t,r){"use strict";var n=r(3400),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])}},6712:function(e,t,r){"use strict";e.exports=r(1843)},7240:function(e,t,r){"use strict";e.exports=r(1132)},6144:function(e,t,r){"use strict";e.exports=r(7776)},2016:function(e,t,r){"use strict";e.exports=r(4884)},5556:function(e,t,r){"use strict";e.exports=r(6744)},6489:function(e,t,r){"use strict";e.exports=r(2028)},3472:function(e,t,r){"use strict";var n=r(2016);n.register([r(7240),r(260),r(6712),r(5556),r(6489),r(7312),r(6144)]),e.exports=n},260:function(e,t,r){"use strict";e.exports=r(5792)},7312:function(e,t,r){"use strict";e.exports=r(6272)},2196: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}]},3916:function(e,t,r){"use strict";var n=r(2196),a=r(5376),i=r(3816),o=r(1780).templatedArray;r(6208),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"}}})},272:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(6196).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)}},2300:function(e,t,r){"use strict";var n=r(3400),a=r(4040),i=r(1780).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)}}}},7192:function(e,t,r){"use strict";var n=r(3400),a=r(6308);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)),m=n.extendFlat({},v.font);m.color||(m.color=g),n.coerceFont(i,"hoverlabel.font",m)}i("captureevents",!!p)}},9208:function(e,t,r){"use strict";var n=r(8248),a=r(6896);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)}}},5216:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(1272),o=r(7192),l=r(3916);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})}},6196:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(7316),o=r(3400),l=o.strTranslate,s=r(4460),c=r(6308),u=r(3616),f=r(3024),d=r(2736),h=r(3972),p=r(6476),v=r(1780).arrayEditor,y=r(3652);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),z=M[t.showarrow?"annotationTail":"annotationPosition"],R=t.captureevents||M.annotationText||z,E=I.append("g").style("pointer-events",R?"all":null).call(h,"pointer").on("click",(function(){e._dragging=!1,e.emit("plotly_clickannotation",G(n.event))}));t.hovertext&&E.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,fontWeight:n.weight,fontStyle:n.style,fontVariant:n.variant},{container:w._hoverlayer.node(),outerContainer:w._paper.node(),gd:e})})).on("mouseout",(function(){f.loneUnhover(w._hoverlayer.node())}));var N=t.borderwidth,F=t.borderpad,H=N+F,j=E.append("rect").attr("class","bg").style("stroke-width",N+"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 V=t.font,U=w._meta?o.templateString(t.text,w._meta):t.text,q=E.append("text").classed("annotation-text",!0).text(U);M.annotationText?q.call(d.makeEditable,{delegate:E,gd:e}).call(Z).on("edit",(function(r){t.text=r,this.call(Z),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(Z)}else n.selectAll("#"+O).remove();function G(e){var n={index:r,annotation:t._input,fullAnnotation:t,event:e};return i&&(n.subplotId=i),n}function Z(r){return r.call(u.font,V).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()&&E.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=E.select(".annotation-text-math-group"),f=!n.empty(),v=u.bBox((f?n:q).node()),b=v.width,_=v.height,k=t.width||b,R=t.height||_,F=Math.round(k+2*H),V=Math.round(R+2*H);function U(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 Z=!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=V*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)&&(Z=!0):Z=!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*U(.5,t.xanchor)-le*U(.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*U($,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(Z)E.remove();else{var be=0,_e=0;if("left"!==t.align&&(be=(k-b)*("center"===t.align?.5:1)),"top"!==t.valign&&(_e=(R-_)*("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,R),j.call(u.setRect,N/2,N/2,F-N,V-N),E.call(u.setTranslate,Math.round(D.x.text-F/2),Math.round(D.y.text-V/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"),z=+j.attr("height"),R=v-.5*O,N=R+O,F=b-.5*z,H=F+z,B=[[R,F,R,H],[R,H,N,H],[N,H,N,F],[N,F,R,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,V=t.arrowcolor,U=t.arrowside,q=P.append("g").style({opacity:c.opacity(V)}).classed("annotation-arrow-g",!0),G=q.append("path").attr("d","M"+d+","+h+"L"+s+","+f).style("stroke-width",Y+"px").call(c.stroke,c.rgb(V));if(y(G,U,t),M.annotationPosition&&G.node().parentNode&&!i){var Z=s,W=f;if(t.standoff){var X=Math.sqrt(Math.pow(s-d,2)+Math.pow(f-h,2));Z+=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-Z)+","+(h-W),transform:l(Z,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(E);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;E.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),z&&p.init({element:E.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(E,n)},clickFn:function(r,n){t.captureevents&&e.emit("plotly_clickannotation",G(n))},doneFn:function(){h(E),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}},3652:function(e,t,r){"use strict";var n=r(3428),a=r(6308),i=r(2196),o=r(3400),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 z();if(b){if(b*b>w*w+T*T)return void z();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 z();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 z();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 z(){e.style("stroke-dasharray","0px,100px")}function R(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&&R(v,o,f,g),x&&R(p,u,d,y)}},9180:function(e,t,r){"use strict";var n=r(6196),a=r(2300);e.exports={moduleType:"component",name:"annotations",layoutAttributes:r(3916),supplyLayoutDefaults:r(5216),includeBasePlot:r(6632)("annotations"),calcAutorange:r(272),draw:n.draw,drawOne:n.drawOne,drawRaw:n.drawRaw,hasClickToShow:a.hasClickToShow,onClick:a.onClick,convertCoords:r(9208)}},5899:function(e,t,r){"use strict";var n=r(3916),a=r(7824).overrideAll,i=r(1780).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")},76:function(e,t,r){"use strict";var n=r(3400),a=r(4460);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()}},2808:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(1272),o=r(7192),l=r(5899);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})}},1836:function(e,t,r){"use strict";var n=r(6196).drawRaw,a=r(4424),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))}}},6864:function(e,t,r){"use strict";var n=r(4040),a=r(3400);e.exports={moduleType:"component",name:"annotations3d",schema:{subplots:{scene:{annotations:r(5899)}}},layoutAttributes:r(5899),handleDefaults:r(2808),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(76),draw:r(1836)}},4976:function(e,t,r){"use strict";e.exports=r(8700),r(5168),r(7020),r(7411),r(5668),r(2787),r(2084),r(6368),r(4747),r(5616),r(632),r(3040),r(1104),r(9075),r(4592),r(5348)},7776:function(e,t,r){"use strict";var n=r(4976),a=r(3400),i=r(9032),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}}},2548: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},6308:function(e,t,r){"use strict";var n=r(9760),a=r(8248),i=r(8116).isTypedArray,o=e.exports={},l=r(2548);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.interpolate=function(e,t,r){var a=n(e).toRgb(),i=n(t).toRgb(),o={r:r*a.r+(1-r)*i.r,g:r*a.g+(1-r)*i.g,b:r*a.b+(1-r)*i.b};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)}}},616:function(e,t,r){"use strict";var n=r(4724),a=r(5376),i=r(2880).extendFlat,o=r(7824).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")},3964: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"}}},4013:function(e,t,r){"use strict";var n=r(3400),a=r(1780),i=r(6332),o=r(5404),l=r(5936),s=r(2568),c=r(616);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={noAutotickangles:!0,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,{weight:A.weight,style:A.style,variant:A.variant,color:A.color,size:n.bigFont(S.size)});n.coerceFont(d,"title.font",O),d("title.side",y?"top":"right")}},7848:function(e,t,r){"use strict";var n=r(3428),a=r(9760),i=r(7316),o=r(4040),l=r(4460),s=r(6476),c=r(3400),u=c.strTranslate,f=r(2880).extendFlat,d=r(3972),h=r(3616),p=r(6308),v=r(1668),y=r(2736),g=r(4288).flipScale,m=r(5955),x=r(7668),b=r(4724),_=r(4284),w=_.LINE_SPACING,T=_.FROM_TL,M=_.FROM_BR,k=r(3964).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];if((n=d[0].trace)._module){var h=n._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,z=o?t.y:1-t.y,R="paper"===t.yref,E="paper"===t.xref,N=r._fullLayout,F=N._size,H=t._fillcolor,j=t._line,B=t.title,Y=B.side,V=t._zrange||n.extent(("function"==typeof H?H:j.color).domain()),U="function"==typeof j.color?j.color:function(){return j.color},q="function"==typeof H?H:function(){return H},G=t._levels,Z=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,V),W=Z.fill,X=Z.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=E?F.w:r._fullLayout.width,te=R?F.h:r._fullLayout.height,re=Math.round(o?I*ee+C:z*te+P),ne={center:.5,right:1}[O]||0,ae={top:1,middle:.5}[D]||0,ie=o?I-ne*K:z-ae*K,oe=o?z-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,noAutotickangles:"y"===o,noHover:!0,noTickson:!0,noTicklabelmode:!0,noInsideRange:!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,V);se.position=K+(o?I+C/F.w:z+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=z+P/F.h,se.titlex=oe+C/F.w),j.color&&"auto"===t.tickmode){se.tickmode="linear",se.tick0=G.start;var ue=G.size,fe=c.constrain(Q/50,4,15)+1,de=(V[1]-V[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(G.start)/G.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:N._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*z+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?N.width:N.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).attr("style",""),m.exit().remove();var x=V.map(se.c2p).map(Math.round).sort((function(e,t){return e-t}));m.each((function(e,i){var l=[0===i?V[0]:(W[i]+W[i-1])/2,i===W.length-1?V[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,U(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&&z<=0&&(b+=w=b/2,y+=w),N._hColorbarMoveTitle=w,N._hColorbarMoveCBTitle=y;var H=L+A,j=(o?re:le)-H/2-(o?C:0),V=(o?le:re)-(o?Q:P+y-w);e.select("."+k.cbbg).attr("x",j).attr("y",V).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 U=v?Math.max(c-10,0):0;e.selectAll("."+k.cboutline).attr("x",(o?re:le+C)+U).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+U),2)).call(p.stroke,t.outlinecolor).style({fill:"none","stroke-width":A});var q=o?ne*b:0,G=o?0:(1-ae)*b-y;if(q=E?F.l-q:-q,G=R?F.t-G:-G,e.attr("transform",u(q,G)),!o&&(L||a(S).getAlpha()&&!a.equals(N.paper_bgcolor,S))){var Z=me.selectAll("text"),W=Z[0].length,X=e.select("."+k.cbbg).node(),K=h.bBox(X),$=h.getTranslate(e),ee=2;Z.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=z,te.t=Q*ue,te.b=Q*fe):(te.t=te.b=0,te.yt=z+s*ue,te.yb=z-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-z,te.t=b*ue,te.b=b*fe):(te.t=de*ue,te.b=de*fe,te.yt=z-g*ue,te.yb=z+g*fe));var he=t.y<.5?"b":"t",be=t.x<.5?"l":"r";r._fullLayout._reservedMargin[t._id]={};var _e={r:N.width-j-q,l:j+te.r,b:N.height-V-G,t:V+te.b};E&&R?i.autoMargin(r,t._id,te):E?r._fullLayout._reservedMargin[t._id][he]=_e[he]:R||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()}}},553:function(e,t,r){"use strict";var n=r(3400);e.exports=function(e){return n.isPlainObject(e.colorbar)}},5080:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"colorbar",attributes:r(616),supplyDefaults:r(4013),draw:r(7848).draw,hasColorbar:r(553)}},9084:function(e,t,r){"use strict";var n=r(616),a=r(3756).counter,i=r(2996),o=r(8304).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}},7128:function(e,t,r){"use strict";var n=r(8248),a=r(3400),i=r(4288).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))}},5504:function(e,t,r){"use strict";var n=r(3400),a=r(4288).hasColorscale,i=r(4288).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"})}},7260:function(e,t,r){"use strict";var n=r(8248),a=r(3400),i=r(553),o=r(4013),l=r(8304).isValid,s=r(4040).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)))}},4288:function(e,t,r){"use strict";var n=r(3428),a=r(9760),i=r(8248),o=r(3400),l=r(6308),s=r(8304).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"];a&&a._inputArray&&(a=a._inputArray);var 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)}}},8932:function(e,t,r){"use strict";var n=r(8304),a=r(4288);e.exports={moduleType:"component",name:"colorscale",attributes:r(9084),layoutAttributes:r(2332),supplyLayoutDefaults:r(1608),handleDefaults:r(7260),crossTraceDefaults:r(5504),calc:r(7128),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}},2332:function(e,t,r){"use strict";var n=r(2880).extendFlat,a=r(9084),i=r(8304).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}))}},1608:function(e,t,r){"use strict";var n=r(3400),a=r(1780),i=r(2332),o=r(7260);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]}}}},8304:function(e,t,r){"use strict";var n=r(9760),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)}}},8316: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}},7416:function(e,t,r){"use strict";var n=r(3400),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]}},2760: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)}},6476:function(e,t,r){"use strict";var n=r(9128),a=r(2264),i=r(9184),o=r(3400).removeElement,l=r(3816),s=e.exports={};s.align=r(8316),s.getCursor=r(7416);var c=r(2616);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},2616:function(e,t,r){"use strict";var n=r(5924),a=r(1200),i=r(2200).getGraphDiv,o=r(2456),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}))}},8192:function(e,t){"use strict";t.u={valType:"string",values:["solid","dot","dash","longdash","dashdot","longdashdot"],dflt:"solid",editType:"style"},t.c={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"}},3616:function(e,t,r){"use strict";var n=r(3428),a=r(3400),i=a.numberFormat,o=r(8248),l=r(9760),s=r(4040),c=r(6308),u=r(8932),f=a.strTranslate,d=r(2736),h=r(9616),p=r(4284).LINE_SPACING,v=r(3448).DESELECTDIM,y=r(3028),g=r(7152),m=r(624).appendArrayPointValue,x=e.exports={};function b(e,t,r,n){var a=t.fillpattern,i=t.fillgradient,o=a&&x.getPatternAttr(a.shape,0,"");if(o){var l=x.getPatternAttr(a.bgcolor,0,null),s=x.getPatternAttr(a.fgcolor,0,null),u=a.fgopacity,f=x.getPatternAttr(a.size,0,8),d=x.getPatternAttr(a.solidity,0,.3),h=t.uid;x.pattern(e,"point",r,h,o,f,d,void 0,a.fillmode,l,s,u)}else if(i&&"none"!==i.type){var p,v,y=i.type,g="scatterfill-"+t.uid;n&&(g="legendfill-"+t.uid),n||void 0===i.start&&void 0===i.stop?("horizontal"===y&&(y+="reversed"),e.call(x.gradient,r,g,y,i.colorscale,"fill")):("horizontal"===y?(p={x:i.start,y:0},v={x:i.stop,y:0}):"vertical"===y&&(p={x:0,y:i.start},v={x:0,y:i.stop}),p.x=t._xA.c2p(void 0===p.x?t._extremes.x.min[0].val:p.x,!0),p.y=t._yA.c2p(void 0===p.y?t._extremes.y.min[0].val:p.y,!0),v.x=t._xA.c2p(void 0===v.x?t._extremes.x.max[0].val:v.x,!0),v.y=t._yA.c2p(void 0===v.y?t._extremes.y.max[0].val:v.y,!0),e.call(A,r,g,"linear",i.colorscale,"fill",p,v,!0,!1))}else t.fillcolor&&e.call(c.fill,t.fillcolor)}x.font=function(e,t,r,n,i,o,l){a.isPlainObject(t)&&(l=t.variant,o=t.style,i=t.weight,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),i&&e.style("font-weight",i),o&&e.style("font-style",o),l&&e.style("font-variant",l)},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,!1)},x.fillGroupStyle=function(e,t,r){e.style("stroke-width",0).each((function(e){var a=n.select(this);e[0].trace&&b(a,e[0].trace,t,r)}))};var _=r(1984);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=i("~f"),k={radial:{type:"radial"},radialreversed:{type:"radial",reversed:!0},horizontal:{type:"linear",start:{x:1,y:0},stop:{x:0,y:0}},horizontalreversed:{type:"linear",start:{x:1,y:0},stop:{x:0,y:0},reversed:!0},vertical:{type:"linear",start:{x:0,y:1},stop:{x:0,y:0}},verticalreversed:{type:"linear",start:{x:0,y:1},stop:{x:0,y:0},reversed:!0}};function A(e,t,r,i,o,s,u,f,d,h){var p,v=o.length;"linear"===i?p={node:"linearGradient",attrs:{x1:u.x,y1:u.y,x2:f.x,y2:f.y,gradientUnits:d?"userSpaceOnUse":"objectBoundingBox"},reversed:h}:"radial"===i&&(p={node:"radialGradient",reversed:h});for(var y=new Array(v),g=0;g<v;g++)p.reversed?y[v-1-g]=[M(100*(1-o[g][0])),o[g][1]]:y[g]=[M(100*o[g][0]),o[g][1]];var m=t._fullLayout,x="g"+m._uid+"-"+r,b=m._defs.select(".gradients").selectAll("#"+x).data([i+y.join(";")],a.identity);b.exit().remove(),b.enter().append(p.node).each((function(){var e=n.select(this);p.attrs&&e.attr(p.attrs),e.attr("id",x);var t=e.selectAll("stop").data(y);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,B(x,t)).style(s+"-opacity",null),e.classed("gradient_filled",!0)}x.gradient=function(e,t,r,n,a,i){var o=k[n];return A(e,t,r,o.type,a,i,o.start,o.stop,!1,o.reversed)},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 z=[o||"noSh",h||"noBg",p||"noFg",s,u].join(";"),R=S._defs.select(".patterns").selectAll("#"+O).data([z],a.identity);R.exit().remove(),R.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",B(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=te(e,r),h=U(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],k[_]||(_=0));var w=l.pattern,M=w&&x.getPatternAttr(w.shape,e.i,"");if(_&&"none"!==_){var A=e.mgc;A?g=!0:A=b.color;var L=r.uid;g&&(L+="-"+e.i),x.gradient(t,i,L,_,[[0,A],[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),z=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 R=r.uid;S&&(R+="-"+e.i),x.pattern(t,"point",i,R,M,I,z,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,te(n,t),U(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 L,S,O={start:1,end:-1,middle:0,bottom:1,top:-1};function D(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=O[s]*c,v=.75*r+O[l]*c+(O[l]-1)*u*r/2;e.attr("text-anchor",s),i||o.attr("transform",f(h,v))}function C(e,t){var r=e.ts||t.textfont.size;return o(r)&&r>0?r:0}function P(e,t,r){return r&&(e=F(e)),t?z(e[1]):I(e[0])}function I(e){var t=n.round(e,2);return L=t,t}function z(e){var t=n.round(e,2);return S=t,t}function R(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[[I(t[0]+(d&&u/d)),z(t[1]+(d&&f/d))],[I(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=C(e,t),g=i?i(e):e.tc||t.textfont.color;o.call(x.font,{family:e.tf||t.textfont.family,weight:e.tw||t.textfont.weight,style:e.ty||t.textfont.style,variant:e.tv||t.textfont.variant,size:y,color:g}).text(c).call(d.convertToTspans,r).call(D,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=C(e,t);c.fill(a,i);var u=s.traceIs(t,"bar-like");D(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(R(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=[R(e[a],e[0],e[1],t)];for(r=1;r<a;r++)i.push(R(e[r-1],e[r],e[r+1],t));for(i.push(R(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"+I(t[0])+"V"+P(t,1,r)},vh:function(e,t,r){return"V"+z(t[1])+"H"+P(t,0,r)},hvh:function(e,t,r){return"H"+I((e[0]+t[0])/2)+"V"+z(t[1])+"H"+P(t,0,r)},vhv:function(e,t,r){return"V"+z((e[1]+t[1])/2)+"H"+I(t[0])+"V"+P(t,1,r)}},N=function(e,t,r){return"L"+P(t,0,r)+","+P(t,1,r)};function F(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]:L||0,u=t?t[1]:S||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]||N;return function(e){for(var r="M"+I(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=F,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 H=0;function j(e){var t=e.getAttribute("data-unformatted");if(null!==t)return t+e.getAttribute("data-math")+e.getAttribute("text-anchor")+e.getAttribute("style")}function B(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=j(e)),r){if(i=x.savedBBoxes[r])return a.extendFlat({},i)}else if(1===e.childNodes.length){var s=e.childNodes[0];if(r=j(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 H>=1e4&&(x.savedBBoxes={},H=0),r&&(x.savedBBoxes[r]=y),H++,a.extendFlat({},y)},x.setClipUrl=function(e,t,r){e.attr("clip-path",B(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 Y=/\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(Y,"");e=(e+=n).trim(),this.setAttribute("transform",e)}))}};var V=/translate\([^)]*\)\s*$/;function U(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=U;var q,G,Z,W,X,J,K=Math.atan2,Q=Math.cos,$=Math.sin;function ee(e,t){var r=t[0],n=t[1];return[r*Q(e)-n*$(e),r*$(e)+n*Q(e)]}function te(e,t){var r,n,i=e.ma;void 0===i&&((i=t.marker.angle)&&!a.isArrayOrTypedArray(i)||(i=0));var l=t.marker.angleref;if("previous"===l||"north"===l){if(t._geo){var s=t._geo.project(e.lonlat);r=s[0],n=s[1]}else{var c=t._xA,u=t._yA;if(!c||!u)return 90;r=c.c2p(e.x),n=u.c2p(e.y)}if(t._geo){var f,d=e.lonlat[0],h=e.lonlat[1],p=t._geo.project([d,h+1e-5]),v=t._geo.project([d+1e-5,h]),y=K(v[1]-n,v[0]-r),g=K(p[1]-n,p[0]-r);if("north"===l)f=i/180*Math.PI;else if("previous"===l){var m=d/180*Math.PI,x=h/180*Math.PI,b=q/180*Math.PI,_=G/180*Math.PI,w=b-m,T=Q(_)*$(w),M=$(_)*Q(x)-Q(_)*$(x)*Q(w);f=-K(T,M)-Math.PI,q=d,G=h}var k=ee(y,[Q(f),0]),A=ee(g,[$(f),0]);i=K(k[1]+A[1],k[0]+A[0])/Math.PI*180,"previous"!==l||J===t.uid&&e.i===X+1||(i=null)}if("previous"===l&&!t._geo)if(J===t.uid&&e.i===X+1&&o(r)&&o(n)){var L=r-Z,S=n-W,O=t.line&&t.line.shape||"",D=O.slice(O.length-1);"h"===D&&(S=0),"v"===D&&(L=0),i+=K(S,L)/Math.PI*180+90}else i=null}return Z=r,W=n,X=e.i,J=t.uid,i}x.getMarkerAngle=te},1984:function(e,t,r){"use strict";var n,a,i,o,l=r(9604),s=r(3428).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}}},7644: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"}}}},4880:function(e,t,r){"use strict";var n=r(8248),a=r(4040),i=r(4460),o=r(3400),l=r(3792);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")}}}},3792: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)]}}},5200:function(e,t,r){"use strict";var n=r(8248),a=r(4040),i=r(3400),o=r(1780),l=r(7644);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))}}},4968:function(e,t,r){"use strict";var n=r(3400),a=r(7824).overrideAll,i=r(7644),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(5200),calc:r(4880),makeComputeError:r(3792),plot:r(8512),style:r(2036),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))}}},8512:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(3616),o=r(3028);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()}}))}}))}},2036:function(e,t,r){"use strict";var n=r(3428),a=r(6308);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)}))}},5756:function(e,t,r){"use strict";var n=r(5376),a=r(5460).hoverlabel,i=r(2880).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"}}},5056:function(e,t,r){"use strict";var n=r(3400),a=r(4040);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.font.weight,s,"htw"),u(c.hoverlabel.font.style,s,"hty"),u(c.hoverlabel.font.variant,s,"htv"),u(c.hoverlabel.namelength,s,"hnl"),u(c.hoverlabel.align,s,"hta"))}}}},2376:function(e,t,r){"use strict";var n=r(4040),a=r(3292).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())}},2456:function(e){"use strict";e.exports={YANGLE:60,HOVERARROWSIZE:6,HOVERTEXTPAD:3,HOVERFONTSIZE:13,HOVERFONT:"Arial, sans-serif",HOVERMINTIME:50,HOVERID:"-hover"}},5448:function(e,t,r){"use strict";var n=r(3400),a=r(5756),i=r(6132);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)}},624:function(e,t,r){"use strict";var n=r(3400);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]}},3292:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(9760),o=r(3400),l=o.pushUnique,s=o.strTranslate,c=o.strRotate,u=r(5924),f=r(2736),d=r(2213),h=r(3616),p=r(6308),v=r(6476),y=r(4460),g=r(4040),m=r(624),x=r(2456),b=r(7864),_=r(1140),w=x.YANGLE,T=Math.PI*w/180,M=1/Math.sin(T),k=Math.cos(T),A=Math.sin(T),L=x.HOVERARROWSIZE,S=x.HOVERTEXTPAD,O={box:!0,ohlc:!0,violin:!0,candlestick:!0},D={scatter:!0,scattergl:!0,splom:!0};function C(e,t){return e.distance-t.distance}function P(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 s=t.target;o.throttle(e._fullLayout._uid+x.HOVERID,x.HOVERMINTIME,(function(){!function(e,t,r,i,s){r||(r="xy");var c,f,h,x=Array.isArray(r)?r:[r],b=e._fullLayout,_=b.hoversubplots,w=b._plots||[],T=w[r],k=b._has("cartesian"),A=t.hovermode||b.hovermode,S="x"===(A||"").charAt(0),I="y"===(A||"").charAt(0);if(k&&(S||I)&&"axis"===_)for(var R=x.length,B=0;B<R;B++)if(w[c=x[B]]){f=y.getFromId(e,c,"x"),h=y.getFromId(e,c,"y");var q=(S?f:h)._subplotsWith;if(q&&q.length)for(var G=0;G<q.length;G++)l(x,q[G])}if(T&&"single"!==_){var Z=T.overlays.map((function(e){return e.id}));x=x.concat(Z)}for(var W=x.length,X=new Array(W),J=new Array(W),K=!1,Q=0;Q<W;Q++)if(w[c=x[Q]])K=!0,X[Q]=w[c].xaxis,J[Q]=w[c].yaxis;else{if(!b[c]||!b[c]._subplot)return void o.warn("Unrecognized subplot: "+c);var $=b[c]._subplot;X[Q]=$.xaxis,J[Q]=$.yaxis}if(A&&!K&&(A="closest"),-1===["x","y","closest","x unified","y unified"].indexOf(A)||!e.calcdata||e.querySelector(".zoombox")||e._dragging)return v.unhoverRaw(e,t);var ee=b.hoverdistance;-1===ee&&(ee=1/0);var te=b.spikedistance;-1===te&&(te=1/0);var re,ne,ae,ie,oe,le,se,ce,ue,fe,de,he,pe,ve=[],ye=[],ge={hLinePoint:null,vLinePoint:null},me=!1;if(Array.isArray(t))for(A="array",ae=0;ae<t.length;ae++)(oe=e.calcdata[t[ae].curveNumber||0])&&(le=oe[0].trace,"skip"!==oe[0].trace.hoverinfo&&(ye.push(oe),"h"===le.orientation&&(me=!0)));else{var xe,be,_e=e.calcdata.slice();for(_e.sort((function(e,t){return(e[0].trace.zorder||0)-(t[0].trace.zorder||0)})),ie=0;ie<_e.length;ie++)oe=_e[ie],"skip"!==(le=oe[0].trace).hoverinfo&&m.isTraceInSubplots(le,x)&&(ye.push(oe),"h"===le.orientation&&(me=!0));if(s){if(!1===u.triggerHandler(e,"plotly_beforehover",t))return;var we=s.getBoundingClientRect();xe=t.clientX-we.left,be=t.clientY-we.top,b._calcInverseTransform(e);var Te=o.apply3DTransform(b._invTransform)(xe,be);if(xe=Te[0],be=Te[1],xe<0||xe>X[0]._length||be<0||be>J[0]._length)return v.unhoverRaw(e,t)}else xe="xpx"in t?t.xpx:X[0]._length/2,be="ypx"in t?t.ypx:J[0]._length/2;if(t.pointerX=xe+X[0]._offset,t.pointerY=be+J[0]._offset,re="xval"in t?m.flat(x,t.xval):m.p2c(X,xe),ne="yval"in t?m.flat(x,t.yval):m.p2c(J,be),!a(re[0])||!a(ne[0]))return o.warn("Fx.hover failed",t,e),v.unhoverRaw(e,t)}var Me=1/0;function ke(r,n){for(ie=0;ie<ye.length;ie++)if((oe=ye[ie])&&oe[0]&&oe[0].trace&&!0===(le=oe[0].trace).visible&&0!==le._length&&-1===["carpet","contourcarpet"].indexOf(le._module.name)){if(ue=A,m.isUnifiedHover(ue)&&(ue=ue.charAt(0)),"splom"===le.type?se=x[ce=0]:(se=m.getSubplot(le),ce=x.indexOf(se)),he={cd:oe,trace:le,xa:X[ce],ya:J[ce],maxHoverDistance:ee,maxSpikeDistance:te,index:!1,distance:Math.min(Me,ee),spikeDistance:1/0,xSpike:void 0,ySpike:void 0,color:p.defaultLine,name:le.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},b[se]&&(he.subplot=b[se]._subplot),b._splomScenes&&b._splomScenes[le.uid]&&(he.scene=b._splomScenes[le.uid]),"array"===ue){var i=t[ie];"pointNumber"in i?(he.index=i.pointNumber,ue="closest"):(ue="","xval"in i&&(fe=i.xval,ue="x"),"yval"in i&&(de=i.yval,ue=ue?"closest":"y"))}else void 0!==r&&void 0!==n?(fe=r,de=n):(fe=re[ce],de=ne[ce]);if(pe=ve.length,0!==ee)if(le._module&&le._module.hoverPoints){var l=le._module.hoverPoints(he,fe,de,ue,{finiteRange:!0,hoverLayer:b._hoverlayer,hoversubplots:_,gd:e});if(l)for(var s,c=0;c<l.length;c++)s=l[c],a(s.x0)&&a(s.y0)&&ve.push(F(s,A))}else o.log("Unrecognized trace type in hover:",le);if("closest"===A&&ve.length>pe&&(ve.splice(0,pe),Me=ve[0].distance),k&&0!==te&&0===ve.length){he.distance=te,he.index=!1;var u=le._module.hoverPoints(he,fe,de,"closest",{hoverLayer:b._hoverlayer});if(u&&(u=u.filter((function(e){return e.spikeDistance<=te}))),u&&u.length){var f,d=u.filter((function(e){return e.xa.showspikes&&"hovered data"!==e.xa.spikesnap}));if(d.length){var h=d[0];a(h.x0)&&a(h.y0)&&(f=Le(h),(!ge.vLinePoint||ge.vLinePoint.spikeDistance>f.spikeDistance)&&(ge.vLinePoint=f))}var v=u.filter((function(e){return e.ya.showspikes&&"hovered data"!==e.ya.spikesnap}));if(v.length){var y=v[0];a(y.x0)&&a(y.y0)&&(f=Le(y),(!ge.hLinePoint||ge.hLinePoint.spikeDistance>f.spikeDistance)&&(ge.hLinePoint=f))}}}}}function Ae(e,t,r){for(var n,a=null,i=1/0,o=0;o<e.length;o++)f&&f._id!==e[o].xa._id||h&&h._id!==e[o].ya._id||(n=e[o].spikeDistance,r&&0===o&&(n=-1/0),n<=i&&n<=t&&(a=e[o],i=n));return a}function Le(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}ke();var Se={fullLayout:b,container:b._hoverlayer,event:t},Oe=e._spikepoints,De={vLinePoint:ge.vLinePoint,hLinePoint:ge.hLinePoint};e._spikepoints=De;var Ce=function(){var e=ve.filter((function(e){return f&&f._id===e.xa._id&&h&&h._id===e.ya._id})),t=ve.filter((function(e){return!(f&&f._id===e.xa._id&&h&&h._id===e.ya._id)}));e.sort(C),t.sort(C),ve=function(e,t){for(var r=t.charAt(0),n=[],a=[],i=[],o=0;o<e.length;o++){var l=e[o];g.traceIs(l.trace,"bar-like")||g.traceIs(l.trace,"box-violin")?i.push(l):l.trace[r+"period"]?a.push(l):n.push(l)}return n.concat(a).concat(i)}(ve=e.concat(t),A)};Ce();var Pe=A.charAt(0),Ie=("x"===Pe||"y"===Pe)&&ve[0]&&D[ve[0].trace.type];if(k&&0!==te&&0!==ve.length){var ze=Ae(ve.filter((function(e){return e.ya.showspikes})),te,Ie);ge.hLinePoint=Le(ze);var Re=Ae(ve.filter((function(e){return e.xa.showspikes})),te,Ie);ge.vLinePoint=Le(Re)}if(0===ve.length){var Ee=v.unhoverRaw(e,t);return!k||null===ge.hLinePoint&&null===ge.vLinePoint||j(Oe)&&H(e,ge,Se),Ee}if(k&&j(Oe)&&H(e,ge,Se),m.isXYhover(ue)&&0!==ve[0].length&&"splom"!==ve[0].trace.type){var Ne=ve[0],Fe=(ve=O[Ne.trace.type]?ve.filter((function(e){return e.trace.index===Ne.trace.index})):[Ne]).length;ke(Y("x",Ne,b),Y("y",Ne,b));var He,je=[],Be={},Ye=0,Ve=function(e){var t=O[e.trace.type]?P(e):e.trace.index;if(Be[t]){var r=Be[t]-1,n=je[r];r>0&&Math.abs(e.distance)<Math.abs(n.distance)&&(je[r]=e)}else Ye++,Be[t]=Ye,je.push(e)};for(He=0;He<Fe;He++)Ve(ve[He]);for(He=ve.length-1;He>Fe-1;He--)Ve(ve[He]);ve=je,Ce()}var Ue=e._hoverdata,qe=[],Ge=V(e),Ze=U(e);for(ae=0;ae<ve.length;ae++){var We=ve[ae],Xe=m.makeEventData(We,We.trace,We.cd);if(!1!==We.hovertemplate){var Je=!1;We.cd[We.index]&&We.cd[We.index].ht&&(Je=We.cd[We.index].ht),We.hovertemplate=Je||We.trace.hovertemplate||!1}if(We.xa&&We.ya){var Ke=We.x0+We.xa._offset,Qe=We.x1+We.xa._offset,$e=We.y0+We.ya._offset,et=We.y1+We.ya._offset,tt=Math.min(Ke,Qe),rt=Math.max(Ke,Qe),nt=Math.min($e,et),at=Math.max($e,et);Xe.bbox={x0:tt+Ze,x1:rt+Ze,y0:nt+Ge,y1:at+Ge}}We.eventData=[Xe],qe.push(Xe)}e._hoverdata=qe;var it="y"===A&&(ye.length>1||ve.length>1)||"closest"===A&&me&&ve.length>1,ot=p.combine(b.plot_bgcolor||p.background,b.paper_bgcolor),lt=z(ve,{gd:e,hovermode:A,rotateLabels:it,bgColor:ot,container:b._hoverlayer,outerContainer:b._paper.node(),commonLabelOpts:b.hoverlabel,hoverdistance:b.hoverdistance}),st=lt.hoverLabels;if(m.isUnifiedHover(A)||(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},T=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=E(e,t),v=e.anchor,k="end"===v?-1:1;if("middle"===v)u=(c=e.crossPos+(i?T(h.y-e.by/2):w(e.bx/2+e.tx2width/2)))+(i?T(e.by):w(e.bx));else if(i)u=(c=e.crossPos+T(L+h.y)-T(e.by/2-L))+T(e.by);else{var A=w(k*L+h.x),S=A+w(k*e.bx);c=e.crossPos+Math.min(A,S),u=e.crossPos+Math.max(A,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?M: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 A=y[l],S=y[l+1],O=A[A.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(A.push.apply(A,S),y.splice(l+1,1),u=0,s=A.length-1;s>=0;s--)u+=A[s].dp;for(o=u/A.length,s=A.length-1;s>=0;s--)A[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}}}(st,it,b,lt.commonLabelBoundingBox),N(st,it,b._invScaleX,b._invScaleY)),s&&s.tagName){var ct=g.getComponentMethod("annotations","hasClickToShow")(e,qe);d(n.select(s),ct?"pointer":"")}s&&!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,Ue)&&(Ue&&e.emit("plotly_unhover",{event:t,points:Ue}),e.emit("plotly_hover",{event:t,points:e._hoverdata,xaxes:X,yaxes:J,xvals:re,yvals:ne}))}(e,t,r,i,s)}))},t.loneHover=function(e,t){var r=!0;Array.isArray(e)||(r=!1,e=[e]);var a=t.gd,i=V(a),o=U(a),l=!1,s=z(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),h=Math.max(l,s),v=e.trace;if(g.traceIs(v,"gl3d")){var y=a._fullLayout[v.scene]._scene.container,m=y.offsetLeft,x=y.offsetTop;u+=m,f+=m,d+=x,h+=x}c.bbox={x0:u+o,x1:f+o,y0:d+i,y1:h+i},t.inOut_bbox&&t.inOut_bbox.push(c.bbox)}else c=!1;return{color:e.color||p.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,fontWeight:e.fontWeight,fontStyle:e.fontStyle,fontVariant:e.fontVariant,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:l,bgColor:t.bgColor||p.background,container:n.select(t.container),outerContainer:t.outerContainer||t.container}).hoverLabels,c=0,u=0;return s.sort((function(e,t){return e.y0-t.y0})).each((function(e,r){var n=e.y0-e.by/2;e.offset=n-5<c?c-n+5:0,c=n+e.by+e.offset,r===t.anchorIndex&&(u=e.offset)})).each((function(e){e.offset-=u})),N(s,l,a._fullLayout._invScaleX,a._fullLayout._invScaleY),r?s:s.node()};var I=/<extra>([\s\S]*)<\/extra>/;function z(e,t){var r=t.gd,a=r._fullLayout,i=t.hovermode,l=t.rotateLabels,u=t.bgColor,d=t.container,v=t.outerContainer,y=t.commonLabelOpts||{};if(0===e.length)return[[]];var T=t.fontFamily||x.HOVERFONT,M=t.fontSize||x.HOVERFONTSIZE,k=t.fontWeight||a.font.weight,A=t.fontStyle||a.font.style,O=t.fontVariant||a.font.variant,D=e[0],C=D.xa,I=D.ya,z=i.charAt(0),E=z+"Label",N=D[E];if(void 0===N&&"multicategory"===C.type)for(var F=0;F<e.length&&void 0===(N=e[F][E]);F++);var H=q(r,v),j=H.top,B=H.width,Y=H.height,V=void 0!==N&&D.distance<=t.hoverdistance&&("x"===i||"y"===i);if(V){var U,G,Z=!0;for(U=0;U<e.length;U++)if(Z&&void 0===e[U].zLabel&&(Z=!1),G=e[U].hoverinfo||e[U].trace.hoverinfo){var W=Array.isArray(G)?G:G.split("+");if(-1===W.indexOf("all")&&-1===W.indexOf(i)){V=!1;break}}Z&&(V=!1)}var X=d.selectAll("g.axistext").data(V?[0]:[]);X.enter().append("g").classed("axistext",!0),X.exit().remove();var J={minX:0,maxX:0,minY:0,maxY:0};if(X.each((function(){var e=n.select(this),t=o.ensureSingle(e,"path","",(function(e){e.style({"stroke-width":"1px"})})),l=o.ensureSingle(e,"text","",(function(e){e.attr("data-notex",1)})),c=y.bgcolor||p.defaultLine,u=y.bordercolor||p.contrast(c),d=p.contrast(c),v={weight:y.font.weight||k,style:y.font.style||A,variant:y.font.variant||O,family:y.font.family||T,size:y.font.size||M,color:y.font.color||d};t.style({fill:c,stroke:u}),l.text(N).call(h.font,v).call(f.positionText,0,0).call(f.convertToTspans,r),e.attr("transform","");var g,m,x=q(r,l.node());if("x"===i){var b="top"===C.side?"-":"";l.attr("text-anchor","middle").call(f.positionText,0,"top"===C.side?j-x.bottom-L-S:j-x.top+L+S),g=C._offset+(D.x0+D.x1)/2,m=I._offset+("top"===C.side?0:I._length);var _=x.width/2+S,w=g;g<_?w=_:g>a.width-_&&(w=a.width-_),t.attr("d","M"+(g-w)+",0L"+(g-w+L)+","+b+L+"H"+_+"v"+b+(2*S+x.height)+"H"+-_+"V"+b+L+"H"+(g-w-L)+"Z"),g=w,J.minX=g-_,J.maxX=g+_,"top"===C.side?(J.minY=m-(2*S+x.height),J.maxY=m-S):(J.minY=m+S,J.maxY=m+(2*S+x.height))}else{var P,z,R;"right"===I.side?(P="start",z=1,R="",g=C._offset+C._length):(P="end",z=-1,R="-",g=C._offset),m=I._offset+(D.y0+D.y1)/2,l.attr("text-anchor",P),t.attr("d","M0,0L"+R+L+","+L+"V"+(S+x.height/2)+"h"+R+(2*S+x.width)+"V-"+(S+x.height/2)+"H"+R+L+"V-"+L+"Z"),J.minY=m-(S+x.height/2),J.maxY=m+(S+x.height/2),"right"===I.side?(J.minX=g+L,J.maxX=g+L+(2*S+x.width)):(J.minX=g-L-(2*S+x.width),J.maxX=g-L);var E,F=x.height/2,H=j-x.top-F,B="clip"+a._uid+"commonlabel"+I._id;if(g<x.width+2*S+L){E="M-"+(L+S)+"-"+F+"h-"+(x.width-S)+"V"+F+"h"+(x.width-S)+"Z";var Y=x.width-g+S;f.positionText(l,Y,H),"end"===P&&l.selectAll("tspan").each((function(){var e=n.select(this),t=h.tester.append("text").text(e.text()).call(h.font,v),a=q(r,t.node());Math.round(a.width)<Math.round(x.width)&&e.attr("x",Y-a.width),t.remove()}))}else f.positionText(l,z*(S+L),H),E=null;var V=a._topclips.selectAll("#"+B).data(E?[0]:[]);V.enter().append("clipPath").attr("id",B).append("path"),V.exit().remove(),V.select("path").attr("d",E),h.setClipUrl(l,E?B:null,r)}e.attr("transform",s(g,m))})),m.isUnifiedHover(i)){d.selectAll("g.hovertext").remove();var K=e.filter((function(e){return"none"!==e.hoverinfo}));if(0===K.length)return[];var Q=a.hoverlabel,$=Q.font,ee={showlegend:!0,legend:{title:{text:N,font:$},font:$,bgcolor:Q.bgcolor,bordercolor:Q.bordercolor,borderwidth:1,tracegroupgap:7,traceorder:a.legend?a.legend.traceorder:void 0,orientation:"v"}},te={font:$};b(ee,te,r._fullData);var re=te.legend;re.entries=[];for(var ne=0;ne<K.length;ne++){var ae=K[ne];if("none"!==ae.hoverinfo){var ie=R(ae,!0,i,a,N),oe=ie[0],le=ie[1];ae.name=le,ae.text=""!==le?le+" : "+oe:oe;var se=ae.cd[ae.index];se&&(se.mc&&(ae.mc=se.mc),se.mcc&&(ae.mc=se.mcc),se.mlc&&(ae.mlc=se.mlc),se.mlcc&&(ae.mlc=se.mlcc),se.mlw&&(ae.mlw=se.mlw),se.mrc&&(ae.mrc=se.mrc),se.dir&&(ae.dir=se.dir)),ae._distinct=!0,re.entries.push([ae])}}re.entries.sort((function(e,t){return e[0].trace.index-t[0].trace.index})),re.layer=d,re._inHover=!0,re._groupTitleFont=Q.grouptitlefont,_(r,re);var ce,ue,fe,de,he=d.select("g.legend"),pe=q(r,he.node()),ve=pe.width+2*S,ye=pe.height+2*S,ge=K[0],me=(ge.x0+ge.x1)/2,xe=(ge.y0+ge.y1)/2,be=!(g.traceIs(ge.trace,"bar-like")||g.traceIs(ge.trace,"box-violin"));"y"===z?be?(ue=xe-S,ce=xe+S):(ue=Math.min.apply(null,K.map((function(e){return Math.min(e.y0,e.y1)}))),ce=Math.max.apply(null,K.map((function(e){return Math.max(e.y0,e.y1)})))):ue=ce=o.mean(K.map((function(e){return(e.y0+e.y1)/2})))-ye/2,"x"===z?be?(fe=me+S,de=me-S):(fe=Math.max.apply(null,K.map((function(e){return Math.max(e.x0,e.x1)}))),de=Math.min.apply(null,K.map((function(e){return Math.min(e.x0,e.x1)})))):fe=de=o.mean(K.map((function(e){return(e.x0+e.x1)/2})))-ve/2;var _e,we,Te=C._offset,Me=I._offset;return de+=Te-ve,ue+=Me-ye,_e=(fe+=Te)+ve<B&&fe>=0?fe:de+ve<B&&de>=0?de:Te+ve<B?Te:fe-me<me-de+ve?B-ve:0,_e+=S,we=(ce+=Me)+ye<Y&&ce>=0?ce:ue+ye<Y&&ue>=0?ue:Me+ye<Y?Me:ce-xe<xe-ue+ye?Y-ye:0,we+=S,he.attr("transform",s(_e-1,we-1)),he}var ke=d.selectAll("g.hovertext").data(e,(function(e){return P(e)}));return ke.enter().append("g").classed("hovertext",!0).each((function(){var e=n.select(this);e.append("rect").call(p.fill,p.addOpacity(u,.8)),e.append("text").classed("name",!0),e.append("path").style("stroke-width","1px"),e.append("text").classed("nums",!0).call(h.font,{weight:k,style:A,variant:O,family:T,size:M})})),ke.exit().remove(),ke.each((function(e){var t=n.select(this).attr("transform",""),o=e.color;Array.isArray(o)&&(o=o[e.eventData[0].pointNumber]);var d=e.bgcolor||o,v=p.combine(p.opacity(d)?d:p.defaultLine,u),y=p.combine(p.opacity(o)?o:p.defaultLine,u),g=e.borderColor||p.contrast(v),m=R(e,V,i,a,N,t),x=m[0],b=m[1],_=t.select("text.nums").call(h.font,{family:e.fontFamily||T,size:e.fontSize||M,color:e.fontColor||g,weight:e.fontWeight||k,style:e.fontStyle||A,variant:e.fontVariant||O}).text(x).attr("data-notex",1).call(f.positionText,0,0).call(f.convertToTspans,r),D=t.select("text.name"),C=0,P=0;if(b&&b!==x){D.call(h.font,{family:e.fontFamily||T,size:e.fontSize||M,color:y,weight:e.fontWeight||k,style:e.fontStyle||A,variant:e.fontVariant||O}).text(b).attr("data-notex",1).call(f.positionText,0,0).call(f.convertToTspans,r);var I=q(r,D.node());C=I.width+2*S,P=I.height+2*S}else D.remove(),t.select("rect").remove();t.select("path").style({fill:v,stroke:g});var z=e.xa._offset+(e.x0+e.x1)/2,E=e.ya._offset+(e.y0+e.y1)/2,F=Math.abs(e.x1-e.x0),H=Math.abs(e.y1-e.y0),U=q(r,_.node()),G=U.width/a._invScaleX,Z=U.height/a._invScaleY;e.ty0=(j-U.top)/a._invScaleY,e.bx=G+2*S,e.by=Math.max(Z+2*S,P),e.anchor="start",e.txwidth=G,e.tx2width=C,e.offset=0;var W,X,J=(G+L+S+C)*a._invScaleX;if(l)e.pos=z,W=E+H/2+J<=Y,X=E-H/2-J>=0,"top"!==e.idealAlign&&W||!X?W?(E+=H/2,e.anchor="start"):e.anchor="middle":(E-=H/2,e.anchor="end"),e.crossPos=E;else{if(e.pos=E,W=z+F/2+J<=B,X=z-F/2-J>=0,"left"!==e.idealAlign&&W||!X)if(W)z+=F/2,e.anchor="start";else{e.anchor="middle";var K=J/2,Q=z+K-B,$=z-K;Q>0&&(z-=Q),$<0&&(z+=-$)}else z-=F/2,e.anchor="end";e.crossPos=z}_.attr("text-anchor",e.anchor),C&&D.attr("text-anchor",e.anchor),t.attr("transform",s(z,E)+(l?c(w):""))})),{hoverLabels:ke,commonLabelBoundingBox:J}}function R(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=B(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(I,(function(t,r){return l=B(r,e.nameLength),""}))}return[s,l]}function E(e,t){var r=0,n=e.offset;return t&&(n*=-A,r=e.offset*k),{x:r,y:n}}function N(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,u=r.select("text.nums"),d=e.anchor,p="end"===d?-1:1,v=(l={start:1,end:-1,middle:0}[(a=e).anchor],c=(s=l*(L+S))+l*(a.txwidth+S),"middle"===a.anchor&&(s-=a.tx2width/2,c+=a.txwidth/2+S),{alignShift:l,textShiftX:s,text2ShiftX:c}),y=E(e,t),g=y.x,m=y.y,x="middle"===d;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*L+g)+","+o(L+m)+"v"+o(e.by/2-L)+"h"+i(p*e.bx)+"v-"+o(e.by)+"H"+i(p*L+g)+"V"+o(m-L)+"Z");var b=g+v.textShiftX,_=m+e.ty0-e.by/2+S,w=e.textAlign||"auto";"auto"!==w&&("left"===w&&"start"!==d?(u.attr("text-anchor","start"),b=x?-e.bx/2-e.tx2width/2+S:-e.bx-S):"right"===w&&"end"!==d&&(u.attr("text-anchor","end"),b=x?e.bx/2-e.tx2width/2-S:e.bx+S)),u.call(f.positionText,i(b),o(_)),e.tx2width&&(r.select("text.name").call(f.positionText,i(v.text2ShiftX+v.alignShift*S+g),o(m+e.ty0-e.by/2+S)),r.select("rect").call(h.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 F(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("fontWeight","htw","hoverlabel.font.weight"),u("fontStyle","hty","hoverlabel.font.style"),u("fontVariant","htv","hoverlabel.font.variant"),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:y.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:y.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=y.tickText(e.xa,e.xa.c2l(e.xerr),"hover").text;void 0!==e.xerrneg?e.xLabel+=" +"+f+" / -"+y.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=y.tickText(e.ya,e.ya.c2l(e.yerr),"hover").text;void 0!==e.yerrneg?e.yLabel+=" +"+d+" / -"+y.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 H(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 d=p.combine(l.plot_bgcolor,l.paper_bgcolor);if(u){var v,g,m=t.hLinePoint;n=m&&m.xa,"cursor"===(a=m&&m.ya).spikesnap?(v=c.pointerX,g=c.pointerY):(v=n._offset+m.x,g=a._offset+m.y);var x,b,_=i.readability(m.color,d)<1.5?p.contrast(d):m.color,w=a.spikemode,T=a.spikethickness,M=a.spikecolor||_,k=y.getPxPosition(e,a);if(-1!==w.indexOf("toaxis")||-1!==w.indexOf("across")){if(-1!==w.indexOf("toaxis")&&(x=k,b=v),-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":h.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:d}).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,d)<1.5?p.contrast(d):D.color,z=n.spikemode,R=n.spikethickness,E=n.spikecolor||I,N=y.getPxPosition(e,n);if(-1!==z.indexOf("toaxis")||-1!==z.indexOf("across")){if(-1!==z.indexOf("toaxis")&&(C=N,P=O),-1!==z.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":R,stroke:E,"stroke-dasharray":h.dashStyle(n.spikedash,R)}).classed("spikeline",!0).classed("crisp",!0),o.insert("line",":first-child").attr({x1:S,x2:S,y1:C,y2:P,"stroke-width":R+2,stroke:d}).classed("spikeline",!0).classed("crisp",!0)}-1!==z.indexOf("marker")&&o.insert("circle",":first-child").attr({cx:S,cy:N-("top"!==n.side?R:-R),r:R,fill:E}).classed("spikeline",!0)}}}function j(e,t){return!t||t.vLinePoint!==e._spikepoints.vLinePoint||t.hLinePoint!==e._spikepoints.hLinePoint}function B(e,t){return f.plainText(e||"",{len:t,allowedTags:["br","sub","sup","b","i","em"]})}function Y(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 V(e){return e.offsetTop+e.clientTop}function U(e){return e.offsetLeft+e.clientLeft}function q(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)}}},6132:function(e,t,r){"use strict";var n=r(3400),a=r(6308),i=r(624).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"),s("weight"),s("style"),s("variant"),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)}},1008:function(e,t,r){"use strict";var n=r(3400),a=r(5460);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("hoversubplots"),r("hovermode")}},3024:function(e,t,r){"use strict";var n=r(3428),a=r(3400),i=r(6476),o=r(624),l=r(5460),s=r(3292);e.exports={moduleType:"component",name:"fx",constants:r(2456),schema:{layout:l},attributes:r(5756),layoutAttributes:l,supplyLayoutGlobalDefaults:r(1976),supplyDefaults:r(5448),supplyLayoutDefaults:r(8336),calc:r(5056),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(2376)}},5460:function(e,t,r){"use strict";var n=r(2456),a=r(5376),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"},hoversubplots:{valType:"enumerated",values:["single","overlaying","axis"],dflt:"overlaying",editType:"none"},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"}}},8336:function(e,t,r){"use strict";var n=r(3400),a=r(5460),i=r(1008),o=r(6132);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)}},1976:function(e,t,r){"use strict";var n=r(3400),a=r(6132),i=r(5460);e.exports=function(e,t){a(e,t,(function(r,a){return n.coerce(e,t,i,r,a)}))}},2704:function(e,t,r){"use strict";var n=r(3400),a=r(3756).counter,i=r(6968).u,o=r(3816).idRegex,l=r(1780),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 z=m[L];for(n=S;n!==D;n+=O)if((l=s[z][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}}}}}},5760:function(e,t,r){"use strict";var n=r(3816),a=r(1780).templatedArray;r(6208),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"})},3556:function(e,t,r){"use strict";var n=r(8248),a=r(6896);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)}}},7404:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(1272),o=r(5760);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})}},963:function(e,t,r){"use strict";var n=r(3428),a=r(3616),i=r(4460),o=r(9811),l=r(9616);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)}))}}}},7402:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"images",layoutAttributes:r(5760),supplyLayoutDefaults:r(7404),includeBasePlot:r(6632)("images"),draw:r(963),convertCoords:r(3556)}},3800:function(e,t,r){"use strict";var n=r(5376),a=r(2548);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"},indentation:{valType:"number",min:-15,dflt:0,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","top center","top right"],editType:"legend"},editType:"legend"},editType:"legend"}},5196: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}},7864:function(e,t,r){"use strict";var n=r(4040),a=r(3400),i=r(1780),o=r(5464),l=r(3800),s=r(4859),c=r(2451);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=(r.shapes||[]).filter((function(e){return e.showlegend})),T=u.concat(w).filter((function(t){return e===(t.legend||"legend")})),M=0;M<T.length;M++)if((v=T[M]).visible){var k=v._isShape;(v.showlegend||v._dfltShowLegend&&!(v._module&&v._module.attributes&&v._module.attributes.showlegend&&!1===v._module.attributes.showlegend.dflt))&&(x++,v.showlegend&&(b=!0,(!k&&n.traceIs(v,"pie-like")||!0===v._input.showlegend)&&x++),a.coerceFont(y,"legendgrouptitle.font",m)),(!k&&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 A=a.coerce(t,r,s,"showlegend",b&&x>("legend"===e?1:0));if(!1===A&&(r[e]=void 0),(!1!==A||f.uirevision)&&(h("uirevision",r.uirevision),!1!==A)){h("borderwidth");var L,S,O,D="h"===h("orientation"),C="paper"===h("yref"),P="paper"===h("xref"),I="left";if(D?(L=0,n.getComponentMethod("rangeslider","isVisible")(t.xaxis)?C?(S=1.1,O="bottom"):(S=1,O="top"):C?(S=-.1,O="top"):(S=0,O="bottom")):(S=1,O="auto",P?L=1.02:(L=1,I="right")),a.coerce(f,d,{x:{valType:"number",editType:"legend",min:P?-2:0,max:P?3:1,dflt:L}},"x"),a.coerce(f,d,{y:{valType:"number",editType:"legend",min:C?-2:0,max:C?3:1,dflt:S}},"y"),h("traceorder",_),c.isGrouped(r[e])&&h("tracegroupgap"),h("entrywidth"),h("entrywidthmode"),h("indentation"),h("itemsizing"),h("itemwidth"),h("itemclick"),h("itemdoubleclick"),h("groupclick"),h("xanchor",I),h("yanchor",O),h("valign"),a.noneOrAll(f,d,["x","y"]),h("title.text")){h("title.side",D?"left":"top");var z=a.extendFlat({},p,{size:a.bigFont(p.size)});a.coerceFont(h,"title.font",z)}}}}e.exports=function(e,t,r){var n,i=r.slice(),o=t.shapes;if(o)for(n=0;n<o.length;n++){var l=o[n];if(l.showlegend){var s={_input:l._input,visible:l.visible,showlegend:l.showlegend,legend:l.legend};i.push(s)}}var c=["legend"];for(n=0;n<i.length;n++)a.pushUnique(c,i[n].legend);for(t._legends=[],n=0;n<c.length;n++){var f=c[n];u(f,e,t,i),t[f]&&t[f].visible&&(t[f]._id=f),t._legends.push(f)}}},1140:function(e,t,r){"use strict";var n=r(3428),a=r(3400),i=r(7316),o=r(4040),l=r(5924),s=r(6476),c=r(3616),u=r(6308),f=r(2736),d=r(3048),h=r(5196),p=r(4284),v=p.LINE_SPACING,y=p.FROM_TL,g=p.FROM_BR,m=r(3076),x=r(2012),b=r(2451),_=1,w=/^legend[0-9]*$/;function T(e,t){var r,l,d=t||{},p=e._fullLayout,w=P(d),T=d._inHover;if(T?(l=d.layer,r="hover"):(l=p._infolayer,r=w),l){var L;if(r+=p._uid,e._legendMouseDownTime||(e._legendMouseDownTime=0),T){if(!d.entries)return;L=m(d.entries,d)}else{for(var I=(e.calcdata||[]).slice(),z=p.shapes,R=0;R<z.length;R++){var E=z[R];if(E.showlegend){var N={_isShape:!0,_fullInput:E,index:E._index,name:E.name||E.label.text||"shape "+E._index,legend:E.legend,legendgroup:E.legendgroup,legendgrouptitle:E.legendgrouptitle,legendrank:E.legendrank,legendwidth:E.legendwidth,showlegend:E.showlegend,visible:E.visible,opacity:E.opacity,mode:"line"===E.type?"lines":"markers",line:E.line,marker:{line:E.line,color:E.fillcolor,size:12,symbol:"rect"===E.type?"square":"circle"===E.type?"circle":"hexagon2"}};I.push([{trace:N}])}}L=p.showlegend&&m(I,d,p._legends.length>1)}var F=p.hiddenlabels||[];if(!(T||p.showlegend&&L.length))return l.selectAll("."+w).remove(),p._topdefs.select("#"+r).remove(),i.autoMargin(e,w);var H=a.ensureSingle(l,"g",w,(function(e){T||e.attr("pointer-events","all")})),j=a.ensureSingleById(p._topdefs,"clipPath",r,(function(e){e.append("rect")})),B=a.ensureSingle(H,"rect","bg",(function(e){e.attr("shape-rendering","crispEdges")}));B.call(u.stroke,d.bordercolor).call(u.fill,d.bgcolor).style("stroke-width",d.borderwidth+"px");var Y,V=a.ensureSingle(H,"g","scrollbox"),U=d.title;d._titleWidth=0,d._titleHeight=0,U.text?((Y=a.ensureSingle(V,"text",w+"titletext")).attr("text-anchor","start").call(c.font,U.font).text(U.text),O(Y,V,e,d,_)):V.selectAll("."+w+"titletext").remove();var q=a.ensureSingle(H,"rect","scrollbar",(function(e){e.attr(h.scrollBarEnterAttrs).call(u.fill,h.scrollBarColor)})),G=V.selectAll("g.groups").data(L);G.enter().append("g").attr("class","groups"),G.exit().remove();var Z=G.selectAll("g.traces").data(a.identity);Z.enter().append("g").attr("class","traces"),Z.exit().remove(),Z.style("opacity",(function(e){var t=e[0].trace;return o.traceIs(t,"pie-like")?-1!==F.indexOf(e[0].label)?.5:1:"legendonly"===t.visible?.5:1})).each((function(){n.select(this).call(A,e,d)})).call(x,e,d).each((function(){T||n.select(this).call(S,e,w)})),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.indentation+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,z=i.width/2;a._maxWidth=Math.max(S?I&&"left"===L?l.l+l.w:z:O?I&&"right"===L?l.r+l.w:z:l.w,2*y);var R=0,E=0;r.each((function(e){var t=M(e,a,y);R=Math.max(R,t),E+=t})),k=null;var N=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?(N=Math.max(N,H),H=0,j+=F+w,F=t):F=Math.max(F,t),c.setTranslate(this,H,j),H+=r})),a._width=Math.max(N,H)+d,a._height=j+F+g}else{var B=r.size(),Y=E+p+(B-1)*v<a._maxWidth,V=0,U=0,q=0,G=0;r.each((function(e){var t=e[0].height,r=M(e,a,y),n=Y?r:R;f||(n+=v),n+d+U-v>=a._maxWidth&&(N=Math.max(N,G),U=0,q+=V,a._height+=V,V=0),c.setTranslate(this,A[0]+d+U,A[1]+d+q+t/2+v),G=U+r+v,U+=n,V=Math.max(V,t)})),Y?(a._width=U+p,a._height=V+g):(a._width=Math.max(N,G)+p,a._height+=V+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 Z=e._context.edits,W=Z.legendText||Z.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,G,Z,d)},function(){var t,u,m,x,b=p._size,_=d.borderwidth,M="paper"===d.xref,A="paper"===d.yref;if(U.text&&function(e,t,r){if("top center"===t.title.side||"top right"===t.title.side){var n=t.title.font.size*v,a=0,i=e.node(),o=c.bBox(i).width;"top center"===t.title.side?a=.5*(t._width-2*r-2*h.titlePad-o):"top right"===t.title.side&&(a=t._width-2*r-2*h.titlePad-o),f.positionText(e,r+h.titlePad+a,r+n)}}(Y,d,_),!T){var L,S;L=M?b.l+b.w*d.x-y[D(d)]*d._width:p.width*d.x-y[D(d)]*d._width,S=A?b.t+b.h*(1-d.y)-y[C(d)]*d._effHeight:p.height*(1-d.y)-y[C(d)]*d._effHeight;var O=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,w,L,S);if(O)return;if(p.margin.autoexpand){var P=L,I=S;L=M?a.constrain(L,0,p.width-d._width):P,S=A?a.constrain(S,0,p.height-d._effHeight):I,L!==P&&a.log("Constrain "+w+".x to make legend fit inside graph"),S!==I&&a.log("Constrain "+w+".y to make legend fit inside graph")}c.setTranslate(H,L,S)}if(q.on(".drag",null),H.on("wheel",null),T||d._height<=d._maxHeight||e._context.staticPlot){var z=d._effHeight;T&&(z=d._height),B.attr({width:d._width-_,height:z-_,x:_/2,y:_/2}),c.setTranslate(V,0,0),j.select("rect").attr({width:d._width-2*_,height:z-2*_,x:_,y:_}),c.setClipUrl(V,r,e),c.setRect(q,0,0,0,0),delete d._scrollY}else{var R,E,N,F=Math.max(h.scrollBarMinHeight,d._effHeight*d._effHeight/d._height),G=d._effHeight-F-2*h.scrollBarMargin,Z=d._height-d._effHeight,W=G/Z,X=Math.min(d._scrollY||0,Z);B.attr({width:d._width-2*_+h.scrollBarWidth+h.scrollBarMargin,height:d._effHeight-_,x:_/2,y:_/2}),j.select("rect").attr({width:d._width-2*_+h.scrollBarWidth+h.scrollBarMargin,height:d._effHeight-2*_,x:_,y:_+X}),c.setClipUrl(V,r,e),Q(X,F,W),H.on("wheel",(function(){Q(X=a.constrain(d._scrollY+n.event.deltaY/G*Z,0,Z),F,W),0!==X&&X!==Z&&n.event.preventDefault()}));var J=n.behavior.drag().on("dragstart",(function(){var e=n.event.sourceEvent;R="touchstart"===e.type?e.changedTouches[0].clientY:e.clientY,N=X})).on("drag",(function(){var e=n.event.sourceEvent;2===e.buttons||e.ctrlKey||(E="touchmove"===e.type?e.changedTouches[0].clientY:e.clientY,X=function(e,t,r){var n=(r-t)/W+e;return a.constrain(n,0,Z)}(N,R,E),Q(X,F,W))}));q.call(J);var K=n.behavior.drag().on("dragstart",(function(){var e=n.event.sourceEvent;"touchstart"===e.type&&(R=e.changedTouches[0].clientY,N=X)})).on("drag",(function(){var e=n.event.sourceEvent;"touchmove"===e.type&&(E=e.changedTouches[0].clientY,X=function(e,t,r){var n=(t-r)/W+e;return a.constrain(n,0,Z)}(N,R,E),Q(X,F,W))}));V.call(K)}function Q(t,r,n){d._scrollY=e._fullLayout[w]._scrollY=t,c.setTranslate(V,0,-t),c.setRect(q,d._width,h.scrollBarMargin+t*n,h.scrollBarWidth,r),j.select("rect").attr("y",_+t)}e._context.edits.legendPosition&&(H.classed("cursor-move",!0),s.init({element:H.node(),gd:e,prepFn:function(){var e=c.getTranslate(H);m=e.x,x=e.y},moveFn:function(e,r){var n=m+e,a=x+r;c.setTranslate(H,n,a),t=s.align(n,d._width,b.l,b.l+b.w,d.xanchor),u=s.align(a+d._height,-d._height,b.t+b.h,b.t,d.yanchor)},doneFn:function(){if(void 0!==t&&void 0!==u){var r={};r[w+".x"]=t,r[w+".y"]=u,o.call("_guiRelayout",e,r)}},clickFn:function(t,r){var n=l.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,H,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);var c=l.triggerHandler(e,"plotly_legendclick",s);if(1===n){if(!1===c)return;t._clickTimeout=setTimeout((function(){e._fullLayout&&d(r,e,n)}),e._context.doubleClickDelay)}else 2===n&&(t._clickTimeout&&clearTimeout(t._clickTimeout),e._legendMouseDownTime=0,!1!==l.triggerHandler(e,"plotly_legenddoubleclick",s)&&!1!==c&&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.indentation+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 i._isShape?o.call("_guiRelayout",t,"shapes["+u.index+"].name",l.name):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.indentation+r.itemwidth;a.groupTitle&&(w=h.itemGap,u-=r.indentation+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])}}}},3076:function(e,t,r){"use strict";var n=r(4040),a=r(2451);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}},3048:function(e,t,r){"use strict";var n=r(4040),a=r(3400),i=a.pushUnique,o=!0;e.exports=function(e,t,r){var l=t._fullLayout;if(!t._dragged&&!t._editing){var s,c=l.legend.itemclick,u=l.legend.itemdoubleclick,f=l.legend.groupclick;if(1===r&&"toggle"===c&&"toggleothers"===u&&o&&t.data&&t._context.showTips?(a.notifier(a._(t,"Double-click on legend to isolate one trace"),"long"),o=!1):o=!1,1===r?s=c:2===r&&(s=u),s){var d="togglegroup"===f,h=l.hiddenlabels?l.hiddenlabels.slice():[],p=e.data()[0][0];if(!p.groupTitle||!p.noClick){var v=t._fullData,y=(l.shapes||[]).filter((function(e){return e.showlegend})),g=v.concat(y),m=p.trace;m._isShape&&(m=m._fullInput);var x,b,_,w,T,M=m.legendgroup,k={},A=[],L=[],S=[],O=(l.shapes||[]).map((function(e){return e._input})),D=!1,C=m.legend,P=m._fullInput;if(P&&P._isShape||!n.traceIs(m,"pie-like")){var I,z=M&&M.length,R=[];if(z)for(x=0;x<g.length;x++)(I=g[x]).visible&&I.legendgroup===M&&R.push(x);if("toggle"===s){var E;switch(m.visible){case!0:E="legendonly";break;case!1:E=!1;break;case"legendonly":E=!0}if(z)if(d)for(x=0;x<g.length;x++){var N=g[x];!1!==N.visible&&N.legendgroup===M&&ee(N,E)}else ee(m,E);else ee(m,E)}else if("toggleothers"===s){var F,H,j,B,Y=!0;for(x=0;x<g.length;x++)if(F=(B=g[x])===m,H=!0!==B.showlegend,!(F||H||z&&B.legendgroup===M||B.legend!==C||!0!==B.visible||n.traceIs(B,"notLegendIsolatable"))){Y=!1;break}for(x=0;x<g.length;x++)if(!1!==(B=g[x]).visible&&B.legend===C&&!n.traceIs(B,"notLegendIsolatable"))switch(m.visible){case"legendonly":ee(B,!0);break;case!0:j=!!Y||"legendonly",F=B===m,H=!0!==B.showlegend&&!B.legendgroup,ee(B,!!(F||z&&B.legendgroup===M||H)||j)}}for(x=0;x<L.length;x++)if(_=L[x]){var V=_.constructUpdate(),U=Object.keys(V);for(b=0;b<U.length;b++)w=U[b],(k[w]=k[w]||[])[S[x]]=V[w]}for(T=Object.keys(k),x=0;x<T.length;x++)for(w=T[x],b=0;b<A.length;b++)k[w].hasOwnProperty(b)||(k[w][b]=void 0);D?n.call("_guiUpdate",t,k,{shapes:O},A):n.call("_guiRestyle",t,k,A)}else{var q=p.label,G=h.indexOf(q);if("toggle"===s)-1===G?h.push(q):h.splice(G,1);else if("toggleothers"===s){var Z=-1!==G,W=[];for(x=0;x<t.calcdata.length;x++){var X=t.calcdata[x];for(b=0;b<X.length;b++){var J=X[b].label;C===X[0].trace.legend&&q!==J&&(-1===h.indexOf(J)&&(Z=!0),i(h,J),W.push(J))}}if(!Z)for(var K=0;K<W.length;K++){var Q=h.indexOf(W[K]);-1!==Q&&h.splice(Q,1)}}n.call("_guiRelayout",t,"hiddenlabels",h)}}}}function $(e,t){var r=A.indexOf(e),n=k.visible;return n||(n=k.visible=[]),-1===A.indexOf(e)&&(A.push(e),r=A.length-1),n[r]=t,r}function ee(e,t){if(!p.groupTitle||d){var r,i=e._fullInput||e,o=i._isShape,l=i.index;if(void 0===l&&(l=i._index),n.hasTransform(i,"groupby")){var s=L[l];if(!s){var c=n.getTransformIndices(i,"groupby"),u=c[c.length-1];s=a.keyedContainer(i,"transforms["+u+"].styles","target","value.visible"),L[l]=s}var f=s.get(e._group);void 0===f&&(f=!0),!1!==f&&s.set(e._group,t),S[l]=$(l,!1!==i.visible)}else{var h=!1!==i.visible&&t;o?(r=h,O[l].visible=r,D=!0):$(l,h)}}}}},2451: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")}},2780:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"legend",layoutAttributes:r(3800),supplyLayoutDefaults:r(7864),draw:r(1140),style:r(2012)}},2012:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(3400),o=i.strTranslate,l=r(3616),s=r(6308),c=r(4288).extractOpts,u=r(3028),f=r(528),d=r(9656).castOption,h=r(5196);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=f.cornerradius?"M6,3a3,3,0,0,1-3,3H-3a3,3,0,0,1-3-3V-3a3,3,0,0,1,3-3H3a3,3,0,0,1,3,3Z":"M6,6H-6V-6H6Z",p=o?u.visible&&u.type===o:a.traceIs(u,"bar"),v=n.select(i).select("g.legendpoints").selectAll("path.legend"+o).data(p?[e]:[]);v.enter().append("path").classed("legend"+o,!0).attr("d",h).attr("transform",_),v.exit().remove(),v.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="pieLike",y=i.minExtend(s,{marker:{line:{width:p}}},v),g=i.minExtend(l,{trace:y},v);f(u,g,y,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.indentation,s=r.valign,c=e[0].lineHeight,u=e[0].height;if("middle"===s&&0===l||!c||!u)a.attr("transform",null);else{var f={top:1,bottom:-1}[s]*(.5*(c-u+3))||0,d=r.indentation;a.attr("transform",o(d,f))}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 h=a.selectAll("g.legendsymbols").data([e]);h.enter().append("g").classed("legendsymbols",!0),h.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,!0);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),b.tw=g("textfont.weight",x),b.ty=g("textfont.style",x),b.tv=g("textfont.variant",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)}))}))}},6540:function(e,t,r){"use strict";r(6052),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"}}},1868:function(e,t,r){"use strict";var n=r(4040),a=r(7316),i=r(9811),o=r(9224),l=r(4016).eraseActiveShape,s=r(3400),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)void 0===r._rangeInitial0&&void 0===r._rangeInitial1?u[h+".autorange"]=!0:void 0===r._rangeInitial0?(u[h+".autorange"]=r._autorangeInitial,u[h+".range"]=[null,r._rangeInitial1]):void 0===r._rangeInitial1?(u[h+".range"]=[r._rangeInitial0,null],u[h+".autorange"]=r._autorangeInitial):u[h+".range"]=[r._rangeInitial0,r._rangeInitial1],void 0!==r._showSpikeInitial&&(u[h+".showspikes"]=r._showSpikeInitial,"on"!==d||r._showSpikeInitial||(d="off"));else{var g=[r.r2l(r.range[0]),r.r2l(r.range[1])],m=[v*g[0]+y*g[1],v*g[1]+y*g[0]];u[h+".range[0]"]=r.l2r(m[0]),u[h+".range[1]"]=r.l2r(m[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}},6052:function(e,t,r){"use strict";var n=r(1868),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}},824:function(e,t,r){"use strict";var n=r(3400),a=r(6308),i=r(1780),o=r(6540);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")}},3080:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"modebar",layoutAttributes:r(6540),supplyLayoutDefaults:r(824),manage:r(8816)}},8816:function(e,t,r){"use strict";var n=r(9811),a=r(3028),i=r(4040),o=r(624).isUnifiedHover,l=r(6400),s=r(1868),c=r(6052).DRAW_MODES,u=r(3400).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=[],z=[];(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?z=["zoom3d","pan3d","orbitRotation","tableRotation"]:(v||b)&&!A||_?z=["zoom2d","pan2d"]:w||g?z=["pan2d"]:T&&(z=["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)&&z.push("select2d","lasso2d");var R=[],E=function(e){-1===R.indexOf(e)&&-1!==P.indexOf(e)&&R.push(e)};if(Array.isArray(h)){for(var N=[],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"))&&z.push(H):"togglespikelines"===H?E("toggleSpikelines"):"togglehover"===H?E("toggleHover"):"hovercompare"===H?E("hoverCompareCartesian"):"hoverclosest"===H?(E("hoverClosestCartesian"),E("hoverClosestGeo"),E("hoverClosest3d"),E("hoverClosestGl2d"),E("hoverClosestPie")):"v1hovermode"===H&&(E("toggleHover"),E("hoverClosestCartesian"),E("hoverCompareCartesian"),E("hoverClosestGeo"),E("hoverClosest3d"),E("hoverClosestGl2d"),E("hoverClosestPie"))):N.push(H)}h=N}return O(z),O(C.concat(I)),O(R),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)}},6400:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(3400),o=r(9224),l=r(5788).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}},6680:function(e,t,r){"use strict";var n=r(5376),a=r(2548),i=(0,r(1780).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"}},5984:function(e){"use strict";e.exports={yPad:.02,minButtonWidth:30,rx:3,ry:3,lightAmount:25,darkAmount:10}},2148:function(e,t,r){"use strict";var n=r(3400),a=r(6308),i=r(1780),o=r(1272),l=r(6680),s=r(5984);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")}}},216:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(7316),o=r(6308),l=r(3616),s=r(3400),c=s.strTranslate,u=r(2736),f=r(9811),d=r(4284),h=d.LINE_SPACING,p=d.FROM_TL,v=d.FROM_BR,y=r(5984),g=r(8040);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)}))}},8040:function(e,t,r){"use strict";var n=r(3220),a=r(3400).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}},1152:function(e,t,r){"use strict";e.exports={moduleType:"component",name:"rangeselector",schema:{subplots:{xaxis:{rangeselector:r(6680)}}},layoutAttributes:r(6680),handleDefaults:r(2148),draw:r(216)}},8820:function(e,t,r){"use strict";var n=r(2548);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"}},6652:function(e,t,r){"use strict";var n=r(9811).list,a=r(9280).getAutoRange,i=r(4636);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))}}},4636: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}},1659:function(e,t,r){"use strict";var n=r(3400),a=r(1780),i=r(9811),o=r(8820),l=r(936);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)}}},60:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(7316),o=r(3400),l=o.strTranslate,s=r(3616),c=r(6308),u=r(1668),f=r(7952),d=r(9811),h=r(6476),p=r(3972),v=r(4636);function y(e){return"number"==typeof e.clientX?e.clientX:e.touches&&e.touches.length>0?e.touches[0].clientX:0}function g(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 m(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 x(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 b(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 _(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 w(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 T,M=o.simpleMap(s.range,r.r2l),k=o.simpleMap(r.range,r.r2l);T=k[0]<k[1]?[Math.min(M[0],k[0]),Math.max(M[1],k[1])]:[Math.max(M[0],k[0]),Math.min(M[1],k[1])],s.range=s._input.range=o.simpleMap(T,r.l2r)}r.cleanRange("rangeslider.range");var A=t._size,L=r.domain;s._width=A.w*(L[1]-L[0]);var S=Math.round(A.l+A.w*L[0]),O=Math.round(A.t+A.h*(1-r._counterDomainMin)+("bottom"===r.side?r._depth:0)+s._offsetShift+v.extraPad);i.attr("transform",l(S,O)),s._rl=o.simpleMap(s.range,r.r2l);var D=s._rl[0],C=s._rl[1],P=C-D;if(s.p2d=function(e){return e/s._width*P+D},s.d2p=function(e){return(e-D)/P*s._width},r.rangebreaks){var I=r.locateBreaks(D,C);if(I.length){var z,R,E=0;for(z=0;z<I.length;z++)E+=(R=I[z]).max-R.min;var N=s._width/(C-D-E),F=[-N*D];for(z=0;z<I.length;z++)R=I[z],F.push(F[F.length-1]-N*(R.max-R.min));for(s.d2p=function(e){for(var t=F[0],r=0;r<I.length;r++){var n=I[r];if(e>=n.max)t=F[r+1];else if(e<n.min)break}return t+N*e},z=0;z<I.length;z++)(R=I[z]).pmin=s.d2p(R.min),R.pmax=s.d2p(R.max);s.p2d=function(e){for(var t=F[0],r=0;r<I.length;r++){var n=I[r];if(e>=n.pmax)t=F[r+1];else if(e<n.pmin)break}return(e-t)/N}}}if("match"!==f.rangemode){var H=c.r2l(f.range[0]),j=c.r2l(f.range[1])-H;s.d2pOppAxis=function(e){return(e-H)/j*s._height}}i.call(g,e,r,s).call(m,e,r,s).call(x,e,r,s).call(b,e,r,s,f).call(_,e,r,s).call(w,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=y(u),v=d-e.node().getBoundingClientRect().left,g=i.d2p(r._rl[0]),m=i.d2p(r._rl[1]),x=h.coverSlip();function b(e){var u,h,b,_=+y(e)-d;switch(f){case l:if(b="ew-resize",g+_>r._length||m+_<0)return;u=g+_,h=m+_;break;case s:if(b="col-resize",g+_>r._length)return;u=g+_,h=m;break;case c:if(b="col-resize",m+_<0)return;u=g,h=m+_;break;default:b="ew-resize",u=v,h=v+_}if(h<u){var w=h;h=u,u=w}i._pixelMin=u,i._pixelMax=h,p(n.select(x),b),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 _(){x.removeEventListener("mousemove",b),x.removeEventListener("mouseup",_),this.removeEventListener("touchmove",b),this.removeEventListener("touchend",_),o.removeElement(x)}this.addEventListener("touchmove",b),this.addEventListener("touchend",_),x.addEventListener("mousemove",b),x.addEventListener("mouseup",_)}}(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:O+s._height+s._offsetShift+10+1.5*r.title.font.size,"text-anchor":"middle"}})})))}},7944:function(e,t,r){"use strict";var n=r(9811),a=r(2736),i=r(4636),o=r(4284).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}}},9692:function(e,t,r){"use strict";var n=r(3400),a=r(8820),i=r(936),o=r(7944);e.exports={moduleType:"component",name:"rangeslider",schema:{subplots:{xaxis:{rangeslider:n.extendFlat({},a,{yaxis:i})}}},layoutAttributes:r(8820),handleDefaults:r(1659),calcAutorange:r(6652),draw:r(60),isVisible:o.isVisible,makeData:o.makeData,autoMarginOpts:o.autoMarginOpts}},936: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"}},3956:function(e,t,r){"use strict";var n=r(3916),a=r(2904).line,i=r(8192).u,o=r(2880).extendFlat,l=r(7824).overrideAll,s=r(1780).templatedArray;r(6208),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")},3280:function(e){"use strict";e.exports={BENDPX:1.5,MINSELECT:12,SELECTDELAY:100,SELECTID:"-select"}},4224:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(1272),o=r(3956),l=r(5152);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))}}},3640:function(e,t,r){"use strict";var n=r(9856).readPaths,a=r(5496),i=r(1936).clearOutlineControllers,o=r(6308),l=r(3616),s=r(1780).arrayEditor,c=r(5152),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)}}}},4200:function(e,t,r){"use strict";var n=r(8192).u,a=r(2880).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"}}},1004: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")}},5968:function(e,t,r){"use strict";var n=r(2760).selectMode,a=r(1936).clearOutline,i=r(9856),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():{}}}}},5840:function(e,t,r){"use strict";var n=r(3400).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)}}},2676:function(e,t,r){"use strict";var n=r(3640),a=r(3156);e.exports={moduleType:"component",name:"selections",layoutAttributes:r(3956),supplyLayoutDefaults:r(4224),supplyDrawNewSelectionDefaults:r(1004),includeBasePlot:r(6632)("selections"),draw:n.draw,drawOne:n.drawOne,reselect:a.reselect,prepSelect:a.prepSelect,clearOutline:a.clearOutline,clearSelectionsCache:a.clearSelectionsCache,selectOnClick:a.selectOnClick}},3156:function(e,t,r){"use strict";var n=r(4756),a=r(1456),i=r(4040),o=r(3616).dashStyle,l=r(6308),s=r(3024),c=r(624).makeEventData,u=r(2760),f=u.freeMode,d=u.rectMode,h=u.drawMode,p=u.openMode,v=u.selectMode,y=r(5152),g=r(3068),m=r(5496),x=r(1936).clearOutline,b=r(9856),_=b.handleEllipse,w=b.readPaths,T=r(3940).newShapes,M=r(5968),k=r(3640).activateLastSelection,A=r(3400),L=A.sorterAsc,S=r(2065),O=r(1200),D=r(9811).getFromId,C=r(3696),P=r(9172).redrawReglTraces,I=r(3280),z=I.MINSELECT,R=S.filter,E=S.tester,N=r(5840),F=N.p2r,H=N.axValue,j=N.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)){G(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),Z(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 V(e){return"pointNumber"in e&&"searchInfo"in e}function U(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=V(e[0])?0:e[0][0][0],n=r,a=V(e[0])?0:e[0][0][1],i=a,o=0;o<e.length;o++)if(V(e[o]))t.push(U(e[o]));else{var l=E(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 G(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||Z(r),o||(x(t),n._lastSelectedSubplot=a.id)}function Z(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)||i._xA&&i._xA.overlaying))continue;if(!(-1!==c.indexOf(i.yaxis)||i._yA&&i._yA.overlaying))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 z=C[I],R=z.indexOf("y"),E=z.slice(0,R),N=z.slice(R),F=o&&l?r:void 0;if(F=ie(f,E,N,F)){var H=n;if(!s){var j=D(e,E,"x"),B=D(e,N,"y");H=X(e,[j],[B],z);for(var Y=0;Y<H.length;Y++){var V=H[Y],U=V.cd[0],q=U.trace;if("scattergl"===V._module.name&&!U.t.xpx){var G=q.x,Z=q.y,W=q._length;U.t.xpx=[],U.t.ypx=[];for(var J=0;J<W;J++)U.t.xpx[J]=j.c2p(G[J]),U.t.ypx[J]=B.c2p(Z[J])}"splom"===V._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=E(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),N=t-D.left,F=r-D.top;k._calcInverseTransform(M);var H=A.apply3DTransform(k._invTransform)(N,F);N=H[0],F=H[1];var V,U,W,J,K,ee,ie,oe=k._invScaleX,le=k._invScaleY,se=N,he=F,pe="M"+N+","+F,ve=n.xaxes[0],ye=n.yaxes[0],ge=ve._length,me=ye._length,xe=e.altKey&&!(h(a)&&g);G(e,M,n),u&&(V=R([[N,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+N)),he=Math.max(0,Math.min(me,le*t+F));var r=Math.abs(se-N),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,z)?"h":r<Math.min(.6*a,z)?"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=N,l=se);break;default:i="d"}"h"===i?((J=T?_(w,[se,o],[se,l]):[[N,o],[N,l],[se,l],[se,o]]).xmin=T?se:Math.min(N,se),J.xmax=T?se:Math.max(N,se),J.ymin=Math.min(o,l),J.ymax=Math.max(o,l),Me.attr("d","M"+J.xmin+","+(F-z)+"h-4v"+2*z+"h4ZM"+(J.xmax-1)+","+(F-z)+"h4v"+2*z+"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"+(N-z)+","+J.ymin+"v-4h"+2*z+"v4ZM"+(N-z)+","+(J.ymax-1)+"v4h"+2*z+"v-4Z")):"d"===i&&((J=T?_(w,[N,F],[se,he]):[[N,F],[N,he],[se,he],[se,F]]).xmin=Math.min(N,se),J.xmax=Math.max(N,se),J.ymin=Math.min(F,he),J.ymax=Math.max(F,he),Me.attr("d","M0,0Z"))}else u&&(V.addPt([se,he]),J=V.filtered);if(n.selectionDefs&&n.selectionDefs.length?(W=$(n.mergedPolygons,J,xe),J.subtract=xe,U=q(n.selectionDefs.concat([J]))):(W=[J],U=E(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,U,Se,n),U=f.selectionTesters,ie=f.eventData,c=V?V.filtered:ce(W),O.throttle(Ae,I.SELECTDELAY,(function(){for(var e=(Le=re(U,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),Z(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,C.id)})).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)&&Z(n,L),n.doneFnCompleted&&n.doneFnCompleted(Le),b&&fe(M,ie)})).catch(A.error)}},clearOutline:x,clearSelectionsCache:Z,selectOnClick:Y}},6056:function(e,t,r){"use strict";var n=r(3916),a=r(5376),i=r(2904).line,o=r(8192).u,l=r(2880).extendFlat,s=r(1780).templatedArray,c=(r(6208),r(5464)),u=r(1776).ye,f=r(7728);e.exports=s("shape",{visible:l({},c.visible,{editType:"calc+arraydraw"}),showlegend:{valType:"boolean",dflt:!1,editType:"calc+arraydraw"},legend:l({},c.legend,{editType:"calc+arraydraw"}),legendgroup:l({},c.legendgroup,{editType:"calc+arraydraw"}),legendgrouptitle:{text:l({},c.legendgrouptitle.text,{editType:"calc+arraydraw"}),font:a({editType:"calc+arraydraw"}),editType:"calc+arraydraw"},legendrank:l({},c.legendrank,{editType:"calc+arraydraw"}),legendwidth:l({},c.legendwidth,{editType:"calc+arraydraw"}),type:{valType:"enumerated",values:["circle","rect","path","line"],editType:"calc+arraydraw"},layer:{valType:"enumerated",values:["below","above","between"],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:u({},{keys:Object.keys(f)}),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"})},6084:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(3068),o=r(5152);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)))}}}},3068: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}}},3712:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(1272),o=r(6056),l=r(5152);function s(e,t,r){function i(r,a){return n.coerce(e,t,o,r,a)}if(t._isShape=!0,i("visible")){i("showlegend")&&(i("legend"),i("legendwidth"),i("legendgroup"),i("legendgrouptitle.text"),n.coerceFont(i,"legendgrouptitle.font"),i("legendrank"));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})}},728:function(e,t,r){"use strict";var n=r(3400),a=r(4460),i=r(2736),o=r(3616),l=r(9856).readPaths,s=r(5152),c=s.getPathString,u=r(7728),f=r(4284).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 z=a.getFromId(e,r.xref),R=a.getRefType(r.xref),E=a.getFromId(e,r.yref),N=a.getRefType(r.yref),F=s.getDataToPixel(e,z,!1,R),H=s.getDataToPixel(e,E,!0,N);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,V=B.texty,U=B.xanchor;k.attr({"text-anchor":{left:"start",center:"middle",right:"end"}[U],y:V,x:Y,transform:"rotate("+j+","+Y+","+V+")"}).call(i.positionText,Y,V)}}},5496:function(e,t,r){"use strict";var n=r(3400).strTranslate,a=r(6476),i=r(2760),o=i.drawMode,l=i.selectMode,s=r(4040),c=r(6308),u=r(7e3),f=u.i000,d=u.i090,h=u.i180,p=u.i270,v=r(1936).clearOutlineControllers,y=r(9856),g=y.pointsOnRectangle,m=y.pointsOnEllipse,x=y.writePaths,b=r(3940).newShapes,_=r(3940).createShapeObj,w=r(5968),T=r(728);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,z=o(I),R=l(I);if((z||R)&&(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:V,doneFn:U,clickFn:q},a.init(S[e])}}()),z&&i.hasText){var E=P.select(".label-temp"),N=_(r,i,i.dragmode);T(y,"label-temp",N,E)}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 V(e){(O=+e.srcElement.getAttribute("data-i"))||(O=0),S[O].moveFn=Y}function U(){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)}}},4016:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(3400),o=r(4460),l=r(9856).readPaths,s=r(5496),c=r(728),u=r(1936).clearOutlineControllers,f=r(6308),d=r(3616),h=r(1780).arrayEditor,p=r(6476),v=r(3972),y=r(3068),g=r(5152),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++)!0===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],z=_(e)&&u.editable&&e._fullLayout._activeShapeIndex===t;z&&(O=I?"rgba(0,0,0,0)":e._fullLayout.activeshape.fillcolor,S=e._fullLayout.activeshape.opacity);var R,E=r.append("g").classed("shape-group",!0).attr({"data-index":t}),N=E.append("path").attr(L).style("opacity",S).call(f.stroke,D).call(f.fill,O).call(d.dashLine,P,C);if(T(E,e,u),c(e,t,u,E),(z||e._context.edits.shapePosition)&&(R=h(e.layout,"shapes",u)),z){N.style({cursor:"move"});var F={element:N.node(),plotinfo:w,gd:e,editHelpers:R,hasText:u.label.text||u.label.texttemplate,isActiveShape:!0},H=l(A,e);s(H,N,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,z,R,E=10,N=10,F="pixel"===r.xsizemode,H="pixel"===r.ysizemode,j="line"===r.type,B="path"===r.type,Y=u.modifyItem,V=n.select(t.node().parentNode),U=o.getFromId(e,r.xref),q=o.getRefType(r.xref),G=o.getFromId(e,r.yref),Z=o.getRefType(r.yref),W=g.getDataToPixel(e,U,!1,q),X=g.getDataToPixel(e,G,!0,Z),J=g.getPixelToData(e,U,!1,q),K=g.getPixelToData(e,G,!0,Z),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))R=null;else if(j)R="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>E&&i>N&&!r.shiftKey?p.getCursor(o/a,1-l/i):"move";v(t,s),R=s.split("-")[0]}}function ne(n){b(e)||(F&&(w=W(r.xanchor)),H&&(k=X(r.yanchor)),"path"===r.type?z=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"===R?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)},U&&"date"===U.type&&(o=g.encodeDate(o))),H?Y("yanchor",r.yanchor=K(k+a)):(u=function(e){return K(X(e)+a)},G&&"date"===G.type&&(u=g.encodeDate(u))),Y("path",r.path=M(z,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,V)}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)},U&&"date"===U.type&&(o=g.encodeDate(o))),H?Y("yanchor",r.yanchor=K(k+a)):(u=function(e){return K(X(e)+a)},G&&"date"===G.type&&(u=g.encodeDate(u))),Y("path",r.path=M(z,o,u))}else if(j){if("resize-over-start-point"===R){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"===R){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!==R.indexOf(e)},T=b("n"),q=b("s"),Z=b("w"),Q=b("e"),$=T?A+a:A,ee=q?L+a:L,te=Z?S+n:S,re=Q?O+n:O;H&&(T&&($=A-a),q&&(ee=L-a)),(!H&&ee-$>N||H&&$-ee>N)&&(Y(D,r[D]=H?$:K($)),Y(C,r[C]=H?ee:K(ee))),re-te>E&&(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,V)}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,N,u,t,r,R):!0===u.editable&&N.style("pointer-events",I||f.opacity(O)*S<=.5?"stroke":"all");N.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,N)}))}u._input&&!0===u.visible&&("above"===u.layer?A(e._fullLayout._shapeUpperLayer):"paper"===u.xref||"paper"===u.yref?A(e._fullLayout._shapeLowerLayer):"between"===u.layer?A(w.shapelayerBetween):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]);return delete e._fullLayout._activeShapeIndex,a.call("_guiRelayout",e,{shapes:n})}}},drawLabel:c}},2872:function(e,t,r){"use strict";var n=r(7824).overrideAll,a=r(5464),i=r(5376),o=r(8192).u,l=r(2880).extendFlat,s=r(1776).ye,c=r(7728);e.exports=n({newshape:{visible:l({},a.visible,{}),showlegend:{valType:"boolean",dflt:!1},legend:l({},a.legend,{}),legendgroup:l({},a.legendgroup,{}),legendgrouptitle:{text:l({},a.legendgrouptitle.text,{}),font:i({})},legendrank:l({},a.legendrank,{}),legendwidth:l({},a.legendwidth,{}),line:{color:{valType:"color"},width:{valType:"number",min:0,dflt:4},dash:l({},o,{dflt:"solid"})},fillcolor:{valType:"color",dflt:"rgba(0,0,0,0)"},fillrule:{valType:"enumerated",values:["evenodd","nonzero"],dflt:"evenodd"},opacity:{valType:"number",min:0,max:1,dflt:1},layer:{valType:"enumerated",values:["below","above","between"],dflt:"above"},drawdirection:{valType:"enumerated",values:["ortho","horizontal","vertical","diagonal"],dflt:"diagonal"},name:l({},a.name,{}),label:{text:{valType:"string",dflt:""},texttemplate:s({newshape:!0},{keys:Object.keys(c)}),font:i({}),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"]},textangle:{valType:"angle",dflt:"auto"},xanchor:{valType:"enumerated",values:["auto","left","center","right"],dflt:"auto"},yanchor:{valType:"enumerated",values:["top","middle","bottom"]},padding:{valType:"number",dflt:3,min:0}}},activeshape:{fillcolor:{valType:"color",dflt:"rgb(255,0,255)"},opacity:{valType:"number",min:0,max:1,dflt:.5}}},"none","from-root")},7e3: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)}},5144:function(e,t,r){"use strict";var n=r(6308),a=r(3400);e.exports=function(e,t,r){if(r("newshape.visible"),r("newshape.name"),r("newshape.showlegend"),r("newshape.legend"),r("newshape.legendwidth"),r("newshape.legendgroup"),r("newshape.legendgrouptitle.text"),a.coerceFont(r,"newshape.legendgrouptitle.font"),r("newshape.legendrank"),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")}},9856:function(e,t,r){"use strict";var n=r(9604),a=r(7e3),i=a.CIRCLE_SIDES,o=a.SQRT2,l=r(5840),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,z=!1===a,R=0;R<w.length;R++){for(o=0;o+2<7;o+=2){var E=w[R][o+1],N=w[R][o+2];void 0!==E&&void 0!==N&&(p=E,v=N,r&&(r.xaxis&&r.xaxis.p2r?(z&&(E-=r.xaxis._offset),E=P?c(r.xaxis,r.xanchor)+E:s(r.xaxis,E)):(z&&(E-=C.l),D?E=D.x[0]+E/C.w:E/=C.w),r.yaxis&&r.yaxis.p2r?(z&&(N-=r.yaxis._offset),N=I?c(r.yaxis,r.yanchor)-N:s(r.yaxis,N)):(z&&(N-=C.t),N=D?D.y[1]-N/C.h:1-N/C.h)),w[R][o+1]=E,w[R][o+2]=N)}d[h].push(w[R].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}},3940:function(e,t,r){"use strict";var n=r(2760),a=n.drawMode,i=n.openMode,o=r(7e3),l=o.i000,s=o.i090,c=o.i180,u=o.i270,f=o.cos45,d=o.sin45,h=r(5840),p=h.p2r,v=h.r2p,y=r(1936).clearOutline,g=r(9856),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,visible:y.visible,name:y.name,showlegend:y.showlegend,legend:y.legend,legendwidth:y.legendwidth,legendgroup:y.legendgroup,legendgrouptitle:{text:y.legendgrouptitle.text,font:y.legendgrouptitle.font},legendrank:y.legendrank,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],z=n[l][2],R=n[s][2],E=n[c][2],N=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&&(z=v(g.yaxis,z),R=v(g.yaxis,R),E=v(g.yaxis,E),N=v(g.yaxis,N));var j=(C+I)/2,B=(z+E)/2,Y=b({x0:j,y0:B,x1:j+(I-C+P-D)/2*f,y1:B+(N-R+E-z)/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}},1936: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}}},5152:function(e,t,r){"use strict";var n=r(3068),a=r(3400),i=r(4460);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"}},1592:function(e,t,r){"use strict";var n=r(4016);e.exports={moduleType:"component",name:"shapes",layoutAttributes:r(6056),supplyLayoutDefaults:r(3712),supplyDrawNewShapeDefaults:r(5144),includeBasePlot:r(6632)("shapes"),calcAutorange:r(6084),draw:n.draw,drawOne:n.drawOne}},7728: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)}}},9861:function(e,t,r){"use strict";var n=r(5376),a=r(6741),i=r(2880).extendDeepAll,o=r(7824).overrideAll,l=r(5656),s=r(1780).templatedArray,c=r(876),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")},876: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}},8132:function(e,t,r){"use strict";var n=r(3400),a=r(1272),i=r(9861),o=r(876).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})}},9664:function(e,t,r){"use strict";var n=r(3428),a=r(7316),i=r(6308),o=r(3616),l=r(3400),s=l.strTranslate,c=r(2736),u=r(1780).arrayEditor,f=r(876),d=r(4284),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)}))}}},7544:function(e,t,r){"use strict";var n=r(876);e.exports={moduleType:"component",name:n.name,layoutAttributes:r(9861),supplyLayoutDefaults:r(8132),draw:r(9664)}},1668:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(7316),o=r(4040),l=r(3400),s=l.strTranslate,c=r(3616),u=r(6308),f=r(2736),d=r(3448),h=r(4284).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,I=O.weight,z=O.style,R=O.variant;"title.text"===g?v="titleText":-1!==g.indexOf("axis")?v="axisTitleText":g.indexOf(!0)&&(v="colorbarTitleText");var E=e._context.edits[v];""===S?k=0:S.replace(p," % ")===m.replace(p," % ")&&(k=.2,A=!0,E||(S="")),r._meta?S=l.templateString(S,r._meta):M._meta&&(S=l.templateString(S,M._meta));var N,F=S||E;T||(T=l.ensureSingle(M._infolayer,"g","g-"+t),N=M._hColorbarMoveTitle);var H=T.selectAll("text").data(F?[0]:[]);if(H.enter().append("text"),H.text(S).attr("class",t),H.exit().remove(),!F)return T;function j(e){l.syncOrAsync([B,Y],e)}function B(t){var r;return!w&&N&&(w={}),w?(r="",w.rotate&&(r+="rotate("+[w.rotate,_.x,_.y]+")"),(w.offset||N)&&(r+=s(0,(w.offset||0)-(N||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,"font-style":z,"font-variant":R}).attr(_).call(f.convertToTspans,e),i.previousPromises(e)}function Y(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 H.call(j),E&&(S?H.on(".opacity",null):(k=0,A=!0,H.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)}))),H.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(j)})).on("input",(function(e){this.text(e||" ").call(f.positionText,_.x,_.y)}))),H.classed("js-placeholder",A),T}}},8444:function(e,t,r){"use strict";var n=r(5376),a=r(2548),i=r(2880).extendFlat,o=r(7824).overrideAll,l=r(6741),s=r(1780).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")},1331: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"}}},1384:function(e,t,r){"use strict";var n=r(3400),a=r(1272),i=r(8444),o=r(1331).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})}},4420:function(e,t,r){"use strict";var n=r(3428),a=r(7316),i=r(6308),o=r(3616),l=r(3400),s=r(2736),c=r(1780).arrayEditor,u=r(4284).LINE_SPACING,f=r(1331),d=r(7400);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)}))}}},6908:function(e,t,r){"use strict";var n=r(1331);e.exports={moduleType:"component",name:n.name,layoutAttributes:r(8444),supplyLayoutDefaults:r(1384),draw:r(4420)}},7400:function(e,t,r){"use strict";e.exports=l;var n=r(3428),a=r(6308),i=r(3616),o=r(3400);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,z=y;I+C>s&&(I=s-C);var R=this.container.selectAll("rect.scrollbar-vertical").data(D?[0]:[]);R.exit().on(".drag",null).remove(),R.enter().append("rect").classed("scrollbar-vertical",!0).call(a.fill,l.barColor),D?(this.vbar=R.attr({rx:l.barRadius,ry:l.barRadius,x:I,y:z,width:C,height:P}),this._vbarYMin=z+P/2,this._vbarTranslateMax=T-P):(delete this.vbar,delete this._vbarYMin,delete this._vbarTranslateMax);var E=this.id,N=u-.5,F=D?f+C+.5:f+.5,H=d-.5,j=M?h+A+.5:h+.5,B=o._topdefs.selectAll("#"+E).data(M||D?[0]:[]);if(B.exit().remove(),B.enter().append("clipPath").attr("id",E).append("rect"),M||D?(this._clipRect=B.select("rect").attr({x:Math.floor(N),y:Math.floor(H),width:Math.ceil(F)-Math.floor(N),height:Math.ceil(j)-Math.floor(H)}),this.container.call(i.setClipUrl,E,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 V=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(V),D&&this.vbar.on(".drag",null).call(V)}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)}}},4284: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"}}},6208: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(" ")}}},6880: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"}},9104:function(e){"use strict";e.exports={COMPARISON_OPS:["=","!=","<",">=",">","<="],COMPARISON_OPS2:["=","<",">=",">","<="],INTERVAL_OPS:["[]","()","[)","(]","][",")(","](",")["],SET_OPS:["{}","}{"],CONSTRAINT_REDUCTION:{"=":"=","<":"<","<=":"<",">":">",">=":">","[]":"[]","()":"[]","[)":"[]","(]":"[]","][":"][",")(":"][","](":"][",")[":"]["}}},3448:function(e){"use strict";e.exports={SHOW_PLACEHOLDER:100,HIDE_PLACEHOLDER:1e3,DESELECTDIM:.2}},9032: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"}},9616: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}},4884:function(e,t,r){"use strict";t.version=r(5788).version,r(8324),r(9288);for(var n=r(4040),a=t.register=n.register,i=r(2448),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(5875)),a([r(9180),r(6864),r(2676),r(1592),r(7402),r(6908),r(7544),r(9692),r(1152),r(2704),r(4968),r(8932),r(5080),r(2780),r(3024),r(3080)]),a([r(6580),r(1680)]),window.PlotlyLocales&&Array.isArray(window.PlotlyLocales)&&(a(window.PlotlyLocales),delete window.PlotlyLocales),t.Icons=r(9224);var c=r(3024),u=r(7316);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(8904),t.PlotSchema=r(3060)},9224: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("")}}},8308: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}},1864:function(e,t,r){"use strict";var n=r(435),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)}}},8116:function(e,t,r){"use strict";var n=r(3160).decode,a=r(3620),i=Array.isArray,o=ArrayBuffer,l=DataView;function s(e){return o.isView(e)&&!(e instanceof l)}function c(e){return i(e)||s(e)}t.isTypedArray=s,t.isArrayOrTypedArray=c,t.isArray1D=function(e){return!c(e[0])},t.ensureArray=function(e,t){return i(e)||(e=[]),e.length=t,e};var u={u1c:"undefined"==typeof Uint8ClampedArray?void 0:Uint8ClampedArray,i1:"undefined"==typeof Int8Array?void 0:Int8Array,u1:"undefined"==typeof Uint8Array?void 0:Uint8Array,i2:"undefined"==typeof Int16Array?void 0:Int16Array,u2:"undefined"==typeof Uint16Array?void 0:Uint16Array,i4:"undefined"==typeof Int32Array?void 0:Int32Array,u4:"undefined"==typeof Uint32Array?void 0:Uint32Array,f4:"undefined"==typeof Float32Array?void 0:Float32Array,f8:"undefined"==typeof Float64Array?void 0:Float64Array};function f(e){return e.constructor===ArrayBuffer}function d(e,t,r){if(c(e)){if(c(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(z){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}},5536:function(e){"use strict";e.exports=function(e){return e}},1396: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}},3400:function(e,t,r){"use strict";var n=r(3428),a=r(4336).E9,i=r(7624).E9,o=r(8248),l=r(9032),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(2296),f.keyedContainer=r(7804),f.relativeAttr=r(3193),f.isPlainObject=r(3620),f.toLogRange=r(6896),f.relinkPrivateKeys=r(1528);var h=r(8116);f.isArrayBuffer=h.isArrayBuffer,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(435);f.mod=p.mod,f.modHalf=p.modHalf;var v=r(3064);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(7555);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(4952);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(2996);var m=r(3084);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(2248);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(1864);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(8308);f.isLeftAnchor=_.isLeftAnchor,f.isCenterAnchor=_.isCenterAnchor,f.isRightAnchor=_.isRightAnchor,f.isTopAnchor=_.isTopAnchor,f.isMiddleAnchor=_.isMiddleAnchor,f.isBottomAnchor=_.isBottomAnchor;var w=r(2348);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(2880);f.extendFlat=T.extendFlat,f.extendDeep=T.extendDeep,f.extendDeepAll=T.extendDeepAll,f.extendDeepNoArrays=T.extendDeepNoArrays;var M=r(4248);f.log=M.log,f.warn=M.warn,f.error=M.error;var k=r(3756);f.counterRegex=k.counter;var A=r(1200);f.throttle=A.throttle,f.throttleDone=A.done,f.clearThrottle=A.clear;var L=r(2200);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(6628),f.identity=r(5536),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 E={max:10,count:0,name:"hovertemplate"};f.hovertemplateString=function(){return B.apply(E,arguments)};var N={max:10,count:0,name:"texttemplate"};f.texttemplateString=function(){return B.apply(N,arguments)};var F=/^(\S+)([\*\/])(-?\d+(\.\d+)?)$/,H={max:10,count:0,name:"texttemplate",parseMultDiv:!0};f.texttemplateStringForShapes=function(){return B.apply(H,arguments)};var j=/^[:|\|]/;function B(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(F);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 Y=2e9;f.seedPseudoRandom=function(){Y=2e9},f.pseudoRandom=function(){var e=Y;return Y=(69069*Y+1)%4294967296,Math.abs(Y-e)<429496729?f.pseudoRandom():Y/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 V=f.getFirefoxVersion(),U=null!==V&&V<86;f.getPositionFromD3Event=function(){return U?[n.event.layerX,n.event.layerY]:[n.event.offsetX,n.event.offsetY]}},3620: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")}},7804:function(e,t,r){"use strict";var n=r(2296),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")}}},988:function(e,t,r){"use strict";var n=r(3428);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}},2248:function(e,t,r){"use strict";var n=r(6524);t.init2dArray=function(e,t){for(var r=new Array(e),n=0;nt/2?e-Math.round(e/t)*t:e}}},2296:function(e,t,r){"use strict";var n=r(8248),a=r(8116).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}}},4296:function(e,t,r){"use strict";var n=r(8248),a=r(5928);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}},2416: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)]}},2736:function(e,t,r){"use strict";var n=r(3428),a=r(3400),i=a.strTranslate,o=r(9616),l=r(4284).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)}},6896:function(e,t,r){"use strict";var n=r(8248);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}},1680: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"}}},6580: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"}}},9820:function(e,t,r){"use strict";var n=r(4040);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 z;if(-1===P)z=L;else{for(I=Math.max(O.length,I),z=[],x=0;x=P);x++)z.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 z(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]),I(e,t,"currentIndices"),void 0===r||Array.isArray(r)||(r=[r]),void 0!==r&&I(e,r,"newIndices"),void 0!==r&&t.length!==r.length)throw new Error("current and new indices must be of equal length.")}function R(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 I(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=P(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 V(e,t,r){e=o.getGraphDiv(e),T.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=X(e,n),i=a.flags;i.calc&&(e.calcdata=void 0);var l=[d.previousPromises];i.layoutReplot?l.push(M.layoutReplot):Object.keys(n).length&&(U(e,i,a)||d.supplyDefaults(e),i.legend&&l.push(M.doLegend),i.layoutstyle&&l.push(M.layoutStyles),i.axrange&&q(l,a.rangesAltered),i.ticks&&l.push(M.doTicksRelayout),i.modebar&&l.push(M.doModeBar),i.camera&&l.push(M.doCamera),i.colorbars&&l.push(M.doColorBars),l.push(S)),l.push(d.rehover,d.redrag,d.reselect),c.add(e,V,[e,a.undoit],V,[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 U(e,t,r){var n,a,i=e._fullLayout;if(!t.axrange)return!1;for(var l in t)if("axrange"!==l&&t[l])return!1;var s=function(e,t){return o.coerce(n,a,v,e,t)},c={};for(var u in r.rangesAltered){var f=h.id2name(u);if(n=e.layout[f],a=i[f],p(n,a,s,c),a._matchGroup)for(var d in a._matchGroup)if(d!==u){var y=i[h.id2name(d)];y.autorange=a.autorange,y.range=a.range.slice(),y._input.range=a.range.slice()}}return!0}function q(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(b,M.doAutoRangeAndConstraints,r,M.drawData,M.finalDraw)}var G=/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/,Z=/^[xyz]axis[0-9]*\.autorange$/,W=/^[xyz]axis[0-9]*\.domain(\[[0|1]\])?$/;function X(e,t){var r,n,a,i=e.layout,s=e._fullLayout,c=s._guiEditing,d=H(s._preGUI,c),p=Object.keys(t),v=h.list(e),y=o.extendDeepAll({},t),g={};for(Y(t),p=Object.keys(t),n=0;n0&&"string"!=typeof I.parts[R];)R--;var E=I.parts[R],N=I.parts[R-1]+"."+E,j=I.parts.slice(0,R).join("."),B=l(e.layout,j).get(),V=l(s,j).get(),U=I.get();if(void 0!==z){M[P]=z,L[P]="reverse"===E?z:F(U);var q=f.getLayoutValObject(s,I.parts);if(q&&q.impliedEdits&&null!==z)for(var X in q.impliedEdits)S(o.relativeAttr(P,X),q.impliedEdits[X]);if(-1!==["width","height"].indexOf(P))if(z){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",z?null:s.width),S("height",z?null:s.height);else if(N.match(G))C(N),l(s,j+"._inputRange").set(null);else if(N.match(Z)){C(N),l(s,j+"._inputRange").set(null);var Q=l(s,j).get();Q._inputDomain&&(Q._input.domain=Q._inputDomain.slice())}else N.match(W)&&l(s,j+"._inputDomain").set(null);if("type"===E){O=B;var $="linear"===V.type&&"log"===z,ee="log"===V.type&&"linear"===z;if($||ee){if(O&&O.range)if(V.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(j+".autorange",!0),te<=0?te=re/1e6:re<=0&&(re=te/1e6),S(j+".range[0]",Math.log(te)/Math.LN10),S(j+".range[1]",Math.log(re)/Math.LN10)):(S(j+".range[0]",Math.pow(10,te)),S(j+".range[1]",Math.pow(10,re)))}else S(j+".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,V,z,S),u.getComponentMethod("images","convertCoords")(e,V,z,S)}else S(j+".autorange",!0),S(j+".range",null);l(s,j+"._inputRange").set(null)}else if(E.match(A)){var ne=l(s,P).get(),ae=(z||{}).type;ae&&"-"!==ae||(ae="linear"),u.getComponentMethod("annotations","convertCoords")(e,ne,ae,S),u.getComponentMethod("images","convertCoords")(e,ne,ae,S)}var ie=w.containerArrayMatch(P);if(ie){r=ie.array,n=ie.index;var oe=ie.property,le=q||{editType:"calc"};""!==n&&""===oe&&(w.isAddVal(z)?L[P]=null:w.isRemoveVal(z)?L[P]=(l(i,r).get()||[])[n]:o.warn("unrecognized full object value",t)),k.update(_,le),g[r]||(g[r]={});var se=g[r][n];se||(se=g[r][n]={}),se[oe]=z,delete t[P]}else"reverse"===E?(B.range?B.range.reverse():(S(j+".autorange",!0),B.range=[1,0]),V.autorange?_.calc=!0:_.plot=!0):("dragmode"===P&&(!1===z&&!1!==U||!1!==z&&!1===U)||s._has("scatter-like")&&s._has("regl")&&"dragmode"===P&&("lasso"===z||"select"===z)&&"lasso"!==U&&"select"!==U||s._has("gl2d")?_.plot=!0:q?k.update(_,q):_.calc=!0,I.set(z))}}for(r in g)w.applyContainerArrayChanges(e,d(i,r),g[r],_,d)||(_.plot=!0);for(var ce in D){var ue=(O=h.getFromId(e,ce))&&O._constraintGroup;if(ue)for(var fe in _.calc=!0,ue)D[fe]||(h.getFromId(e,fe)._constraintShrinkable=!0)}(J(e)||t.height||t.width)&&(_.plot=!0);var de=s.shapes;for(n=0;n1;)if(n.pop(),void 0!==(r=l(t,n.join(".")+".uirevision").get()))return r;return t.uirevision}function ne(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,T.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&&L<5&&(L++,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===L&&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])}}}},9172:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(7316),o=r(3400),l=r(2736),s=r(3696),c=r(6308),u=r(3616),f=r(1668),d=r(3080),h=r(4460),p=r(4284),v=r(1888),y=v.enforce,g=v.clean,m=r(9280).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);if(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)}},7024:function(e,t,r){"use strict";var n=r(8248),a=r(6424),i=r(7316),o=r(3400),l=r(7030),s=r(7164),c=r(3268),u=r(5788).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)}))}))}},1480:function(e,t,r){"use strict";var n=r(3400),a=r(7316),i=r(3060),o=r(556).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}}},6720:function(e){"use strict";e.exports={xaxis:{valType:"subplotid",dflt:"x",editType:"calc+clearAxisTypes"},yaxis:{valType:"subplotid",dflt:"y",editType:"calc+clearAxisTypes"}}},9280:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(3400),o=r(9032).FP_SAFE,l=r(4040),s=r(3616),c=r(9811),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&&((k=D-l(b)-s(_))>C?A/k>P&&(w=b,T=_,P=A/k):A/D>P&&(w={val:b.val,nopad:1},T={val:_.val,nopad:1},P=A/D));if(d===v){var I=d-1,z=d+1;if(S)if(0===d)a=[0,1];else{var R=(d>0?f:u).reduce((function(e,t){return Math.max(e,s(t))}),0),E=d/(1-Math.min(.5,R/D));a=d>0?[0,E]:[E,0]}else a=O?[Math.max(0,I),Math.max(1,z)]:[I,z]}else S?(w.val>=0&&(w={val:0,nopad:1}),T.val<=0&&(T={val:0,nopad:1})):O&&(w.val-P*l(w)<0&&(w={val:0,nopad:1}),T.val<=0&&(T={val:1,nopad:1})),P=(T.val-w.val-h(t,b.val,_.val))/(D-l(w)-s(T)),a=[w.val-P*l(w),T.val+P*s(T)];return a=M(a,t),t.limitRange&&t.limitRange(),m&&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}function T(e,t,r){return void 0===t||void 0===r||(t=e.d2l(t))<(r=e.d2l(r))}function M(e,t){if(!t||!t.autorangeoptions)return e;var r=e[0],n=e[1],a=t.autorangeoptions.include;if(void 0!==a){var o=t.d2l(r),l=t.d2l(n);i.isArrayOrTypedArray(a)||(a=[a]);for(var s=0;s=c&&(o=c,r=c),l<=c&&(l=c,n=c)}}return r=function(e,t){var r=t.autorangeoptions;return r&&void 0!==r.minallowed&&T(t,r.minallowed,r.maxallowed)?r.minallowed:r&&void 0!==r.clipmin&&T(t,r.clipmin,r.clipmax)?Math.max(e,t.d2l(r.clipmin)):e}(r,t),n=function(e,t){var r=t.autorangeoptions;return r&&void 0!==r.maxallowed&&T(t,r.minallowed,r.maxallowed)?r.maxallowed:r&&void 0!==r.clipmax&&T(t,r.clipmin,r.clipmax)?Math.min(e,t.d2l(r.clipmax)):e}(n,t),[r,n]}},6808:function(e){"use strict";e.exports=function(e,t,r){var n,a;if(r){var i="reversed"===t||"min reversed"===t||"max reversed"===t;n=r[i?1:0],a=r[i?0:1]}var o=e("autorangeoptions.minallowed",null===a?n:void 0),l=e("autorangeoptions.maxallowed",null===n?a:void 0);void 0===o&&e("autorangeoptions.clipmin"),void 0===l&&e("autorangeoptions.clipmax"),e("autorangeoptions.include")}},4460:function(e,t,r){"use strict";var n=r(3428),a=r(8248),i=r(7316),o=r(4040),l=r(3400),s=l.strTranslate,c=r(2736),u=r(1668),f=r(6308),d=r(3616),h=r(4724),p=r(8728),v=r(9032),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"},z={K:"gridline",L:"path"},R={K:"minor-gridline",L:"path"},E={K:"tick",L:"path"},N={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(4284),j=H.MID_SHIFT,B=H.CAP_SHIFT,Y=H.LINE_SPACING,V=H.OPPOSITE_SIDE,U=e.exports={};U.setConvert=r(8344);var q=r(2976),G=r(9811),Z=G.idSort,W=G.isLinked;U.id2name=G.id2name,U.name2id=G.name2id,U.cleanId=G.cleanId,U.list=G.list,U.listIds=G.listIds,U.getFromId=G.getFromId,U.getFromTrace=G.getFromTrace;var X=r(9280);U.getAutoRange=X.getAutoRange,U.findExtremes=X.findExtremes;var J=1e-4;function K(e){var t=(e[1]-e[0])*J;return[e[0]-t,e[1]+t]}U.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)},U.getRefType=function(e){return void 0===e?e:"paper"===e?"paper":"pixel"===e?"pixel":/( domain)$/.test(e)?"domain":"range"},U.coercePosition=function(e,t,r,n,a,i){var o,s;if("range"!==U.getRefType(n))o=l.ensureNumber,s=r(a,i);else{var c=U.getFromId(t,n);s=r(a,i=c.fraction2r(i)),o=c.cleanPos}e[a]=o(s)},U.cleanPosition=function(e,t,r){return("paper"===r||"pixel"===r?l.ensureNumber:U.getFromId(t,r).cleanPos)(e)},U.redrawComponents=function(e,t){t=t||U.listIds(e);var r=e._fullLayout;function n(n,a,i,l){for(var s=o.getComponentMethod(n,a),c={},u=0;un&&d2e-6||((r-e._forceTick0)/e._minDtick%1+1.000001)%1>2e-6)&&(e._minDtick=0)):e._minDtick=0},U.saveRangeInitial=function(e,t){for(var r=U.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=U.tickIncrement(e,"M6","reverse")+1.5*A:i.exactMonths>o?e=U.tickIncrement(e,"M1","reverse")+15.5*A:e-=L;var c=U.tickIncrement(e,r);if(c<=n)return c}return e}(m,e,g,c,i)),y=m;y<=u;)y=U.tickIncrement(y,g,!1,i);return{start:t.c2r(m,0,i),end:t.c2r(y,0,i),size:g,_dataSpan:u-c}},U.prepMinorTicks=function(e,t,r){if(!t.minor.dtick){delete e.dtick;var n,i=t.dtick&&a(t._tmin);if(i){var o=U.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,U.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)},U.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,U.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=U.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);z--){var R=!z;z?(e._dtickInit=e.dtick,e._tick0Init=e.tick0):(e.minor._dtickInit=e.minor.dtick,e.minor._tick0Init=e.minor.tick0);var E=z?e:l.extendFlat({},e,e.minor);if(R?U.prepMinorTicks(E,e,t):U.prepTicks(E,t),"array"!==E.tickmode)if("sync"!==E.tickmode){var N=K(u),F=N[0],H=N[1],j=a(E.dtick),B="log"===i&&!(j||"L"===E.dtick.charAt(0)),Y=U.tickFirst(E,t);if(z){if(e._tmin=Y,Y=H:Z<=H;Z=U.tickIncrement(Z,W,f,o)){if(z&&V++,E.rangebreaks&&!f){if(Z=h)break}if(D.length>p||Z===G)break;G=Z;var X={value:Z};z?(B&&Z!==(0|Z)&&(X.simpleLabel=!0),s>1&&V%s&&(X.skipLabel=!0),D.push(X)):(X.minor=!0,C.push(X))}}else D=[],v=ie(e);else z?(D=[],v=oe(e,!R)):(C=[],O=oe(e,!R))}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=Re(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,fontWeight:n.weight,fontStyle:n.style,fontVariant:n.variant,fontColor:n.color}}U.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=U.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))):ze(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)}},U.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)},U.tickFirst=function(e,t){var r=e.r2l||Number,i=l.simpleMap(e.range,r,void 0,void 0,t),o=i[1]=0&&r<=e._length?t:null};if(s&&l.isArrayOrTypedArray(e.ticktext)){var h=l.simpleMap(e.range,e.r2l),p=(Math.abs(h[1]-h[0])-(e._lBreaks||0))/1e4;for(i=0;i ")}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,y):"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):ze(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,y):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,y),n||(e.tickprefix&&!v(e.showtickprefix)&&(o.text=e.tickprefix+o.text),e.ticksuffix&&!v(e.showticksuffix)&&(o.text+=e.ticksuffix)),e.labelalias&&e.labelalias.hasOwnProperty(o.text)){var g=e.labelalias[o.text];"string"==typeof g&&(o.text=g)}return("boundaries"===e.tickson||e.showdividers)&&(o.xbnd=[d(o.x-.5),d(o.x+e.dtick-.5)]),o},U.hoverLabelText=function(e,t,r){r&&(e=l.extendFlat({},e,{hoverformat:r}));var n=l.isArrayOrTypedArray(t)?t[0]:t,a=l.isArrayOrTypedArray(t)?t[1]:void 0;if(void 0!==a&&a!==n)return U.hoverLabelText(e,n,r)+" - "+U.hoverLabelText(e,a,r);var i="log"===e.type&&n<=0,o=U.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=U.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=U.getFromId(e,t);r||(r={}),r.axShifts=o,r.overlayingShiftedAx=i;var a=U.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}}})))},U.drawOne=function(e,t,r){var n,a,s,h=(r=r||{}).axShifts||{},p=r.overlayingShiftedAx||[];t.setScale();var v=e._fullLayout,y=t._id,g=y.charAt(0),m=U.counterLetter(y),x=v._plots[t._mainSubplot];if(x){if(t._shiftPusher=t.autoshift||-1!==p.indexOf(t._id)||-1!==p.indexOf(t.overlaying),t._shiftPusher&"free"===t.anchor){var b=t.linewidth/2||0;"inside"===t.ticks&&(b+=t.ticklen),Fe(t,b,h,!0),Fe(t,t.shift||0,h,!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,h));var _=x[g+"axislayer"],w=t._mainLinePosition,T=w+=t._shift,M=t._mainMirrorPosition,k=t._vals=U.calcTicks(t),A=[t.mirror,T,M].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!==v._dfltTitle[g]&&(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 p=[0,1],y="number"==typeof t._shift?t._shift:0;if("x"===g){if("b"===s?n[s]=t._depth:(n[s]=t._depth=Math.max(r.width>0?u-r.top:0,f),p.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-y):(t._depth=Math.max(r.height>0?r.right-u:0,f),n[s]=t._depth+y,p.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[m]="free"===t.anchor?t.position:t._anchorAxis.domain[p[0]],t.title.text!==v._dfltTitle[g]&&(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[m]=t._anchorAxis.domain[p[1]]:"all"!==t.mirror&&"allticks"!==t.mirror||(a[m]=[t._counterDomainMin,t._counterDomainMax][p[1]]))}fe&&(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(ce)}}function de(e){var r=y+(e||"tick");return L[r]||(L[r]=function(e,t,r){var n,a,i,o;if(e._selections[t].size())n=1/0,a=-1/0,i=1/0,o=-1/0,e._selections[t].each((function(){var e=Le(this),t=d.bBox(e.node().parentNode);n=Math.min(n,t.top),a=Math.max(a,t.bottom),i=Math.min(i,t.left),o=Math.max(o,t.right)}));else{var l=U.makeLabelFns(e,r);n=a=l.yFn({dx:0,dy:0,fontSize:0}),i=o=l.xFn({dx:0,dy:0,fontSize:0})}return{top:n,bottom:a,left:i,right:o,height:a-n,width:o-i}}(t,r,T)),L[r]}},U.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},U.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))}},U.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)))}},U.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},U.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},U.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),Ne(t,[E]),o.attr("transform",r.transFn)},U.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&&U.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)}}Ne(t,[z,R])}},U.drawZeroLine=function(e,t,r){r=r||r;var n=t._id+"zl",a=U.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 Z(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),Ne(t,[I])},U.drawLabels=function(e,t,r){r=r||{};var i=e._fullLayout,o=t._id,u=r.cls||o+"tick",f=r.vals.filter((function(e){return e.text})),h=r.labelFns,p=r.secondary?0:t.tickangle,v=(t._prevTickAngles||{})[u],y=r.layer.selectAll("g."+u).data(t.showticklabels?f:[],Me),g=[];function m(e,i){e.each((function(e){var o=n.select(this),l=o.select(".text-math-group"),u=h.anchorFn(e,i),f=r.transFn.call(o.node(),e)+(a(i)&&0!=+i?" rotate("+i+","+h.xFn(e)+","+(h.yFn(e)-e.fontSize/2)+")":""),p=c.lineCount(o),v=Y*e.fontSize,y=h.heightFn(e,a(i)?+i:0,(p-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))}}))}y.enter().append("g").classed(u,1).append("text").attr("text-anchor","middle").each((function(t){var r=n.select(this),a=e._promises.length;r.call(c.positionText,h.xFn(t),h.yFn(t)).call(d.font,{family:t.font,size:t.fontSize,color:t.fontColor,weight:t.fontWeight,style:t.fontStyle,variant:t.fontVariant}).text(t.text).call(c.convertToTspans,e),e._promises[a]?g.push(e._promises.pop().then((function(){m(r,p)}))):m(r,p)})),Ne(t,[N]),y.exit().remove(),r.repositionOnUpdate&&y.each((function(e){n.select(this).select("text").call(c.positionText,h.xFn(e),h.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,g=-1/0;for(var m in y.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)}))}))}))}))},m(y,v+1?v:p);var x=null;t._selections&&(t._selections[u]=y);var b=[function(){return g.length&&Promise.all(g)}];t.automargin&&i._redrawFromAutoMarginCount&&90===v?(x=v,b.push((function(){m(y,v)}))):b.push((function(){if(m(y,p),f.length&&t.autotickangles&&("log"!==t.type||"D"!==String(t.dtick).charAt(0))){x=t.autotickangles[0];var e,n=0,a=[],i=1;y.each((function(e){n=Math.max(n,e.fontSize);var r=t.l2p(e.x),o=Le(this),l=d.bBox(o.node());i=Math.max(i,c.lineCount(o)),a.push({top:0,bottom:10,height:10,left:r-l.width/2,right:r+l.width/2+2,width:l.width+2})}));var o=("boundaries"===t.tickson||t.showdividers)&&!r.secondary,s=f.length,u=Math.abs((f[s-1].x-f[0].x)*t._m)/(s-1),h=o?u/2:u,v=o?t.ticklen:1.25*n*i,g=h/Math.sqrt(Math.pow(h,2)+Math.pow(v,2)),b=t.autotickangles.map((function(e){return e*Math.PI/180})),_=b.find((function(e){return Math.abs(Math.cos(e))<=g}));void 0===_&&(_=b.reduce((function(e,t){return Math.abs(Math.cos(e))j*H&&(C=H,S[L]=O[L]=P[L])}var B=Math.abs(C-D);B-M>0?M*=1+M/(B-=M):M=0,"y"!==t._id.charAt(0)&&(M=-M),S[A]=w.p2r(w.r2p(O[A])+k*M),"min"===w.autorange||"max reversed"===w.autorange?(S[0]=null,w._rangeInitial0=void 0,w._rangeInitial1=void 0):"max"!==w.autorange&&"min reversed"!==w.autorange||(S[1]=null,w._rangeInitial0=void 0,w._rangeInitial1=void 0),i._insideTickLabelsUpdaterange[w._name+".range"]=S}var V=l.syncOrAsync(b);return V&&V.then&&e._promises.push(V),V},U.getPxPosition=function(e,t){var r,n=e._fullLayout._size,a=t._id.charAt(0),i=t.side;return"free"!==t.anchor?r=t._anchorAxis:"x"===a?r={_offset:n.t+(1-(t.position||0))*n.h,_length:0}:"y"===a&&(r={_offset:n.l+(t.position||0)*n.w+t._shift,_length:0}),"top"===i||"left"===i?r._offset:"bottom"===i||"right"===i?r._offset+r._length:void 0},U.shouldShowZeroLine=function(e,t,r){var n=l.simpleMap(t.range,t.r2l);return n[0]*n[1]<=0&&t.zeroline&&("linear"===t.type||"-"===t.type)&&!(t.rangebreaks&&t.maskBreaks(0)===P)&&(Ae(t,0)||!function(e,t,r,n){var a=r._mainAxis;if(a){var i=e._fullLayout,o=t._id.charAt(0),l=U.counterLetter(t._id),s=t._offset+(Math.abs(n[0])1)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=_(o[l])){u=g;break}var f=a("pattern",u);if(f===g)for(l=0;l<2;l++)(c=_(o[l]))&&(t.bounds[l]=o[l]=c-1);if(f)for(l=0;l<2;l++)switch(c=o[l],f){case g: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 m: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)}},4796:function(e,t,r){"use strict";var n=r(8116).isTypedArraySpec;e.exports=function(e,t,r,a){if("category"===t.type){var i,o=e.categoryarray,l=Array.isArray(o)&&o.length>0||n(o);l&&(i="array");var s,c=r("categoryorder",i);"array"===c&&(s=r("categoryarray")),l||"array"!==c||(c=t.categoryorder="trace"),"trace"===c?t._initialCategories=[]:"array"===c?t._initialCategories=s.slice():(s=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&&NC&&(C=N);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 V(e){n.select(e).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function U(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 G(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(V(a),2!==e||ge||Ue(),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 ze(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;u1&&(void 0!==i.maxallowed&&le===(i.range[0]1&&(void 0!==o.maxallowed&&se===(o.range[0]b[1]-1/4096&&(t.domain=l),a.noneOrAll(e.domain,t.domain,l),"sync"===t.tickmode&&(t.tickmode="auto")}return r("layer"),t}},2568:function(e,t,r){"use strict";var n=r(5024);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)}},6312:function(e,t,r){"use strict";var n=r(6808);e.exports=function(e,t,r,a){var i=t._template||{},o=t.type||i.type||"-";r("minallowed"),r("maxallowed");var l,s=r("range");s||a.noInsiderange||"log"===o||(!(l=r("insiderange"))||null!==l[0]&&null!==l[1]||(t.insiderange=!1,l=void 0),l&&(s=r("range",l)));var c,u=t.getAutorangeDflt(s,a),f=r("autorange",u);!s||(null!==s[0]||null!==s[1])&&(null!==s[0]&&null!==s[1]||"reversed"!==f&&!0!==f)&&(null===s[0]||"min"!==f&&"max reversed"!==f)&&(null===s[1]||"max"!==f&&"min reversed"!==f)||(s=void 0,delete t.range,t.autorange=!0,c=!0),c||(f=r("autorange",u=t.getAutorangeDflt(s,a))),f&&(n(r,f,s),"linear"!==o&&"-"!==o||r("rangemode")),t.cleanRange()}},1160:function(e,t,r){"use strict";var n=r(4284).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()}},8344:function(e,t,r){"use strict";var n=r(3428),a=r(4336).E9,i=r(3400),o=i.numberFormat,l=r(8248),s=i.cleanNumber,c=i.ms2DateTime,u=i.dateTime2ms,f=i.ensureNumber,d=i.isArrayOrTypedArray,h=r(9032),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(9811),T=r(3816),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 z(e){var t=I(e);return void 0!==t?t:l(e)?+e:void 0}function R(e){return l(e)?+e:I(e)}function E(e,t,r){return n.round(r+t*e,2)}function N(e,t,r){return(e-r)/t}var F=function(t){return l(t)?E(t,e._m,e._b):v},H=function(t){return N(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 E(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)?E(t,e._m2,f):0},H=function(t){var r=e._rangebreaks.length;if(!r)return N(t,e._m,e._b);for(var n=0,a=0;ae._rangebreaks[a].pmax&&(n=a+1);return N(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=z,e.r2c=function(t){var r=R(t);return void 0!==r?r:e.fraction2r(.5)},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"string"==typeof e&&""!==e?e:f(e)}):"multicategory"===e.type&&(e.r2d=e.c2d=e.l2d=C,e.d2r=e.d2l_noadd=z,e.r2c=function(t){var r=z(t);return void 0!==r?r:e.fraction2r(.5)},e.r2c_just_indices=I,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 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;as[1]&&(a[l?0:1]=n),a[0]===a[1]){var c=e.l2r(r),u=e.l2r(n);if(void 0!==r){var f=c+1;void 0!==n&&(f=Math.min(f,u)),a[l?1:0]=f}if(void 0!==n){var d=u+1;void 0!==r&&(d=Math.max(d,c)),a[l?0:1]=d}}}},e.cleanRange=function(t,r){e._cleanRange(t,r),e.limitRange(t)},e._cleanRange=function(t,r){r||(r={}),t||(t="range");var n,a,o=i.nestedProperty(e,t).get();if(a=(a="date"===e.type?i.dfltRange(e.calendar):"y"===h?T.DFLTRANGEY:"realaxis"===e._name?[0,1]:r.dfltRange||T.DFLTRANGEX).slice(),"tozero"!==e.rangemode&&"nonnegative"!==e.rangemode||(a[0]=0),o&&2===o.length){var s=null===o[0],c=null===o[1];for("date"!==e.type||e.autorange||(o[0]=i.cleanDate(o[0],v,e.calendar),o[1]=i.cleanDate(o[1],v,e.calendar)),n=0;n<2;n++)if("date"===e.type){if(!i.isDateTime(o[n],e.calendar)){e[t]=a;break}if(e.r2l(o[0])===e.r2l(o[1])){var u=i.constrain(e.r2l(o[0]),i.MIN_MS+1e3,i.MAX_MS-1e3);o[0]=e.l2r(u-1e3),o[1]=e.l2r(u+1e3);break}}else{if(!l(o[n])){if(s||c||!l(o[1-n])){e[t]=a;break}o[n]=o[1-n]*(n?10:.1)}if(o[n]<-p?o[n]=-p:o[n]>p&&(o[n]=p),o[0]===o[1]){var f=Math.max(1,Math.abs(1e-6*o[0]));o[0]-=f,o[1]+=f}}}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)}},4944:function(e,t,r){"use strict";var n=r(4040).traceIs,a=r(2976);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(){w.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()?" - ":"")}},w.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=w.graphJson(e,!1,"keepdata"),a.node().submit(),r.remove(),e.emit("plotly_afterexport"),!1}};var k=["days","shortDays","months","shortMonths","periods","dateTime","date","time","decimal","thousands","grouping","currency"],A=["year","month","dayMonth","dayMonthYear"];function L(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&&z.length>1){for(s.getComponentMethod("grid","sizeDefaults")(c,l),o=0;o15&&z.length>15&&0===l.shapes.length&&0===l.images.length,w.linkSubplots(d,l,u,n),w.cleanPlot(d,l,u,n);var H=!(!n._has||!n._has("gl2d")),j=!(!l._has||!l._has("gl2d")),B=!(!n._has||!n._has("cartesian"))||H,Y=!(!l._has||!l._has("cartesian"))||j;B&&!Y?n._bgLayer.remove():Y&&!B&&(l._shouldCreateBgLayer=!0),n._zoomlayer&&!e._dragging&&v({_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 u=1-2*l;n=Math.round(u*n),a=Math.round(u*a)}}var d=w.layoutAttributes.width.min,h=w.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}),w.sanitizeMargins(r)},w.supplyLayoutModuleDefaults=function(e,t,r,n){var a,i,o,l=s.componentsRegistry,c=t._basePlotModules,u=s.subplotsRegistry.cartesian;for(a in l)(o=l[a]).includeBasePlot&&o.includeBasePlot(e,t);for(var d in c.length||c.push(u),t._has("cartesian")&&(s.getComponentMethod("grid","contentDefaults")(e,t),u.finalizeSubplots(e,t)),t._subplots)t._subplots[d].sort(f.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,_=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:_,size:r.t+y}},v[t]=1}else delete p[t],delete v[t];if(!n._replotting)return w.doAutoMargin(e)}},w.doAutoMargin=function(e){var t=e._fullLayout,r=t.width,n=t.height;t._size||(t._size={}),P(t);var a=t._size,i=t.margin,l={t:0,b:0,l:0,r:0},c=f.extendFlat({},a),u=i.l,d=i.r,h=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 _=e._fullLayout._reservedMargin;for(var T in _)for(var M in _[T]){var k=_[T][M];l[M]=Math.max(l[M],k)}for(var A in y.base={l:{val:0,size:u},r:{val:1,size:d},t:{val:1,size:h},b:{val:0,size:v}},l){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);l[A]=Math.max(0,l[A]-O)}for(var D in y){var C=y[D].l||{},I=y[D].b||{},z=C.val,R=C.size,E=I.val,N=I.size,F=r-l.r-l.l,H=n-l.t-l.b;for(var j in y){if(o(R)&&y[j].r){var B=y[j].r.val,Y=y[j].r.size;if(B>z){var V=(R*B+(Y-F)*z)/(B-z),U=(Y*(1-z)+(R-F)*(1-B))/(B-z);V+U>u+d&&(u=V,d=U)}}if(o(N)&&y[j].t){var q=y[j].t.val,G=y[j].t.size;if(q>E){var Z=(N*q+(G-H)*E)/(q-E),W=(G*(1-E)+(N-H)*(1-q))/(q-E);Z+W>v+h&&(v=Z,h=W)}}}}}var X=f.constrain(r-i.l-i.r,2,m),J=f.constrain(n-i.t-i.b,2,x),K=Math.max(0,r-X),Q=Math.max(0,n-J);if(K){var $=(u+d)/K;$>1&&(u/=$,d/=$)}if(Q){var ee=(v+h)/Q;ee>1&&(v/=ee,h/=ee)}if(a.l=Math.round(u)+l.l,a.r=Math.round(d)+l.r,a.t=Math.round(h)+l.t,a.b=Math.round(v)+l.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&&(w.didMarginChange(c,a)||function(e){if("_redrawFromAutoMarginCount"in e._fullLayout)return!1;var t=p.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 s.call("redraw",e)})),e._transitionData._interruptCallbacks.push((function(){e.emit("plotly_transitioninterrupted",[])}));var i=0,o=0;function l(){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 s.call("redraw",e)})).then((function(){e._transitioning=!1,e._transitioningWithDuration=!1,e.emit("plotly_transitioned",[])})).then(t)))}}r.runFn(l),setTimeout(l())}))}],i=f.syncOrAsync(a,e);return i&&i.then||(i=Promise.resolve()),i.then((function(){return e}))}w.didMarginChange=function(e,t){for(var r=0;r1)return!0}return!1},w.graphJson=function(e,t,r,n,a,i){(a&&t&&!e._fullData||a&&!t&&!e._fullLayout)&&w.supplyDefaults(e);var o=a?e._fullData:e.data,s=a?e._fullLayout:e.layout,c=(e._transitionData||{})._frames;function u(e,t){if("function"==typeof e)return t?"_function_":null;if(f.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&&!f.isPlainObject(e.stream))return}else if("keepall"!==r&&"string"==typeof(n=e[i+"src"])&&n.indexOf(":")>0)return;a[i]=u(e[i],t)}else t&&(a[i]="_function")})),a}var i=Array.isArray(e),o=f.isTypedArray(e);if((i||o)&&e.dtype&&e.shape){var s=e.bdata;return u({dtype:e.dtype,shape:e.shape,bdata:f.isArrayBuffer(s)?l.encode(s):s},t)}return i?e.map((function(e){return u(e,t)})):o?f.simpleMap(e,f.identity):f.isJSDate(e)?f.ms2DateTimeLocal(+e):e}var d={data:(o||[]).map((function(e){var r=u(e);return t&&delete r.fit,r}))};if(!t&&(d.layout=u(s),a)){var h=s._size;d.layout.computed={margin:{b:h.b,l:h.l,r:h.r,t:h.t}}}return c&&(d.frames=u(c)),i&&(d.config=u(e._context,!0)),"object"===n?d:JSON.stringify(d)},w.modifyFrames=function(e,t){var r,n,a,i=e._transitionData._frames,o=e._transitionData._frameHash;for(r=0;r=0;i--)if(s[i].enabled){r._indexToPoints=s[i]._indexToPoints;break}n&&n.calc&&(o=n.calc(e,r))}Array.isArray(o)&&o[0]||(o=[{x:h,y:h}]),o[0].t||(o[0].t={}),o[0].trace=r,d[t]=o}}for(E(o,l,u),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}},4664:function(e,t,r){"use strict";var n=r(3400);e.exports=function(e,t){for(var r=0;rf+c||!n(u))}for(var h=0;h=0)return e}else if("string"==typeof e&&"%"===(e=e.trim()).slice(-1)&&n(e.slice(0,-1))&&(e=+e.slice(0,-1))>=0)return e+"%"}function p(e,t,r,n,i,o){var l=!(!1===(o=o||{}).moduleHasSelected),s=!(!1===o.moduleHasUnselected),c=!(!1===o.moduleHasConstrain),u=!(!1===o.moduleHasCliponaxis),f=!(!1===o.moduleHasTextangle),h=!(!1===o.moduleHasInsideanchor),p=!!o.hasPathbar,v=Array.isArray(i)||"auto"===i,y=v||"inside"===i,g=v||"outside"===i;if(y||g){var m=d(n,"textfont",r.font),x=a.extendFlat({},m),b=!(e.textfont&&e.textfont.color);if(b&&delete x.color,d(n,"insidetextfont",x),p){var _=a.extendFlat({},m);b&&delete _.color,d(n,"pathbar.textfont",_)}g&&d(n,"outsidetextfont",m),l&&n("selected.textfont.color"),s&&n("unselected.textfont.color"),c&&n("constraintext"),u&&n("cliponaxis"),f&&n("textangle"),n("texttemplate")}y&&h&&n("insidetextanchor")}e.exports={supplyDefaults:function(e,t,r,n){function u(r,n){return a.coerce(e,t,f,r,n)}if(l(e,t,n,u)){s(e,t,n,u),u("xhoverformat"),u("yhoverformat"),u("zorder"),u("orientation",t.x&&!t.y?"h":"v"),u("base"),u("offset"),u("width"),u("text"),u("hovertext"),u("hovertemplate");var d=u("textposition");p(e,0,n,u,d,{moduleHasSelected:!0,moduleHasUnselected:!0,moduleHasConstrain:!0,moduleHasCliponaxis:!0,moduleHasTextangle:!0,moduleHasInsideanchor:!0}),c(e,t,u,r,n);var h=(t.marker.line||{}).color,v=o.getComponentMethod("errorbars","supplyDefaults");v(e,t,h||i.defaultLine,{axis:"y"}),v(e,t,h||i.defaultLine,{axis:"x",inherit:"y"}),a.coerceSelectionMarkerOpacity(t,u)}else t.visible=!1},crossTraceDefaults:function(e,t){var r,n;function i(e,t){return a.coerce(n._input,n,f,e,t)}for(var o=0;oi))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 i(e)?t0?t+=r:u<0&&(t-=r)}return t}function z(e){var t=u,r=e.b,a=I(e);return n.inbox(r-t,a-t,_+(a-t)/(a-r)-1)}var R=e[f+"a"],E=e[d+"a"];v=Math.abs(R.r2c(R.range[1])-R.r2c(R.range[0]));var N=n.getDistanceFunction(a,h,p,(function(e){return(h(e)+p(e))/2}));if(n.getClosest(y,N,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"]=E.c2p(F[d],!0),e[d+"LabelVal"]=H;var j=m.extents[m.extents.round(F.p)];e[f+"0"]=R.c2p(x?O(F):j[0],!0),e[f+"1"]=R.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(R,e[f+"LabelVal"],g[f+"hoverformat"]),e.valueLabel=s(E,e[d+"LabelVal"],g[d+"hoverformat"]),e.baseLabel=s(E,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"]=R.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}},1132:function(e,t,r){"use strict";e.exports={attributes:r(832),layoutAttributes:r(9324),supplyDefaults:r(1508).supplyDefaults,crossTraceDefaults:r(1508).crossTraceDefaults,supplyLayoutDefaults:r(7156),calc:r(9439),crossTraceCalc:r(6376).crossTraceCalc,colorbar:r(5528),arraysToCalcdata:r(4664),plot:r(8184).plot,style:r(100).style,styleOnSelect:r(100).styleOnSelect,hoverPoints:r(1020).hoverPoints,eventData:r(2160),selectPoints:r(5784),moduleType:"trace",name:"bar",basePlotModule:r(7952),categories:["bar-like","cartesian","svg","bar","oriented","errorBarsOK","showLegend","zoomScale"],animatable:!0,meta:{}}},9324: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"},barcornerradius:{valType:"any",editType:"calc"}}},7156:function(e,t,r){"use strict";var n=r(4040),a=r(4460),i=r(3400),o=r(9324),l=r(1508).validateCornerradius;e.exports=function(e,t,r){function s(r,n){return i.coerce(e,t,o,r,n)}for(var c=!1,u=!1,f=!1,d={},h=s("barmode"),p=0;p0)-(e<0)}function k(e,t){return e0}function S(e,t,r,n,a){return!(e<0||t<0)&&(r<=e&&n<=t||r<=t&&n<=e||(a?e>=r*(t/n):t>=n*(e/r)))}function O(e){return"auto"===e?0:e}function D(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 C(e,t,r,n,a,i){var o=!!i.isHorizontal,l=!!i.constrained,s=i.angle||0,c=i.anchor,u="end"===c,f="start"===c,d=((i.leftToRight||0)+1)/2,h=1-d,p=i.hasB,v=i.r,y=i.overhead,g=a.width,m=a.height,x=Math.abs(t-e),b=Math.abs(n-r),w=x>2*_&&b>2*_?_:0;x-=2*w,b-=2*w;var T=O(s);"auto"!==s||g<=x&&m<=b||!(g>x||m>b)||(g>b||m>x)&&g_){var S=function(e,t,r,n,a,i,o,l,s){var c,u,f,d,h,p=Math.max(0,Math.abs(t-e)-2*_),v=Math.max(0,Math.abs(n-r)-2*_),y=i-_,g=o?y-Math.sqrt(y*y-(y-o)*(y-o)):y,m=s?2*y:l?y-o:2*g,x=s?2*y:l?2*g:y-o;return a.y/a.x>=v/(p-m)?d=v/a.y:a.y/a.x<=(v-x)/p?d=p/a.x:!s&&l?(c=a.x*a.x+a.y*a.y/4,f=(p-y)*(p-y)+(v/2-y)*(v/2-y)-y*y,d=(-(u=-2*a.x*(p-y)-a.y*(v/2-y))+Math.sqrt(u*u-4*c*f))/(2*c)):s?(c=(a.x*a.x+a.y*a.y)/4,f=(p/2-y)*(p/2-y)+(v/2-y)*(v/2-y)-y*y,d=(-(u=-a.x*(p/2-y)-a.y*(v/2-y))+Math.sqrt(u*u-4*c*f))/(2*c)):(c=a.x*a.x/4+a.y*a.y,f=(p/2-y)*(p/2-y)+(v-y)*(v-y)-y*y,d=(-(u=-a.x*(p/2-y)-2*a.y*(v-y))+Math.sqrt(u*u-4*c*f))/(2*c)),d=Math.min(1,d),h=l?Math.max(0,y-Math.sqrt(Math.max(0,y*y-(y-(v-a.y*d)/2)*(y-(v-a.y*d)/2)))-o):Math.max(0,y-Math.sqrt(Math.max(0,y*y-(y-(p-a.x*d)/2)*(y-(p-a.x*d)/2)))-o),{scale:d,pad:h}}(e,t,r,n,L,v,y,o,p);M=S.scale,A=S.pad}else M=1,l&&(M=Math.min(1,x/L.x,b/L.y)),A=0;var C=a.left*h+a.right*d,P=(a.top+a.bottom)/2,I=(e+_)*h+(t-_)*d,z=(r+n)/2,R=0,E=0;if(f||u){var N=(o?L.x:L.y)/2;v&&(u||p)&&(w+=A);var F=o?k(e,t):k(r,n);o?f?(I=e+F*w,R=-F*N):(I=t-F*w,R=F*N):f?(z=r+F*w,E=-F*N):(z=n-F*w,E=F*N)}return{textX:C,textY:P,targetX:I,targetY:z,anchorX:R,anchorY:E,scale:M,rotate:T}}e.exports={plot:function(e,t,r,f,y,g){var w=t.xaxis,P=t.yaxis,I=e._fullLayout,z=e._context.staticPlot;y||(y={mode:I.barmode,norm:I.barmode,gap:I.bargap,groupgap:I.bargroupgap},h("bar",I));var R=i.makeTraceGroups(f,r,"trace bars").each((function(r){var c=n.select(this),f=r[0].trace,h=r[0].t,R="waterfall"===f.type,E="funnel"===f.type,N="histogram"===f.type,F="bar"===f.type,H=F||E,j=0;R&&f.connector.visible&&"between"===f.connector.mode&&(j=f.connector.line.width/2);var B="h"===f.orientation,Y=L(y),V=i.ensureSingle(c,"g","points"),U=T(f),q=V.selectAll("g.point").data(i.identity,U);q.enter().append("g").classed("point",!0),q.exit().remove(),q.each((function(c,T){var L,R,E=n.select(this),V=function(e,t,r,n){var a=[],i=[],o=n?t:r,l=n?r:t;return a[0]=o.c2p(e.s0,!0),i[0]=l.c2p(e.p0,!0),a[1]=o.c2p(e.s1,!0),i[1]=l.c2p(e.p1,!0),n?[a,i]:[i,a]}(c,w,P,B),U=V[0][0],q=V[0][1],G=V[1][0],Z=V[1][1],W=0==(B?q-U:Z-G);if(W&&H&&v.getLineWidth(f,c)&&(W=!1),W||(W=!(a(U)&&a(q)&&a(G)&&a(Z))),c.isBlank=W,W&&(B?q=U:Z=G),j&&!W&&(B?(U-=k(U,q)*j,q+=k(U,q)*j):(G-=k(G,Z)*j,Z+=k(G,Z)*j)),"waterfall"===f.type){if(!W){var X=f[c.dir].marker;L=X.line.width,R=X.color}}else L=v.getLineWidth(f,c),R=c.mc||f.marker.color;function J(e){var t=n.round(L/2%1,2);return 0===y.gap&&0===y.groupgap?n.round(Math.round(e)-t,2):e}var K=l.opacity(R)<1||L>.01?J:function(e,t,r){return r&&e===t?e:Math.abs(e-t)>=2?J(e):e>t?Math.ceil(e):Math.floor(e)};e._context.staticPlot||(U=K(U,q,B),q=K(q,U,B),G=K(G,Z,!B),Z=K(Z,G,!B));var Q,$=B?w.c2p:P.c2p;Q=c.s0>0?c._sMax:c.s0<0?c._sMin:c.s1>0?c._sMax:c._sMin;var ee,te,re=F||N?function(e,t){if(!e)return 0;var r,n=B?Math.abs(Z-G):Math.abs(q-U),a=B?Math.abs(q-U):Math.abs(Z-G),i=K(Math.abs($(Q,!0)-$(0,!0))),o=c.hasB?Math.min(n/2,a/2):Math.min(n/2,i);return r="%"===t?n*(Math.min(50,e)/100):e,K(Math.max(Math.min(r,o),0))}(h.cornerradiusvalue,h.cornerradiusform):0,ne="M"+U+","+G+"V"+Z+"H"+q+"V"+G+"Z",ae=0;if(re&&c.s){var ie=0===M(c.s0)||M(c.s)===M(c.s0)?c.s1:c.s0;if((ae=K(c.hasB?0:Math.abs($(Q,!0)-$(ie,!0))))0?Math.sqrt(ae*(2*re-ae)):0,fe=oe>0?Math.max:Math.min;ee="M"+U+","+G+"V"+(Z-ce*le)+"H"+fe(q-(re-ae)*oe,U)+"A "+re+","+re+" 0 0 "+se+" "+q+","+(Z-re*le-ue)+"V"+(G+re*le+ue)+"A "+re+","+re+" 0 0 "+se+" "+fe(q-(re-ae)*oe,U)+","+(G+ce*le)+"Z"}else if(c.hasB)ee="M"+(U+re*oe)+","+G+"A "+re+","+re+" 0 0 "+se+" "+U+","+(G+re*le)+"V"+(Z-re*le)+"A "+re+","+re+" 0 0 "+se+" "+(U+re*oe)+","+Z+"H"+(q-re*oe)+"A "+re+","+re+" 0 0 "+se+" "+q+","+(Z-re*le)+"V"+(G+re*le)+"A "+re+","+re+" 0 0 "+se+" "+(q-re*oe)+","+G+"Z";else{var de=(te=Math.abs(Z-G)+ae)0?Math.sqrt(ae*(2*re-ae)):0,pe=le>0?Math.max:Math.min;ee="M"+(U+de*oe)+","+G+"V"+pe(Z-(re-ae)*le,G)+"A "+re+","+re+" 0 0 "+se+" "+(U+re*oe-he)+","+Z+"H"+(q-re*oe+he)+"A "+re+","+re+" 0 0 "+se+" "+(q-de*oe)+","+pe(Z-(re-ae)*le,G)+"V"+G+"Z"}}else ee=ne}else ee=ne;var ve=A(i.ensureSingle(E,"path"),I,y,g);if(ve.style("vector-effect",z?"none":"non-scaling-stroke").attr("d",isNaN((q-U)*(Z-G))||W&&e._context.staticPlot?"M0,0Z":ee).call(s.setClipUrl,t.layerClipId,e),!I.uniformtext.mode&&Y){var ye=s.makePointStyleFns(f);s.singlePointStyle(c,ve,f,ye,e)}!function(e,t,r,n,a,l,c,f,h,y,g,w,T){var M,L=t.xaxis,P=t.yaxis,I=e._fullLayout;function z(t,r,n){return i.ensureSingle(t,"text").text(r).attr({class:"bartext bartext-"+M,"text-anchor":"middle","data-notex":1}).call(s.font,n).call(o.convertToTspans,e)}var R=n[0].trace,E="h"===R.orientation,N=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)}(I,n,a,L,P);M=function(e,t){var r=v.getValue(e.textposition,t);return v.coerceEnumerated(x,r)}(R,a);var F="stack"===w.mode||"relative"===w.mode,H=n[a],j=!F||H._outmost,B=H.hasB,Y=y&&y-g>_;if(N&&"none"!==M&&(!H.isBlank&&l!==c&&f!==h||"auto"!==M&&"inside"!==M)){var V=I.font,U=p.getBarColor(n[a],R),q=p.getInsideTextFont(R,a,V,U),G=p.getOutsideTextFont(R,a,V),Z=R.insidetextanchor||"end",W=r.datum();E?"log"===L.type&&W.s0<=0&&(l=L.range[0]0&&Q>0;ae=Y?B?S(re-2*y,ne,K,Q,E)||S(re,ne-2*y,K,Q,E):E?S(re-(y-g),ne,K,Q,E)||S(re,ne-2*(y-g),K,Q,E):S(re,ne-(y-g),K,Q,E)||S(re-2*(y-g),ne,K,Q,E):S(re,ne,K,Q,E),ie&&ae?M="inside":(M="outside",X.remove(),X=null)}else M="inside";if(!X){var oe=(X=z(r,N,$=i.ensureUniformFontSize(e,"outside"===M?G:q))).attr("transform");if(X.attr("transform",""),K=(J=s.bBox(X.node())).width,Q=J.height,X.attr("transform",oe),K<=0||Q<=0)return void X.remove()}var le,se=R.textangle;le="outside"===M?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=O(c),y=D(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,M=0,A=l?k(t,e):k(r,n);return l?(b=t-A*o,T=A*g):(w=n+A*o,M=-A*g),{textX:m,textY:x,targetX:b,targetY:w,anchorX:T,anchorY:M,scale:p,rotate:v}}(l,c,f,h,J,{isHorizontal:E,constrained:"both"===R.constraintext||"outside"===R.constraintext,angle:se}):C(l,c,f,h,J,{isHorizontal:E,constrained:"both"===R.constraintext||"inside"===R.constraintext,angle:se,anchor:Z,hasB:B,r:y,overhead:g}),le.fontSize=$.size,d("histogram"===R.type?"bar":R.type,le,I),H.transform=le;var ce=A(X,I,w,T);i.setTransormAndDisplay(ce,le)}else r.select("text").remove()}(e,t,E,r,T,U,q,G,Z,re,ae,y,g),t.layerClipId&&s.hideOutsideRangePoint(c,E.select("text"),w,P,f.xcalendar,f.ycalendar)}));var G=!1===f.cliponaxis;s.setClipUrl(c,G?null:t.layerClipId,e)}));c.getComponentMethod("errorbars","plot")(e,R,t,y)},toMoveInsideBar:C}},5784: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}},5592:function(e,t,r){"use strict";var n=r(6308),a=r(4288).hasColorscale,i=r(7260),o=r(3400).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")}},2744:function(e,t,r){"use strict";var n=r(3428),a=r(3400);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",a.isArrayOrTypedArray(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")}else"none"===h&&s("textposition","none");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}}},3644:function(e,t,r){"use strict";var n=r(624).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}},1552:function(e,t,r){"use strict";var n=r(3616),a=r(6308);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)}},9656:function(e,t,r){"use strict";var n=r(3400);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(n.isArrayOrTypedArray(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,l=y.castOption(e.insidetextfont.weight,t.pts)||y.castOption(e.textfont.weight,t.pts)||r.weight,s=y.castOption(e.insidetextfont.style,t.pts)||y.castOption(e.textfont.style,t.pts)||r.style,c=y.castOption(e.insidetextfont.variant,t.pts)||y.castOption(e.textfont.variant,t.pts)||r.variant;return{color:n||o.contrast(t.color),family:a,size:i,weight:l,style:s,variant:c}}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(s.isArrayOrTypedArray(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 E(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")}R(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,o=y.castOption(e.outsidetextfont.weight,t.pts)||y.castOption(e.textfont.weight,t.pts)||r.weight,l=y.castOption(e.outsidetextfont.style,t.pts)||y.castOption(e.textfont.style,t.pts)||r.style,s=y.castOption(e.outsidetextfont.variant,t.pts)||y.castOption(e.textfont.variant,t.pts)||r.variant;return{color:n,family:a,size:i,weight:o,style:l,variant:s}}(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:z(v.r,_);if(p.targetX=c+M[0]*p.rCenter+(p.x||0),p.targetY=u+M[1]*p.rCenter+(p.y||0),E(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,c,u,f,d,h,p,v;function g(e,t){return e.pxmid[1]-t.pxmid[1]}function m(e,t){return t.pxmid[1]-e.pxmid[1]}function x(e,r){r||(r={});var a,u,f,h,p=r.labelExtraY+(n?r.yLabelMax:r.yLabelMin),v=n?e.yLabelMin:e.yLabelMax,g=n?e.yLabelMax:e.yLabelMin,m=e.cyFinal+o(e.px0[1],e.px1[1]),x=p-v;if(x*c>0&&(e.labelExtraY=x),s.isArrayOrTypedArray(t.pull))for(u=0;u=(y.castOption(t.pull,f.pts)||0)||((e.pxmid[1]-f.pxmid[1])*c>0?(x=f.cyFinal+o(f.px0[1],f.px1[1])-v-e.labelExtraY)*c>0&&(e.labelExtraY+=x):(g+e.labelExtraY-m)*c>0&&(a=3*l*Math.abs(u-d.indexOf(e)),(h=f.cxFinal+i(f.px0[0],f.px1[0])+a-(e.cxFinal+e.pxmid[0])-e.labelExtraX)*l>0&&(e.labelExtraX+=h)))}for(n=0;n<2;n++)for(a=n?g:m,o=n?Math.max:Math.min,c=n?1:-1,r=0;r<2;r++){for(i=r?Math.max:Math.min,l=r?1:-1,(u=e[n][r]).sort(a),f=e[1-n][r],d=f.concat(u),p=[],h=0;hMath.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:R,transformInsideText:w,determineInsideTextFont:b,positionTitleOutside:D,prerenderTitles:_,layoutAreas:I,attachFxHandlers:x,computeTransform:E}},2152:function(e,t,r){"use strict";var n=r(3428),a=r(528),i=r(2744).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)}))}))}},528:function(e,t,r){"use strict";var n=r(6308),a=r(9656).castOption,i=r(1552);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)}},148:function(e,t,r){"use strict";var n=r(3400);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}}}}}},8800:function(e,t,r){"use strict";var n=r(3400),a=r(4040),i=r(2904),o=r(8200),l=r(3028),s=r(3980),c=r(1147),u=r(3912),f=r(4428),d=r(6828),h=r(1731),p=r(124),v=r(840),y=r(3400).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"),m("zorder");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 ir!=(c=a[n][1])>=r&&(o=a[n-1][0],l=a[n][0],c-s&&(i=o+(l-o)*(r-s)/(c-s),f=Math.min(f,i),p=Math.max(p,i)));return{x0:f=Math.max(f,0),x1:p=Math.min(p,d._length),y0:r,y1:r}}(f._polygons);null===P&&(P={x0:y[0],x1:y[0],y0:y[1],y1:y[1]});var I=l.defaultLine;return l.opacity(f.fillcolor)?I=f.fillcolor:l.opacity((f.line||{}).color)&&(I=f.line.color),n.extendFlat(e,{distance:e.maxHoverDistance,x0:P.x0,x1:P.x1,y0:P.y0,y1:P.y1,color:I,hovertemplate:!1}),delete e.index,f.text&&!n.isArrayOrTypedArray(f.text)?e.text=String(f.text):e.text=f.name,[e]}}},5875:function(e,t,r){"use strict";var n=r(3028);e.exports={hasLines:n.hasLines,hasMarkers:n.hasMarkers,hasText:n.hasText,isBubble:n.isBubble,attributes:r(2904),layoutAttributes:r(5308),supplyDefaults:r(8800),crossTraceDefaults:r(5036),supplyLayoutDefaults:r(9748),calc:r(6356).calc,crossTraceCalc:r(6664),arraysToCalcdata:r(148),plot:r(6504),colorbar:r(5528),formatLabels:r(6688),style:r(6844).style,styleOnSelect:r(6844).styleOnSelect,hoverPoints:r(8723),selectPoints:r(1560),animatable:!0,moduleType:"trace",name:"scatter",basePlotModule:r(7952),categories:["cartesian","svg","symbols","errorBarsOK","showLegend","scatter-like","zoomScale"],meta:{}}},5308: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"}}},9748:function(e,t,r){"use strict";var n=r(3400),a=r(5308);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))}},6828:function(e,t,r){"use strict";var n=r(3400).isArrayOrTypedArray,a=r(4288).hasColorscale,i=r(7260);e.exports=function(e,t,r,o,l,s){s||(s={});var c=(e.marker||{}).color;c&&c._inputArray&&(c=c._inputArray),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")}},2340:function(e,t,r){"use strict";var n=r(3616),a=r(9032),i=a.BADNUM,o=a.LOG_CLIP,l=o+.5,s=o-.5,c=r(3400),u=c.segmentsIntersect,f=c.constrain,d=r(8200);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,z=D._length,R=t.backoff,E=S.marker,N=t.connectGaps,F=t.baseTolerance,H=t.shape,j="linear"===H,B=S.fill&&"none"!==S.fill,Y=[],V=d.minTolerance,U=e.length,q=new Array(U),G=0;function Z(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*z*(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[G-1][0],a=r===q[G-1][1];if(!n||!a)if(G>1){var i=t===q[G-2][0],o=r===q[G-2][1];n&&(t===ie||t===oe)&&i?o?G--:q[G-1]=e:a&&(r===le||r===se)&&o?i?G--:q[G-1]=e:q[G++]=e}else q[G++]=e}function pe(e){q[G-1][0]!==e[0]&&q[G-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(G)if(te){var n=ne(te,t);n.length>1&&(pe(n[0]),q[G++]=n[1])}else re=ne(q[G-1],t)[0],q[G++]=re;else q[G++]=[K||t[0],Q||t[1]];var a=q[G-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[G++]=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,G))}var me=H.slice(H.length-1);if(R&&"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}}},5528:function(e){"use strict";e.exports={container:"marker",min:"cmin",max:"cmax"}},4428:function(e,t,r){"use strict";var n=r(6308),a=r(4288).hasColorscale,i=r(7260),o=r(3028);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")}},1147:function(e,t,r){"use strict";var n=r(3400).dateTick0,a=r(9032).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"))}}},6504:function(e,t,r){"use strict";var n=r(3428),a=r(4040),i=r(3400),o=i.ensureSingle,l=i.identity,s=r(3616),c=r(3028),u=r(2340),f=r(4328),d=r(2065).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,P,I=w.fill.charAt(w.fill.length-1);"x"!==I&&"y"!==I&&(I=""),"y"===I?(C=1,P=_.c2p(0,!0)):"x"===I&&(C=0,P=b.c2p(0,!0)),f[0][r.isRangePlot?"nodeRangePlot3":"node3"]=M;var z,R,E="",N=[],F=w._prevtrace,H=null,j=null;F&&(E=F._prevRevpath||"",D=F._nextFill,N=F._ownPolygons,H=F._fillsegments,j=F._fillElement);var B,Y,V,U,q,G,Z="",W="",X=[];w._polygons=[];var J=[],K=[],Q=i.noop;if(O=w._ownFill,c.hasLines(w)||"none"!==w.fill){D&&D.datum(f),-1!==["hv","vh","hvh","vhv"].indexOf(T.shape)?(B=s.steps(T.shape),Y=s.steps(T.shape.split("").reverse().join(""))):B=Y="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")},V=function(e){return Y(e.reverse())},K=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}),J=new Array(K.length);var $=0;for(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()}},1560:function(e,t,r){"use strict";var n=r(3028);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 h(e)>f};case">=":return function(e){return h(e)>=f};case"[]":return function(e){var t=h(e);return t>=f[0]&&t<=f[1]};case"()":return function(e){var t=h(e);return t>f[0]&&t=f[0]&&tf[0]&&t<=f[1]};case"][":return function(e){var t=h(e);return t<=f[0]||t>=f[1]};case")(":return function(e){var t=h(e);return tf[1]};case"](":return function(e){var t=h(e);return t<=f[0]||t>f[1]};case")[":return function(e){var t=h(e);return t=f[1]};case"{}":return function(e){return-1!==f.indexOf(h(e))};case"}{":return function(e){return-1===f.indexOf(h(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}},3428: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 z;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,G={}.__proto__?function(e,t){e.__proto__=t}:function(e,t){for(var r in t)e[r]=t[r]};function Z(e){return G(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[N(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 Ne(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 Ge(e,t,r){return this instanceof Ge?(this.h=+e,this.c=+t,void(this.l=+r)):arguments.length<2?e instanceof Ge?new Ge(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 Ge(e,t,r)}Ue.brighter=function(e){return e=Math.pow(.7,arguments.length?e:1),new Ve(this.h,this.s,this.l/e)},Ue.darker=function(e){return e=Math.pow(.7,arguments.length?e:1),new Ve(this.h,this.s,e*this.l)},Ue.rgb=function(){return qe(this.h,this.s,this.l)},i.hcl=Ge;var Ze=Ge.prototype=new Ye;function We(e,t,r){return isNaN(e)&&(e=0),isNaN(t)&&(t=0),new Xe(r,Math.cos(e*=ze)*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 Ge?We(e.h,e.c,e.l):ht((e=ot(e)).r,e.g,e.b):new Xe(e,t,r)}Ze.brighter=function(e){return new Ge(this.h,this.c,Math.min(100,this.l+Je*(arguments.length?e:1)))},Ze.darker=function(e){return new Ge(this.h,this.c,Math.max(0,this.l-Je*(arguments.length?e:1)))},Ze.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 Ge(Math.atan2(r,t)*Re,Math.sqrt(t*t+r*r),e):new Ge(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 Ve(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(R),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=Vt.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 Rr(e){return 1-Math.cos(e*Ie)}function Er(e){return Math.pow(2,10*(e-1))}function Nr(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)||R,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:Vr)})(e)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var Vr={a:1,b:0,c:0,d:1,e:0,f:0};function Ur(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(Ur(r)+"rotate(",null,")")-2,x:_r(e,t)})):t&&r.push(Ur(r)+"rotate("+t+")")}(e.rotate,t.rotate,r,n),function(e,t,r,n){e!==t?n.push({i:r.push(Ur(r)+"skewX(",null,")")-2,x:_r(e,t)}):t&&r.push(Ur(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(Ur(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(Ur(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(zn(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=Rn,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=Nn(l),i=En(i),l&&i;)s=En(s),(o=Nn(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&&!Nn(o)&&(o.t=l,o.m+=f-u),i&&!En(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=Rn,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:Gn,s=n?Zr:Gr;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 Zn(e,Wn(ea(e,t)[2])),Zn(e,Wn(ea(e,t)[2])),e}function ea(e,t){null==t&&(t=10);var r=Un(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=Zn(n.map(a),r?Math:na);return e.domain(t),n=t.map(i),o},o.ticks=function(){var e=Un(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=Ee(y/c*Math.sin(g))),l&&(A=Ee(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(za(Na,i)+","+za(Na,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=Va,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=Za,t=Ga;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*ze);K.transition=function(e){for(var t,r,n=ti||++ai,a=li(e),i=[],o=ri||{time:Date.now(),ease:zr,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]>2],i+=n[(3&r[t])<<4|r[t+1]>>4],i+=n[(15&r[t+1])<<2|r[t+2]>>6],i+=n[63&r[t+2]];return a%3==2?i=i.substring(0,i.length-1)+"=":a%3==1&&(i=i.substring(0,i.length-2)+"=="),i},l=function(e){var t,r,n,i,o,l=.75*e.length,s=e.length,c=0;"="===e[e.length-1]&&(l--,"="===e[e.length-2]&&l--);var u=new ArrayBuffer(l),f=new Uint8Array(u);for(t=0;t>4,f[c++]=(15&n)<<4|i>>2,f[c++]=(3&i)<<6|63&o;return u}},7624:function(e,t,r){"use strict";function n(e,t){if((r=(e=t?e.toExponential(t-1):e.toExponential()).indexOf("e"))<0)return null;var r,n=e.slice(0,r);return[n.length>1?n[0]+n.slice(2):n,+e.slice(r+1)]}r.d(t,{E9:function(){return d},SO: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},4336:function(e,t,r){"use strict";r.d(t,{Yn:function(){return p},m_:function(){return d},E9:function(){return v}});var n=r(8208),a=r(8931),i=r(6192),o=r(8936),l=r(2171),s=r(3528);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:U,e:U,f:X,H:q,I:G,j:Z,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},ze={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 Ne(e,t,r,n)},d:z,e:z,f:j,H:E,I:E,j:R,L:H,m:I,M:N,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:V,S:F,u:k,U:A,V:L,w:M,W:S,x:function(e,t,n){return Ne(e,r,t,n)},X:function(e,t,r){return Ne(e,l,t,r)},y:D,Y:O,Z:C,"%":B};function Re(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.ot.ceil(l):(0,n.ot)(l),l=a.c.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.qT.ceil(l):(0,i.qT)(l),l=o.c.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 Ne(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=ze[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=Re(r,Pe),Pe.X=Re(l,Pe),Pe.c=Re(t,Pe),Ie.x=Re(r,Ie),Ie.X=Re(l,Ie),Ie.c=Re(t,Ie),{format:function(e){var t=Re(e+="",Pe);return t.toString=function(){return e},t},parse:function(e){var t=Ee(e+="",!1);return t.toString=function(){return e},t},utcFormat:function(e){var t=Re(e+="",Ie);return t.toString=function(){return e},t},utcParse:function(e){var t=Ee(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 z(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.d=+n[0],r+n[0].length):-1}function R(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 E(e,t,r){var n=g.exec(t.slice(r,r+2));return n?(e.H=+n[0],r+n[0].length):-1}function N(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 V(e,t,r){var n=g.exec(t.slice(r));return n?(e.s=+n[0],r+n[0].length):-1}function U(e,t){return b(e.getDate(),t,2)}function q(e,t){return b(e.getHours(),t,2)}function G(e,t){return b(e.getHours()%12||12,t,2)}function Z(e,t){return b(1+o.c.count((0,l.c)(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.uU.count((0,l.c)(e)-1,e),t,2)}function te(e,t){var r=e.getDay();return e=r>=4||0===r?(0,i.kD)(e):i.kD.ceil(e),b(i.kD.count((0,l.c)(e),e)+(4===(0,l.c)(e).getDay()),t,2)}function re(e){return e.getDay()}function ne(e,t){return b(i.qT.count((0,l.c)(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.c.count((0,s.c)(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.EV.count((0,s.c)(e)-1,e),t,2)}function me(e,t){var r=e.getUTCDay();return e=r>=4||0===r?(0,n.yA)(e):n.yA.ceil(e),b(n.yA.count((0,s.c)(e),e)+(4===(0,s.c)(e).getUTCDay()),t,2)}function xe(e){return e.getUTCDay()}function be(e,t){return b(n.ot.count((0,s.c)(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},8936:function(e,t,r){"use strict";r.d(t,{m:function(){return o}});var n=r(1628),a=r(9792),i=(0,n.c)((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.iy)/a.SK}),(function(e){return e.getDate()-1}));t.c=i;var o=i.range},9792:function(e,t,r){"use strict";r.d(t,{KK:function(){return l},SK:function(){return o},cg:function(){return i},iy:function(){return a},yc:function(){return n}});var n=1e3,a=6e4,i=36e5,o=864e5,l=6048e5},3220:function(e,t,r){"use strict";r.r(t),r.d(t,{timeDay:function(){return g.c},timeDays:function(){return g.m},timeFriday:function(){return m.iB},timeFridays:function(){return m.sJ},timeHour:function(){return v},timeHours:function(){return y},timeInterval:function(){return n.c},timeMillisecond:function(){return i},timeMilliseconds:function(){return o},timeMinute:function(){return d},timeMinutes:function(){return h},timeMonday:function(){return m.qT},timeMondays:function(){return m.QP},timeMonth:function(){return b},timeMonths:function(){return _},timeSaturday:function(){return m.Wc},timeSaturdays:function(){return m.aI},timeSecond:function(){return c},timeSeconds:function(){return u},timeSunday:function(){return m.uU},timeSundays:function(){return m.Ab},timeThursday:function(){return m.kD},timeThursdays:function(){return m.eC},timeTuesday:function(){return m.Mf},timeTuesdays:function(){return m.Oc},timeWednesday:function(){return m.eg},timeWednesdays:function(){return m.sn},timeWeek:function(){return m.uU},timeWeeks:function(){return m.Ab},timeYear:function(){return w.c},timeYears:function(){return w.Q},utcDay:function(){return O.c},utcDays:function(){return O.o},utcFriday:function(){return D.od},utcFridays:function(){return D.iG},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.ot},utcMondays:function(){return D.iO},utcMonth:function(){return P},utcMonths:function(){return I},utcSaturday:function(){return D.Ad},utcSaturdays:function(){return D.K8},utcSecond:function(){return c},utcSeconds:function(){return u},utcSunday:function(){return D.EV},utcSundays:function(){return D.Wq},utcThursday:function(){return D.yA},utcThursdays:function(){return D.ob},utcTuesday:function(){return D.sG},utcTuesdays:function(){return D.kl},utcWednesday:function(){return D._6},utcWednesdays:function(){return D.W_},utcWeek:function(){return D.EV},utcWeeks:function(){return D.Wq},utcYear:function(){return z.c},utcYears:function(){return z.i}});var n=r(1628),a=(0,n.c)((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.c)((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(9792),s=(0,n.c)((function(e){e.setTime(e-e.getMilliseconds())}),(function(e,t){e.setTime(+e+t*l.yc)}),(function(e,t){return(t-e)/l.yc}),(function(e){return e.getUTCSeconds()})),c=s,u=s.range,f=(0,n.c)((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*l.yc)}),(function(e,t){e.setTime(+e+t*l.iy)}),(function(e,t){return(t-e)/l.iy}),(function(e){return e.getMinutes()})),d=f,h=f.range,p=(0,n.c)((function(e){e.setTime(e-e.getMilliseconds()-e.getSeconds()*l.yc-e.getMinutes()*l.iy)}),(function(e,t){e.setTime(+e+t*l.cg)}),(function(e,t){return(t-e)/l.cg}),(function(e){return e.getHours()})),v=p,y=p.range,g=r(8936),m=r(6192),x=(0,n.c)((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(2171),T=(0,n.c)((function(e){e.setUTCSeconds(0,0)}),(function(e,t){e.setTime(+e+t*l.iy)}),(function(e,t){return(t-e)/l.iy}),(function(e){return e.getUTCMinutes()})),M=T,k=T.range,A=(0,n.c)((function(e){e.setUTCMinutes(0,0,0)}),(function(e,t){e.setTime(+e+t*l.cg)}),(function(e,t){return(t-e)/l.cg}),(function(e){return e.getUTCHours()})),L=A,S=A.range,O=r(8931),D=r(8208),C=(0,n.c)((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,z=r(3528)},1628:function(e,t,r){"use strict";r.d(t,{c: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}},8931:function(e,t,r){"use strict";r.d(t,{o:function(){return o}});var n=r(1628),a=r(9792),i=(0,n.c)((function(e){e.setUTCHours(0,0,0,0)}),(function(e,t){e.setUTCDate(e.getUTCDate()+t)}),(function(e,t){return(t-e)/a.SK}),(function(e){return e.getUTCDate()-1}));t.c=i;var o=i.range},8208:function(e,t,r){"use strict";r.d(t,{Ad:function(){return d},EV:function(){return o},K8:function(){return x},W_:function(){return y},Wq:function(){return h},_6:function(){return c},iG:function(){return m},iO:function(){return p},kl:function(){return v},ob:function(){return g},od:function(){return f},ot:function(){return l},sG:function(){return s},yA:function(){return u}});var n=r(1628),a=r(9792);function i(e){return(0,n.c)((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.KK}))}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},3528:function(e,t,r){"use strict";r.d(t,{i:function(){return i}});var n=r(1628),a=(0,n.c)((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.c)((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.c=a;var i=a.range},6192:function(e,t,r){"use strict";r.d(t,{Ab:function(){return h},Mf:function(){return s},Oc:function(){return v},QP:function(){return p},Wc:function(){return d},aI:function(){return x},eC:function(){return g},eg:function(){return c},iB:function(){return f},kD:function(){return u},qT:function(){return l},sJ:function(){return m},sn:function(){return y},uU:function(){return o}});var n=r(1628),a=r(9792);function i(e){return(0,n.c)((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.iy)/a.KK}))}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},2171:function(e,t,r){"use strict";r.d(t,{Q:function(){return i}});var n=r(1628),a=(0,n.c)((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.c)((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.c=a;var i=a.range},1252: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):[]}},8248:function(e,t,r){"use strict";var n=r(4576);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}},2408: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}},6860: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}},4492: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}},4212: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}},800: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)}},1784: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}},1616: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)}},1944: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}},9444: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}},8268: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}},1856: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}},9216: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}},7736: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}},8848: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}},6635: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}},6524:function(e,t,r){e.exports={create:r(4212),clone:r(6860),copy:r(4492),identity:r(6635),transpose:r(6520),invert:r(4308),adjoint:r(2408),determinant:r(800),multiply:r(944),translate:r(5176),scale:r(8152),rotate:r(16),rotateX:r(5456),rotateY:r(4840),rotateZ:r(4192),fromRotation:r(1616),fromRotationTranslation:r(1944),fromScaling:r(9444),fromTranslation:r(8268),fromXRotation:r(1856),fromYRotation:r(9216),fromZRotation:r(7736),fromQuat:r(1784),frustum:r(8848),perspective:r(1296),perspectiveFromFieldOfView:r(3688),ortho:r(7688),lookAt:r(6508),str:r(9412)}},4308: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}},6508:function(e,t,r){var n=r(6635);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)}},944: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}},7688: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}},1296: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}},3688: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}},16: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)}},5456: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}},4840: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}},4192: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}},8152: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}},9412: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]+")"}},5176: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}},6520: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}},2264:function(e,t,r){"use strict";var n,a=r(1820);n="function"==typeof r.g.matchMedia?!r.g.matchMedia("(hover: none)").matches:a,e.exports=n},9184:function(e,t,r){"use strict";var n=r(1820);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}()},1820:function(e){e.exports=!0},4576: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}},9128: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}},8324: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}},4756:function(e,t,r){var n,a=r(2928),i=r(8648),o=r(9819),l=r(1403),s=r(2368),c=r(7792),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},2928: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")}}}},8648: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}},7792: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=[E(s(e).toString(16)),E(s(t).toString(16)),E(s(r).toString(16)),E(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]:N(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 z(e){return c(1,u(0,e))}function R(e){return parseInt(e,16)}function E(e){return 1==e.length?"0"+e:""+e}function N(e){return e<=1&&(e=100*e+"%"),e}function F(e){return a.round(255*parseFloat(e)).toString(16)}function H(e){return R(e)/255}var j,B,Y,V=(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 U(e){return!!V.CSS_UNIT.exec(e)}e.exports?e.exports=d:void 0===(n=function(){return d}.call(t,r,t,e))||(e.exports=n)}(Math)},7020:function(e,t,r){var n=r(8700),a=r(896),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},2787:function(e,t,r){var n=r(8700),a=r(896);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},2084:function(e,t,r){var n=r(8700),a=r(896);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},6368:function(e,t,r){var n=r(8700),a=r(896);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},4747:function(e,t,r){var n=r(8700),a=r(896);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},5616:function(e,t,r){var n=r(8700),a=r(896);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},632:function(e,t,r){var n=r(8700),a=r(896);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},3040:function(e,t,r){var n=r(8700),a=r(896);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},9075:function(e,t,r){var n=r(8700),a=r(896),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},4592:function(e,t,r){var n=r(8700),a=r(896),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},5348:function(e,t,r){var n=r(8700),a=r(896);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]},8700:function(e,t,r){var n=r(896);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},5168:function(e,t,r){var n=r(896),a=r(8700);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(3472)}()},e.exports=t()},4610:(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.A=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(6540)),o=(a=r(5556))&&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{"use strict";r.d(t,{R:()=>o,x:()=>l});var n=r(6540);const a={},i=n.createContext(a);function o(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8509.15e604b0.js.LICENSE.txt b/assets/js/8509.15e604b0.js.LICENSE.txt new file mode 100644 index 0000000000..4ebf436df6 --- /dev/null +++ b/assets/js/8509.15e604b0.js.LICENSE.txt @@ -0,0 +1,16 @@ +/* + * @copyright 2016 Sean Connelly (@voidqk), http://syntheti.cc + * @license MIT + * @preserve Project Home: https://github.com/voidqk/polybooljs + */ + +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + +/*! Native Promise Only + v0.8.1 (c) Kyle Simpson + MIT License: http://getify.mit-license.org +*/ diff --git a/assets/js/87030e10.4920f4b4.js b/assets/js/87030e10.4920f4b4.js new file mode 100644 index 0000000000..89e29f708a --- /dev/null +++ b/assets/js/87030e10.4920f4b4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9673],{6093:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var i=t(4848),s=t(8453);const o={},a="ADR 0024: Runtime Off-chain Logic (ROFL)",r={id:"adrs/0024-off-chain-runtime-logic",title:"ADR 0024: Runtime Off-chain Logic (ROFL)",description:"Component",source:"@site/docs/adrs/0024-off-chain-runtime-logic.md",sourceDirName:"adrs",slug:"/adrs/0024-off-chain-runtime-logic",permalink:"/adrs/0024-off-chain-runtime-logic",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0024-off-chain-runtime-logic.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0022: Forward-Secret Master Secrets",permalink:"/adrs/0022-keymanager-master-secrets"}},d={},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:"Attestation",id:"attestation",level:3},{value:"Updates to the ORC Manifest",id:"updates-to-the-orc-manifest",level:3},{value:"Updates to the Runtime Host Protocol",id:"updates-to-the-runtime-host-protocol",level:3},{value:"Updates to EnclaveRPC RAK Binding",id:"updates-to-enclaverpc-rak-binding",level:3},{value:"Updates to the Runtime Host Sandbox",id:"updates-to-the-runtime-host-sandbox",level:3},{value:"Configuration",id:"configuration",level:3},{value:"Untrusted Local Storage",id:"untrusted-local-storage",level:3},{value:"Updates to the Oasis SDK",id:"updates-to-the-oasis-sdk",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}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-0024-runtime-off-chain-logic-rofl",children:"ADR 0024: Runtime Off-chain Logic (ROFL)"}),"\n",(0,i.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,i.jsx)(n.p,{children:"Oasis Core, Oasis SDK"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2024-02-26: Notifications"}),"\n",(0,i.jsx)(n.li,{children:"2023-11-27: Initial draft"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"Sometimes we may want the runtime compute nodes to run additional off-chain\nlogic that communicates with the on-chain state securely (e.g. ensuring that the\noff-chain logic is being run by the same node operator, is properly attested\nwhen running in a TEE, etc.)."}),"\n",(0,i.jsx)(n.p,{children:"The off-chain logic may then perform non-deterministic and potentially expensive\nthings (like remote HTTPS requests or complex local computation) and securely\ninteract with the on-chain logic via transactions."}),"\n",(0,i.jsx)(n.p,{children:"The main use case driving this proposal is support for running attested light\nclient committees that read and verify information from other chains, then make\nthis information available to Oasis runtimes with no additional trust\nassumptions."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.p,{children:"While similar functionality can be implemented entirely independently on the\napplication layer (and such solutions already exist), this proposal attempts to\nreuse the same security and attestation infrastructure that is already available\nfor on-chain parts of the runtimes, specifically:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Compute nodes and runtime binary distribution and execution can stay the same\nas it has been for existing node operators that run the runtimes. Handling of\nthe off-chain logic part should be done transparently if the runtime provides\nit."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Existing attestation, consensus and freshness proof flows can be leveraged for\nensuring that the off-chain logic is running in a secure environment."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"One important consideration is also whether to have the off-chain logic part of\nthe same runtime binary or have it as a completely separate binary running in\nits own process. This proposal decides on the latter to ensure that the\noff-chain TCB is completely separate from the on-chain TCB. Given that the logic\nrunning off-chain can be much more complex and can interact with untrusted\nexternal services, ensuring this separation is important as a defense-in-depth\nmeasure."}),"\n",(0,i.jsx)(n.p,{children:"The proposed architecture extends the composition of the runtime so that it now\ncontains the following components:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Runtime On-chain Logic (RONL)"})," is what has existed as the sole runtime\ncomponent before this proposal. It contains the logic (and TCB) that is\nresponsible for executing the deterministic on-chain logic of the runtime."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Runtime Off-chain Logic (ROFL)"})," is an optional runtime component that may\nrun in parallel with RONL and is part of its own TCB. It also uses the same\ngeneral runtime framework and RHP, but instead of implementing the on-chain\nbatch scheduling, execution and query methods, it only implements specific\nnotification hooks that can trigger arbitrary actions."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Both RONL and ROFL are managed as independent runtimes by the Oasis Node as\nhost, using the existing runtime host architecture. Failure of ROFL does not\naffect RONL which can proceed to run as usual."}),"\n",(0,i.jsx)(n.h3,{id:"attestation",children:"Attestation"}),"\n",(0,i.jsx)(n.p,{children:"An assumption made in this proposal is that both RONL and ROFL components are\ndeveloped and built together, by the same entity, and are part of the same\nrelease. This means that we can simplify attestation by making RONL being able\nto attest ROFL by being aware of its exact identity."}),"\n",(0,i.jsx)(n.p,{children:"The idea is that during the release build process, ROFL is built first, its\nsigner-independent identity (e.g. MRENCLAVE) is measured and included during\ncompilation of RONL. The signer-dependent part of identity (e.g. MRSIGNER) is\nassumed to be the same for both and can be read from trusted CPU state (since it\nmay not be available during the build process due to offline signing)."}),"\n",(0,i.jsx)(n.p,{children:"Alternatively, one can imagine a proposal where the ROFL identity is backed by\nsome sort of on-chain governance process defined in the RONL component. Defining\nsuch a mechanism is outside the scope of this proposal."}),"\n",(0,i.jsx)(n.p,{children:"The process for ROFL attestation proceeds as follows:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Remote Attestation."})," The normal runtime attestation flow is initiated by\nthe host. As a result of this flow, the ",(0,i.jsx)(n.code,{children:"node.CapabilityTEE"})," structure is\ngenerated which includes the remote attestation quote and additional data."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Node Endorsement."})," The host verifies the ",(0,i.jsx)(n.code,{children:"node.CapabilityTEE"})," structure\nand if deemed correct, it signs it using the node's identity key and the\nfollowing domain separation context:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-core/node: endorse TEE capability\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The signature is stored in a new structure ",(0,i.jsx)(n.code,{children:"EndorsedCapabilityTEE"})," which is\ndefined as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'type EndorsedCapabilityTEE struct {\n // CapabilityTEE is the TEE capability structure to be endorsed.\n CapabilityTEE CapabilityTEE `json:"capability_tee"`\n\n // NodeEndorsement is the node endorsement signature.\n NodeEndorsement signature.Signature `json:"node_endorsement"`\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Updating Node-Endorsed CapabilityTEE in ROFL."})," The ",(0,i.jsx)(n.code,{children:"EndorsedCapabilityTEE"}),"\nis sent to ROFL to be stored and available for establishing secure EnclaveRPC\nsessions."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"RONL Verification."})," When establishing a new session with RONL, the\nendorsed TEE capability is presented during session establishment. RONL\nverifies the quote, ensures the enclave identity is one of the known\nidentities set at compile-time and verifies the node endorsement against the\nlocally known node identity (both RONL and ROFL must be from the same node)."]}),"\n",(0,i.jsx)(n.p,{children:"If all the checks pass, a secure EnclaveRPC session is established."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This flow needs to be repeated whenever RAK changes for any reason and also\nperiodically to ensure freshness (consistent with the quote policy configured\nfor the runtime in the consensus layer)."}),"\n",(0,i.jsx)(n.h3,{id:"updates-to-the-orc-manifest",children:"Updates to the ORC Manifest"}),"\n",(0,i.jsx)(n.p,{children:"The ORC manifest is extended with a field that can specify extra components\nwhich currently include ROFL binaries in a similar way as we already support\nregular runtime binaries (e.g. specifying the executable and SGX metadata)."}),"\n",(0,i.jsx)(n.p,{children:"The manifest is updated as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'// Manifest is a deserialized runtime bundle manifest.\ntype Manifest struct {\n // ... existing fields omitted ...\n\n // Components are the additional runtime components.\n Components []*Component `json:"components,omitempty"`\n}\n\n// ComponentKind is the kind of a component.\ntype ComponentKind string\n\nconst (\n // ComponentInvalid is an invalid component.\n ComponentInvalid ComponentKind = ""\n // ComponentRONL is the on-chain logic component.\n ComponentRONL ComponentKind = "ronl"\n // ComponentROFL is the off-chain logic component.\n ComponentROFL ComponentKind = "rofl"\n)\n\n// Component is a runtime component.\ntype Component struct {\n // Kind is the component kind.\n Kind ComponentKind `json:"kind"`\n\n // Name is the name of the component that can be used to filter components\n // when multiple are provided by a runtime.\n Name string `json:"name,omitempty"`\n\n // Executable is the name of the runtime ELF executable file.\n Executable string `json:"executable"`\n\n // SGX is the SGX specific manifest metadata if any.\n SGX *SGXMetadata `json:"sgx,omitempty"`\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["The top-level ",(0,i.jsx)(n.code,{children:"executable"})," and ",(0,i.jsx)(n.code,{children:"sgx"})," fields are supported for backwards\ncompatibility and implicitly define a new ",(0,i.jsx)(n.code,{children:"Component"})," of kind ",(0,i.jsx)(n.code,{children:"ComponentRONL"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"updates-to-the-runtime-host-protocol",children:"Updates to the Runtime Host Protocol"}),"\n",(0,i.jsx)(n.p,{children:"This proposal includes some non-breaking updates to the Runtime Host Protocol in\norder to support the ROFL component, as follows:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Consensus Block Notification."})," No updates are required to facilitate\nnotifications about consensus layer blocks as this is already handled as part\nof the existing RHP flow. The only change is that for ROFL, these\nnotifications invoke a hook that can be implemented by the runtime."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Runtime Transaction Submission."})," A new method ",(0,i.jsx)(n.code,{children:"HostSubmitTx"})," is introduced\nwhich allows ROFL to submit transactions to the runtime. It works by queueing\nthe transaction in the transaction pool (local queue) for later scheduling."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'type HostSubmitTxRequest struct {\n // RuntimeID is the identifier of the target runtime.\n RuntimeID common.Namespace `json:"runtime_id"`\n // Data is the raw transaction data.\n Data []byte `json:"data"`\n // Wait specifies whether the call should wait until the transaction is\n // included in a block.\n Wait bool `json:"wait,omitempty"`\n // Prove specifies whether the response should include a proof of\n // transaction being included in a block.\n Prove bool `json:"prove,omitempty"`\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Notify Registration."})," A new method ",(0,i.jsx)(n.code,{children:"HostRegisterNotify"})," is introduced which\nallows ROFL to register to be notified by the host when specific events occur.\nNote that delivery of these notifications is best effort as a dishonest host\nmay withold notification delivery or generate spurious notifications."]}),"\n",(0,i.jsx)(n.p,{children:"Registering for notifications overwrites any previous configuration."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'type HostRegisterNotifyRequest struct {\n // RuntimeBlock subscribes to runtime block notifications.\n RuntimeBlock bool `json:"runtime_block,omitempty"`\n // RuntimeEvent subscribes to runtime event emission notifications.\n RuntimeEvent *struct {\n // Tags specifies which event tags to subscribe to.\n Tags [][]byte `json:"tags,omitempty"`\n } `json:"runtime_event,omitempty"`\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Notification Delivery."})," A new method ",(0,i.jsx)(n.code,{children:"RuntimeNotify"})," is introduced which\nallows the host to deliver event notifications based on previously registered\nnotifiers."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'type RuntimeNotifyRequest struct {\n // RuntimeBlock notifies about a new runtime block.\n RuntimeBlock *roothash.AnnotatedBlock `json:"runtime_block,omitempty"`\n // RuntimeEvent notifies about a specific runtime event being emitted.\n RuntimeEvent *struct {\n // Block is the block header of the block that emitted the event.\n Block *roothash.AnnotatedBlock `json:"block"`\n // Tags are the matching tags that were emitted.\n Tags [][]byte `json:"tags"`\n } `json:"runtime_event,omitempty"`\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"RONL-ROFL Communication."})," The existing EnclaveRPC is reused to facilitate\nthe communication between the two components if/when needed. For this purpose\nthe endpoint identifier ",(0,i.jsx)(n.code,{children:"ronl"})," is made available in the ROFL host method\nhandler to address the RONL component."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Updating Node-Endorsed CapabilityTEE in ROFL."})," A new method\n",(0,i.jsx)(n.code,{children:"RuntimeCapabilityTEEUpdateEndorsementRequest"})," is introduced which allows the\nnode to refresh the ",(0,i.jsx)(n.code,{children:"EndorsedCapabilityTEE"})," for ROFL."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'type RuntimeCapabilityTEEUpdateEndorsementRequest struct {\n // EndorsedCapabilityTEE is an endorsed TEE capability.\n EndorsedCapabilityTEE node.EndorsedCapabilityTEE `json:"ect"`\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"updates-to-enclaverpc-rak-binding",children:"Updates to EnclaveRPC RAK Binding"}),"\n",(0,i.jsxs)(n.p,{children:["Version 2 of the ",(0,i.jsx)(n.code,{children:"RAKBinding"})," structure is introduced for establishment of\nEnclaveRPC sessions, as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"pub enum RAKBinding {\n // ... previous versions omitted ...\n\n /// V2 format which supports endorsed CapabilityTEE structures.\n #[cbor(rename = 2)]\n V2 {\n ect: EndorsedCapabilityTEE,\n binding: Signature,\n },\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Additionally, the relevant EnclaveRPC session implementation is updated to\nfacilitate thew new authentication mechanism via endorsed TEE capabilities and\nthe session demultiplexer is updated to support authentication policies on\nincoming connections."}),"\n",(0,i.jsx)(n.h3,{id:"updates-to-the-runtime-host-sandbox",children:"Updates to the Runtime Host Sandbox"}),"\n",(0,i.jsx)(n.p,{children:"This proposal updates the runtime host sandbox to support optionally allowing\nexternal network requests. These are then allowed only for the ROFL component\n(if any is available for a runtime)."}),"\n",(0,i.jsx)(n.p,{children:"The following modifications are required:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["When setting up the Bubblewrap sandbox, ",(0,i.jsx)(n.code,{children:"--share-net"})," is passed to share the\nnetwork namespace with the sandboxed runtime. All other namespaces are still\nunshared."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The runtime loader is modified to accept an additional argument\n",(0,i.jsx)(n.code,{children:"--allow-network"})," which then changes the usercall extension to pass through\nany address passed in the ",(0,i.jsx)(n.code,{children:"connect_stream"})," handler."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsx)(n.p,{children:"ROFL may require additional configuration which it may do through one of several\nways:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"On-chain Configuration."})," Configuration for the ROFL component may be stored\nin on-chain state. ROFL would then query the current configuration and apply\nit locally."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Local Per-Node Configuration."})," In case some per-node configuration is\nrequired (e.g. to allow the node operator to override a default), the existing\nruntime local configuration mechanism can be used where configuration is\nprovided as part of the RHP handshake. All configuration for ROFL should be\ncontained under the ",(0,i.jsx)(n.code,{children:"rofl"})," configuration key."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"untrusted-local-storage",children:"Untrusted Local Storage"}),"\n",(0,i.jsxs)(n.p,{children:["ROFL may utilize the existing untrusted node-local storage to store things like\nsealed data local to the node. This store is shared between RONL and ROFL, but\nall ROFL keys are transparently prefixed by ",(0,i.jsx)(n.code,{children:"rofl."})," on the host such that only\nRONL can see (but not necessarily read) ROFL's keys but not vice versa."]}),"\n",(0,i.jsx)(n.h3,{id:"updates-to-the-oasis-sdk",children:"Updates to the Oasis SDK"}),"\n",(0,i.jsx)(n.p,{children:"A convenient way to develop ROFL modules alongside the on-chain support\nfunctionality should be implemented in the Oasis SDK, including a convenient way\nfor ROFL to submit runtime transactions in a way that can be verified on-chain\nas coming from a specific node/runtime instance."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Oasis runtimes can easily be extended with arbitrary off-chain logic that can\nsecurely interact with on-chain functionality."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Node operators do not need to perform much additional configuration in order\nto support the new off-chain logic."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Additional complexity is introduced to the Runtime Host Protocol and to the\nnode binary."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>r});var i=t(6540);const s={},o=i.createContext(s);function a(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8786ced4.14029fc6.js b/assets/js/8786ced4.14029fc6.js new file mode 100644 index 0000000000..c599ff493e --- /dev/null +++ b/assets/js/8786ced4.14029fc6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5214],{7494:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>o,frontMatter:()=>d,metadata:()=>c,toc:()=>l});var t=s(4848),i=s(8453);const d={},r="ADR 0014: Signing Runtime Transactions with Hardware Wallet",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0014-runtime-signing-tx-with-hardware-wallet.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},a={},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:"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}];function h(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0014-signing-runtime-transactions-with-hardware-wallet",children:"ADR 0014: Signing Runtime Transactions with Hardware Wallet"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis SDK"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["2023-02-24:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"APDU: Define Oasis native and Ethereum-compatible address length."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["2023-02-09:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Encode ",(0,t.jsx)(n.code,{children:"Meta.runtime_id"})," and ",(0,t.jsx)(n.code,{children:"Meta.orig_to"})," as Base16."]}),"\n",(0,t.jsxs)(n.li,{children:["Change ",(0,t.jsx)(n.code,{children:"SIG"})," in ",(0,t.jsx)(n.code,{children:"SIGN_RT_SECP256K1"})," to 65-byte encoded R,S,V format."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["2023-01-23:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Fix Deoxys-II field description in ",(0,t.jsx)(n.a,{href:"#signing-encrypted-runtime-transactions",children:"Signing encrypted runtime\ntransactions"})," section."]}),"\n",(0,t.jsxs)(n.li,{children:["Rename ",(0,t.jsx)(n.code,{children:"SIGN_PT_"})," instructions in APDUSPEC to ",(0,t.jsx)(n.code,{children:"SIGN_RT_"})," for consistency\nwith oasis-core and oasis-sdk codebase."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["2023-01-03:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Add Sapphire runtime ID and consensus address on Mainnet."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["2022-12-13:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Fix Secp256k1 public key size."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["2022-10-12:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Add Sapphire runtime ID and consensus address on Testnet,"}),"\n",(0,t.jsxs)(n.li,{children:["Remove redundant ",(0,t.jsx)(n.code,{children:"sig_context"})," from ",(0,t.jsx)(n.code,{children:"Meta"}),","]}),"\n",(0,t.jsxs)(n.li,{children:["Require ",(0,t.jsx)(n.code,{children:"tx.call.format"})," to be either ",(0,t.jsx)(n.code,{children:"0"})," or ",(0,t.jsx)(n.code,{children:"1"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.li,{children:"2022-07-15: Initial public version"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Proposed"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsx)(n.p,{children:"This document proposes additions to APDU specification, guidelines for parsing\nruntime transactions and general UI/UX for signing them on a hardware wallet:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#apduspec-additions",children:"APDUSPEC additions"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#changes-to-allowance-transaction",children:"Changes to Allowance transaction"})}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"#signing-general-runtime-transactions",children:"Signing general runtime transactions"}),","]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"#signing-smart-contract-runtime-transactions",children:"Signing smart contract runtime transactions"}),","]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"#signing-evm-runtime-transactions",children:"Signing EVM runtime transactions"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"#signing-encrypted-runtime-transactions",children:"Signing encrypted runtime transactions"}),","]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"test-vectors",children:"Test vectors"}),"\n",(0,t.jsxs)(n.p,{children:["Test vectors for all runtime transactions in this ADR can be generated by\nusing ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/tools/gen_runtime_vectors",children:"gen_runtime_vectors"})," tool as part of the Oasis SDK."]}),"\n",(0,t.jsx)(n.h3,{id:"runtime-transaction-format",children:"Runtime transaction format"}),"\n",(0,t.jsxs)(n.p,{children:["The format of the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L86-L96",children:"runtime transaction"})," to be signed by the\nhardware wallet is the following:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-rust",children:'/// 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'})}),"\n",(0,t.jsxs)(n.p,{children:["The transaction ",(0,t.jsxs)(n.strong,{children:["can be signed with ",(0,t.jsx)(n.code,{children:"Secp256k1"}),' ("Ethereum"), ',(0,t.jsx)(n.code,{children:"Ed25519"})," key,\nor ",(0,t.jsx)(n.code,{children:"Sr25519"})," key!"]})," Information on this along with the gas fee is stored inside\n",(0,t.jsxs)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L159-L173",children:[(0,t.jsx)(n.code,{children:"ai"})," field"]}),"."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"call"})," is defined as ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L129-L146",children:"follows"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-rust",children:'/// 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'})}),"\n",(0,t.jsxs)(n.p,{children:["If ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/transaction.rs#L113-L121",children:(0,t.jsx)(n.code,{children:"format"})})," is:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"0"}),", the transaction is unencrypted,"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"1"}),", the transaction is encrypted,"]}),"\n",(0,t.jsxs)(n.li,{children:["any other, the transaction should be rejected with ",(0,t.jsx)(n.code,{children:"unsupported call format"}),"\nerror unless implemented outside the scope of this ADR."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"method"})," contains the name of the runtime module followed by ",(0,t.jsx)(n.code,{children:"."})," and the method\nname. If ",(0,t.jsx)(n.code,{children:"format"})," is ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"method"})," is empty."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"body"})," contains a CBOR-encoded transaction. If ",(0,t.jsx)(n.code,{children:"format"})," equals ",(0,t.jsx)(n.code,{children:"1"}),", ",(0,t.jsx)(n.code,{children:"body"}),"\ncontains CBOR-encoded ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/callformat.rs#L7-L16",children:(0,t.jsx)(n.code,{children:"CallEnvelopeX25519DeoxysII"})}),"\nwhich contains the encrypted transaction body inside its ",(0,t.jsx)(n.code,{children:"data"})," field."]}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.h3,{id:"apduspec-additions",children:"APDUSPEC additions"}),"\n",(0,t.jsx)(n.h4,{id:"get_addr_secp256k1",children:"GET_ADDR_SECP256K1"}),"\n",(0,t.jsx)(n.h5,{id:"command",children:"Command"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CLA"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Application Identifier"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"INS"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Instruction ID"}),(0,t.jsx)(n.td,{children:"0x04"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P1"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Request User confirmation"}),(0,t.jsx)(n.td,{children:"No = 0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P2"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Parameter 2"}),(0,t.jsx)(n.td,{children:"ignored"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"L"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Bytes in payload"}),(0,t.jsx)(n.td,{children:"(depends)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[0]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"44"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[1]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"60"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[2]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[3]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[4]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"The first three items in the derivation path are hardened."}),"\n",(0,t.jsx)(n.h5,{id:"response",children:"Response"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Note"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"PK"}),(0,t.jsx)(n.td,{children:"byte (33)"}),(0,t.jsx)(n.td,{children:"Public Key"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"ADDR"}),(0,t.jsx)(n.td,{children:"byte (40)"}),(0,t.jsx)(n.td,{children:"Lower-case hex addr"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SW1-SW2"}),(0,t.jsx)(n.td,{children:"byte (2)"}),(0,t.jsx)(n.td,{children:"Return code"}),(0,t.jsx)(n.td,{children:"see list of return codes"})]})]})]}),"\n",(0,t.jsx)(n.h4,{id:"get_addr_sr25519",children:"GET_ADDR_SR25519"}),"\n",(0,t.jsx)(n.h5,{id:"command-1",children:"Command"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CLA"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Application Identifier"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"INS"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Instruction ID"}),(0,t.jsx)(n.td,{children:"0x03"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P1"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Request User confirmation"}),(0,t.jsx)(n.td,{children:"No = 0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P2"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Parameter 2"}),(0,t.jsx)(n.td,{children:"ignored"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"L"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Bytes in payload"}),(0,t.jsx)(n.td,{children:"(depends)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[0]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"44"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[1]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"474"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[2]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[3]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[4]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"The first three items in the derivation path are hardened."}),"\n",(0,t.jsx)(n.h5,{id:"response-1",children:"Response"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Note"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"PK"}),(0,t.jsx)(n.td,{children:"byte (32)"}),(0,t.jsx)(n.td,{children:"Public Key"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"ADDR"}),(0,t.jsx)(n.td,{children:"byte (46)"}),(0,t.jsx)(n.td,{children:"Bech32 addr"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SW1-SW2"}),(0,t.jsx)(n.td,{children:"byte (2)"}),(0,t.jsx)(n.td,{children:"Return code"}),(0,t.jsx)(n.td,{children:"see list of return codes"})]})]})]}),"\n",(0,t.jsx)(n.h4,{id:"sign_rt_ed25519",children:"SIGN_RT_ED25519"}),"\n",(0,t.jsx)(n.h5,{id:"command-2",children:"Command"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CLA"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Application Identifier"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"INS"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Instruction ID"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P1"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Payload desc"}),(0,t.jsx)(n.td,{children:"0 = init"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"1 = add"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"2 = last"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P2"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"----"}),(0,t.jsx)(n.td,{children:"not used"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"L"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Bytes in payload"}),(0,t.jsx)(n.td,{children:"(depends)"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"The first packet/chunk includes only the derivation path."}),"\n",(0,t.jsx)(n.p,{children:"All other packets/chunks should contain message to sign."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"First Packet"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[0]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"44"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[1]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"474"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[2]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[3]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[4]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"Other Chunks/Packets"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsx)(n.tbody,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Data"}),(0,t.jsx)(n.td,{children:"bytes..."}),(0,t.jsx)(n.td,{children:"Meta+Message"}),(0,t.jsx)(n.td,{})]})})]}),"\n",(0,t.jsx)(n.p,{children:"Data is defined as:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Meta"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR metadata"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Message"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR data to sign"}),(0,t.jsx)(n.td,{})]})]})]}),"\n",(0,t.jsx)(n.h5,{id:"response-2",children:"Response"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Note"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SIG"}),(0,t.jsx)(n.td,{children:"byte (64)"}),(0,t.jsx)(n.td,{children:"Signature"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SW1-SW2"}),(0,t.jsx)(n.td,{children:"byte (2)"}),(0,t.jsx)(n.td,{children:"Return code"}),(0,t.jsx)(n.td,{children:"see list of return codes"})]})]})]}),"\n",(0,t.jsx)(n.h4,{id:"sign_rt_secp256k1",children:"SIGN_RT_SECP256K1"}),"\n",(0,t.jsx)(n.h5,{id:"command-3",children:"Command"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CLA"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Application Identifier"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"INS"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Instruction ID"}),(0,t.jsx)(n.td,{children:"0x07"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P1"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Payload desc"}),(0,t.jsx)(n.td,{children:"0 = init"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"1 = add"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"2 = last"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P2"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"----"}),(0,t.jsx)(n.td,{children:"not used"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"L"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Bytes in payload"}),(0,t.jsx)(n.td,{children:"(depends)"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"The first packet/chunk includes only the derivation path."}),"\n",(0,t.jsx)(n.p,{children:"All other packets/chunks should contain message to sign."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"First Packet"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[0]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"44"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[1]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"60"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[2]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[3]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[4]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"Other Chunks/Packets"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsx)(n.tbody,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Data"}),(0,t.jsx)(n.td,{children:"bytes..."}),(0,t.jsx)(n.td,{children:"Meta+Message"}),(0,t.jsx)(n.td,{})]})})]}),"\n",(0,t.jsx)(n.p,{children:"Data is defined as:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Meta"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR metadata"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Message"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR data to sign"}),(0,t.jsx)(n.td,{})]})]})]}),"\n",(0,t.jsx)(n.h5,{id:"response-3",children:"Response"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Note"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SIG"}),(0,t.jsx)(n.td,{children:"byte (65)"}),(0,t.jsx)(n.td,{children:"Signature"}),(0,t.jsx)(n.td,{children:"R,S,V bigendian integers"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SW1-SW2"}),(0,t.jsx)(n.td,{children:"byte (2)"}),(0,t.jsx)(n.td,{children:"Return code"}),(0,t.jsx)(n.td,{children:"see list of return codes"})]})]})]}),"\n",(0,t.jsx)(n.h4,{id:"sign_rt_sr25519",children:"SIGN_RT_SR25519"}),"\n",(0,t.jsx)(n.h5,{id:"command-4",children:"Command"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"CLA"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Application Identifier"}),(0,t.jsx)(n.td,{children:"0x05"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"INS"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Instruction ID"}),(0,t.jsx)(n.td,{children:"0x06"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P1"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Payload desc"}),(0,t.jsx)(n.td,{children:"0 = init"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"1 = add"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{}),(0,t.jsx)(n.td,{children:"2 = last"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"P2"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"----"}),(0,t.jsx)(n.td,{children:"not used"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"L"}),(0,t.jsx)(n.td,{children:"byte (1)"}),(0,t.jsx)(n.td,{children:"Bytes in payload"}),(0,t.jsx)(n.td,{children:"(depends)"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:"The first packet/chunk includes only the derivation path."}),"\n",(0,t.jsx)(n.p,{children:"All other packets/chunks should contain message to sign."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"First Packet"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[0]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"44"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[1]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"474"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[2]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[3]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Path[4]"}),(0,t.jsx)(n.td,{children:"byte (4)"}),(0,t.jsx)(n.td,{children:"Derivation Path Data"}),(0,t.jsx)(n.td,{children:"?"})]})]})]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.em,{children:"Other Chunks/Packets"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsx)(n.tbody,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Data"}),(0,t.jsx)(n.td,{children:"bytes..."}),(0,t.jsx)(n.td,{children:"Meta+Message"}),(0,t.jsx)(n.td,{})]})})]}),"\n",(0,t.jsx)(n.p,{children:"Data is defined as:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Expected"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Meta"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR metadata"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Message"}),(0,t.jsx)(n.td,{children:"bytes.."}),(0,t.jsx)(n.td,{children:"CBOR data to sign"}),(0,t.jsx)(n.td,{})]})]})]}),"\n",(0,t.jsx)(n.h5,{id:"response-4",children:"Response"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Content"}),(0,t.jsx)(n.th,{children:"Note"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SIG"}),(0,t.jsx)(n.td,{children:"byte (64)"}),(0,t.jsx)(n.td,{children:"Signature"}),(0,t.jsx)(n.td,{})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"SW1-SW2"}),(0,t.jsx)(n.td,{children:"byte (2)"}),(0,t.jsx)(n.td,{children:"Return code"}),(0,t.jsx)(n.td,{children:"see list of return codes"})]})]})]}),"\n",(0,t.jsx)(n.h4,{id:"meta-parameter",children:"Meta parameter"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"Meta"})," is a CBOR-encoded string \u2192 string map with the following fields:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"runtime_id"}),": Base16-encoded ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/runtime/identifiers.md",children:"runtime ID"})," (64-byte string)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"chain_context"}),": ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/genesis.md#genesis-documents-hash",children:"chain ID"})," (64-byte string)"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"orig_to"})," (optional): Base16-encoded ethereum destination address (40-byte\nstring)"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"changes-to-allowance-transaction",children:"Changes to Allowance transaction"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/services/staking.md#allow",children:(0,t.jsx)(n.code,{children:"staking.Allow"})})," transaction already exists on the consensus layer. We propose\nthe following improvement to the UI:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Type > | < To > | < Amount > | < Fee > | < Gas limit > | < Network > | < > | < |\n| Allowance | | ROSE +- | ROSE | | | APPROVE | REJECT |\n| | | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"IMPROVEMENT:"})," The hardware wallet renders the\nfollowing literals in place of ",(0,t.jsx)(n.code,{children:"TO"})," for specific ",(0,t.jsx)(n.code,{children:"NETWORK"})," and addresses:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qrnu9yhwzap7rqh6tdcdcpz0zf86hwhycchkhvt8"})," \u2192 ",(0,t.jsx)(n.code,{children:"Cipher"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qqdn25n5a2jtet2s5amc7gmchsqqgs4j0qcg5k0t"})," \u2192 ",(0,t.jsx)(n.code,{children:"Cipher"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qzvlg0grjxwgjj58tx2xvmv26era6t2csqn22pte"})," \u2192 ",(0,t.jsx)(n.code,{children:"Emerald"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qr629x0tg9gm5fyhedgs9lw5eh3d8ycdnsxf0run"})," \u2192 ",(0,t.jsx)(n.code,{children:"Emerald"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qrd3mnzhhgst26hsp96uf45yhq6zlax0cuzdgcfc"})," \u2192 ",(0,t.jsx)(n.code,{children:"Sapphire"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, To: ",(0,t.jsx)(n.code,{children:"oasis1qqczuf3x6glkgjuf0xgtcpjjw95r3crf7y2323xd"})," \u2192 ",(0,t.jsx)(n.code,{children:"Sapphire"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["For more information on how the addresses above are derived from the runtime ID\ncheck the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/consensus/services/staking.md#runtime-accounts",children:"runtime accounts"})," section."]}),"\n",(0,t.jsx)(n.h3,{id:"signing-general-runtime-transactions",children:"Signing general runtime transactions"}),"\n",(0,t.jsx)(n.h4,{id:"deposit",children:"Deposit"}),"\n",(0,t.jsxs)(n.p,{children:["We propose the following UI for ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/consensus_accounts/types.rs#L4-L13",children:(0,t.jsx)(n.code,{children:"consensus.Deposit"})})," runtime transaction:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Deposit | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"MIXED_TO"})," can either be ",(0,t.jsx)(n.code,{children:"oasis1"})," or the Ethereum's ",(0,t.jsx)(n.code,{children:"0x"})," address. If ",(0,t.jsx)(n.code,{children:"Meta"}),"\ndoes not contain ",(0,t.jsx)(n.code,{children:"orig_to"})," field, render the ",(0,t.jsx)(n.code,{children:"tx.call.body.to"})," value in\n",(0,t.jsx)(n.code,{children:"oasis1"})," format in place of ",(0,t.jsx)(n.code,{children:"MIXED_TO"}),". If ",(0,t.jsx)(n.code,{children:"Meta.orig_to"})," is set,\nthen:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Check that the ethereum address stored in ",(0,t.jsx)(n.code,{children:"orig_to"})," field maps to the\nnative address in ",(0,t.jsx)(n.code,{children:"tx.call.body.to"})," according to ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/types/address.go#L135-L142",children:"the reference\nimplementation of the mapping"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["Render ",(0,t.jsx)(n.code,{children:"orig_to"})," value in ",(0,t.jsx)(n.code,{children:"0x"})," format in place of ",(0,t.jsx)(n.code,{children:"MIXED_TO"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["In addition, if ",(0,t.jsx)(n.code,{children:"tx.call.body.to"})," is empty, then the deposit is made to the\nsigner's account inside the runtime. In this case ",(0,t.jsx)(n.code,{children:"Self"})," literal is rendered in\nplace of ",(0,t.jsx)(n.code,{children:"MIXED_TO"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"AMOUNT"})," and ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"SYM"})," beside. These are\ndetermined by the following mapping hardcoded in the hardware wallet:"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.code,{children:"(Network, Runtime ID, Denomination) \u2192 (Number of decimals, SYM)"})}),"\n",(0,t.jsxs)(n.p,{children:["Denomination information is stored in ",(0,t.jsx)(n.code,{children:"tx.part.body.amount[1]"})," or\n",(0,t.jsx)(n.code,{children:"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)."]}),"\n",(0,t.jsx)(n.p,{children:"The hardware wallet should have at least the following mappings hardcoded:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:['Network: Mainnet, runtime ID: Cipher, Denomination: "" \u2192 9, ',(0,t.jsx)(n.code,{children:"ROSE"})]}),"\n",(0,t.jsxs)(n.li,{children:['Network: Testnet, runtime ID: Cipher, Denomination: "" \u2192 9, ',(0,t.jsx)(n.code,{children:"TEST"})]}),"\n",(0,t.jsxs)(n.li,{children:['Network: Mainnet, runtime ID: Emerald, Denomination: "" \u2192 18, ',(0,t.jsx)(n.code,{children:"ROSE"})]}),"\n",(0,t.jsxs)(n.li,{children:['Network: Testnet, runtime ID: Emerald, Denomination: "" \u2192 18, ',(0,t.jsx)(n.code,{children:"TEST"})]}),"\n",(0,t.jsxs)(n.li,{children:['Network: Mainnet, runtime ID: Sapphire, Denomination: "" \u2192 18, ',(0,t.jsx)(n.code,{children:"ROSE"})]}),"\n",(0,t.jsxs)(n.li,{children:['Network: Testnet, runtime ID: Sapphire, Denomination: "" \u2192 18, ',(0,t.jsx)(n.code,{children:"TEST"})]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"If the lookup fails, the following policy should be respected:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"SYM"})," is rendered as empty string."]}),"\n",(0,t.jsx)(n.li,{children:"The number of decimals is 18, if runtime ID matches any Emerald or Sapphire\nruntime on any network."}),"\n",(0,t.jsx)(n.li,{children:"Otherwise, the number of decimals is 9."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"RUNTIME"})," shows the 32-byte hex encoded runtime ID stored in ",(0,t.jsx)(n.code,{children:"Meta.runtime_id"}),".\nIf ",(0,t.jsx)(n.code,{children:"NETWORK"})," matches Mainnet or Testnet, then human-readable version of\n",(0,t.jsx)(n.code,{children:"RUNTIME"})," is shown:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, runtime ID: ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000e199119c992377cb"})," \u2192 ",(0,t.jsx)(n.code,{children:"Cipher"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, runtime ID: ",(0,t.jsx)(n.code,{children:"0000000000000000000000000000000000000000000000000000000000000000"})," \u2192 ",(0,t.jsx)(n.code,{children:"Cipher"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, runtime ID: ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000e2eaa99fc008f87f"})," \u2192 ",(0,t.jsx)(n.code,{children:"Emerald"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, runtime ID: ",(0,t.jsx)(n.code,{children:"00000000000000000000000000000000000000000000000072c8215e60d5bca7"})," \u2192 ",(0,t.jsx)(n.code,{children:"Emerald"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Mainnet, runtime ID: ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000f80306c9858e7279"})," \u2192 ",(0,t.jsx)(n.code,{children:"Sapphire"})]}),"\n",(0,t.jsxs)(n.li,{children:["Network: Testnet, runtime ID: ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c"})," \u2192 ",(0,t.jsx)(n.code,{children:"Sapphire"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"SIGNATURE CONTEXT COMPUTATION:"})," ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/ba9802c0c2ccce366bec65f8426a0f3413670aff/docs/crypto.md#chain-domain-separation",children:"Chain domain separation"})," context\nfor ",(0,t.jsx)(n.strong,{children:"runtime"})," transactions beginning with\n",(0,t.jsx)(n.code,{children:"oasis-runtime-sdk/tx: v0 for chain "})," and followed by the hash derived from\n",(0,t.jsx)(n.code,{children:"Meta.runtime_id"})," and ",(0,t.jsx)(n.code,{children:"Meta.chain_context"}),". See ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/client-sdk/go/crypto/signature/context.go",children:"golang implementation"})," for the reference implementation."]}),"\n",(0,t.jsx)(n.h4,{id:"withdraw",children:"Withdraw"}),"\n",(0,t.jsxs)(n.p,{children:["We propose the following UI for ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/consensus_accounts/types.rs#L15-L23",children:(0,t.jsx)(n.code,{children:"consensus.Withdraw"})})," method:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Withdraw | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If ",(0,t.jsx)(n.code,{children:"tx.call.body.to"})," is empty, then the withdrawal is made to the signer's\nconsensus account. In this case ",(0,t.jsx)(n.code,{children:"Self"})," literal is rendered in\nplace of ",(0,t.jsx)(n.code,{children:"TO"}),"."]}),"\n",(0,t.jsx)(n.h4,{id:"transfer",children:"Transfer"}),"\n",(0,t.jsxs)(n.p,{children:["We propose the following UI for the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/modules/accounts/types.rs#L8-L13",children:(0,t.jsx)(n.code,{children:"accounts.Transfer"})})," method:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Type > | < To (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Transfer | | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n"})}),"\n",(0,t.jsx)(n.h4,{id:"example",children:"Example"}),"\n",(0,t.jsxs)(n.p,{children:["The user wants to deposit 100 ROSE to\n",(0,t.jsx)(n.code,{children:"0xDce075E1C39b1ae0b75D554558b6451A226ffe00"})," account on Emerald on the Mainnet.\nFirst they sign the deposit allowance transaction for Emerald."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Type > | < To > | < Amount > | < Gas limit > | < Fee > | < Network > | < > | < |\n| Allowance | Emerald | ROSE +100.0 | 1277 | ROSE 0.0 | Mainnet | APPROVE | REJECT |\n| | Mainnet | | | | | | |\n"})}),"\n",(0,t.jsx)(n.p,{children:"Next, they sign the runtime deposit transaction."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsx)(n.p,{children:"Then, they transfer some tokens to another account inside the runtime:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsx)(n.p,{children:"Finally, the user withdraws the remainder of tokens back to the Mainnet."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsx)(n.h3,{id:"signing-smart-contract-runtime-transactions",children:"Signing smart contract runtime transactions"}),"\n",(0,t.jsx)(n.h4,{id:"uploading-smart-contract",children:"Uploading smart contract"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L99-L110",children:(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.h4,{id:"instantiating-smart-contract",children:"Instantiating smart contract"}),"\n",(0,t.jsxs)(n.p,{children:["We propose the following UI for the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L119-L133",children:(0,t.jsx)(n.code,{children:"contracts.Instantiate"})})," method:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Review Contract > | < Code ID > | < Amount (1/1) > | < Data (1/1) > | ... | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Instantiation | | | | ... | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | ... | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"DATA"})," is a JSON-like representation of ",(0,t.jsx)(n.code,{children:"tx.call.body.data"}),", if the latter\nis a CBOR-encoded map. If ",(0,t.jsx)(n.code,{children:"tx.call.body.data"})," is empty or not present,\nthen Data screen is hidden. If ",(0,t.jsx)(n.code,{children:"tx.call.body.data"})," is in some other format,\nrequire ",(0,t.jsx)(n.strong,{children:"blind signing"})," mode and hide Data screen."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"When\nsigning blindly, it is crucial that the user trusts the client application that\nit generated a non-malicious transaction!"})]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"AMOUNT"})," consult the ",(0,t.jsx)(n.a,{href:"#deposit",children:"runtime deposit"})," behavior."]}),"\n",(0,t.jsxs)(n.p,{children:["There can be multiple Data screens Data 1, Data 2, ..., Data N for each key in\n",(0,t.jsx)(n.code,{children:"tx.call.body.data"})," map. ",(0,t.jsx)(n.code,{children:"DATA"})," can be one of the following types:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"string"}),"\n",(0,t.jsx)(n.li,{children:"number (integer, float)"}),"\n",(0,t.jsx)(n.li,{children:"array"}),"\n",(0,t.jsx)(n.li,{children:"map"}),"\n",(0,t.jsx)(n.li,{children:"boolean"}),"\n",(0,t.jsx)(n.li,{children:"null"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Strings are rendered as UTF-8 strings and the following characters need to be\nescaped: ",(0,t.jsx)(n.code,{children:":"}),", ",(0,t.jsx)(n.code,{children:","}),", ",(0,t.jsx)(n.code,{children:"}"}),", ",(0,t.jsx)(n.code,{children:"]"}),", ",(0,t.jsx)(n.code,{children:"\u2026"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Numbers are rendered in standard general base-10 encoding. Floats use decimal\nperiod and should be rendered with at least one decimal."}),"\n",(0,t.jsx)(n.p,{children:"For strings and numbers that cannot fit a single page, a pagination is\nactivated."}),"\n",(0,t.jsxs)(n.p,{children:["Boolean and null values are rendered as ",(0,t.jsx)(n.code,{children:"true"}),", ",(0,t.jsx)(n.code,{children:"false"})," and ",(0,t.jsx)(n.code,{children:"null"})," respectively\non a single page."]}),"\n",(0,t.jsxs)(n.p,{children:["Array and map is rendered in form ",(0,t.jsx)(n.code,{children:"VAL1,VAL2,..."})," and ",(0,t.jsx)(n.code,{children:"KEY1:VAL1,KEY1:VAL1,..."}),"\nrespectively. For security, ",(0,t.jsx)(n.strong,{children:"the items of the map must be sorted\nlexicographically by KEY"}),". ",(0,t.jsx)(n.code,{children:"KEY"})," and ",(0,t.jsx)(n.code,{children:"VAL"})," can be of any supported type. If it\nis a map or array it is rendered as ",(0,t.jsx)(n.code,{children:"{DATA}"})," or ",(0,t.jsx)(n.code,{children:"[DATA]"})," respectively\nto avoid disambiguation. Otherwise, it is just ",(0,t.jsx)(n.code,{children:"DATA"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"\u2026"})," is appended at\nthe end and the screen ",(0,t.jsx)(n.strong,{children:"becomes confirmable"}),". If the user double-clicks it, a\nsubscreen for item ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"N"})," titled Data n.1,\nData n.2, ..., Data n.N which renders the item ",(0,t.jsx)(n.code,{children:"n"})," as\n",(0,t.jsx)(n.code,{children:"DATA"})," for an array item or ",(0,t.jsx)(n.code,{children:"DATA:DATA"})," for a map item:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Data 1.1 (1/1) > | < Data 1.2 (1/1) | < Data 1.3 (1/1) | ... | < |\n| | | | | BACK |\n| | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.em,{children:"BACK"})," screen."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"blind signing"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"The following UI is shown when blind-signing a non-encrypted transaction due\nto too complex function parameters."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Review Contract > | < BLIND > | < Instance ID (1/1) > | < Amount > | < Fee > | < Network > | < ParaTime > | < > | < |\n| Instantiation | SIGNING! | | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | |\n"})}),"\n",(0,t.jsx)(n.h4,{id:"calling-smart-contract",children:"Calling smart contract"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L142-L153",children:(0,t.jsx)(n.code,{children:"contracts.Call"})})," method:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Review Contract > | < Instance ID > | < Amount (1/1) > | < Data (1/1) > | ... | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | | | | ... | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | ... | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The Data screen behavior is the same as for\n",(0,t.jsx)(n.a,{href:"#instantiating-smart-contract",children:(0,t.jsx)(n.code,{children:"contracts.Instantiate"})})," transaction."]}),"\n",(0,t.jsx)(n.h4,{id:"upgrading-smart-contracts",children:"Upgrading smart contracts"}),"\n",(0,t.jsxs)(n.p,{children:["We propose the following UI for the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/contracts/src/types.rs#L160-L174",children:(0,t.jsx)(n.code,{children:"contracts.Upgrade"})})," method:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsxs)(n.p,{children:["The Data screen behavior is the same as for the\n",(0,t.jsx)(n.a,{href:"#instantiating-smart-contract",children:"contract instantiate"})," transaction."]}),"\n",(0,t.jsx)(n.h4,{id:"example-1",children:"Example"}),"\n",(0,t.jsxs)(n.p,{children:["To upload, instantiate and call the ",(0,t.jsx)(n.a,{href:"/dapp/cipher/hello-world#deploying-the-contract",children:"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,t.jsx)(n.code,{children:"Code ID"})," 3 for the uploaded contract."]}),"\n",(0,t.jsxs)(n.p,{children:["Next, the user instantiates the contract and obtains the ",(0,t.jsx)(n.code,{children:"Instance ID"})," 2."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsxs)(n.p,{children:["Finally, they perform a call to ",(0,t.jsx)(n.code,{children:"say_hello"})," function on a smart contract\npassing the ",(0,t.jsx)(n.code,{children:'{"who":"me"}'})," object as a function argument."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsx)(n.p,{children:"For a complete example, the user can provide a more complex object:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "who": {\n "username": "alice",\n "client_secret": "e5868ebb4445fc2ad9f949956c1cb9ddefa0d421",\n "last_logins": [1646835046, 1615299046, 1583763046, 1552140646],\n "redirect": null\n }\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"In this case the hardware wallet renders the following UI."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsx)(n.h3,{id:"signing-evm-runtime-transactions",children:"Signing EVM runtime transactions"}),"\n",(0,t.jsx)(n.h4,{id:"creating-smart-contract",children:"Creating smart contract"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/evm/src/types.rs#L3-L8",children:(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.h4,{id:"calling-smart-contract-1",children:"Calling smart contract"}),"\n",(0,t.jsxs)(n.p,{children:["In contrast to ",(0,t.jsx)(n.code,{children:"contracts.Call"}),", ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/modules/evm/src/types.rs#L10-L16",children:(0,t.jsx)(n.code,{children:"evm.Call"})})," method requires contract ABI and\nsupport for RLP decoding in order to extract argument names from\n",(0,t.jsx)(n.code,{children:"tx.call.body.data"}),". This is outside of the scope of this ADR and the ",(0,t.jsx)(n.strong,{children:"blind\nsigning"}),", explicitly allowed by the user, is performed."]}),"\n",(0,t.jsx)(n.p,{children:"We propose the following UI:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| Review Contract > | < BLIND > | < Tx hash (1/1) > | < Address (1/1) > | < Amount > | < Fee > | < Gas limit > | < Network > | < ParaTime > | < > | < |\n| Call | SIGNING! | |
| | | | | | APPROVE | REJECT |\n| (ParaTime) | | | | | | | | | | |\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"TX_HASH"})," is a hex representation of sha256 checksum of ",(0,t.jsx)(n.code,{children:"tx.call.body.data"}),"\nfield."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ADDRESS"})," is a hex-encoded address of the smart contract."]}),"\n",(0,t.jsx)(n.h3,{id:"signing-encrypted-runtime-transactions",children:"Signing encrypted runtime transactions"}),"\n",(0,t.jsxs)(n.p,{children:["Encrypted transactions (",(0,t.jsx)(n.code,{children:"tx.call.format == 1"}),") contain call data inside the\n",(0,t.jsxs)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/c36a7ee194abf4ca28fdac0edbefe3843b39bf69/runtime-sdk/src/types/callformat.rs#L7-L16",children:["envelope's ",(0,t.jsx)(n.code,{children:"data"})," field"]})," encrypted with Deoxys-II\nephemeral key and X25519 key derivation."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"blind signing"})," and the hardware wallet should\nshow the hash of the encrypted call data, the public key and the nonce:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-ledger",children:"| 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"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"TX_HASH"})," is a hex representation of sha256 checksum of ",(0,t.jsx)(n.code,{children:"tx.call.body.data"}),"\nfield."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"PUBLIC_KEY"})," is a hex representation of the 32-byte ",(0,t.jsx)(n.code,{children:"tx.call.body.pk"})," field."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"NONCE"})," is a hex representation of the 15-byte ",(0,t.jsx)(n.code,{children:"tx.call.body.nonce"})," field."]}),"\n",(0,t.jsxs)(n.p,{children:["Since the transaction stored inside the ",(0,t.jsx)(n.code,{children:"tx.call.body.data"})," field is encrypted,\nthere is also no way to discriminate between the transactions, for example\n",(0,t.jsx)(n.code,{children:"contracts.Call"}),", ",(0,t.jsx)(n.code,{children:"contracts.Upgrade"})," or ",(0,t.jsx)(n.code,{children:"evm.Call"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsx)(n.p,{children:"Users will have a similar experience for signing runtime transactions on any\nwallet implementing this ADR."}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsx)(n.p,{children:"For some transactions, user will need to trust the client application and use\nblind signing."}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsxs)(n.h4,{id:"consideration-of-roothashsubmitmsg-transactions",children:["Consideration of ",(0,t.jsx)(n.code,{children:"roothash.SubmitMsg"})," transactions"]}),"\n",(0,t.jsxs)(n.p,{children:["This ADR does not propose a UI for ",(0,t.jsx)(n.em,{children:"generic"})," runtime calls\n(",(0,t.jsx)(n.code,{children:"roothash.SubmitMsg"}),", see ",(0,t.jsx)(n.a,{href:"/adrs/0011-incoming-runtime-messages",children:"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."]}),"\n",(0,t.jsx)(n.h4,{id:"signing-contract-uploads-on-hardware-wallets",children:"Signing contract uploads on hardware wallets"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.h4,{id:"consideration-of-adding-from-screen",children:["Consideration of adding ",(0,t.jsx)(n.code,{children:"From"})," screen"]}),"\n",(0,t.jsxs)(n.p,{children:["None of the proposed UIs and the existing implementation of signing the\nconsensus transactions on Ledger show ",(0,t.jsx)(n.em,{children:"who"})," is a signer of the transaction.\nThe signer's ",(0,t.jsx)(n.em,{children:"from"})," address can be extracted from\n",(0,t.jsx)(n.code,{children:"tx.ai.si[0].address_spec.signature."}),"\nfor oasis native address and if the signer wants to show the Ethereum address,\n",(0,t.jsx)(n.code,{children:"Meta.orig_from"})," should be populated and the hardware wallet should\nverify it before showing the tx."]}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://github.com/Zondax/ledger-oasis/blob/master/docs/APDUSPEC.md",children:"Existing APDU specification"})}),"\n"]})]})}function o(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>c});var t=s(6540);const i={},d=t.createContext(i);function r(e){const n=t.useContext(d);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(d.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/885a74d0.e529ea42.js b/assets/js/885a74d0.e529ea42.js new file mode 100644 index 0000000000..96d4f2d4ed --- /dev/null +++ b/assets/js/885a74d0.e529ea42.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7964],{7248:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var t=s(4848),r=s(8453);const o={},i="Local Network Runner",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/oasis-net-runner.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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={},d=[{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}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"local-network-runner",children:"Local Network Runner"}),"\n",(0,t.jsxs)(n.p,{children:["In order to make development easier (and also to facilitate automated E2E\ntests), the Oasis Core repository provides a utility called ",(0,t.jsx)(n.code,{children:"oasis-net-runner"}),"\nthat enables developers to quickly set up local networks."]}),"\n",(0,t.jsxs)(n.p,{children:["Before proceeding, make sure to look at the ",(0,t.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"prerequisites"})," required for running\nan Oasis Core environment followed by ",(0,t.jsx)(n.a,{href:"/core/development-setup/building",children:"build instructions"})," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."]}),"\n",(0,t.jsx)(n.h2,{id:"unsafe-non-sgx-environment",children:"Unsafe Non-SGX Environment"}),"\n",(0,t.jsxs)(n.p,{children:["To start a simple Oasis network as defined by ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/oasis-net-runner/fixtures/default.go",children:"the default network fixture"}),"\nrunning the ",(0,t.jsx)(n.code,{children:"simple-keyvalue"})," test runtime, do:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"./go/oasis-net-runner/oasis-net-runner \\\n --fixture.default.node.binary go/oasis-node/oasis-node \\\n --fixture.default.runtime.binary target/default/release/simple-keyvalue \\\n --fixture.default.runtime.loader target/default/release/oasis-core-runtime-loader \\\n --fixture.default.keymanager.binary target/default/release/simple-keymanager\n"})}),"\n",(0,t.jsx)(n.p,{children:"Wait for the network to start, there should be messages about nodes being\nstarted and at the end the following message should appear:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/tests/runtimes/simple-keyvalue",children:"simple-keyvalue example"})," and ",(0,t.jsx)(n.a,{href:"/paratime/",children:"Building a runtime"})," chapter in the Oasis SDK."]}),"\n",(0,t.jsxs)(n.p,{children:["Finally, to test Oasis node, we will run a test client written specifically\nfor the ",(0,t.jsx)(n.code,{children:"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:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"./target/default/release/simple-keyvalue-client \\\n --runtime-id 8000000000000000000000000000000000000000000000000000000000000000 \\\n --node-address unix:/tmp/oasis-net-runner530668299/net-runner/network/client-0/internal.sock\n"})}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk",children:"Oasis SDK"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"sgx-environment",children:"SGX Environment"}),"\n",(0,t.jsxs)(n.p,{children:["To run an Oasis node under SGX follow the same steps as for non-SGX, except the\n",(0,t.jsx)(n.code,{children:"oasis-net-runner"})," invocation:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"./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/release/simple-keyvalue.sgxs \\\n --fixture.default.runtime.loader target/default/release/oasis-core-runtime-loader \\\n --fixture.default.keymanager.binary target/sgx/x86_64-fortanix-unknown-sgx/release/simple-keymanager.sgxs\n"})}),"\n",(0,t.jsx)(n.h2,{id:"common-issues",children:"Common Issues"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"/tmp/oasis-net-runner"})," (unless overriden via ",(0,t.jsx)(n.code,{children:"--basedir"})," options)."]}),"\n",(0,t.jsxs)(n.p,{children:["Specifically look at ",(0,t.jsx)(n.code,{children:"node.log"})," and ",(0,t.jsx)(n.code,{children:"console.log"})," files located in directories\nfor each of the nodes comprising the local network."]}),"\n",(0,t.jsx)(n.h3,{id:"user-namespace-permission-issues",children:"User Namespace Permission Issues"}),"\n",(0,t.jsxs)(n.p,{children:["The Oasis Core compute nodes use ",(0,t.jsx)(n.a,{href:"/core/runtime/#runtimes",children:"sandboxing"})," to execute runtime binaries and\nthe sandbox implementation requires that the process is able to create\nnon-privileged user namespaces."]}),"\n",(0,t.jsxs)(n.p,{children:["In case this is not available, the following error message may appear in\n",(0,t.jsx)(n.code,{children:"console.log"})," of any compute or key manager nodes:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsx)(n.p,{children:"In this case do as indicated in the message and run:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"sysctl kernel.unprivileged_userns_clone=1\n"})}),"\n",(0,t.jsxs)(n.p,{children:["This could also happen if you are running in a Docker container without\nspecifying additional options at startup. See the ",(0,t.jsx)(n.a,{href:"/core/development-setup/prerequisites#using-the-development-docker-image",children:"Using the Development Docker\nImage"})," section of the Prerequisites for details."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>a});var t=s(6540);const r={},o=t.createContext(r);function i(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/886d3d06.2b6c9e02.js b/assets/js/886d3d06.2b6c9e02.js new file mode 100644 index 0000000000..9928e0d7be --- /dev/null +++ b/assets/js/886d3d06.2b6c9e02.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9206],{1270:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>r,contentTitle:()=>t,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var i=o(4848),s=o(8453);const a={},t="Setup",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/setup.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,frontMatter:{},sidebar:"general",previous:{title:"Oasis CLI",permalink:"/general/manage-tokens/cli/"},next:{title:"Network",permalink:"/general/manage-tokens/cli/network"}},r={},c=[{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}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"setup",children:"Setup"}),"\n",(0,i.jsx)(n.h2,{id:"download-and-run",children:"Download and Run"}),"\n",(0,i.jsxs)(n.p,{children:["Download the latest release ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/cli/releases",children:"here"})," and extract it to your\nfavorite application folder."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/cli",children:"build it from source"}),"."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["We suggest that you update your system path to include a directory containing\nthe ",(0,i.jsx)(n.code,{children:"oasis"})," binary or create a symbolic link to ",(0,i.jsx)(n.code,{children:"oasis"})," in your\nsystem path, so you can access it globally."]})}),"\n",(0,i.jsxs)(n.p,{children:["Run the Oasis CLI by typing ",(0,i.jsx)(n.code,{children:"oasis"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/dapp/",children:"ParaTimes supported by the Oasis Foundation"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsx)(n.p,{children:"The configuration folder of Oasis CLI is located:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["on Windows:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"%USERPROFILE%\\AppData\\Roaming\\oasis\\"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["on macOS:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"/Users/$USER/Library/Application Support/oasis/"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["on Linux:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"$HOME/.config/oasis/"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["There, you will find ",(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:".wallet"})," extension."]}),"\n",(0,i.jsx)(n.h2,{id:"multiple-profiles",children:"Multiple Profiles"}),"\n",(0,i.jsx)(n.p,{children:"You can utilize multiple profiles of your Oasis CLI. To create a new profile,\nmove your existing configuration folder to another place, for example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"mv $HOME/.config/oasis $HOME/.config/oasis_dev\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Then, invoke ",(0,i.jsx)(n.code,{children:"oasis"})," with arbitrary command to set up a fresh configuration\nfolder under ",(0,i.jsx)(n.code,{children:"~/.config/oasis"}),". For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet list\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"ACCOUNT\tKIND\tADDRESS \n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now you can switch between the ",(0,i.jsx)(n.code,{children:"oasis_dev"})," and the new profile by passing\n",(0,i.jsx)(n.code,{children:"--config"})," parameter pointing to ",(0,i.jsx)(n.code,{children:"cli.toml"})," in the desired configuration folder."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis wallet list --config ~/.config/oasis_dev/cli.toml\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"ACCOUNT KIND ADDRESS\noscar file (ed25519-adr8:0) oasis1qp87hflmelnpqhzcqcw8rhzakq4elj7jzv090p3e\n"})}),"\n",(0,i.jsx)(n.h2,{id:"back-up-your-wallet",children:"Back Up Your Wallet"}),"\n",(0,i.jsxs)(n.p,{children:["To back up your complete Oasis CLI configuration including your wallet, archive\nthe configuration folder containing ",(0,i.jsx)(n.code,{children:"cli.toml"})," and ",(0,i.jsx)(n.code,{children:".wallet"})," files."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>t,x:()=>l});var i=o(6540);const s={},a=i.createContext(s);function t(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8b083473.4b4e0acb.js b/assets/js/8b083473.4b4e0acb.js new file mode 100644 index 0000000000..0b70de1cf6 --- /dev/null +++ b/assets/js/8b083473.4b4e0acb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[598],{666:(e,o,s)=>{s.r(o),s.d(o,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>c,toc:()=>d});var n=s(4848),i=s(8453);const t={},r="RPC",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/rpc.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Oasis Node",permalink:"/core/oasis-node"},next:{title:"Metrics",permalink:"/core/oasis-node/metrics"}},a={},d=[{value:"Protocol",id:"protocol",level:2},{value:"Errors",id:"errors",level:2},{value:"Services",id:"services",level:2}];function l(e){const o={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.h1,{id:"rpc",children:"RPC"}),"\n",(0,n.jsxs)(o.p,{children:["Oasis Node exposes an RPC interface to enable external applications to query\ncurrent ",(0,n.jsx)(o.a,{href:"/core/consensus/",children:"consensus"})," and ",(0,n.jsx)(o.a,{href:"/core/runtime/",children:"runtime"})," states, ",(0,n.jsx)(o.a,{href:"/core/consensus/transactions#submission",children:"submit transactions"}),", etc."]}),"\n",(0,n.jsxs)(o.p,{children:["The RPC interface is ONLY exposed via an AF_LOCAL socket called ",(0,n.jsx)(o.code,{children:"internal.sock"}),"\nlocated in the node's data directory. ",(0,n.jsx)(o.strong,{children:"This interface should NEVER be directly\nexposed over the network as it has no authentication and allows full control,\nincluding shutdown, of a node."})]}),"\n",(0,n.jsx)(o.p,{children:"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."}),"\n",(0,n.jsx)(o.admonition,{type:"info",children:(0,n.jsxs)(o.p,{children:["An example of such a gateway is the ",(0,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core-rosetta-gateway",children:"Oasis Core Rosetta Gateway"})," which exposes\na subset of the consensus layer via the ",(0,n.jsx)(o.a,{href:"https://www.rosetta-api.org",children:"Rosetta API"}),"."]})}),"\n",(0,n.jsx)(o.h2,{id:"protocol",children:"Protocol"}),"\n",(0,n.jsxs)(o.p,{children:["Like other parts of Oasis Core, the RPC interface exposed by Oasis Node uses the\n",(0,n.jsx)(o.a,{href:"https://grpc.io",children:"gRPC protocol"})," with the ",(0,n.jsx)(o.a,{href:"/core/authenticated-grpc#cbor-codec",children:"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,n.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-sdk",children:"Oasis SDK"})," for more information."]}),"\n",(0,n.jsxs)(o.p,{children:["For example to create a gRPC client connected to the Oasis Node endpoint exposed\nby your local node at ",(0,n.jsx)(o.code,{children:"/path/to/datadir/internal.sock"})," you can do:"]}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-golang",children:'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'})}),"\n",(0,n.jsxs)(o.p,{children:["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,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/grpc?tab=doc",children:"API documentation"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"errors",children:"Errors"}),"\n",(0,n.jsxs)(o.p,{children:["We use a specific convention to provide more information about the exact error\nthat occurred when processing a gRPC request. See the ",(0,n.jsx)(o.a,{href:"/core/authenticated-grpc#errors",children:"gRPC specifics"})," section\nfor details."]}),"\n",(0,n.jsx)(o.h2,{id:"services",children:"Services"}),"\n",(0,n.jsxs)(o.p,{children:["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.jsx)(o.code,{children:"oasis-core."})," followed by the service identifier. A single slash (",(0,n.jsx)(o.code,{children:"/"}),") is used\nas the separator in method names, e.g., ",(0,n.jsx)(o.code,{children:"/oasis-core.NodeControl/IsSynced"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"The following gRPC services are exposed (with links to API documentation):"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"General"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/control/api?tab=doc#NodeController",children:"Node Control"})," (",(0,n.jsx)(o.code,{children:"oasis-core.NodeController"}),")"]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Consensus Layer"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend",children:"Consensus (client subset)"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Consensus"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#LightClientBackend",children:"Consensus (light client subset)"})," (",(0,n.jsx)(o.code,{children:"oasis-core.ConsensusLight"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Backend",children:"Staking"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Staking"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Backend",children:"Registry"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Registry"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/scheduler/api?tab=doc#Backend",children:"Scheduler"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Scheduler"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api?tab=doc#Backend",children:"RootHash"})," (",(0,n.jsx)(o.code,{children:"oasis-core.RootHash"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/governance/api?tab=doc#Backend",children:"Governance"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Governance"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/beacon/api?tab=doc#Backend",children:"Beacon"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Beacon"}),")"]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.strong,{children:"Runtime Layer"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/storage/api?tab=doc#Backend",children:"Storage"})," (",(0,n.jsx)(o.code,{children:"oasis-core.Storage"}),")"]}),"\n",(0,n.jsxs)(o.li,{children:[(0,n.jsx)(o.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/client/api?tab=doc#RuntimeClient",children:"Runtime Client"})," (",(0,n.jsx)(o.code,{children:"oasis-core.RuntimeClient"}),")"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(o.p,{children:"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:"}),"\n",(0,n.jsx)(o.pre,{children:(0,n.jsx)(o.code,{className:"language-golang",children:'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'})})]})}function h(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,o,s)=>{s.d(o,{R:()=>r,x:()=>c});var n=s(6540);const i={},t=n.createContext(i);function r(e){const o=n.useContext(t);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function c(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(t.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8f21ad56.51fb326f.js b/assets/js/8f21ad56.51fb326f.js new file mode 100644 index 0000000000..16c01e8e08 --- /dev/null +++ b/assets/js/8f21ad56.51fb326f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2676],{1968:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var i=s(4848),r=s(8453);const t={},o="Upgrade Log",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/testnet/upgrade-log.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Testnet",permalink:"/node/testnet/"},next:{title:"Genesis Document",permalink:"/node/genesis-doc"}},d={},l=[{value:"2023-10-12 Upgrade",id:"2023-10-12-upgrade",level:2},{value:"Instructions",id:"instructions",level:3},{value:"Configuration Changes",id:"configuration-changes",level:3},{value:"Data Directory Changes",id:"data-directory-changes",level:3},{value:"State Changes",id:"state-changes",level:3},{value:"General",id:"general",level:4},{value:"Registry",id:"registry",level:4},{value:"Root Hash",id:"root-hash",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:"Consensus",id:"consensus",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-1",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-1",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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"upgrade-log",children:"Upgrade Log"}),"\n",(0,i.jsx)(n.p,{children:"For each upgrade of the Testnet network, we are tracking important changes for\nnode operators' deployments."}),"\n",(0,i.jsx)(n.p,{children:"They are enumerated and explained in this document."}),"\n",(0,i.jsx)(n.h2,{id:"2023-10-12-upgrade",children:"2023-10-12 Upgrade"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"29570"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2023-10-12 07:56\nUTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions",children:"Instructions"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["(optional) Vote for the upgrade. On 2023-10-09, an upgrade proposal will be\nproposed which (if accepted) will schedule the upgrade on epoch ",(0,i.jsx)(n.strong,{children:"29570"}),".\nSee the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Governance documentation"})," for details on voting for proposals."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The following steps should be performed only after the network has reached the\nupgrade epoch and has halted:"}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["Download the Testnet genesis file published in the\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2023-10-12",children:"Testnet 2023-10-12 release"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["Testnet state at epoch ",(0,i.jsx)(n.strong,{children:"29570"})," will be exported and migrated to a 23.0\ncompatible genesis file."]}),(0,i.jsx)(n.p,{children:"The new genesis file will be published on the above link soon after reaching the\nupgrade epoch."})]}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Verify the provided Testnet upgrade genesis file by comparing it to the\nlocal network state dump."}),"\n",(0,i.jsxs)(n.p,{children:["The state changes are described in the ",(0,i.jsx)(n.a,{href:"#state-changes",children:"State Changes"}),"\nsection below."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Replace the old genesis file with the new Testnet genesis file."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Ensure your node will remain stopped by disabling auto-starting via your\nprocess manager (e.g., ",(0,i.jsx)(n.a,{href:"https://systemd.io/",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org/",children:"Supervisor"}),")"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Back up the entire data directory of your node. Verify that the backup\nincludes the following folders:"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["for consensus: ",(0,i.jsx)(n.code,{children:"tendermint/abci-state"})," and ",(0,i.jsx)(n.code,{children:"tendermint/data"})]}),"\n",(0,i.jsxs)(n.li,{children:["for runtimes: ",(0,i.jsx)(n.code,{children:"runtimes/*/mkvs_storage.badger.db"})," and\n",(0,i.jsx)(n.code,{children:"runtimes/*/worker-local-storage.badger.db"})]}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"7",children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),". This must be performed ",(0,i.jsx)(n.em,{children:"before"})," replacing the Oasis Node\nbinary."]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsx)(n.p,{children:"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,i.jsx)(n.p,{children:"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."})]}),"\n",(0,i.jsxs)(n.ol,{start:"8",children:["\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v23.0",children:"23.0"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Oasis Core 23.0 binary in our published releases is built only for Ubuntu\n22.04 (GLIBC>=2.32). You'll have to build it yourself if you're using prior\nUbuntu versions (or other distributions using older system libraries)."})}),"\n",(0,i.jsxs)(n.ol,{start:"9",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Perform any needed ",(0,i.jsx)(n.a,{href:"#configuration-changes",children:"configuration changes"})," described\nbelow."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(only Rosetta Gateway operators) Replace old version of Oasis Rosetta\nGateway with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.6.0",children:"2.6.0"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Start your node and re-enable auto-starting via your process manager."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"configuration-changes",children:"Configuration Changes"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["To see the full extent of the changes examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v23.0/CHANGELOG.md",children:"Change Log"})," of the 23.0\nrelease."]})}),"\n",(0,i.jsxs)(n.p,{children:["The node configuration has been refactored so that everything is now configured\nvia a YAML configuration file and ",(0,i.jsx)(n.strong,{children:"configuring via command-line options is no\nlonger supported"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node config migrate --in config.yml --out new-config.yml\n"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"After you are satisfied with the new configuration file, replace the old file\nwith the new one as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"mv new-config.yml config.yml\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"The configuration format for seed nodes has changed and it now requires the\nnode's P2P public key to be used. In case your old configuration file contains\nknown Testnet seed nodes, this transformation is performed automatically."}),(0,i.jsx)(n.p,{children:"However, if it contains unknown seed nodes then the conversion did not happen\nautomatically and you may need to obtain the seed node's P2P public key. For\nTestnet you can use the following addresses:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:26656"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"HcDFrTp/MqRHtju5bCx6TIhIMd6X/0ZQ3lUG73q5898=@34.86.165.6:9200"})}),"\n"]}),(0,i.jsx)(n.p,{children:"Please be aware that every seed node should be configured to listen on two\ndistinct ports. One is dedicated to peer discovery within the CometBFT P2P\nnetwork, while the other is used to bootstrap the Oasis P2P network."})]}),"\n",(0,i.jsx)(n.h3,{id:"data-directory-changes",children:"Data Directory Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The subdirectory (located inside the node's data directory) used to store\nconsensus-related data, previously called ",(0,i.jsx)(n.code,{children:"tendermint"})," (after the consensus\nlayer protocol backend) has been renamed to ",(0,i.jsx)(n.code,{children:"consensus"})," in Oasis Core 23.0. If\nany of your scripts rely on specific directory names, please make sure to update\nthem to reflect the changed sdirectory name."]}),"\n",(0,i.jsx)(n.h3,{id:"state-changes",children:"State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["All state changes will be done automatically with the migration command provided\nby the new version of ",(0,i.jsx)(n.code,{children:"oasis-node"}),". It can be used as follows to derive the same\ngenesis file from an existing state dump at the correct height (assuming there\nis a ",(0,i.jsx)(n.code,{children:"genesis.json"})," present in the current working directory):"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node genesis migrate --genesis.new_chain_id testnet-2023-10-12\n"})})]}),"\n",(0,i.jsx)(n.h4,{id:"general",children:"General"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"testnet-2023-10-12"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be removed as it is no longer used."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"registry",children:"Registry"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes[].txn_scheduler.propose_batch_timeout"})})," specifies how\nlong to wait before accepting proposal from the next backup scheduler. It will\nbe set to ",(0,i.jsx)(n.code,{children:"5000000000"})," (5 seconds). Previously the value was represented in\nthe number of consensus layer blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.prove_freshness"})})," specifies the cost of the\nfreshness proof transaction. It will be set to ",(0,i.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"keymanager.params.gas_costs.update_policy"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"tee_features": {\n "sgx": {\n "pcs": true,\n "signed_attestations": true,\n "max_attestation_age": 1200\n },\n "freshness_proofs": true\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"5"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"root-hash",children:"Root Hash"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_past_roots_stored"})})," specifies the maximum number of\npast runtime state roots that are stored in consensus state for each runtime.\nIt will be set to ",(0,i.jsx)(n.code,{children:"1200"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"staking",children:"Staking"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.commission_schedule_rules.min_commission_rate"})})," specifies\nthe minimum commission rate. It will be set to ",(0,i.jsx)(n.code,{children:"0"})," to maintain the existing\nbehavior."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.thresholds.node-observer"})})," specifies the stake threshold\nfor registering an observer node. It will be set to ",(0,i.jsx)(n.code,{children:"100000000000"})," base units\n(or ",(0,i.jsx)(n.code,{children:"100"})," tokens), same as for existing compute nodes."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"key-manager",children:"Key Manager"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs"})})," specify the cost of key manager\ntransactions. These will be set to the following values:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"gas_costs": {\n "publish_ephemeral_secret": 1000,\n "publish_master_secret": 1000,\n "update_policy": 1000\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"random-beacon",children:"Random Beacon"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the epoch\nof Testnet's state dump + 1, ",(0,i.jsx)(n.code,{children:"29570"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"governance",children:"Governance"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.enable_change_parameters_proposal"})})," specifies whether\nparameter change governance proposals are allowed. It will be set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"consensus",children:"Consensus"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_block_size"})})," specifies the maximum block size in the\nconsensus layer. It will be set to ",(0,i.jsx)(n.code,{children:"1048576"})," (1 MiB)."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"other",children:"Other"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"Mainnet genesis file"}),"\nto include the Oasis Network's genesis quote:"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2022-04-04-upgrade",children:"2022-04-04 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"15056"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2022-04-04 7:45 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions-1",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#before-upgrade",children:"Before upgrade"})," section for required steps\nto be done before upgrade."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(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,i.jsx)(n.strong,{children:"15056"}),".\nSee the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Governance documentation"}),"\nfor details on voting for proposals."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["The upgrade proposal contains the ",(0,i.jsx)(n.code,{children:'"empty"'})," upgrade handler whose only purpose\nis allow specifying a no-op handler when submitting an upgrade proposal."]})}),"\n",(0,i.jsx)(n.admonition,{title:"This is not dump & restore upgrade",type:"caution",children:(0,i.jsxs)(n.p,{children:["For this upgrade, ",(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades",children:"Handling Network Upgrades"})," for more info."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Once reaching the designated upgrade epoch, your node will stop and needs to\nbe upgraded to Oasis Core ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1",children:"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."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Testnet's genesis file and the genesis document's hash will remain the same."})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["If the nodes are running any ParaTimes, make sure you upgrade to the versions\npublished on the ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet network parameters page"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.em,{children:"multiple"})," ParaTimes\non the same node, you should ",(0,i.jsx)(n.em,{children:"disable"})," the Cipher ParaTime until the new version\nis published."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["If you are running a Rosetta gateway, upgrade it to version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.2.0",children:"2.2.0"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"before-upgrade",children:"Before Upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade will upgrade ",(0,i.jsx)(n.strong,{children:"Oasis Core"})," to ",(0,i.jsxs)(n.strong,{children:["version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1",children:"22.1"})]})," which ",(0,i.jsx)(n.strong,{children:"no longer\nallows running Oasis Node"})," (i.e. the ",(0,i.jsx)(n.code,{children:"oasis-node"})," binary) ",(0,i.jsx)(n.strong,{children:"as root"}),"\n(effective user ID of 0)."]}),"\n",(0,i.jsxs)(n.p,{children:['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,i.jsx)(n.code,{children:"syscall.AllThreadsSyscall"})," does not work if the binary uses ",(0,i.jsx)(n.code,{children:"cgo"}),"\nat all."]}),"\n",(0,i.jsxs)(n.p,{children:["Nothing in Oasis Node will ever require elevated privileges.\nAttempting to run the ",(0,i.jsx)(n.code,{children:"oasis-node"})," process as the root user will now terminate\nimmediately on startup."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["If the previous behavior is required, the binary must be run in unsafe/debug\nmode (via the intentionally undocumented flag), and ",(0,i.jsx)(n.code,{children:"debug.allow_root"})," must also\nbe set."]}),"\n",(0,i.jsx)(n.h2,{id:"2022-03-03-upgrade",children:"2022-03-03 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"14209."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2022-03-03 12:45 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions-2",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["(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,i.jsx)(n.strong,{children:"14209."})," See the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Governance documentation"})," for details on voting for proposals."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.p,{children:"The following steps should be performed only after the network has reached the\nupgrade network and has halted:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Download the Testnet genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2022-03-03",children:"Testnet 2022-03-03 release"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Testnet state at epoch ",(0,i.jsx)(n.strong,{children:"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."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Replace the old genesis file with the new Testnet genesis file.\nThe ",(0,i.jsx)(n.a,{href:"#state-changes",children:"state changes"})," are described and explained below."]}),"\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.0",children:"22.0"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["Perform any needed ",(0,i.jsx)(n.a,{href:"#configuration-changes",children:"configuration changes"})," described below."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"configuration-changes-1",children:"Configuration Changes"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["To see the full extent of the changes examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.0/CHANGELOG.md#220-2022-03-01",children:"Change Log"})," of the 22.0 release."]})}),"\n",(0,i.jsx)(n.p,{children:"If your node is currently configured to run a ParaTime, you need to perform some\nadditional steps."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:".orc"})," extension. Links to updated ParaTime binaries will be\npublished on the ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet network parameters page"})," for their respective\nParaTimes."]}),"\n",(0,i.jsxs)(n.p,{children:["The configuration is simplified as the ",(0,i.jsx)(n.code,{children:"runtime.paths"})," now only needs to list\nall of the supported ",(0,i.jsx)(n.code,{children:".orc"})," files (see below for an example)."]}),"\n",(0,i.jsxs)(n.p,{children:["Instead of separately configuring various roles for a node, there is now a\nsingle configuration flag called ",(0,i.jsx)(n.code,{children:"runtime.mode"})," which enables the correct roles\nas needed. It should be set to one of the following values:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"none"})," (runtime support is disabled, only consensus layer is enabled)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"compute"})," (node is participating as a runtime compute node for all the\nconfigured runtimes)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"keymanager"})," (node is participating as a keymanager node)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"client"})," (node is a stateful runtime client)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"client-stateless"})," (node is a stateless runtime client and connects to\nremote nodes for any state queries)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Nodes that have so far been participating as compute nodes should set the mode\nto ",(0,i.jsx)(n.code,{children:"compute"})," and nodes that have been participating as clients for querying\nand transaction submission should set it to ",(0,i.jsx)(n.code,{children:"client"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The following configuration flags have been removed:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"runtime.supported"})," (existing ",(0,i.jsx)(n.code,{children:"runtime.paths"})," is used instead)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.p2p.enabled"})," (now automatically set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.compute.enabled"})," (now set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.keymanager.enabled"})," (now set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.storage.enabled"})," (no longer needed)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Also the ",(0,i.jsx)(n.code,{children:"worker.client"})," option is no longer needed unless you are providing\nconsensus layer RPC services."]}),"\n",(0,i.jsxs)(n.p,{children:["For example if your ",(0,i.jsx)(n.em,{children:"previous"})," configuration looked like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.em,{children:"new"})," configuration should look like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'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'})}),"\n",(0,i.jsx)(n.h3,{id:"state-changes-1",children:"State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the ",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsx)(n.h3,{id:"general-1",children:(0,i.jsx)(n.strong,{children:"General"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"height"})})," will be set to the height of the Testnet state dump + 1, i.e. ",(0,i.jsx)(n.code,{children:"8535081"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"genesis_time"})})," will be set to ",(0,i.jsx)(n.code,{children:"2022-03-03T13:00:00Z"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"testnet-2022-03-03"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be set to ",(0,i.jsx)(n.code,{children:"24210"})," (more than 1 year from the upgrade)."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"registry-1",children:(0,i.jsx)(n.strong,{children:"Registry"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes"})})," list contains the registered runtimes' descriptors. In\nthis upgrade, all runtime descriptors will be migrated from version ",(0,i.jsx)(n.code,{children:"2"})," to\nversion ",(0,i.jsx)(n.code,{children:"3"}),".\nThe migration will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.suspended_runtimes"})})," list contains the suspended registered\nruntimes' descriptors. In this upgrade, all runtime descriptors will be\nmigrated from version ",(0,i.jsx)(n.code,{children:"2"})," to version ",(0,i.jsx)(n.code,{children:"3"}),".\nThe migration will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n",(0,i.jsxs)(n.li,{children:["Inactive registered entities in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.entities"})})," (and their\ncorresponding nodes in ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.nodes"})}),") that don't pass the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"minimum staking thresholds"})," will be removed.\nThe removal will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"root-hash-1",children:(0,i.jsx)(n.strong,{children:"Root Hash"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"1000"}),".\nThis will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"128"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.runtime_state"})})," contains the state roots of the runtimes.\nEmpty fields will be omitted.\nThis will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"staking-1",children:(0,i.jsx)(n.strong,{children:"Staking"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"node-storage"})," key is removed since Oasis Core 22.0+ removes separate\nstorage nodes (for more details, see: ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/pull/4308",children:"#4308"}),").\nThis will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"})," command."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.reward_schedule"})})," specifies the staking reward schedule\nas an array with elements of the form:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'{\n "until": 14226,\n "scale": "1229"\n}\n'})}),"\n","For example, this element specifies that the staking reward is 0.001229% per\nepoch until epoch ",(0,i.jsx)(n.code,{children:"14226"}),".\nIt will be set to the same schedule that is currently on used on the Mainnet."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"random-beacon-1",children:(0,i.jsx)(n.strong,{children:"Random Beacon"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon"})})," object contains parameters controlling the new\n",(0,i.jsx)(n.a,{href:"../../adrs/0010-vrf-elections",children:"improved VRF-based random beacon"})," introduced in the Damask upgrade."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the\n",(0,i.jsx)(n.code,{children:"14209"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.backend"})})," configures the random beacon backend to use. It\nwill be set to ",(0,i.jsx)(n.code,{children:'"vrf"'})," indicating that the beacon implementing a\n",(0,i.jsx)(n.a,{href:"../../adrs/0010-vrf-elections",children:"VRF-based random beacon"})," should be used."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"3"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.vrf_parameters.interval"})})," is the duration of an epoch.\nIt will be set to ",(0,i.jsx)(n.code,{children:"600"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"300"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.vrf_parameters.gas_costs.vrf_prove"})})," specifies the cost for\na VRF prove transaction.\nIt will be set to ",(0,i.jsx)(n.code,{children:"1000"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.params.pvss_parameters"})})," control the behavior of the\n",(0,i.jsx)(n.a,{href:"/adrs/0007-improved-random-beacon",children:"previous random beacon implementing a PVSS scheme"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Since PVSS is no longer supported, all its configuration options are removed\nas well."}),"\n",(0,i.jsx)(n.h3,{id:"governance-1",children:(0,i.jsx)(n.strong,{children:"Governance"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.stake_threshold"})})," is a new parameter specifying the\nsingle unified stake threshold representing the percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes\nin terms of total voting power for a governance proposal to pass.\nIt will be set to ",(0,i.jsx)(n.code,{children:"68"})," (i.e. 68%)."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.quorum"})})," is the minimum percentage of voting power that\nneeds to be cast on a proposal for the result to be valid."]}),"\n",(0,i.jsxs)(n.p,{children:["It will be removed since it is being replaced by the single\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.staking_threshold"})})," parameter."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.threshold"})})," is the minimum percentage of ",(0,i.jsx)(n.code,{children:"VoteYes"})," votes\nin order for a proposal to be accepted."]}),"\n",(0,i.jsxs)(n.p,{children:["It will be removed since it is being replaced by the single\n",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.staking_threshold"})})," parameter."]}),"\n",(0,i.jsxs)(n.p,{children:["This will be done automatically with the ",(0,i.jsx)(n.code,{children:"oasis-node debug fix-genesis"}),"\ncommand."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"consensus-1",children:(0,i.jsx)(n.strong,{children:"Consensus"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.state_checkpoint_interval"})})," parameter controls the\ninterval (in blocks) on which state checkpoints should be taken. It will be\nincreased from ",(0,i.jsx)(n.code,{children:"10000"})," to ",(0,i.jsx)(n.code,{children:"100000"})," to improve nodes' performance since\ncomputing checkpoints is I/O intensive."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2021-08-11-upgrade",children:"2021-08-11 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"8844."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2021-08-11 08:50 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"proposed-parameter-changes",children:"Proposed Parameter Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"Oasis Core 21.2.8"})," release contains the ",(0,i.jsxs)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.2.8/go/upgrade/migrations/consensus_parameters.go",children:[(0,i.jsx)(n.code,{children:"consensus-params-update-2021-08"})," upgrade handler"]})," which will update the following parameters in the consensus layer:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"staking.params.max_allowances"})," ** specifies the maximum number of allowances on account can store. It will be set to ",(0,i.jsx)(n.code,{children:"16"})," (default value is ",(0,i.jsx)(n.code,{children:"0"}),") to enable support for beneficiary allowances which are required to transfer tokens into a ParaTime. ",(0,i.jsx)(n.em,{children:"Note that this has already been the case on Testnet since the"})," ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#2021-06-23-upgrade",children:(0,i.jsx)(n.em,{children:"2021-06-23 upgrade"})}),(0,i.jsx)(n.em,{children:"."})]}),"\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"staking.params.gas_costs"})," ** , ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.gas_costs"})})," and ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.max_validators"})})," is the maximum size of the consensus committee (i.e. the validator set). It will be increased to",(0,i.jsx)(n.code,{children:"110"})," (it was set to ",(0,i.jsx)(n.code,{children:"100"})," previously)."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"instructions---before-upgrade-system-preparation",children:"Instructions - Before Upgrade System Preparation"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["This upgrade will upgrade ",(0,i.jsx)(n.strong,{children:"Oasis Core"})," to version ",(0,i.jsx)(n.strong,{children:"21.2.8"})," which:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Has a check that makes sure the ",(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#increase-file-descriptor-limit",children:"File Descriptor Limit"})," documentation page for details on how to increase the limit on your system."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Stop your node, replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"21.2.8"})," and restart your node."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.admonition,{title:"This is not dump & restore upgrade",type:"caution",children:(0,i.jsxs)(n.p,{children:["For this upgrade, ",(0,i.jsx)(n.strong,{children:"do NOT wipe state"}),"."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"21.2.8"}),".","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"Otherwise, you need to upgrade your node to Oasis Core 21.2.8 first and then restart it."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["If you use a process manager like ",(0,i.jsx)(n.a,{href:"https://github.com/systemd/systemd",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org",children:"Supervisor"}),", you can configure it to restart the Oasis Node automatically."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Testnet's genesis file and the genesis document's hash will remain the same."})}),"\n",(0,i.jsx)(n.h2,{id:"2021-06-23-upgrade",children:"2021-06-23 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"7553."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2021-06-23 14:30 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions-3",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["See ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#before-upgrade",children:"Before upgrade"})," section for required steps to be done before upgrade."]}),"\n",(0,i.jsxs)(n.li,{children:["(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,i.jsx)(n.strong,{children:"7553."})," See the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Governance documentation"})," for details on voting for proposals."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["The upgrade proposal contains the ",(0,i.jsx)(n.code,{children:'"consensus-max-allowances-16"'})," upgrade handler whose only purpose is to set the**",(0,i.jsx)(n.code,{children:"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."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Stop your node, replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.4",children:"21.2.4"})," and restart your node."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.admonition,{title:"This is not dump & restore upgrade",type:"caution",children:(0,i.jsxs)(n.p,{children:["For this upgrade, ",(0,i.jsx)(n.strong,{children:"do NOT wipe state"}),"."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.4",children:"21.2.4"}),".","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"Otherwise, you need to upgrade your node to Oasis Core 21.2.4 first and then restart it."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["If you use a process manager like ",(0,i.jsx)(n.a,{href:"https://github.com/systemd/systemd",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org",children:"Supervisor"}),", you can configure it to restart the Oasis Node automatically."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Testnet's genesis file and the genesis document's hash will remain the same."})}),"\n",(0,i.jsx)(n.h3,{id:"before-upgrade-1",children:"Before upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade will upgrade Oasis Core to version ",(0,i.jsx)(n.strong,{children:"21.2.x"})," which includes the new ",(0,i.jsx)(n.a,{href:"https://github.com/dgraph-io/badger",children:(0,i.jsx)(n.strong,{children:"BadgerDB"})})," ",(0,i.jsx)(n.strong,{children:"v3"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Upon startup, Oasis Node will start migrating all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})," files (Badger v2 files) and start writing Badger v3 DB to files with the ",(0,i.jsx)(n.code,{children:".migrate"})," suffix."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If the migration fails in the middle, Oasis Node will delete all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.migrate"})," files the next time it starts and start the migration (of the remaining ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})]}),"\n",(0,i.jsx)(n.p,{children:"files) again."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If the migration succeeds, Oasis Node will append the ",(0,i.jsx)(n.code,{children:".backup"})," suffix to all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})," files (Badger v2 files) and remove the ",(0,i.jsx)(n.code,{children:".migrate"})," suffix from all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.migrate"})," files (Badger v3 files)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"extra-storage-requirements",children:"Extra storage requirements"}),"\n",(0,i.jsx)(n.p,{children:"Your node will thus need to have extra storage space to store both the old and the new BadgerDB files."}),"\n",(0,i.jsxs)(n.p,{children:["To see estimate how much extra space the migration will need, use the ",(0,i.jsx)(n.code,{children:"du"})," tool:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"shopt -s globstar\ndu -h /**/*.badger.db | sort -h -r\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This is an example output from a Testnet node that uses ",(0,i.jsx)(n.code,{children:"/srv/oasis/node"})," as the ",(0,i.jsx)(n.code,{children:""}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"6.3G\t/srv/oasis/node/tendermint/data/blockstore.badger.db\n2.7G\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db\n1.4G\t/srv/oasis/node/tendermint/data/state.badger.db\n158M\t/srv/oasis/node/persistent-store.badger.db\n164K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints\n80K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334\n80K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334\n76K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334/fc815694d8219acb97fc0207a2159601df76df4d96802c147252ad0f2fd8a3f3\n76K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334/613e734e4ee4999bf71c3a190df13ea9d9b7d65af6a7fd8b2c9a477f2d052313\n68K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4424334/fc815694d8219acb97fc0207a2159601df76df4d96802c147252ad0f2fd8a3f3/chunks\n68K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4423334/613e734e4ee4999bf71c3a190df13ea9d9b7d65af6a7fd8b2c9a477f2d052313/chunks\n20K\t/srv/oasis/node/tendermint/data/evidence.badger.db\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["After you've confirmed your node is up and running, you can safely delete all the ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.backup"})," files."]})}),"\n",(0,i.jsx)(n.h4,{id:"extra-memory-requirements",children:"Extra memory requirements"}),"\n",(0,i.jsx)(n.p,{children:"BadgerDB v2 to v3 migration can use a number of Go routines to migrate different database files in parallel."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"badger.migrate.num_go_routines"}),") if your node has less than 8 GB of RAM."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"config.yml"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"# 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"})}),"\n",(0,i.jsx)(n.h2,{id:"2021-04-13-upgrade",children:"2021-04-13 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"5662."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2021-04-13 12:00 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions-4",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Runtime operators see ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#before-upgrade",children:"Before upgrade"})," section for required steps to be done before upgrade."]}),"\n",(0,i.jsxs)(n.li,{children:["(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,i.jsx)(n.strong,{children:"5662."})," See the ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"Governance documentation"})," for details on voting for proposals."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.p,{children:"Following steps should be performed only after the network has reached the upgrade network and has halted:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Download the Testnet genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2021-04-13",children:"Testnet 2021-04-13 release"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Testnet state at epoch ",(0,i.jsx)(n.strong,{children:"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."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Replace the old genesis file with the new Testnet genesis file."}),"\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1",children:"21.1"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"before-upgrade-2",children:"Before upgrade"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Runtime operators"})}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade requires a runtime storage node migration to be performed ",(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Backup your node's data directory"})}),(0,i.jsx)(n.p,{children:"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."}),(0,i.jsxs)(n.p,{children:["For example, to backup the ",(0,i.jsx)(n.code,{children:"/serverdir/node"})," directory using the rsync tool, run:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n"})})]}),"\n",(0,i.jsxs)(n.p,{children:["The storage database on all storage nodes needs to be migrated with the following command (using the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1",children:"21.1"})," binary):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n"})}),"\n",(0,i.jsx)(n.p,{children:"After the migration to v5 completes, you will see an output similar to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"...\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"})}),"\n",(0,i.jsxs)(n.p,{children:["Take note of the displayed ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h2,{id:"2021-03-24-upgrade",children:"2021-03-24 Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"5128."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Testnet network to reach this epoch at around 2021-03-24 11:30 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions-5",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(optional) To ensure your node will stop at epoch ",(0,i.jsx)(n.strong,{children:"5128"})," ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-create-proposal",children:"submit the following upgrade descriptor"})," at any time before the upgrade:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "name": "testnet-upgrade-2021-03-24",\n "method": "internal",\n "identifier": "testnet-upgrade-2021-03-24",\n "epoch": 5128\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Download the Testnet genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/testnet-artifacts/releases/tag/2021-03-24",children:"Testnet 2021-03-24 release"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Testnet state at epoch ",(0,i.jsx)(n.strong,{children:"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."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["(optional) Verify the provided Testnet genesis file by comparing it to network state dump. See instructions in the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades#verify-genesis",children:"Handling Network Upgrades"})," guide."]}),"\n",(0,i.jsx)(n.li,{children:"Replace the old genesis file with the new Testnet genesis file."}),"\n",(0,i.jsx)(n.li,{children:"Stop your node (if you haven't stopped it already by submitting the upgrade descriptor)."}),"\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.0.1",children:"21.0.1"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["Update your node's configuration or perform any additional needed steps as per ",(0,i.jsx)(n.a,{href:"#additional-steps",children:"Additional Steps"})," below."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For more detailed instructions, see the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades",children:"Handling Network Upgrades"})," guide."]})}),"\n",(0,i.jsx)(n.h3,{id:"additional-steps",children:"Additional steps"}),"\n",(0,i.jsxs)(n.p,{children:["Examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.0.1/CHANGELOG.md#210-2021-03-18",children:"Changelog"})," of the 21.0 release."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Runtime operators"})}),"\n",(0,i.jsxs)(n.p,{children:["In addition to some ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.0.1/CHANGELOG.md#configuration-changes",children:"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."]}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Backup your node's data directory"})}),(0,i.jsx)(n.p,{children:"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."}),(0,i.jsxs)(n.p,{children:["For example, to backup the ",(0,i.jsx)(n.code,{children:"/serverdir/node"})," directory using the rsync tool, run:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n"})})]}),"\n",(0,i.jsxs)(n.p,{children:["For this upgrade, the runtime node operators need to perform an additional migration of the storage nodes. ",(0,i.jsx)(n.strong,{children:"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):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Storage access policy changes"})}),(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"worker.storage.public_rpc.enabled"})," flag set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),(0,i.jsx)(n.p,{children:"Otherwise, external runtime clients wont be able to connect to any storage nodes."})]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var i=s(6540);const r={},t=i.createContext(r);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8fa03331.cbc6894d.js b/assets/js/8fa03331.cbc6894d.js new file mode 100644 index 0000000000..0a1fb2723c --- /dev/null +++ b/assets/js/8fa03331.cbc6894d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8104],{1960:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>l,frontMatter:()=>i,metadata:()=>d,toc:()=>h});var s=t(4848),o=t(8453);const i={},a="Using State Sync for Quick Bootstraping",d={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",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,unlisted:!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:172612742e4,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"}},r={},h=[{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 CLI",id:"oasis-cli",level:4}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"using-state-sync-for-quick-bootstraping",children:"Using State Sync for Quick Bootstraping"}),"\n",(0,s.jsxs)(n.p,{children:["The State Sync is a way to ",(0,s.jsx)(n.strong,{children:"quickly bootstrap"})," a ",(0,s.jsx)(n.strong,{children:"full Oasis node"})," (either a\n",(0,s.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"validator node"})," or a\n",(0,s.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"non-validator node"}),") by using the\n",(0,s.jsx)(n.a,{href:"https://docs.tendermint.com/main/tendermint-core/light-client.html",children:"Tendermint's Light Client protocol"}),". It allows one to initialize a node from a\ntrusted height, its corresponding block's header and a trusted validator set\n(given in the ",(0,s.jsx)(n.a,{href:"/node/genesis-doc",children:"genesis document"}),"). It does so by securely\nupdating the node's trusted state by requesting and verifying a minimal set of\ndata from the network's full nodes."]}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["If you have access to an Oasis node that is synced with the latest height,\nanother option to speed bootstraping a new Oasis node is to ",(0,s.jsx)(n.a,{href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",children:"copy state from one\nnode to the other"}),"."]})}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Tendermint's Light Client protocol requires at least 1 full node to be correct\nto be able to ",(0,s.jsx)(n.a,{href:"https://docs.tendermint.com/main/tendermint-core/light-client.html#where-to-obtain-trusted-height-hash",children:"detect and submit evidence for a light client attack"}),"."]})}),"\n",(0,s.jsxs)(n.p,{children:["To configure your node to use the state sync, amend your node's configuration\n(i.e. ",(0,s.jsx)(n.code,{children:"config.yml"}),") with (non-relevant fields omitted):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'... trimmed ...\n\n# Consensus.\nconsensus:\n\n ... trimmed ...\n\n # Enable consensus state sync (i.e. CometBFT light client sync).\n state_sync:\n enabled: true\n trust_height: {{ trusted_height }}\n trust_hash: "{{ trusted_height_hash }}"\n\n... trimmed ...\n\n'})}),"\n",(0,s.jsx)(n.p,{children:"and replace the following variables in the configuration snippet:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"{{ trusted_height }}"}),": Trusted height defines the height at which your node should trust the chain."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"{{ trusted_height_hash }}"}),": Trusted height hash defines the hash of the block header corresponding to the trusted height."]}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{type:"danger",children:[(0,s.jsxs)(n.p,{children:["You need to ",(0,s.jsx)(n.strong,{children:"delete any existing node state"})," (if it exists), otherwise the\nstate sync will be skipped. To do that, follow the ",(0,s.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wiping Node State"}),"\ninstructions."]}),(0,s.jsx)(n.p,{children:"If existing node state is found and state sync is skipped, you will see\nsomething like the following in your node's logs:"}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{"caller":"full.go:709","level":"info","module":"cometbft","msg":"state sync enabled","ts":"2023-11-16T20:06:58.56502593Z"}\n{"caller":"node.go:770","level":"info","module":"cometbft:base","msg":"Found local state with non-zero height, skipping state sync","ts":"2023-11-16T20:06:59.22387592Z"}\n'})})]}),"\n",(0,s.jsx)(n.h3,{id:"obtaining-trusted-height-and-hash",children:"Obtaining Trusted Height and Hash"}),"\n",(0,s.jsx)(n.p,{children:"To obtain the trusted height and the corresponding block header's hash, use one\nof the following options."}),"\n",(0,s.jsx)(n.h4,{id:"block-explorers",children:"Block Explorers"}),"\n",(0,s.jsxs)(n.p,{children:["Browse to one of our block explorers (e.g. ",(0,s.jsx)(n.a,{href:"https://www.oasisscan.com",children:"Oasis Scan"}),", ",(0,s.jsx)(n.a,{href:"https://oasismonitor.com",children:"Oasis Monitor"}),") and\nobtain the trusted height and hash there:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Obtain the current block height from the main page, e.g. 4819139."}),"\n",(0,s.jsxs)(n.li,{children:["Click on block height's number to view the block's details and obtain its\nhash, e.g. ",(0,s.jsx)(n.code,{children:"377520acaf7b8011b95686b548504a973aa414abba2db070b6a85725dec7bd21"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"a-trusted-node",children:"A Trusted Node"}),"\n",(0,s.jsx)(n.p,{children:"If you have an existing node that you trust, you can use its status output to\nretrieve the current block height and hash by running:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),"\n",(0,s.jsx)(n.p,{children:"This will give you output like the following (non-relevant fields omitted):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "software_version": "23.0.5",\n "identity": {\n ...\n },\n "consensus": {\n ...\n "latest_height": 18466200,\n "latest_hash": "9611c81c7e231a281f1de491047a833364f97c38142a80abd65ce41bce123378",\n "latest_time": "2023-11-27T08:31:15Z",\n "latest_epoch": 30760,\n ...\n },\n ...\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["the values you need are ",(0,s.jsx)(n.code,{children:"latest_height"})," and ",(0,s.jsx)(n.code,{children:"latest_hash"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"public-rosetta-gateway",children:"Public Rosetta Gateway"}),"\n",(0,s.jsx)(n.p,{children:"First obtain the network's Genesis document's hash (e.g. from the Networks Parameters Page):"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["mainnet: ",(0,s.jsx)(n.a,{href:"https://docs.oasis.io/node/mainnet/",children:"b11b369e0da5bb230b220127f5e7b242d385ef8c6f54906243f30af63c815535"})]}),"\n",(0,s.jsxs)(n.li,{children:["testnet: ",(0,s.jsx)(n.a,{href:"https://docs.oasis.io/node/testnet/",children:"0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Query our public Rosetta Gateway instance and obtain the trusted height and hash\nthere (replace the ",(0,s.jsx)(n.code,{children:""})," with the value obtained in the previous step):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'curl -X POST https://rosetta.oasis.io/api/block \\\n-H "Content-Type: application/json" \\\n-d \'{\n "network_identifier": {\n "blockchain": "Oasis",\n "network": ""\n },\n "block_identifier": {\n "index": 0\n }\n}\'\n'})}),"\n",(0,s.jsx)(n.p,{children:"This will give you output like the following (non-relevant fields omitted):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n\t"block": {\n\t\t"block_identifier": {\n\t\t\t"index": 16787439,\n\t\t\t"hash": "443b71d835dbae7ea6233b06280ab596287d5c45f88fa76a71bf6cc52366592e"\n\t\t},\n ...\n\t}\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["The values you need are ",(0,s.jsx)(n.code,{children:"index"})," and ",(0,s.jsx)(n.code,{children:"hash"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"oasis-cli",children:"Oasis CLI"}),"\n",(0,s.jsx)(n.p,{children:"Query our public Oasis node's endpoint using the Oasis CLI and obtain the\ntrusted height and hash there:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"oasis network status\n"})}),"\n",(0,s.jsx)(n.p,{children:"This will give you output like the following (non-relevant fields omitted):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "software_version": "23.0.5",\n "identity": {\n ...\n },\n "consensus": {\n ...\n "latest_height": 18466200,\n "latest_hash": "9611c81c7e231a281f1de491047a833364f97c38142a80abd65ce41bce123378",\n "latest_time": "2023-11-27T08:31:15Z",\n "latest_epoch": 30760,\n ...\n },\n ...\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["The values you need are ",(0,s.jsx)(n.code,{children:"latest_height"})," and ",(0,s.jsx)(n.code,{children:"latest_hash"})," ."]})]})}function l(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>d});var s=t(6540);const o={},i=s.createContext(o);function a(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/904dacd1.c439162d.js b/assets/js/904dacd1.c439162d.js new file mode 100644 index 0000000000..0bc20601b5 --- /dev/null +++ b/assets/js/904dacd1.c439162d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3993],{6082:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>g,frontMatter:()=>r,metadata:()=>t,toc:()=>c});var a=i(4848),s=i(8453);const r={},o="Signing Key Manager Policy",t={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,unlisted:!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:172612742e4,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"}},d={},c=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"signing-key-manager-policy",children:"Signing Key Manager Policy"}),"\n",(0,a.jsxs)(n.p,{children:["This guide will describe how to print and sign an Oasis ",(0,a.jsx)(n.a,{href:"/core/consensus/services/keymanager#policies",children:"key manager policy"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsx)(n.p,{children:"These instructions are only applicable if you are part of a key manager policy\nsigner set."})}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(n.h3,{id:"oasis-node-binary",children:"Oasis Node Binary"}),"\n",(0,a.jsxs)(n.p,{children:["Make sure you have followed the ",(0,a.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node binary installation guide"})," and have\nthe Oasis Node binary installed on your system."]}),"\n",(0,a.jsx)(n.h3,{id:"entity",children:"Entity"}),"\n",(0,a.jsx)(n.p,{children:"Similarly to other things, an entity's private key is used to sign a key manager\npolicy."}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/keymanager-paratime/blob/main/src/lib.rs",children:"its source\ncode"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsx)(n.p,{children:"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."})}),"\n",(0,a.jsxs)(n.p,{children:["To provision a new entity, follow the ",(0,a.jsx)(n.a,{href:"/node/run-your-node/validator-node#initialize-entity",children:"instructions in our Validator Node\nguide"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"caution",children:(0,a.jsx)(n.p,{children:"Currently, Ledger-based signers do not support signing key manager policies."})}),"\n",(0,a.jsxs)(n.admonition,{type:"danger",children:[(0,a.jsxs)(n.p,{children:["In case a file-based signer needs to be used, we strongly recommend using an\n",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Air_gap_(networking)",children:"offline/air-gapped machine"})," for this purpose and never exposing the entity's\nprivate key to an online machine."]}),(0,a.jsx)(n.p,{children:"Gaining access to the entity's private key can compromise the trusted key\nmanager policy signer set and hence the key manager itself."})]}),"\n",(0,a.jsx)(n.h2,{id:"define-variables",children:"Define Variables"}),"\n",(0,a.jsx)(n.p,{children:"For easier handling of key manager policy files, define the following variables:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"POLICY=path/to/policy.cbor\nKEY=path/to/entity/key.pem\nNAME=your_name\n"})}),"\n",(0,a.jsx)(n.h2,{id:"printing-a-policy",children:"Printing a Policy"}),"\n",(0,a.jsx)(n.p,{children:"To print and inspect a key manager policy, use the following command:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis-node keymanager verify_policy \\\n --keymanager.policy.file $POLICY \\\n --keymanager.policy.ignore.signature \\\n --verbose\n"})}),"\n",(0,a.jsx)(n.p,{children:"This should output something like the following:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",metastring:'title="Example of an actual Oasis Testnet Key Manager policy"',children:'{\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'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:'"serial"'})," key, e.g. ",(0,a.jsx)(n.code,{children:"8"}),", represents the key manager policy's serial number\nthat must increase with every update of the key manager policy."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:'"id"'})," key, e.g.\n",(0,a.jsx)(n.code,{children:'"4000000000000000000000000000000000000000000000004a1a53dff2ae482d"'}),", represents\nthe key manager ParaTime's runtime ID."]}),"\n",(0,a.jsxs)(n.p,{children:["The keys below ",(0,a.jsx)(n.code,{children:'"enclaves"'}),", e.g.\n",(0,a.jsx)(n.code,{children:'"ZhD5ufyc/MReZD1qMSKNCRxnkNiZ3BtxqcYdx4+M0N9AJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'}),"\nand ",(0,a.jsx)(n.code,{children:'"jTX8etUcGSQBq3C4WbLlexga7dhQFnwzSJOEmRCPvfRAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'}),",\nrepresent the identities of the key manager enclaves.\nEach key manager enclave ID is comprised of two parts: its ",(0,a.jsx)(n.code,{children:"MRENCLAVE"})," and its\n",(0,a.jsx)(n.code,{children:"MRSIGNER"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Each key manager enclave identity has two lists: ",(0,a.jsx)(n.code,{children:'"may_query"'})," and\n",(0,a.jsx)(n.code,{children:'"may_replicate"'}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Items in ",(0,a.jsx)(n.code,{children:'"may_query"'})," list, e.g.\n",(0,a.jsx)(n.code,{children:'"0000000000000000000000000000000000000000000000000000000000000000"'})," and\n",(0,a.jsx)(n.code,{children:'"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)."]}),"\n",(0,a.jsxs)(n.p,{children:["The items under runtime IDs of the ParaTimes, e.g.\n",(0,a.jsx)(n.code,{children:'"c0SidcKhBx3iuonmtXURnFB+qIVkg+nAiaAozAh16ltAJdq369ofvsxONjdgbgISFND0HG0EIv03iyqLiIGEWQ=="'}),"\nand\n",(0,a.jsx)(n.code,{children:'"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,a.jsx)(n.code,{children:"MRENCLAVE"})," and its ",(0,a.jsx)(n.code,{children:"MRSIGNER"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Items in ",(0,a.jsx)(n.code,{children:'"may_replicate"'})," list, e.g.\n",(0,a.jsx)(n.code,{children:'"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."]}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["To see what has changed between two key manager policies, diff the outputs\nof the ",(0,a.jsx)(n.code,{children:"oasis-node keymanager verify_policy"})," commands for the corresponding key\nmanager policy files."]})}),"\n",(0,a.jsx)(n.h2,{id:"signing-a-policy",children:"Signing a Policy"}),"\n",(0,a.jsx)(n.p,{children:"Once a key manager policy has been inspected, use the following command to sign\nit:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"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"})})]})}function g(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>t});var a=i(6540);const s={},r=a.createContext(s);function o(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/916ebde8.cbf10973.js b/assets/js/916ebde8.cbf10973.js new file mode 100644 index 0000000000..dde78a25b6 --- /dev/null +++ b/assets/js/916ebde8.cbf10973.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6627],{9625:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"ROSE Wallet","description":"The Oasis team developed two wallets specialized for the Oasis Network transactions. You can learn how to use them below.","slug":"general/manage-tokens/oasis-wallets","permalink":"/general/manage-tokens/oasis-wallets","sidebar":"general","navigation":{"previous":{"title":"Staking and Delegating","permalink":"/general/manage-tokens/staking-and-delegating"},"next":{"title":"Web","permalink":"/general/manage-tokens/oasis-wallets/web"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/917d8c1f.071bce35.js b/assets/js/917d8c1f.071bce35.js new file mode 100644 index 0000000000..ce63c83a6c --- /dev/null +++ b/assets/js/917d8c1f.071bce35.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6202],{103:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>d,toc:()=>l});var t=i(4848),o=i(8453);const s={},r="Single Validator Node Network",d={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,unlisted:!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:1715584634e3,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"}},a={},l=[{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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"single-validator-node-network",children:"Single Validator Node Network"}),"\n",(0,t.jsx)(n.p,{children:'It is possible to provision a local "network" consisting of a single validator\nnode. This may be useful for specific development use cases.'}),"\n",(0,t.jsxs)(n.p,{children:["Before proceeding, make sure to look at the ",(0,t.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"prerequisites"})," required for running\nan Oasis Core environment followed by ",(0,t.jsx)(n.a,{href:"/core/development-setup/building",children:"build instructions"})," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."]}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"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."})}),"\n",(0,t.jsx)(n.h2,{id:"provisioning-an-entity",children:"Provisioning an Entity"}),"\n",(0,t.jsxs)(n.p,{children:["To provision an ",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#entities-and-nodes",children:"entity"})," we first prepare an empty directory under\n",(0,t.jsx)(n.code,{children:"/path/to/entity"})," and then initialize the entity:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"mkdir -p /path/to/entity\ncd /path/to/entity\noasis-node registry entity init --signer.backend file --signer.dir .\n"})}),"\n",(0,t.jsx)(n.h2,{id:"provisioning-a-node",children:"Provisioning a Node"}),"\n",(0,t.jsxs)(n.p,{children:["To provision a ",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#entities-and-nodes",children:"node"})," we first prepare an empty directory under ",(0,t.jsx)(n.code,{children:"/path/to/node"}),"\nand the initialize the node. The node is provisioned as a validator."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsxs)(n.p,{children:["After the node is provisioned we proceed with updating the ",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#register-node",children:"entity whitelist"}),"\nso that the node will be able to register itself:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsx)(n.h2,{id:"creating-a-test-genesis-document",children:"Creating a Test Genesis Document"}),"\n",(0,t.jsx)(n.p,{children:'To create a test genesis document for your development "network" use the\nfollowing commands:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"This enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise."})}),"\n",(0,t.jsx)(n.h2,{id:"running-the-node",children:"Running the Node"}),"\n",(0,t.jsx)(n.p,{children:"To run the single validator node, use the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"This enables unsafe debug-only flags which must never be used in a\nproduction setting as they may result in node compromise."})}),"\n",(0,t.jsx)(n.h2,{id:"using-the-node-cli",children:"Using the Node CLI"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"oasis-node"})," exposes ",(0,t.jsx)(n.a,{href:"/core/oasis-node/rpc",children:"an RPC interface"})," via a UNIX socket located in its\ndata directory (e.g., under ",(0,t.jsx)(n.code,{children:"/path/to/node/internal.sock"}),"). To simplify the\nfollowing instructions set up an ",(0,t.jsx)(n.code,{children:"ADDR"})," environment variable pointing to it:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"export ADDR=unix:/path/to/node/internal.sock\n"})}),"\n",(0,t.jsx)(n.p,{children:"This can then be used to execute CLI commands against the running node (in a\nseparate terminal). For example to show all registered entities:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"oasis-node registry entity list -a $ADDR -v\n"})}),"\n",(0,t.jsx)(n.p,{children:"Giving output similar to:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'{"v":1,"id":"UcxpyD0kSo/5keRqv8pLypM/Mg5S5iULRbt7Uf73vKQ=","nodes":["jo+quvaFYAP4Chyf1PRqCZZObqpDeJCxfBzTyghiXxs="]}\n{"v":1,"id":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","allow_entity_signed_nodes":true}\n'})}),"\n",(0,t.jsx)(n.p,{children:"Or getting a list of all staking accounts:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"oasis-node stake list -a $ADDR\n"})}),"\n",(0,t.jsx)(n.p,{children:"Giving output similar to:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"oasis1qzzd6khm3acqskpxlk9vd5044cmmcce78y5l6000\noasis1qz3xllj0kktskjzlk0qacadgwpfe8v7sy5kztvly\noasis1qrh4wqfknrlvv7whjm7mjsjlvka2h35ply289pp2\n"})})]})}function p(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>d});var t=i(6540);const o={},s=t.createContext(o);function r(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/919a9404.cc638059.js b/assets/js/919a9404.cc638059.js new file mode 100644 index 0000000000..03e5d03d40 --- /dev/null +++ b/assets/js/919a9404.cc638059.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[64],{6075:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>a});var s=i(4848),t=i(8453);const r={},o="ADR 0005: Runtime Compute Node Slashing",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0005-runtime-compute-slashing.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},d={},a=[{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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-0005-runtime-compute-node-slashing",children:"ADR 0005: Runtime Compute Node Slashing"}),"\n",(0,s.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,s.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"2020-10-14: Evidence expiry, duplicate evidence detection"}),"\n",(0,s.jsx)(n.li,{children:"2020-09-28: Initial draft"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Accepted"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.p,{children:"This proposal introduces a slashing mechanism for punishing misbehaving compute\nnodes as follows:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Per-runtime configurable slashing parameters"})," are added to the runtime\ndescriptor similar to the global slashing configuration that currently exists\nin the staking service."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"runtime-descriptor",children:"Runtime Descriptor"}),"\n",(0,s.jsxs)(n.p,{children:["This proposal updates the runtime staking parameters (stored under the ",(0,s.jsx)(n.code,{children:"staking"}),"\nfield of the runtime descriptor) as follows:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,s.jsx)(n.h3,{id:"slashing-parameters",children:"Slashing Parameters"}),"\n",(0,s.jsxs)(n.p,{children:["The slash reason type in the staking module is changed from ",(0,s.jsx)(n.code,{children:"int"})," to ",(0,s.jsx)(n.code,{children:"uint8"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"The slash reason definitions are updated as follows:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-golang",children:"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"})}),"\n",(0,s.jsx)(n.h3,{id:"executor-commitments",children:"Executor Commitments"}),"\n",(0,s.jsxs)(n.p,{children:["The executor commitment body structures are updated to make certain fields\noptional and to introduce the ",(0,s.jsx)(n.code,{children:"failure"})," field as follows:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,s.jsxs)(n.p,{children:["The notion of an ",(0,s.jsx)(n.em,{children:"failure-indicating"})," executor commitment is introduced as being\nan executor commitment with the following field values:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"header.round"}),", ",(0,s.jsx)(n.code,{children:"header.previous_hash"}),", ",(0,s.jsx)(n.code,{children:"txn_sched_sig"}),", ",(0,s.jsx)(n.code,{children:"input_root"})," and\n",(0,s.jsx)(n.code,{children:"input_storage_sigs"})," are set as for usual commitments (e.g., they must be\nvalid)."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"All other fields must be omitted or set to nil."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"root-hash-commitment-processing",children:"Root Hash Commitment Processing"}),"\n",(0,s.jsx)(n.p,{children:"The processing of executor commitments by the commitment pool is modified as\nfollows:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Adding new commitments (",(0,s.jsx)(n.code,{children:"AddExecutorCommitment"}),")"]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["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,s.jsx)(n.em,{children:"Evidence"})," subsection below."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Discrepancy detection (",(0,s.jsx)(n.code,{children:"DetectDiscrepancy"}),")"]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"If any executor commitment indicates failure, the discrepancy detection\nprocess signals a discrepancy (which implies that discrepancy resolution is\ntriggered)."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Discrepancy resolution (",(0,s.jsx)(n.code,{children:"ResolveDiscrepancy"}),")"]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["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,s.jsx)(n.code,{children:"SlashRuntimeIncorrectResults"})," reason)."]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.p,{children:"Any slashing instructions related to freezing nodes are currently ignored."}),"\n",(0,s.jsx)(n.h3,{id:"state",children:"State"}),"\n",(0,s.jsx)(n.p,{children:"This proposal introduces/updates the following consensus state in the roothash\nmodule:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["List of past valid evidence (",(0,s.jsx)(n.code,{children:"0x24"}),")"]})}),"\n",(0,s.jsx)(n.p,{children:"A hash uniquely identifying the evidence is stored for each successfully\nprocessed evidence that has not yet expired using the following key format:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"0x24 \n"})}),"\n",(0,s.jsx)(n.p,{children:"The value is empty as we only need to detect duplicate evidence."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"transaction-methods",children:"Transaction Methods"}),"\n",(0,s.jsx)(n.p,{children:"This proposal updates the following transaction methods in the roothash module:"}),"\n",(0,s.jsx)(n.h4,{id:"evidence",children:"Evidence"}),"\n",(0,s.jsx)(n.p,{children:"The evidence method allows anyone to submit evidence of runtime node\nmisbehavior."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"roothash.Evidence\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Body:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"id"})," specifies the runtime identifier of a runtime this evidence is for."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"equivocation_executor"})," (optional) specifies evidence of an executor node\nequivocating when signing commitments."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"equivocation_batch"})," (optional) specifies evidence of an executor node\nequivocating when signing proposed batches."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["If no evidence is specified (e.g., all evidence fields are ",(0,s.jsx)(n.code,{children:"nil"}),") the method\ncall is invalid and must fail with ",(0,s.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"For all kinds of evidence, the following steps are performed to verify evidence\nvalidity:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Current state for the runtime identified by ",(0,s.jsx)(n.code,{children:"id"})," is fetched. If the runtime\ndoes not exist, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If no slashing instructions for ",(0,s.jsx)(n.code,{children:"SlashRuntimeEquivocation"})," are configured for\nthe given runtime, there is no point in collecting evidence so the method call\nmust fail with ",(0,s.jsx)(n.code,{children:"ErrRuntimeDoesNotSlash"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["When processing ",(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"EquivocationExecutor"})})," evidence, the following steps are\nperformed to verify evidence validity:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"header.round"})," fields of both commitments are compared. If they are not the\nsame, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Both executor commitments are checked for basic validity. If either is\ninvalid, the evidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"header.previous_hash"}),", ",(0,s.jsx)(n.code,{children:"header.io_root"}),", ",(0,s.jsx)(n.code,{children:"header.state_root"})," and\n",(0,s.jsx)(n.code,{children:"header.messages_hash"})," fields of both commitments are compared. If they are\nthe same, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The failure indication fields of both commitments are compared. If they are\nthe same, the evidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"header.round"})," field is compared with the runtime's current state. If it is\nmore than ",(0,s.jsx)(n.code,{children:"max_evidence_age"})," (consensus parameter) rounds behind, the evidence\nis invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Public keys of signers of both commitments are compared. If they are not the\nsame, the evidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Signatures of both commitments are verified. If either is invalid, the\nevidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Otherwise the evidence is valid."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["When processing ",(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"EquivocationBatch"})})," evidence, the following steps are\nperformed to verify evidence validity:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"header.round"})," fields of both proposed batches are compared. If they are\nnot the same, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"header"})," fields of both proposed batches are checked for basic validity.\nIf any is invalid, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"io_root"})," fields of both proposed batches are compared. If they are the\nsame, the evidence is invalid."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Public keys of signers of both commitments are compared. If they are not the\nsame, the evidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Signatures of both proposed batches are validated. If either is invalid, the\nevidence is invalid."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Otherwise the evidence is valid."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"For all kinds of valid evidence, the following steps are performed after\nvalidation:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["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,s.jsx)(n.em,{children:"list of past valid\nevidence"}),". If evidence already exists there, the method fails with\n",(0,s.jsx)(n.code,{children:"ErrDuplicateEvidence"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["The valid evidence hash is stored in the ",(0,s.jsx)(n.em,{children:"list of past valid evidence"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["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,s.jsx)(n.code,{children:"SlashRuntimeEquivocation"})," reason."]}),"\n",(0,s.jsx)(n.p,{children:"Any slashing instructions related to freezing nodes are currently ignored."}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h3,{id:"evidence-expiry",children:"Evidence Expiry"}),"\n",(0,s.jsxs)(n.p,{children:["On each epoch transition, for each runtime, expired evidence (as defined by the\n",(0,s.jsx)(n.code,{children:"max_evidence_age"})," and the current runtime's round) must be pruned from the\n",(0,s.jsx)(n.em,{children:"list of past valid evidence"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"evidence-collection",children:"Evidence Collection"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,s.jsx)(n.h4,{id:"roothash",children:"Roothash"}),"\n",(0,s.jsx)(n.p,{children:"This proposal introduces the following new consensus parameters in the roothash\nmodule:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"max_evidence_age"})," (uint64) specifies the maximum age of submitted evidence in\nthe number of rounds."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Compute nodes can be disincentivized to submit incorrect results by runtimes\nconfiguring slashing parameters."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Checking for duplicate evidence requires additional state in the consensus\nlayer to store the evidence hashes (73 bytes per evidence)."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Expiring old evidence requires additional per-runtime state lookups and\nupdates that happen on each epoch transition."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"This proposal does not introduce any kind of slashing for liveness."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"This proposal does not introduce freezing misbehaving nodes."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/2078",children:"oasis-core#2078"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>c});var s=i(6540);const t={},r=s.createContext(t);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/94ed66ea.2b02e784.js b/assets/js/94ed66ea.2b02e784.js new file mode 100644 index 0000000000..67e9f3796d --- /dev/null +++ b/assets/js/94ed66ea.2b02e784.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6205],{2960:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>i,default:()=>l,frontMatter:()=>c,metadata:()=>r,toc:()=>d});var o=t(4848),n=t(8453);const c={},i="Committee Scheduler",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/scheduler.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Registry",permalink:"/core/consensus/services/registry"},next:{title:"Governance",permalink:"/core/consensus/services/governance"}},a={},d=[{value:"Events",id:"events",level:2},{value:"Validator Committee",id:"validator-committee",level:2}];function h(e){const s={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",p:"p",...(0,n.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.h1,{id:"committee-scheduler",children:"Committee Scheduler"}),"\n",(0,o.jsxs)(s.p,{children:["The committee scheduler service is responsible for periodically scheduling all\ncommittees (validator, compute, key manager) based on ",(0,o.jsx)(s.a,{href:"/core/consensus/services/epochtime",children:"epoch-based time"})," and\nentropy provided by the ",(0,o.jsx)(s.a,{href:"/core/consensus/services/beacon",children:"random beacon"}),"."]}),"\n",(0,o.jsxs)(s.p,{children:["The service interface definition lives in ",(0,o.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/scheduler/api",children:(0,o.jsx)(s.code,{children:"go/scheduler/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,o.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/scheduler/api?tab=doc",children:"consensus service API documentation"}),"."]}),"\n",(0,o.jsx)(s.h2,{id:"events",children:"Events"}),"\n",(0,o.jsx)(s.h2,{id:"validator-committee",children:"Validator Committee"}),"\n",(0,o.jsxs)(s.p,{children:["To schedule the validator committee, the committee scheduler selects among\nnodes ",(0,o.jsx)(s.a,{href:"/core/consensus/services/registry#register-node",children:"registered"})," with the ",(0,o.jsx)(s.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#RoleValidator",children:(0,o.jsx)(s.code,{children:"RoleValidator"})})," role.\nEach node's entity must have an ",(0,o.jsx)(s.a,{href:"/core/consensus/services/staking#escrow",children:"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."]}),"\n",(0,o.jsxs)(s.p,{children:["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,o.jsx)(s.code,{children:".scheduler.params.max_validators"})," (consult the ",(0,o.jsx)(s.a,{href:"/node/genesis-doc#committee-scheduler",children:"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."]}),"\n",(0,o.jsxs)(s.p,{children:["When the committee scheduler schedules the validator committee, it additionally\nassigns each member a ",(0,o.jsx)(s.em,{children:"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."]}),"\n",(0,o.jsxs)(s.p,{children:["The committee scheduler assigns a validator's voting power proportional to its\nentity's ",(0,o.jsx)(s.a,{href:"/core/consensus/services/staking#escrow",children:"escrow account balance"}),"."]})]})}function l(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>i,x:()=>r});var o=t(6540);const n={},c=o.createContext(n);function i(e){const s=o.useContext(c);return o.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),o.createElement(c.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/977c4838.af586900.js b/assets/js/977c4838.af586900.js new file mode 100644 index 0000000000..303fd09a8b --- /dev/null +++ b/assets/js/977c4838.af586900.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9628],{7715:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>d,default:()=>p,frontMatter:()=>a,metadata:()=>c,toc:()=>u});var r=t(4848),o=t(8453),i=t(2550),s=t(6116);const a={},d="Run Node",c={id:"node/README",title:"Run Node",description:"Welcome! This documentation is designed to provide you with a comprehensive",source:"@site/docs/node/README.mdx",sourceDirName:"node",slug:"/node/",permalink:"/node/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",next:{title:"Mainnet",permalink:"/node/mainnet/"}},l={},u=[{value:"Validator and ParaTime nodes",id:"validator-and-paratime-nodes",level:2},{value:"DApp Developers",id:"dapp-developers",level:2},{value:"Quick Navigation",id:"quick-navigation",level:2}];function h(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"run-node",children:"Run Node"}),"\n",(0,r.jsx)(n.p,{children:"Welcome! This documentation is designed to provide you with a comprehensive\nunderstanding and step-by-step guidance for becoming a node operator within the\nOasis Network."}),"\n",(0,r.jsx)(n.p,{children:"Embark on your journey by setting up a node on the Testnet. The Testnet serves\nas an experimental sandbox, offering a safe environment for learning and\nexperimentation, free from the risks associated with real token loss."}),"\n",(0,r.jsxs)(n.p,{children:["For any queries or support related to node operation, our team and community\nmembers are readily available on ",(0,r.jsx)(n.a,{href:"https://oasis.io/discord",children:"Discord"})," to assist you."]}),"\n",(0,r.jsx)(n.h2,{id:"validator-and-paratime-nodes",children:"Validator and ParaTime nodes"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network"})," consists of the consensus layer and ParaTimes. Consensus and\nParaTime nodes can be operated by anyone."]}),"\n",(0,r.jsxs)(n.p,{children:["To run a ",(0,r.jsx)(n.strong,{children:"validator node"}),", make sure your system meets the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/prerequisites/hardware-recommendations",children:"hardware"})," and the\n",(0,r.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration",children:"system"})," prerequisites and has ",(0,r.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node"})," installed."]}),"\n",(0,r.jsxs)(n.p,{children:["Then proceed by following the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"Run a Validator Node"})," guide to:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Create your entity."}),"\n",(0,r.jsx)(n.li,{children:"Initialize and configure your node."}),"\n",(0,r.jsx)(n.li,{children:"Put enough stake in your escrow account."}),"\n",(0,r.jsx)(n.li,{children:"Register your entity on the network."}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["To run a ",(0,r.jsx)(n.strong,{children:"ParaTime node"})," make sure to first set up a validator node. Then,\nset up a ",(0,r.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",children:"trusted execution environment (TEE)"}),", if you want to run confidential\nParaTimes. Afterwards, proceed to the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"Run a ParaTime node"})," chapter."]}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["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,r.jsx)(n.a,{href:"https://www.oasisscan.com/validators",children:"Oasis Scan"}),"."]})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsx)(n.p,{children:"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."})}),"\n",(0,r.jsx)(n.h2,{id:"dapp-developers",children:"DApp Developers"}),"\n",(0,r.jsxs)(n.p,{children:["If you are ",(0,r.jsx)(n.strong,{children:"building a service"})," on top of the Oasis Network, you will simply\nwant to set up your own ",(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Non-validator node"})})," and (optionally) a\n",(0,r.jsx)(n.strong,{children:(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"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."]}),"\n",(0,r.jsx)(n.h2,{id:"quick-navigation",children:"Quick Navigation"}),"\n",(0,r.jsx)(i.A,{items:[(0,s.$)("/node/mainnet/"),(0,s.$)("/node/testnet/"),(0,s.$)("/node/run-your-node/prerequisites"),(0,s.$)("/node/run-your-node/validator-node"),(0,s.$)("/node/run-your-node/paratime-node"),(0,s.$)("/node/run-your-node/paratime-client-node"),(0,s.$)("/node/web3"),(0,s.$)("/node/grpc")]})]})}function p(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>x});t(6540);var r=t(4164),o=t(8774),i=t(4142),s=t(5846),a=t(6654),d=t(1312),c=t(1107);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=t(4848);function h(e){let{href:n,children:t}=e;return(0,u.jsx)(o.A,{href:n,className:(0,r.A)("card padding--lg",l.cardContainer),children:t})}function p(e){let{href:n,icon:t,title:o,description:i}=e;return(0,u.jsxs)(h,{href:n,children:[(0,u.jsxs)(c.A,{as:"h2",className:(0,r.A)("text--truncate",l.cardTitle),title:o,children:[t," ",o]}),i&&(0,u.jsx)("p",{className:(0,r.A)("text--truncate",l.cardDescription),title:i,children:i})]})}function m(e){let{item:n}=e;const t=(0,i.Nr)(n),r=function(){const{selectMessage:e}=(0,s.W)();return n=>e(n,(0,d.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,u.jsx)(p,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??r(n.items.length)}):null}function f(e){let{item:n}=e;const t=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.cC)(n.docId??void 0);return(0,u.jsx)(p,{href:n.href,icon:t,title:n.label,description:n.description??r?.description})}function x(e){let{item:n}=e;switch(n.type){case"link":return(0,u.jsx)(f,{item:n});case"category":return(0,u.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},2550:(e,n,t)=>{t.d(n,{A:()=>d});t(6540);var r=t(4164),o=t(4142),i=t(5965),s=t(4848);function a(e){let{className:n}=e;const t=(0,o.$S)();return(0,s.jsx)(d,{items:t.items,className:n})}function d(e){const{items:n,className:t}=e;if(!n)return(0,s.jsx)(a,{...e});const d=(0,o.d1)(n);return(0,s.jsx)("section",{className:(0,r.A)("row",t),children:d.map(((e,n)=>(0,s.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,s.jsx)(i.A,{item:e})},n)))})}},5846:(e,n,t)=>{t.d(n,{W:()=>c});var r=t(6540),o=t(4586);const i=["zero","one","two","few","many","other"];function s(e){return i.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:s(["one","other"]),select:e=>1===e?"one":"other"};function d(){const{i18n:{currentLocale:e}}=(0,o.A)();return(0,r.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:s(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function c(){const e=d();return{selectMessage:(n,t)=>function(e,n,t){const r=e.split("|");if(1===r.length)return r[0];r.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const o=t.select(n),i=t.pluralForms.indexOf(o);return r[Math.min(i,r.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>i});var r=t(2252);function o(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&o(n.items)}}function i(e){const n=(0,r.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)o(n.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]}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>a});var r=t(6540);const o={},i=r.createContext(o);function s(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9795c642.2ecf17d0.js b/assets/js/9795c642.2ecf17d0.js new file mode 100644 index 0000000000..10a191a59f --- /dev/null +++ b/assets/js/9795c642.2ecf17d0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7444],{8339:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var t=o(4848),s=o(8453);const i={},r="Consensus Validator Node",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/run-node/validator-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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}];function c(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"consensus-validator-node",children:"Consensus Validator Node"}),"\n",(0,t.jsx)(n.p,{children:"This guide provides an overview of the technical setup and stake requirements to\nbecome a validator on the consensus layer of the Oasis Network."}),"\n",(0,t.jsx)(n.h2,{id:"about-oasis-network",children:"About Oasis Network"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network"}),"'s consensus Layer is a decentralised set of validator nodes that maintain a proof-of-stake blockchain."]}),"\n",(0,t.jsx)(n.p,{children:"Hence, it needs a set of distributed node operators that run different nodes (including validator nodes)."}),"\n",(0,t.jsx)(n.h2,{id:"technical-setup",children:"Technical setup"}),"\n",(0,t.jsxs)(n.p,{children:["Make sure your system meets the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/hardware-recommendations",children:"Hardware"})," prerequisites and has ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node"})," installed."]}),"\n",(0,t.jsxs)(n.p,{children:["Then proceed by following the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"Run a Validator Node"})," guide to:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Create your entity."}),"\n",(0,t.jsx)(n.li,{children:"Initialize and configure your node."}),"\n",(0,t.jsx)(n.li,{children:"Put enough stake in your escrow account."}),"\n",(0,t.jsx)(n.li,{children:"Register your entity on the network."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"stake-requirements",children:"Stake requirements"}),"\n",(0,t.jsx)(n.p,{children:"To become a validator on the Oasis Network, you need to have enough tokens staked in your escrow account."}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["For more information about obtaining information on your entity's account, see the ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/account#show",children:"Account Get Info"})," doc."]})}),"\n",(0,t.jsx)(n.p,{children:"Currently, you should have:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["100 ROSE staked for your entity's registration since that is the ",(0,t.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"current entity's staking threshold"}),"."]}),"\n",(0,t.jsxs)(n.li,{children:["100 ROSE staked for your validator node's registration since that is the ",(0,t.jsx)(n.a,{href:"/node/genesis-doc#staking-thresholds",children:"current validator node's staking threshold"}),"."]}),"\n",(0,t.jsx)(n.li,{children:"Enough ROSE staked to be in the top 120 entities (by stake) so your validator will be elected into the consensus committee."}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["The size of the consensus committee (i.e. the validator set) is configured by the ",(0,t.jsxs)(n.a,{href:"/node/genesis-doc#consensus",children:[(0,t.jsx)(n.strong,{children:"max_validators"})," consensus parameter"]}),"."]})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["To determine if you are eligible to receive a delegation from the Oasis Protocol Foundation, see the ",(0,t.jsx)(n.a,{href:"/get-involved/delegation-policy",children:"Delegation Policy"})," document."]})})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/994ee662.99189101.js b/assets/js/994ee662.99189101.js new file mode 100644 index 0000000000..760f8956d6 --- /dev/null +++ b/assets/js/994ee662.99189101.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2625],{3796:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});var o=t(4848),s=t(8453);const a={},i="Staking and Delegating",r={id:"general/manage-tokens/staking-and-delegating",title:"Staking and Delegating",description:"The Oasis Network is a proof-of-stake network. This means that the voting",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/staking-and-delegating.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Terminology",permalink:"/general/manage-tokens/terminology"},next:{title:"ROSE Wallet",permalink:"/general/manage-tokens/oasis-wallets"}},l={},d=[{value:"How to Delegate?",id:"how-to-delegate",level:2},{value:"Become a validator yourself?",id:"become-a-validator-yourself",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"staking-and-delegating",children:"Staking and Delegating"}),"\n",(0,o.jsxs)(n.p,{children:["The Oasis Network is a proof-of-stake network. This means that the ",(0,o.jsx)(n.strong,{children:"voting\npower of an entity in the network is determined by the amount of tokens staked\nto that entity"}),". For example, this amount determines, how frequent the\nvalidator will be elected to propose a new block. Each epoch, the staking\nreward is distributed among the validators based on the amount of ",(0,o.jsx)(n.em,{children:"staked"}),"\ntokens. You can check out the ",(0,o.jsx)(n.strong,{children:"current staking rewards"})," in the ",(0,o.jsx)(n.a,{href:"/general/oasis-network/token-metrics-and-distribution#staking-incentives",children:"Token metrics\nchapter"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["But it's not just the validators that can stake. You can ",(0,o.jsx)(n.em,{children:"delegate"})," your tokens\nto a validator and earn ",(0,o.jsx)(n.strong,{children:"passive income"}),", when the validator receives the\nstaking reward. Of course, the validator may take their cut (the ",(0,o.jsx)(n.em,{children:"commission\nfee"}),") for running the validator node hardware, but in essence staking ",(0,o.jsx)(n.strong,{children:"improves\nthe security of the network"})," because paying the commission fee rewards good\nvalidators and expels the malicious ones. Keep in mind that the validator's\nmisbehavior ",(0,o.jsxs)(n.strong,{children:["will result in ",(0,o.jsx)(n.em,{children:"slashing"})]})," or even ",(0,o.jsx)(n.strong,{children:"losing a portion of the\nstaked tokens"}),"!"]}),"\n",(0,o.jsxs)(n.p,{children:["When you undelegate your tokens, you will need to wait the ",(0,o.jsx)(n.strong,{children:"debonding period"}),"\nto pass in which you will not earn any rewards. Currently, this period is ",(0,o.jsx)(n.strong,{children:"336\nepochs (~14 days)"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"how-to-delegate",children:"How to Delegate?"}),"\n",(0,o.jsxs)(n.p,{children:["Staking can only be performed on the ",(0,o.jsx)(n.strong,{children:"consensus layer"}),". Currently, the Oasis\nWallet - Web and the Browser extension require that you delegate your tokens\nexplicitly from your consensus account. The Oasis CLI and some dApps running in\nParaTimes also allow you to implicitly delegate tokens from your ParaTime\naccount."]}),"\n",(0,o.jsxs)(n.p,{children:["Check out the current validator set, their escrow of staked tokens, the\ncommission rate, and the availability in the ",(0,o.jsx)(n.a,{href:"https://www.oasisscan.com/validators",children:"Oasis Scan explorer"}),"."]}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"The validator set in the morning of March 29, 2024",src:t(6744).A+"",width:"1273",height:"957"})}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsx)(n.p,{children:"Some validators prefer anonymity and they do not list their name or any contact\ninformation. In this case only their entity's Oasis address is shown."})}),"\n",(0,o.jsxs)(n.p,{children:["Regardless of which validator you pick, ",(0,o.jsx)(n.strong,{children:"you will earn the same reward as long\nas the validator is online, proposes and signs valid blocks"}),". We recommend\nthat you consider delegating your tokens to the ones without the largest\ndelegations since this ",(0,o.jsx)(n.strong,{children:"concentrates the voting power and potentially reduces\nthe network security"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"Once you decided which validator you want to delegate to, consult the following\nsections based on your wallet for a step-by-step walkthrough:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#stake",children:"ROSE Wallet - Web"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/browser-extension#stake",children:"ROSE Wallet - Browser Extension"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/general/manage-tokens/cli/account#delegate",children:"Oasis CLI"})}),"\n"]}),"\n",(0,o.jsxs)(n.admonition,{title:"Staking your ROSE is a different transaction than sending them!",type:"danger",children:[(0,o.jsxs)(n.p,{children:["When you stake your tokens (the ",(0,o.jsx)(n.code,{children:"staking.Escrow"})," transaction), you can reclaim\nthem at any time. Sending your tokens (the ",(0,o.jsx)(n.code,{children:"staking.Transfer"})," transaction) on the\nother hand means that the ",(0,o.jsx)(n.strong,{children:"receiver will own the tokens and there is no way of\nretrieving that tokens back by yourself"}),"."]}),(0,o.jsx)(n.p,{children:"If you happen to send your tokens to the validator instead of staking them, try\ncontacting the validator via email or other channels listed on the block\nexplorers and kindly ask them to send the tokens back to you. Know that it is\ncompletely up to them to send the tokens back and there is no other mechanism of\ndoing it."})]}),"\n",(0,o.jsxs)(n.p,{children:["After you delegated your tokens, ",(0,o.jsx)(n.a,{href:"/general/manage-tokens/#check-your-account",children:"check your account balance"}),".\nIf the Escrow is correct, then congratulations, your tokens are successfully\nstaked!"]}),"\n",(0,o.jsx)(n.admonition,{type:"tip",children:(0,o.jsx)(n.p,{children:"Some custody providers may also allow delegation of your tokens. Check out the\n[custody providers][custody-providers] chapter to learn more."})}),"\n",(0,o.jsx)(n.h2,{id:"become-a-validator-yourself",children:"Become a validator yourself?"}),"\n",(0,o.jsxs)(n.p,{children:["If you find the validator commission rates too high, you may be interested in\n",(0,o.jsx)(n.strong,{children:"running your own node and become a validator"}),". You can get started\n",(0,o.jsx)(n.a,{href:"/node/",children:"here"}),". Be sure to\n",(0,o.jsxs)(n.a,{href:"/get-involved/",children:["join the ",(0,o.jsx)(n.strong,{children:"#node-operators"})," channel on Discord and sign up for the node operator mailing list"]}),"!"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},6744:(e,n,t)=>{t.d(n,{A:()=>o});const o=t.p+"assets/images/oasisscan_validators-179f0f40e82465fad25d3d9fa6bd87c5.png"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>r});var o=t(6540);const s={},a=o.createContext(s);function i(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9ba66431.c675478a.js b/assets/js/9ba66431.c675478a.js new file mode 100644 index 0000000000..e7bcff57a7 --- /dev/null +++ b/assets/js/9ba66431.c675478a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1117],{9328:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>d});var i=s(4848),c=s(8453);const r={},o="Staking",t={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/staking.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Random Beacon",permalink:"/core/consensus/services/beacon"},next:{title:"Registry",permalink:"/core/consensus/services/registry"}},a={},d=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,c.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"staking",children:"Staking"}),"\n",(0,i.jsx)(n.p,{children:"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)."}),"\n",(0,i.jsxs)(n.p,{children:["The service interface definition lives in ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/staking/api/api.go",children:(0,i.jsx)(n.code,{children:"go/staking/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc",children:"consensus service API documentation"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"tokens-and-base-units",children:"Tokens and Base Units"}),"\n",(0,i.jsx)(n.p,{children:"Stake amounts can be denominated in tokens and base units."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Genesis",children:[(0,i.jsx)(n.code,{children:"Genesis"}),"'\n",(0,i.jsx)(n.code,{children:"TokenSymbol"})," field"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Another ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#Genesis",children:[(0,i.jsx)(n.code,{children:"Genesis"}),"' field, ",(0,i.jsx)(n.code,{children:"TokenValueExponent"})]}),", defines the\ntoken's value base-10 exponent.\nFor example, if ",(0,i.jsx)(n.code,{children:"TokenValueExponent"})," is 6, then 1 token equals 10^6 (i.e. one\nmillion) base units."]}),"\n",(0,i.jsx)(n.p,{children:"Internally, base units are used for all stake calculation and processing."}),"\n",(0,i.jsx)(n.h2,{id:"accounts",children:"Accounts"}),"\n",(0,i.jsx)(n.p,{children:"A staking account is an entry in the staking ledger. It can hold both general\nand escrow accounts."}),"\n",(0,i.jsx)(n.p,{children:"Each staking account has an address which is derived from the corresponding\npublic key as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"[ 1 byte ][ first 20 bytes of SHA512-256( || || ) ]\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Where ",(0,i.jsx)(n.code,{children:""})," and ",(0,i.jsx)(n.code,{children:""})," represent the staking account\naddress' context version and identifier and ",(0,i.jsx)(n.code,{children:""})," represents the data\nspecific to the address kind."]}),"\n",(0,i.jsx)(n.p,{children:"There are two kinds of accounts:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"User accounts linked to a specific public key."}),"\n",(0,i.jsxs)(n.li,{children:["Runtime accounts linked to a specific ",(0,i.jsx)(n.a,{href:"/core/runtime/identifiers",children:"runtime identifier"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Addresses use ",(0,i.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32",children:"Bech32 encoding"})," for text serialization with ",(0,i.jsx)(n.code,{children:"oasis"})," as its human\nreadable part (HRP) prefix (for both kinds of accounts)."]}),"\n",(0,i.jsx)(n.h3,{id:"user-accounts",children:"User Accounts"}),"\n",(0,i.jsxs)(n.p,{children:["In case of user accounts, the ",(0,i.jsx)(n.code,{children:""})," and ",(0,i.jsx)(n.code,{children:""})," are as\ndefined by the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables",children:[(0,i.jsx)(n.code,{children:"AddressV0Context"})," variable"]}),", and ",(0,i.jsx)(n.code,{children:""})," represents the\naccount signer's public key (e.g. entity id)."]}),"\n",(0,i.jsxs)(n.p,{children:["For more details, see the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAddress",children:[(0,i.jsx)(n.code,{children:"NewAddress"})," function"]}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["When generating an account's private/public key pair, follow ",(0,i.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR 0008:\nStandard Account Key Generation"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"runtime-accounts",children:"Runtime Accounts"}),"\n",(0,i.jsxs)(n.p,{children:["In case of runtime accounts, the ",(0,i.jsx)(n.code,{children:""})," and ",(0,i.jsx)(n.code,{children:""})," are as\ndefined by the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables",children:[(0,i.jsx)(n.code,{children:"AddressRuntimeV0Context"})," variable"]}),", and ",(0,i.jsx)(n.code,{children:""})," represents the\n",(0,i.jsx)(n.a,{href:"/core/runtime/identifiers",children:"runtime identifier"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["For more details, see the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewRuntimeAddress",children:[(0,i.jsx)(n.code,{children:"NewRuntimeAddress"})," function"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The runtime accounts belong to runtimes and can only be manipulated by the\nruntime by ",(0,i.jsx)(n.a,{href:"/core/runtime/messages",children:"emitting messages"})," to the consensus layer."]}),"\n",(0,i.jsx)(n.h3,{id:"reserved-addresses",children:"Reserved Addresses"}),"\n",(0,i.jsx)(n.p,{children:"Some staking account addresses are reserved to prevent them from being\naccidentally used in the actual ledger."}),"\n",(0,i.jsx)(n.p,{children:"Currently, they are:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"oasis1qrmufhkkyyf79s5za2r8yga9gnk4t446dcy3a5zm"}),": common pool address\n(defined by ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables",children:[(0,i.jsx)(n.code,{children:"CommonPoolAddress"})," variable"]}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"oasis1qqnv3peudzvekhulf8v3ht29z4cthkhy7gkxmph5"}),": per-block fee accumulator\naddress (defined by ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables",children:[(0,i.jsx)(n.code,{children:"FeeAccumulatorAddress"})," variable"]}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"oasis1qp65laz8zsa9a305wxeslpnkh9x4dv2h2qhjz0ec"}),": governance deposits address\n(defined by the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#pkg-variables",children:[(0,i.jsx)(n.code,{children:"GovernanceDeposits"})," variable"]}),")."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"general",children:"General"}),"\n",(0,i.jsx)(n.p,{children:"General accounts store account's general balance and nonce.\nNonce is the incremental number that must be unique for each account's\ntransaction."}),"\n",(0,i.jsx)(n.h3,{id:"escrow",children:"Escrow"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["Delegation provisions, also called commissions, are specified by the\n",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionSchedule",children:[(0,i.jsx)(n.code,{children:"CommissionSchedule"})," field"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h4,{id:"delegation",children:"Delegation"}),"\n",(0,i.jsxs)(n.p,{children:["When a delegator wants to delegate some of amount of stake to a staking account,\nhe needs to escrow stake using ",(0,i.jsx)(n.a,{href:"#add-escrow",children:"Add Escrow method"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Similarly, when a delegator wants to reclaim some amount of escrowed stake back\nto his general account, he needs to reclaim stake using ",(0,i.jsx)(n.a,{href:"#reclaim-escrow",children:"Reclaim Escrow method"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.em,{children:"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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"shares_per_base_unit = account_issued_shares / account_delegated_base_units\n"})}),"\n",(0,i.jsx)(n.p,{children:"For example, if an escrow account has the following state:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"escrow": {\n "active": {\n "balance": "250",\n "total_shares": "1000"\n },\n ...\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["then the current share price (i.e. ",(0,i.jsx)(n.code,{children:"shares_per_base_unit"}),") is 1000 / 250 = 4."]}),"\n",(0,i.jsx)(n.p,{children:"Delegating 500 base units to this escrow account would result in 500 * 4 = 2000\nnewly issued shares."}),"\n",(0,i.jsx)(n.p,{children:"Thus, the escrow account would have the following state afterwards:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"escrow": {\n "active": {\n "balance": "750",\n "total_shares": "3000"\n },\n ...\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["When a delegator wants to reclaim a certain number of escrowed stake, the\n",(0,i.jsx)(n.em,{children:"base unit price"})," (in shares) must be calculated based on the escrow account's\ncurrent active balance and the number of issued shares:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"base_units_per_share = account_delegated_base_units / account_issued_shares\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Returning to our example escrow account, the current base unit price (i.e.\n",(0,i.jsx)(n.code,{children:"base_units_per_share"}),") is 750 / 3000 = 0.25."]}),"\n",(0,i.jsx)(n.p,{children:"Reclaiming 1200 shares would result in 1200 * 0.25 = 300 base units being\nreclaimed."}),"\n",(0,i.jsx)(n.p,{children:"The escrow account would have the following state afterwards:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"escrow": {\n "active": {\n "balance": "450",\n "total_shares": "1800"\n },\n ...\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Reclaiming escrow does not complete immediately, but may be subject to a\ndebonding period during in which the stake still remains escrowed."}),"\n",(0,i.jsx)(n.h4,{id:"commission-schedule",children:"Commission Schedule"}),"\n",(0,i.jsxs)(n.p,{children:["A staking account can be configured to take a commission on staking rewards\ngiven to its node(s). They are defined by the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionRateStep",children:[(0,i.jsx)(n.code,{children:"CommissionRateStep"})," type"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The commission rate must be within bounds, which the staking account can also\nspecify using the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionRateBoundStep",children:[(0,i.jsx)(n.code,{children:"CommissionRateBoundStep"})," type"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The commission rates and rate bounds can change over time which is defined\nby the ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionSchedule",children:[(0,i.jsx)(n.code,{children:"CommissionSchedule"})," type"]}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#CommissionScheduleRules",children:[(0,i.jsx)(n.code,{children:"CommissionScheduleRules"})," consensus parameter"]}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,i.jsx)(n.p,{children:"The following sections describe the methods supported by the consensus staking\nservice."}),"\n",(0,i.jsx)(n.h3,{id:"transfer",children:"Transfer"}),"\n",(0,i.jsxs)(n.p,{children:["Transfer enables stake transfer between different accounts in the staking\nledger. A new transfer transaction can be generated using\n",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewTransferTx",children:[(0,i.jsx)(n.code,{children:"NewTransferTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.Transfer\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type Transfer struct {\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"to"})," specifies the destination account's address."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," specifies the amount of base units to transfer."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the source account."}),"\n",(0,i.jsx)(n.h3,{id:"burn",children:"Burn"}),"\n",(0,i.jsxs)(n.p,{children:["Burn destroys some stake in the caller's account. A new burn transaction can be\ngenerated using ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewBurnTx",children:[(0,i.jsx)(n.code,{children:"NewBurnTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.Burn\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type Burn struct {\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," specifies the amount of base units to burn."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the caller's account."}),"\n",(0,i.jsx)(n.h3,{id:"add-escrow",children:"Add Escrow"}),"\n",(0,i.jsxs)(n.p,{children:["Escrow transfers stake into an escrow account.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"#delegation",children:"Delegation section"})," of this document.\nA new add escrow transaction can be generated using ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAddEscrowTx",children:[(0,i.jsx)(n.code,{children:"NewAddEscrowTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.AddEscrow\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type Escrow struct {\n Account Address `json:"account"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"account"})," specifies the destination escrow account's address."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," specifies the amount of base units to transfer."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the source account."}),"\n",(0,i.jsx)(n.h3,{id:"reclaim-escrow",children:"Reclaim Escrow"}),"\n",(0,i.jsxs)(n.p,{children:["Reclaim escrow starts the escrow reclamation process.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"#delegation",children:"Delegation section"})," of this document.\nA new reclaim escrow transaction can be generated using\n",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewReclaimEscrowTx",children:[(0,i.jsx)(n.code,{children:"NewReclaimEscrowTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.ReclaimEscrow\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type ReclaimEscrow struct {\n Account Address `json:"account"`\n Shares quantity.Quantity `json:"shares"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"account"})," specifies the source escrow account's address."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"shares"})," specifies the number of shares to reclaim."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the destination account."}),"\n",(0,i.jsx)(n.h3,{id:"amend-commission-schedule",children:"Amend Commission Schedule"}),"\n",(0,i.jsxs)(n.p,{children:["Amend commission schedule updates the commission schedule specified for the\ngiven escrow account.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"#commission-schedule",children:"Commission Schedule section"})," of this document.\nA new amend commission schedule transaction can be\ngenerated using ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAmendCommissionScheduleTx",children:[(0,i.jsx)(n.code,{children:"NewAmendCommissionScheduleTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.AmendCommissionSchedule\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type AmendCommissionSchedule struct {\n Amendment CommissionSchedule `json:"amendment"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amendment"})," defines the amended commission schedule."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the escrow account."}),"\n",(0,i.jsx)(n.h3,{id:"allow",children:"Allow"}),"\n",(0,i.jsxs)(n.p,{children:["Allow enables an account holder to set an allowance for a beneficiary. A new\nallow transaction can be generated using ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewAllowTx",children:[(0,i.jsx)(n.code,{children:"NewAllowTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.Allow\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type Allow struct {\n Beneficiary Address `json:"beneficiary"`\n Negative bool `json:"negative,omitempty"`\n AmountChange quantity.Quantity `json:"amount_change"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"beneficiary"})," specifies the beneficiary account address."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount_change"})," specifies the absolute value of the amount of base units to\nchange the allowance for."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"negative"})," specifies whether the ",(0,i.jsx)(n.code,{children:"amount_change"})," should be subtracted instead\nof added."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the general account. Upon executing\nthe allow the following actions are performed:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If either the ",(0,i.jsx)(n.code,{children:"disable_transfers"})," staking consensus parameter is set to ",(0,i.jsx)(n.code,{children:"true"}),"\nor the ",(0,i.jsx)(n.code,{children:"max_allowances"})," staking consensus parameter is set to zero, the method\nfails with ",(0,i.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["It is checked whether either the transaction signer address or the\n",(0,i.jsx)(n.code,{children:"beneficiary"})," address are reserved. If any are reserved, the method fails with\n",(0,i.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Address specified by ",(0,i.jsx)(n.code,{children:"beneficiary"})," is compared with the transaction signer\naddress. If the addresses are the same, the method fails with\n",(0,i.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The account indicated by the signer is loaded."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"ErrTooManyAllowances"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The set of allowances is updated so that the allowance is updated as specified\nby ",(0,i.jsx)(n.code,{children:"amount_change"}),"/",(0,i.jsx)(n.code,{children:"negative"}),". In case the change would cause the allowance to\nbe equal to zero or negative, the allowance is removed."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The account is saved."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The corresponding ",(0,i.jsx)(n.a,{href:"#allowance-change-event",children:(0,i.jsx)(n.code,{children:"AllowanceChangeEvent"})})," is emitted."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"withdraw",children:"Withdraw"}),"\n",(0,i.jsxs)(n.p,{children:["Withdraw enables a beneficiary to withdraw from the given account. A new\nwithdraw transaction can be generated using ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#NewWithdrawTx",children:[(0,i.jsx)(n.code,{children:"NewWithdrawTx"})," function"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"staking.Withdraw\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type Withdraw struct {\n From Address `json:"from"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"from"})," specifies the account address to withdraw from."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," specifies the amount of base units to withdraw."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer implicitly specifies the destination general account.\nUpon executing the withdrawal the following actions are performed:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If either the ",(0,i.jsx)(n.code,{children:"disable_transfers"})," staking consensus parameter is set to ",(0,i.jsx)(n.code,{children:"true"}),"\nor the ",(0,i.jsx)(n.code,{children:"max_allowances"})," staking consensus parameter is set to zero, the method\nfails with ",(0,i.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["It is checked whether either the transaction signer address or the\n",(0,i.jsx)(n.code,{children:"from"})," address are reserved. If any are reserved, the method fails with\n",(0,i.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Address specified by ",(0,i.jsx)(n.code,{children:"from"})," is compared with the transaction signer address.\nIf the addresses are the same, the method fails with ",(0,i.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The source account indicated by ",(0,i.jsx)(n.code,{children:"from"})," is loaded."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"The destination account indicated by the transaction signer is loaded."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"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.jsx)(n.code,{children:"ErrInsufficientBalance"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"amount"})," is added to the destination general account balance."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Both source and destination accounts are saved."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The corresponding ",(0,i.jsx)(n.a,{href:"#transfer-event",children:(0,i.jsx)(n.code,{children:"TransferEvent"})})," is emitted."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The corresponding ",(0,i.jsx)(n.a,{href:"#allowance-change-event",children:(0,i.jsx)(n.code,{children:"AllowanceChangeEvent"})})," is emitted with the updated\nallowance."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"events",children:"Events"}),"\n",(0,i.jsx)(n.h3,{id:"transfer-event",children:"Transfer Event"}),"\n",(0,i.jsx)(n.p,{children:"The transfer event is emitted when tokens are transferred from a source account\nto a destination account."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type TransferEvent struct {\n From Address `json:"from"`\n To Address `json:"to"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"from"})," contains the address of the source account."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"to"})," contains the address of the destination account."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," contains the amount (in base units) transferred."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"burn-event",children:"Burn Event"}),"\n",(0,i.jsx)(n.p,{children:"The burn event is emitted when tokens are burned."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type BurnEvent struct {\n Owner Address `json:"owner"`\n Amount quantity.Quantity `json:"amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"owner"})," contains the address of the account that burned tokens."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," contains the amount (in base units) burned."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"escrow-event",children:"Escrow Event"}),"\n",(0,i.jsx)(n.p,{children:"Escrow events are emitted when tokens are escrowed, taken from escrow by the\nprotocol or reclaimed from escrow by the account owner."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type EscrowEvent struct {\n Add *AddEscrowEvent `json:"add,omitempty"`\n Take *TakeEscrowEvent `json:"take,omitempty"`\n Reclaim *ReclaimEscrowEvent `json:"reclaim,omitempty"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"add"})," is set if the emitted event is an ",(0,i.jsx)(n.em,{children:"Add Escrow"})," event."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"take"})," is set if the emitted event is a ",(0,i.jsx)(n.em,{children:"Take Escrow"})," event."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"reclaim"})," is set if the emitted event is a ",(0,i.jsx)(n.em,{children:"Reclaim Escrow"})," event."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"add-escrow-event",children:"Add Escrow Event"}),"\n",(0,i.jsx)(n.p,{children:"The add escrow event is emitted when funds are escrowed."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"owner"})," contains the address of the source account."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"escrow"})," contains the address of the destination account the tokens are being\nescrowed to."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," contains the amount (in base units) escrowed."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"take-escrow-event",children:"Take Escrow Event"}),"\n",(0,i.jsx)(n.p,{children:"The take escrow event is emitted by the protocol when escrowed funds are\nslashed for whatever reason."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type TakeEscrowEvent struct {\n Owner Address `json:"owner"`\n Amount quantity.Quantity `json:"amount"`\n DebondingAmount quantity.Quantity `json:"debonding_amount"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"owner"})," contains the address of the account escrow has been taken from."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," contains the total amount (in base units) taken. The debonding and\nactive escrow balances are slashed in equal proportions."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"debonding_amount"})," contains the amount (in base units) taken from just the\ndebonding escrow balance."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"reclaim-escrow-event",children:"Reclaim Escrow Event"}),"\n",(0,i.jsx)(n.p,{children:"The reclaim escrow event is emitted when a reclaim escrow operation completes\nsuccessfully (after the debonding period has passed)."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"owner"})," contains the address of the account that reclaimed tokens from escrow."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"escrow"})," contains the address of the account escrow has been reclaimed from."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount"})," contains the amount (in base units) reclaimed."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"shares"})," contains the amount of shares reclaimed."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"allowance-change-event",children:"Allowance Change Event"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"owner"})," contains the address of the account owner where allowance has been\nchanged."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"beneficiary"})," contains the address of the beneficiary."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"allowance"})," contains the new total allowance."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"amount_change"})," contains the absolute amount the allowance has changed for."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"negative"})," specifies whether the allowance has been reduced rather than\nincreased."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The event is emitted even if the new allowance is zero."}),"\n",(0,i.jsx)(n.h2,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"max_allowances"})," (uint32) specifies the maximum number of ",(0,i.jsx)(n.a,{href:"#allow",children:"allowances"})," an\naccount can store. Zero means that allowance functionality is disabled."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"test-vectors",children:"Test Vectors"}),"\n",(0,i.jsxs)(n.p,{children:["To generate test vectors for various staking ",(0,i.jsx)(n.a,{href:"/core/consensus/transactions",children:"transactions"}),", run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make -C go staking/gen_vectors\n"})}),"\n",(0,i.jsxs)(n.p,{children:["For more information about the structure of the test vectors see the section\non ",(0,i.jsx)(n.a,{href:"/core/consensus/test-vectors",children:"Transaction Test Vectors"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>t});var i=s(6540);const c={},r=i.createContext(c);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9e0d9849.91e84288.js b/assets/js/9e0d9849.91e84288.js new file mode 100644 index 0000000000..324c1c6303 --- /dev/null +++ b/assets/js/9e0d9849.91e84288.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5783],{3682:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"operators","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/9fa9d380.8498c3eb.js b/assets/js/9fa9d380.8498c3eb.js new file mode 100644 index 0000000000..07f92a04ac --- /dev/null +++ b/assets/js/9fa9d380.8498c3eb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9051],{1025:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>d,metadata:()=>l,toc:()=>h});var t=o(4848),i=o(8453),r=o(5965),s=o(6116);const d={},a="Non-validator Node",l={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.mdx",sourceDirName:"node/run-your-node",slug:"/node/run-your-node/non-validator-node",permalink:"/node/run-your-node/non-validator-node",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/non-validator-node.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},c={},h=[{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},{value:"See also",id:"see-also",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"non-validator-node",children:"Non-validator Node"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["These instructions are for setting up a ",(0,t.jsx)(n.em,{children:"non-validator"})," node. If you want to run a ",(0,t.jsx)(n.em,{children:"validator"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"instructions for running a validator node"}),". Similarly, if you want to run a ",(0,t.jsx)(n.em,{children:"ParaTime"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"instructions for running a ParaTime node"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the ",(0,t.jsx)(n.a,{href:"prerequisites",children:"Prerequisites"})," chapter and have the Oasis Node binary installed on your systems."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-a-working-directory",children:"Creating a Working Directory"}),"\n",(0,t.jsxs)(n.p,{children:["We will be creating the following directory structure inside a chosen top-level ",(0,t.jsx)(n.code,{children:"/node"})," (feel free to name your directories however you wish) directory:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"etc"}),": This will store the node configuration and genesis file."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"data"}),": This will store the data directory needed by the running ",(0,t.jsx)(n.code,{children:"oasis-node"})," binary, including the complete blockchain state."]}),"\n",(0,t.jsxs)(n.p,{children:["The directory permissions should be ",(0,t.jsx)(n.code,{children:"rwx------"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"To create the directory structure, use the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"mkdir -m700 -p /node/{etc,data}\n"})}),"\n",(0,t.jsx)(n.h3,{id:"copying-the-genesis-file",children:"Copying the Genesis File"}),"\n",(0,t.jsxs)(n.p,{children:["The latest genesis file can be found in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),"). You should download the latest ",(0,t.jsx)(n.code,{children:"genesis.json"})," file and copy it to the ",(0,t.jsx)(n.code,{children:"/node/etc"})," directory we just created."]}),"\n",(0,t.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"This will configure the given node to only follow the consensus layer."})}),"\n",(0,t.jsxs)(n.p,{children:["In order to configure the node create the ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file with the following content:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"mode: client\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: info\n cometbft/context: error\n default: info\n\ngenesis:\n file: /node/etc/genesis.json\np2p:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n seeds:\n - {{ seed_node_address }}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"{{ seed_node_address }}"}),": The seed node address in the form ",(0,t.jsx)(n.code,{children:"ID@IP:port"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["You can find the current Oasis Seed Node address in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Make sure the ",(0,t.jsx)(n.code,{children:"consensus"})," port (default: ",(0,t.jsx)(n.code,{children:"26656"}),") and ",(0,t.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,t.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,t.jsx)(n.code,{children:"TCP"})," and ",(0,t.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,t.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,t.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,t.jsx)(n.h2,{id:"checking-node-status",children:"Checking Node Status"}),"\n",(0,t.jsx)(n.p,{children:"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),"\n",(0,t.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsx)(r.A,{item:(0,s.$)("/node/grpc")})]})}function f(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},5965:(e,n,o)=>{o.d(n,{A:()=>g});o(6540);var t=o(4164),i=o(8774),r=o(4142),s=o(5846),d=o(6654),a=o(1312),l=o(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=o(4848);function u(e){let{href:n,children:o}=e;return(0,h.jsx)(i.A,{href:n,className:(0,t.A)("card padding--lg",c.cardContainer),children:o})}function f(e){let{href:n,icon:o,title:i,description:r}=e;return(0,h.jsxs)(u,{href:n,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,t.A)("text--truncate",c.cardTitle),title:i,children:[o," ",i]}),r&&(0,h.jsx)("p",{className:(0,t.A)("text--truncate",c.cardDescription),title:r,children:r})]})}function p(e){let{item:n}=e;const o=(0,r.Nr)(n),t=function(){const{selectMessage:e}=(0,s.W)();return n=>e(n,(0,a.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return o?(0,h.jsx)(f,{href:o,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??t(n.items.length)}):null}function m(e){let{item:n}=e;const o=(0,d.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",t=(0,r.cC)(n.docId??void 0);return(0,h.jsx)(f,{href:n.href,icon:o,title:n.label,description:n.description??t?.description})}function g(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(m,{item:n});case"category":return(0,h.jsx)(p,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},5846:(e,n,o)=>{o.d(n,{W:()=>l});var t=o(6540),i=o(4586);const r=["zero","one","two","few","many","other"];function s(e){return r.filter((n=>e.includes(n)))}const d={locale:"en",pluralForms:s(["one","other"]),select:e=>1===e?"one":"other"};function a(){const{i18n:{currentLocale:e}}=(0,i.A)();return(0,t.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:s(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),d}}),[e])}function l(){const e=a();return{selectMessage:(n,o)=>function(e,n,o){const t=e.split("|");if(1===t.length)return t[0];t.length>o.pluralForms.length&&console.error(`For locale=${o.locale}, a maximum of ${o.pluralForms.length} plural forms are expected (${o.pluralForms.join(",")}), but the message contains ${t.length}: ${e}`);const i=o.select(n),r=o.pluralForms.indexOf(i);return t[Math.min(r,t.length-1)]}(o,n,e)}}},6116:(e,n,o)=>{o.d(n,{$:()=>r});var t=o(2252);function i(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&i(n.items)}}function r(e){const n=(0,t.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)i(n.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]}},8453:(e,n,o)=>{o.d(n,{R:()=>s,x:()=>d});var t=o(6540);const i={},r=t.createContext(i);function s(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9fda2e12.460e79f5.js b/assets/js/9fda2e12.460e79f5.js new file mode 100644 index 0000000000..ac7fbdd279 --- /dev/null +++ b/assets/js/9fda2e12.460e79f5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8537],{3744:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>h,contentTitle:()=>d,default:()=>u,frontMatter:()=>c,metadata:()=>l,toc:()=>p});var t=n(4848),r=n(8453),i=n(5965),o=n(2550),a=n(6116);const c={description:"Home of the Oasis dApp developer resources"},d="Create dApp",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Home of the Oasis dApp developer resources"},sidebar:"developers",next:{title:"Sapphire ParaTime",permalink:"/dapp/sapphire/"}},h={},p=[{value:"Consensus Layer RPC Endpoints",id:"consensus-layer-rpc-endpoints",level:2},{value:"Consensus Layer Block Explorers",id:"consensus-layer-block-explorers",level:2},{value:"Consensus Layer Indexers",id:"consensus-layer-indexers",level:2},{value:"Rosetta Endpoints",id:"rosetta-endpoints",level:2},{value:"See also",id:"see-also",level:2}];function x(e){const s={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"create-dapp",children:"Create dApp"}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.img,{alt:"Oasis architectural design including ParaTime and consensus layers",src:n(141).A+"",width:"1523",height:"718"})}),"\n",(0,t.jsxs)(s.p,{children:["The ",(0,t.jsx)(s.a,{href:"/general/oasis-network/",children:"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."]}),"\n",(0,t.jsx)(s.p,{children:"Learn more by exploring the ParaTimes below!"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{style:{textAlign:"right"}}),(0,t.jsx)(s.th,{children:"EVM-compatible"}),(0,t.jsx)(s.th,{children:"Oasis Wasm"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{style:{textAlign:"right"},children:(0,t.jsx)(s.strong,{children:"Confidential"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(i.A,{item:(0,a.$)("/dapp/sapphire/")})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(i.A,{item:(0,a.$)("/dapp/cipher/")})})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{style:{textAlign:"right"},children:(0,t.jsx)(s.strong,{children:"Non-Confidential"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(i.A,{item:(0,a.$)("/dapp/emerald/")})}),(0,t.jsx)(s.td,{})]})]})]}),"\n",(0,t.jsxs)(s.p,{children:["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,t.jsx)(s.em,{children:"privacy service"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["The Oasis team prepared a rich cross-chain toolkit called the\n",(0,t.jsx)(s.a,{href:"/dapp/opl/",children:(0,t.jsx)(s.strong,{children:"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."]}),"\n",(0,t.jsx)(i.A,{item:(0,a.$)("/dapp/opl/")}),"\n",(0,t.jsx)(s.h2,{id:"consensus-layer-rpc-endpoints",children:"Consensus Layer RPC Endpoints"}),"\n",(0,t.jsx)(s.admonition,{type:"danger",children:(0,t.jsxs)(s.p,{children:["The RPC endpoint is a ",(0,t.jsx)(s.strong,{children:"point of trust"}),". Beside rate limiting, it can also\nperform censorship or even man-in-the-middle attack. If you have security\nconsiderations, we strongly recommend that you ",(0,t.jsx)(s.a,{href:"/node/run-your-node/non-validator-node",children:"run your own client\nnode"}),","]})}),"\n",(0,t.jsxs)(s.p,{children:["Most dApp developers will build dApps on the ParaTime layer (the ",(0,t.jsx)(s.em,{children:"compute"}),"\nlayer) depicted above. For Sapphire and Emerald which are EVM-compatible chains,\nthose dApps connect directly to an ",(0,t.jsx)(s.a,{href:"/node/web3",children:"EVM-compatible Web3 endpoint"}),".\nHowever, if you are building a dApp for Cipher or the one that needs to\nperform consensus operations such as the consensus-layer token transfers,\ngovernance transactions, cross-chain ParaTime deposits and withdrawals and\nsimilar, you will need to connect to the one of the endpoints speaking\n",(0,t.jsx)(s.a,{href:"/node/grpc",children:"Oasis gRPC"}),"."]}),"\n",(0,t.jsx)(s.p,{children:"Public gRPC endpoints (in alphabetic order):"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Provider"}),(0,t.jsx)(s.th,{children:"Mainnet URL"}),(0,t.jsx)(s.th,{children:"Testnet URL"})]})}),(0,t.jsx)(s.tbody,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"grpc.oasis.io:443"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"testnet.grpc.oasis.io:443"})})]})})]}),"\n",(0,t.jsx)(s.h2,{id:"consensus-layer-block-explorers",children:"Consensus Layer Block Explorers"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Name (Provider)"}),(0,t.jsx)(s.th,{children:"Mainnet URL"}),(0,t.jsx)(s.th,{children:"Testnet URL"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["Oasis Scan (",(0,t.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"https://www.oasisscan.com",children:"https://www.oasisscan.com"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"https://testnet.oasisscan.com",children:"https://testnet.oasisscan.com"})})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["Oasis Explorer (",(0,t.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"}),")"]}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.em,{children:"Coming soon"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.em,{children:"Coming soon"})})]})]})]}),"\n",(0,t.jsx)(s.h2,{id:"consensus-layer-indexers",children:"Consensus Layer Indexers"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Name (Provider)"}),(0,t.jsx)(s.th,{children:"Mainnet URL"}),(0,t.jsx)(s.th,{children:"Testnet URL"}),(0,t.jsx)(s.th,{children:"Documentation"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["Oasis Scan (",(0,t.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://api.oasisscan.com/mainnet/v2"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://api.oasisscan.com/testnet/v2"})}),(0,t.jsxs)(s.td,{children:[(0,t.jsx)(s.a,{href:"https://api.oasisscan.com/mainnet/swagger-ui/",children:"Mainnet API"}),", ",(0,t.jsx)(s.a,{href:"https://api.oasisscan.com/testnet/swagger-ui/",children:"Testnet API"})]})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsxs)(s.td,{children:["Oasis Nexus (",(0,t.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"}),")"]}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://nexus.oasis.io/v1"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://testnet.nexus.oasis.io/v1"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"https://nexus.oasis.io/v1/spec/v1.html",children:"API"})})]})]})]}),"\n",(0,t.jsx)(s.h2,{id:"rosetta-endpoints",children:"Rosetta Endpoints"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Provider"}),(0,t.jsx)(s.th,{children:"Mainnet URL"}),(0,t.jsx)(s.th,{children:"Testnet URL"})]})}),(0,t.jsx)(s.tbody,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://rosetta.oasis.io/api/mainnet/v1"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"https://rosetta.oasis.io/api/testnet/v1"})})]})})]}),"\n",(0,t.jsx)(s.admonition,{type:"note",children:(0,t.jsxs)(s.p,{children:["If you are running your own Oasis client node endpoint, a block explorer, an\nindexer, or the Rosetta gateway and wish to be added to these docs, open an\nissue at ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/docs/issues",children:"github.com/oasisprotocol/docs"}),"."]})}),"\n",(0,t.jsx)(s.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsx)(o.A,{items:[(0,a.$)("https://api.docs.oasis.io/js/client"),(0,a.$)("https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go")]})]})}function u(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(x,{...e})}):x(e)}},5965:(e,s,n)=>{n.d(s,{A:()=>j});n(6540);var t=n(4164),r=n(8774),i=n(4142),o=n(5846),a=n(6654),c=n(1312),d=n(1107);const l={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=n(4848);function p(e){let{href:s,children:n}=e;return(0,h.jsx)(r.A,{href:s,className:(0,t.A)("card padding--lg",l.cardContainer),children:n})}function x(e){let{href:s,icon:n,title:r,description:i}=e;return(0,h.jsxs)(p,{href:s,children:[(0,h.jsxs)(d.A,{as:"h2",className:(0,t.A)("text--truncate",l.cardTitle),title:r,children:[n," ",r]}),i&&(0,h.jsx)("p",{className:(0,t.A)("text--truncate",l.cardDescription),title:i,children:i})]})}function u(e){let{item:s}=e;const n=(0,i.Nr)(s),t=function(){const{selectMessage:e}=(0,o.W)();return s=>e(s,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:s}))}();return n?(0,h.jsx)(x,{href:n,icon:"\ud83d\uddc3\ufe0f",title:s.label,description:s.description??t(s.items.length)}):null}function m(e){let{item:s}=e;const n=(0,a.A)(s.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",t=(0,i.cC)(s.docId??void 0);return(0,h.jsx)(x,{href:s.href,icon:n,title:s.label,description:s.description??t?.description})}function j(e){let{item:s}=e;switch(s.type){case"link":return(0,h.jsx)(m,{item:s});case"category":return(0,h.jsx)(u,{item:s});default:throw new Error(`unknown item type ${JSON.stringify(s)}`)}}},2550:(e,s,n)=>{n.d(s,{A:()=>c});n(6540);var t=n(4164),r=n(4142),i=n(5965),o=n(4848);function a(e){let{className:s}=e;const n=(0,r.$S)();return(0,o.jsx)(c,{items:n.items,className:s})}function c(e){const{items:s,className:n}=e;if(!s)return(0,o.jsx)(a,{...e});const c=(0,r.d1)(s);return(0,o.jsx)("section",{className:(0,t.A)("row",n),children:c.map(((e,s)=>(0,o.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,o.jsx)(i.A,{item:e})},s)))})}},5846:(e,s,n)=>{n.d(s,{W:()=>d});var t=n(6540),r=n(4586);const i=["zero","one","two","few","many","other"];function o(e){return i.filter((s=>e.includes(s)))}const a={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,r.A)();return(0,t.useMemo)((()=>{try{return function(e){const s=new Intl.PluralRules(e);return{locale:e,pluralForms:o(s.resolvedOptions().pluralCategories),select:e=>s.select(e)}}(e)}catch(s){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${s.message}\n`),a}}),[e])}function d(){const e=c();return{selectMessage:(s,n)=>function(e,s,n){const t=e.split("|");if(1===t.length)return t[0];t.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${t.length}: ${e}`);const r=n.select(s),i=n.pluralForms.indexOf(r);return t[Math.min(i,t.length-1)]}(n,s,e)}}},6116:(e,s,n)=>{n.d(s,{$:()=>i});var t=n(2252);function r(e){for(const s of e){const e=s.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=s),"category"===s.type&&r(s.items)}}function i(e){const s=(0,t.r)();if(!s)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in s.docsSidebars)r(s.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]}},141:(e,s,n)=>{n.d(s,{A:()=>t});const t=n.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"},8453:(e,s,n)=>{n.d(s,{R:()=>o,x:()=>a});var t=n(6540);const r={},i=t.createContext(r);function o(e){const s=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),t.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a02c83e6.5fd3617b.js b/assets/js/a02c83e6.5fd3617b.js new file mode 100644 index 0000000000..3437e9fbf1 --- /dev/null +++ b/assets/js/a02c83e6.5fd3617b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6391],{5535:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var o=s(4848),t=s(8453);const i={},a="Transactions",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/transactions.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Consensus Layer",permalink:"/core/consensus/"},next:{title:"Services",permalink:"/core/consensus/services"}},r={},d=[{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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"transactions",children:"Transactions"}),"\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"/core/consensus/",children:"consensus backend"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["The transaction API definitions and helper methods for creating and verifying\ntransactions lives in ",(0,o.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/consensus/api/transaction/transaction.go",children:(0,o.jsx)(n.code,{children:"go/consensus/api/transaction"})}),". For more information\nyou can also check out the ",(0,o.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api/transaction?tab=doc",children:"consensus backend API documentation"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"format",children:"Format"}),"\n",(0,o.jsxs)(n.p,{children:["Each (unsigned) transaction is represented by the following ",(0,o.jsx)(n.a,{href:"/core/encoding",children:"encoded"})," structure:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.p,{children:"Fields:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"nonce"})," is the current caller's nonce to prevent replays."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"fee"})," is an optional fee that the caller commits to paying to execute the\ntransaction."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"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.jsx)(n.code,{children:"."}),"). For\nexample, ",(0,o.jsx)(n.code,{children:"staking.Transfer"})," is the method name of the staking service's\n",(0,o.jsx)(n.code,{children:"Transfer"})," method."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"body"})," is the method-specific body."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["The actual transaction that is submitted to the consensus layer must be signed\nwhich means that it is wrapped into a ",(0,o.jsx)(n.a,{href:"/core/crypto#envelopes",children:"signed envelope"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.a,{href:"/core/crypto#domain-separation",children:"Domain separation"})," context (+ ",(0,o.jsx)(n.a,{href:"/core/crypto#chain-domain-separation",children:"chain domain separation"}),"):"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"oasis-core/consensus: tx\n"})}),"\n",(0,o.jsx)(n.h2,{id:"fees",children:"Fees"}),"\n",(0,o.jsx)(n.p,{children:"As the consensus operations require resources to process, the consensus layer\ncharges fees to perform operations."}),"\n",(0,o.jsx)(n.h3,{id:"gas",children:"Gas"}),"\n",(0,o.jsxs)(n.p,{children:["Gas is an unsigned 64-bit integer denominated in ",(0,o.jsx)(n.em,{children:"gas units"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"Different operations cost different amounts of gas as defined by the consensus\nparameters of the consensus component that implements the operation."}),"\n",(0,o.jsxs)(n.p,{children:["Transactions that require fees to process will include a ",(0,o.jsx)(n.code,{children:"fee"})," field to declare\nhow much the caller is willing to pay for fees.\nSpecifying an ",(0,o.jsx)(n.code,{children:"amount"})," (in base units) and ",(0,o.jsx)(n.code,{children:"gas"})," (in gas units) implicitly\ndefines a ",(0,o.jsx)(n.em,{children:"gas price"})," (price of one gas unit) as ",(0,o.jsx)(n.code,{children:"amount / gas"}),".\nConsensus validators may refuse to process operations with a gas price that is\ntoo low."]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'type Fee struct {\n Amount quantity.Quantity `json:"amount"`\n Gas Gas `json:"gas"`\n}\n'})}),"\n",(0,o.jsx)(n.p,{children:"Fees are not refunded."}),"\n",(0,o.jsx)(n.p,{children:"Fields:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"amount"})," is the total fee amount (in base units) to be paid."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"gas"})," is the maximum gas that an operation can use."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"gas-estimation",children:"Gas Estimation"}),"\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend.EstimateGas",children:(0,o.jsx)(n.code,{children:"EstimateGas"})})," for estimating gas."]}),"\n",(0,o.jsxs)(n.p,{children:["The implementation of gas estimation is ",(0,o.jsx)(n.a,{href:"/core/consensus/",children:"backend-specific"})," but usually involves\nsome kind of simulation of transaction execution to derive the maximum amount\nconsumed by execution."]}),"\n",(0,o.jsx)(n.h2,{id:"submission",children:"Submission"}),"\n",(0,o.jsxs)(n.p,{children:["Transactions can be submitted to the consensus layer by calling ",(0,o.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#ClientBackend.SubmitTx",children:(0,o.jsx)(n.code,{children:"SubmitTx"})})," and\nproviding a signed transaction."]}),"\n",(0,o.jsxs)(n.p,{children:["The consensus backend API provides a submission manager for cases where the\n",(0,o.jsx)(n.a,{href:"/core/crypto",children:"signer"})," is available and automatic gas estimation and nonce lookup is desired.\nIt is available via the ",(0,o.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/consensus/api?tab=doc#SignAndSubmitTx",children:(0,o.jsx)(n.code,{children:"SignAndSubmitTx"})})," function."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>c});var o=s(6540);const t={},i=o.createContext(t);function a(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a11d2c44.e5c84bd0.js b/assets/js/a11d2c44.e5c84bd0.js new file mode 100644 index 0000000000..b8221294d0 --- /dev/null +++ b/assets/js/a11d2c44.e5c84bd0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1432],{7648:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>d,toc:()=>l});var r=a(4848),t=a(8453);const i={},o="Upgrading Key Managers",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/keymanager-node/key-manager-upgrade.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},s={},l=[{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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"upgrading-key-managers",children:"Upgrading Key Managers"}),"\n",(0,r.jsx)(n.p,{children:"This guide will describe how to upgrade a key manager node."}),"\n",(0,r.jsx)(n.h2,{id:"about-the-upgrade",children:"About the Upgrade"}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.admonition,{type:"danger",children:(0,r.jsx)(n.p,{children:"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."})}),"\n",(0,r.jsx)(n.h2,{id:"safe-upgrade-procedure",children:"Safe Upgrade Procedure"}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"In case you are running multiple key manager nodes always follow the safe\nupgrade procedure:"})}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Keep approximately one half of nodes running the old version."}),"\n",(0,r.jsx)(n.li,{children:"Upgrade the other half."}),"\n",(0,r.jsx)(n.li,{children:"Wait for the ParaTime upgrade epoch."}),"\n",(0,r.jsxs)(n.li,{children:["Verify that secrets have been replicated ",(0,r.jsx)(n.a,{href:"#verifying-successful-replication",children:"as shown below"}),"."]}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.strong,{children:"Verify again."})}),"\n",(0,r.jsx)(n.li,{children:"Upgrade the rest of the nodes."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"upgrade-nodes",children:"Upgrade Nodes"}),"\n",(0,r.jsx)(n.p,{children:"To upgrade a key manager node, follow the next steps:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsx)(n.li,{children:"Stop the node."}),"\n",(0,r.jsxs)(n.li,{children:["Wipe its local state ",(0,r.jsx)(n.code,{children:"worker-local-storage.badger.db"}),", e.g.:"]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"rm -rf runtimes/4000000000000000000000000000000000000000000000004a1a53dff2ae482d/worker-local-storage.badger.db/\n"})}),"\n",(0,r.jsxs)(n.ol,{start:"3",children:["\n",(0,r.jsxs)(n.li,{children:["Upgrade the key manager runtime:","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["get the new ORC file (",(0,r.jsx)(n.a,{href:"../../mainnet/#key-manager",children:"mainnet"}),", ",(0,r.jsx)(n.a,{href:"../../testnet/#key-manager",children:"testnet"}),");"]}),"\n",(0,r.jsx)(n.li,{children:"update the configuration to replace the ORC file; and"}),"\n",(0,r.jsx)(n.li,{children:"restart the node."}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.li,{children:"Wait for the key material to get replicated from active nodes before\ncontinuing."}),"\n",(0,r.jsxs)(n.li,{children:["Verify that secrets have been replicated ",(0,r.jsx)(n.a,{href:"#verifying-successful-replication",children:"as shown below"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"after-the-upgrade",children:"After the Upgrade"}),"\n",(0,r.jsx)(n.h4,{id:"verifying-successful-replication",children:"Verifying Successful Replication"}),"\n",(0,r.jsxs)(n.p,{children:["After the upgrade epoch and when the key material is successfully replicated,\nthe ",(0,r.jsx)(n.code,{children:"control status"})," output should show ",(0,r.jsx)(n.code,{children:'keymanager.status="ready"'})," and\n",(0,r.jsx)(n.code,{children:"registration.descriptor.runtimes.0.extra_info"})," should contain a hash of the\nkey material state:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'$ oasis-node -a unix:/node/data/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'})}),"\n",(0,r.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,r.jsx)(n.p,{children:"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:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'{"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'})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>o,x:()=>d});var r=a(6540);const t={},i=r.createContext(t);function o(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a14fc975.a6324c35.js b/assets/js/a14fc975.a6324c35.js new file mode 100644 index 0000000000..045218b51e --- /dev/null +++ b/assets/js/a14fc975.a6324c35.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1527],{1819:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var i=s(4848),r=s(8453);const t={},o="Upgrade Log",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/upgrade-log.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Upgrade to Mainnet",permalink:"/node/mainnet/previous-upgrades/mainnet-upgrade"},next:{title:"Testnet",permalink:"/node/testnet/"}},d={},l=[{value:"2023-11-29 (10:02 UTC) - Eden Upgrade",id:"eden-upgrade",level:2},{value:"Configuration Changes",id:"configuration-changes",level:3},{value:"Data Directory Changes",id:"data-directory-changes",level:3},{value:"State Changes",id:"state-changes",level:3},{value:"General",id:"general",level:4},{value:"Registry",id:"registry",level:4},{value:"Root Hash",id:"root-hash",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:"Consensus",id:"consensus",level:4},{value:"Other",id:"other",level:4},{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-1",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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"upgrade-log",children:"Upgrade Log"}),"\n",(0,i.jsx)(n.p,{children:"For each upgrade of the Oasis Network, we are tracking important changes for\nnode operators' deployments."}),"\n",(0,i.jsx)(n.p,{children:"They are enumerated and explained in this document."}),"\n",(0,i.jsx)(n.h2,{id:"eden-upgrade",children:"2023-11-29 (10:02 UTC) - Eden Upgrade"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["For a detailed view of the Eden Upgrade process, please refer to the\n",(0,i.jsx)(n.a,{href:"/node/mainnet/eden-upgrade",children:"Eden Upgrade"})," page."]})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"The Oasis Core 23.0.x binary in our published releases is built only for Ubuntu\n22.04 (GLIBC>=2.32). You'll have to build it yourself if you're using prior\nUbuntu versions (or other distributions using older system libraries)."})}),"\n",(0,i.jsx)(n.h3,{id:"configuration-changes",children:"Configuration Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The node configuration has been refactored so that everything is now configured\nvia a YAML configuration file and ",(0,i.jsx)(n.strong,{children:"configuring via command-line options is no\nlonger supported"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node config migrate --in config.yml --out new-config.yml\n"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"After you are satisfied with the new configuration file, replace the old file\nwith the new one as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"mv new-config.yml config.yml\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"The configuration format for seed nodes has changed and it now requires the\nnode's P2P public key to be used. In case your old configuration file contains\nknown Mainnet seed nodes, this transformation is performed automatically."}),(0,i.jsx)(n.p,{children:"However, if it contains unknown seed nodes then the conversion did not happen\nautomatically and you may need to obtain the seed node's P2P public key. For\nMainnet you can use the following addresses:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"TBD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"TBD"})}),"\n"]}),(0,i.jsx)(n.p,{children:"Please be aware that every seed node should be configured to listen on two\ndistinct ports. One is dedicated to peer discovery within the CometBFT P2P\nnetwork, while the other is used to bootstrap the Oasis P2P network."})]}),"\n",(0,i.jsx)(n.h3,{id:"data-directory-changes",children:"Data Directory Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The subdirectory (located inside the node's data directory) used to store\nconsensus-related data, previously called ",(0,i.jsx)(n.code,{children:"tendermint"})," (after the consensus\nlayer protocol backend) has been renamed to ",(0,i.jsx)(n.code,{children:"consensus"})," in Oasis Core 23.0.x. If\nany of your scripts rely on specific directory names, please make sure to update\nthem to reflect the changed sdirectory name."]}),"\n",(0,i.jsx)(n.h3,{id:"state-changes",children:"State Changes"}),"\n",(0,i.jsx)(n.p,{children:"The following parts of the genesis document will be updated:"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For a more detailed explanation of the parameters below, see the\n",(0,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"})," docs."]})}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["All state changes will be done automatically with the migration command provided\nby the new version of ",(0,i.jsx)(n.code,{children:"oasis-node"}),". It can be used as follows to derive the same\ngenesis file from an existing state dump at the correct height (assuming there\nis a ",(0,i.jsx)(n.code,{children:"genesis.json"})," present in the current working directory):"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node genesis migrate --genesis.new_chain_id oasis-4\n"})})]}),"\n",(0,i.jsx)(n.h4,{id:"general",children:"General"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,i.jsx)(n.code,{children:"oasis-4"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"halt_epoch"})})," will be removed as it is no longer used."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"registry",children:"Registry"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.runtimes[].txn_scheduler.propose_batch_timeout"})})," specifies how\nlong to wait before accepting proposal from the next backup scheduler. It will\nbe set to ",(0,i.jsx)(n.code,{children:"5000000000"})," (5 seconds). Previously the value was represented in\nthe number of consensus layer blocks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"registry.params.gas_costs.prove_freshness"})})," specifies the cost of the\nfreshness proof transaction. It will be set to ",(0,i.jsx)(n.code,{children:"1000"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"keymanager.params.gas_costs.update_policy"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"tee_features": {\n "sgx": {\n "pcs": true,\n "signed_attestations": true,\n "max_attestation_age": 1200\n },\n "freshness_proofs": true\n}\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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,i.jsx)(n.code,{children:"5"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"root-hash",children:"Root Hash"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"roothash.params.max_past_roots_stored"})})," specifies the maximum number of\npast runtime state roots that are stored in consensus state for each runtime.\nIt will be set to ",(0,i.jsx)(n.code,{children:"1200"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"staking",children:"Staking"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.commission_schedule_rules.min_commission_rate"})})," specifies\nthe minimum commission rate. It will be set to ",(0,i.jsx)(n.code,{children:"0"})," to maintain the existing\nbehavior."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"staking.params.thresholds.node-observer"})})," specifies the stake threshold\nfor registering an observer node. It will be set to ",(0,i.jsx)(n.code,{children:"100000000000"})," base units\n(or ",(0,i.jsx)(n.code,{children:"100"})," tokens), same as for existing compute nodes."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"key-manager",children:"Key Manager"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"keymanager.params.gas_costs"})})," specify the cost of key manager\ntransactions. These will be set to the following values:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"gas_costs": {\n "publish_ephemeral_secret": 1000,\n "publish_master_secret": 1000,\n "update_policy": 1000\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"random-beacon",children:"Random Beacon"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"beacon.base"})})," is the network's starting epoch. It will be set to the epoch\nof Mainnet's state dump + 1, ",(0,i.jsx)(n.code,{children:"28017"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"governance",children:"Governance"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.enable_change_parameters_proposal"})})," specifies whether\nparameter change governance proposals are allowed. It will be set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"consensus",children:"Consensus"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"consensus.params.max_block_size"})})," specifies the maximum block size in the\nconsensus layer. It will be set to ",(0,i.jsx)(n.code,{children:"1048576"})," (1 MiB)."]}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"other",children:"Other"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"Mainnet genesis file"}),"\nto include the Oasis Network's genesis quote:"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis\nCommunity Member Daniyar Borangaziyev]:"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"damask-upgrade",children:"2022-04-11 (8:30 UTC) - Damask Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"13402"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Mainnet network to reach this epoch at around 2022-04-11 8:30\nUTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions---voting",children:"Instructions - Voting"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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"}),"."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"At this time only entities which have active validator nodes scheduled in the\nvalidator set are eligible to vote for governance proposals."})}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsxs)(n.p,{children:["At least ",(0,i.jsx)(n.strong,{children:"75%"})," of the total ",(0,i.jsx)(n.strong,{children:"voting power"})," of the validator set needs to\ncast a vote on the upgrade proposal for the result to be valid."]}),(0,i.jsxs)(n.p,{children:["At least ",(0,i.jsx)(n.strong,{children:"90%"})," of the vote needs to be ",(0,i.jsx)(n.strong,{children:"yes"})," votes for a proposal to be\naccepted."]})]}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis Protocol Foundation has submitted an ",(0,i.jsx)(n.a,{href:"/core/consensus/services/governance#submit-proposal",children:"upgrade governance proposal"}),"\nwith the following contents:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'{\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",(0,i.jsx)(n.p,{children:"To view the proposal yourself, you can run the following command on your online\nOasis Node:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node governance list_proposals -a $ADDR\n"})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:"$ADDR"})," represents the path to the internal Oasis Node UNIX socket\nprefixed with ",(0,i.jsx)(n.code,{children:"unix:"})," (e.g.",(0,i.jsx)(n.code,{children:"unix:/serverdir/node/internal.sock"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"The output should look like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'[\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'})}),"\n",(0,i.jsxs)(n.p,{children:["Obtain ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#show",children:"your entity's nonce"})," and store it in the ",(0,i.jsx)(n.code,{children:"NONCE"})," variable. You can do\nthat by running:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"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"})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:""})," is the path to your entity's descriptor, e.g.\n",(0,i.jsx)(n.code,{children:"/serverdir/node/entity/"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To vote for the proposal, use the following command to generate a suitable\ntransaction:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:"TX_FLAGS"})," refer to previously set base and signer flags as described in\nthe ",(0,i.jsx)(n.a,{href:"/core/oasis-node/cli",children:"Oasis node CLI Tools Setup"})," doc."]}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Installing Oasis App on Your Ledger Wallet"}),"."]}),(0,i.jsxs)(n.p,{children:["Note that the previous version of the Oasis App available through Ledger Live,\nversion 1.8.2, doesn't support signing the ",(0,i.jsx)(n.code,{children:"governance.CastVote"})," transaction\ntype."]})]}),"\n",(0,i.jsxs)(n.p,{children:["To submit the generated transaction, copy ",(0,i.jsx)(n.code,{children:"tx_cast_vote.json"})," to the online\nOasis node and submit it from there:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node consensus submit_tx \\\n -a $ADDR \\\n --transaction.file tx_cast_vote.json\n"})}),"\n",(0,i.jsx)(n.h3,{id:"instructions---before-upgrade",children:"Instructions - Before upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade will upgrade ",(0,i.jsx)(n.strong,{children:"Oasis Core"})," to the ",(0,i.jsx)(n.strong,{children:"22.1.x release series"})," which\n",(0,i.jsx)(n.strong,{children:"no longer allow running Oasis Node"})," (i.e. the ",(0,i.jsx)(n.code,{children:"oasis-node"})," binary)\n",(0,i.jsx)(n.strong,{children:"as root"})," (effective user ID of 0)."]}),"\n",(0,i.jsxs)(n.p,{children:['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,i.jsx)(n.code,{children:"syscall.AllThreadsSyscall"})," does not work if the binary uses ",(0,i.jsx)(n.code,{children:"cgo"}),"\nat all."]}),"\n",(0,i.jsxs)(n.p,{children:["Nothing in Oasis Node will ever require elevated privileges.\nAttempting to run the ",(0,i.jsx)(n.code,{children:"oasis-node"})," process as the root user will now terminate\nimmediately on startup."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["Please, follow our ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#create-a-user",children:"Changing Your Setup to Run Oasis Services with Non-root\nSystem User"})," guide for steps-by-step instructions on how\nto update your system."]}),"\n",(0,i.jsxs)(n.p,{children:["If the previous behavior is required, the binary must be run in unsafe/debug\nmode (via the intentionally undocumented flag), and ",(0,i.jsx)(n.code,{children:"debug.allow_root"})," must also\nbe set."]}),"\n",(0,i.jsx)(n.h3,{id:"instructions---upgrade-day",children:"Instructions - Upgrade day"}),"\n",(0,i.jsxs)(n.p,{children:["Following steps should be performed on ",(0,i.jsx)(n.strong,{children:"2022-04-11"})," only after the network has\nreached the upgrade epoch and has halted:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Download the genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2022-04-11",children:"Damask upgrade release"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["Mainnet state at epoch ",(0,i.jsx)(n.strong,{children:"13402"})," will be exported and migrated to a 22.1.x\ncompatible genesis file."]}),(0,i.jsx)(n.p,{children:"Upgrade genesis file will be published on the above link soon after reaching the\nupgrade epoch."})]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Verify the provided Damask upgrade genesis file by comparing it to network\nstate dump."}),"\n",(0,i.jsxs)(n.p,{children:["The state changes are described in the ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/damask-upgrade#proposed-state-changes",children:"Damask Upgrade"})," document."]}),"\n",(0,i.jsxs)(n.p,{children:["See instructions in the ",(0,i.jsx)(n.a,{href:"../run-your-node/maintenance/handling-network-upgrades#verify-genesis",children:"Handling Network Upgrades"})," guide."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Replace the old genesis file with the new Damask upgrade genesis file."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Ensure your node will remain stopped by disabling auto-starting via your\nprocess manager (e.g., ",(0,i.jsx)(n.a,{href:"https://systemd.io/",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org/",children:"Supervisor"}),")"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v22.1.3",children:"22.1.3"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"../run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"State of ParaTimes/runtimes is not affected by this upgrade and should NOT be\nwiped."})}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsxs)(n.p,{children:["We recommend ",(0,i.jsx)(n.strong,{children:"backing up the pre-Damask consensus state"})," so all the\ntransactions and history are not permanently lost."]}),(0,i.jsx)(n.p,{children:"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."})]}),"\n",(0,i.jsxs)(n.ol,{start:"7",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Perform any needed ",(0,i.jsx)(n.a,{href:"#damask-conf-changes",children:"configuration changes"})," described\nbelow."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(only for ParaTime operators) Replace old versions of your ParaTime binaries\nwith the new ",(0,i.jsxs)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/issues/4469",children:["Oasis Runtime Containers (",(0,i.jsx)(n.code,{children:".orc"}),")"]})," introduced in the\nDamask upgrade."]}),"\n",(0,i.jsx)(n.p,{children:"For the official Oasis ParaTimes, use the following versions:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Emerald ParaTime: ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/emerald-paratime/releases/tag/v8.2.0",children:"8.2.0"})]}),"\n",(0,i.jsxs)(n.li,{children:["Cipher ParaTime: ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/cipher-paratime/releases/tag/v1.1.0",children:"1.1.0"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(only Emerald Web3 Gateway operators) Replace old version of Emerald Web3\nGateway with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/emerald-web3-gateway/releases/tag/v2.1.0",children:"2.1.0"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["(only Rosetta Gateway operators) Replace old version of Oasis Rosetta\nGateway with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-rosetta-gateway/releases/tag/v2.2.0",children:"2.2.0"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Start your node and re-enable auto-starting via your process manager."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"damask-conf-changes",children:"Configuration Changes"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["To see the full extent of the changes examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md",children:"Change Log"}),":\nof the ",(0,i.jsx)(n.strong,{children:"Oasis Core 22.1.3"}),", in particular the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#221-2022-04-01",children:"22.1"})," and\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#220-2022-03-01",children:"22.0"})," sections."]})}),"\n",(0,i.jsx)(n.p,{children:"If your node is currently configured to run a ParaTime, you need to perform some\nadditional steps."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:".orc"})," extension."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Links to updated ParaTime binaries will be published on the\n",(0,i.jsx)(n.a,{href:"/node/mainnet/#paratimes",children:"Network Parameters"})," page for their respective\nParaTimes."]})}),"\n",(0,i.jsxs)(n.p,{children:["The configuration is simplified as the ",(0,i.jsx)(n.code,{children:"runtime.paths"})," now only needs to list\nall of the supported ",(0,i.jsx)(n.code,{children:".orc"})," files (see below for an example)."]}),"\n",(0,i.jsxs)(n.p,{children:["Instead of separately configuring various roles for a node, there is now a\nsingle configuration flag called ",(0,i.jsx)(n.code,{children:"runtime.mode"})," which enables the correct roles\nas needed. It should be set to one of the following values:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"none"})," (runtime support is disabled, only consensus layer is enabled)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"compute"})," (node is participating as a runtime compute node for all the\nconfigured runtimes)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"keymanager"})," (node is participating as a keymanager node)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"client"})," (node is a stateful runtime client)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"client-stateless"})," (node is a stateless runtime client and connects to\nremote nodes for any state queries)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Nodes that have so far been participating as compute nodes should set the mode\nto ",(0,i.jsx)(n.code,{children:"compute"})," and nodes that have been participating as clients for querying\nand transaction submission should set it to ",(0,i.jsx)(n.code,{children:"client"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The following configuration flags have been removed:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"runtime.supported"})," (existing ",(0,i.jsx)(n.code,{children:"runtime.paths"})," is used instead)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.p2p.enabled"})," (now automatically set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.compute.enabled"})," (now set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.keymanager.enabled"})," (now set based on runtime mode)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"worker.storage.enabled"})," (no longer needed)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Also the ",(0,i.jsx)(n.code,{children:"worker.client"})," option is no longer needed unless you are providing\nconsensus layer RPC services."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if your ",(0,i.jsx)(n.em,{children:"previous"})," configuration looked like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.em,{children:"new"})," configuration should look like:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'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'})}),"\n",(0,i.jsx)(n.h3,{id:"additional-notes",children:"Additional notes"}),"\n",(0,i.jsxs)(n.p,{children:["Examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md",children:"Change Log"})," of the 22.1.3 release, in particular\nthe ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#221-2022-04-01",children:"22.1"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v22.1.3/CHANGELOG.md#220-2022-03-01",children:"22.0"})," sections."]}),"\n",(0,i.jsx)(n.h2,{id:"2021-08-31-upgrade",children:"2021-08-31 (16:00 UTC) - Parameter Update"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"8049."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Mainnet network to reach this epoch at around 2021-08-31 16:00 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"proposed-parameter-changes",children:"Proposed Parameter Changes"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"Oasis Core 21.2.8"})," release contains the ",(0,i.jsxs)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.2.8/go/upgrade/migrations/consensus_parameters.go",children:[(0,i.jsx)(n.code,{children:"consensus-params-update-2021-08"})," upgrade handler"]})," which will update the following parameters in the consensus layer:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"staking.params.max_allowances"})," ** specifies the maximum number of allowances on account can store. It will be set to ",(0,i.jsx)(n.code,{children:"16"})," (default value is ",(0,i.jsx)(n.code,{children:"0"}),") to enable support for beneficiary allowances which are required to transfer tokens into a ParaTime."]}),"\n",(0,i.jsxs)(n.li,{children:["**",(0,i.jsx)(n.code,{children:"staking.params.gas_costs"})," ** , ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"governance.params.gas_costs"})})," and ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"scheduler.params.max_validators"})})," is the maximum size of the consensus committee (i.e. the validator set). It will be increased to",(0,i.jsx)(n.code,{children:"110"})," (it was set to ",(0,i.jsx)(n.code,{children:"100"})," previously)."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"instructions---voting-1",children:"Instructions - Voting"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.em,{children:(0,i.jsx)(n.strong,{children:"."})})]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"At this time only entities which have active validator nodes scheduled in the validator set are eligible to vote for governance proposals."})}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsxs)(n.p,{children:["At least ",(0,i.jsx)(n.strong,{children:"75%"})," of the ",(0,i.jsx)(n.strong,{children:"voting power"})," needs to cast vote on the upgrade proposal for the result to be valid."]}),(0,i.jsxs)(n.p,{children:["At least ",(0,i.jsx)(n.strong,{children:"90%"})," of the votes need to be ",(0,i.jsx)(n.strong,{children:"yes"})," votes for a proposal to be accepted."]})]}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade will be the first upgrade that will use the new on-chain governance service introduced in the ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade",children:"Cobalt Upgrade"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The Oasis Protocol Foundation has submitted an ",(0,i.jsx)(n.a,{href:"/core/consensus/services/governance#submit-proposal",children:"upgrade governance proposal"})," with the following contents:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'{\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",(0,i.jsx)(n.p,{children:"To view the proposal yourself, you can run the following command on your online Oasis Node:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node governance list_proposals -a $ADDR | jq\n"})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:"$ADDR"})," represents the path to the internal Oasis Node UNIX socket prefixed with ",(0,i.jsx)(n.code,{children:"unix:"})," (e.g.",(0,i.jsx)(n.code,{children:"unix:/serverdir/node/internal.sock"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"The output should look like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'[\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'})}),"\n",(0,i.jsxs)(n.p,{children:["Obtain ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#show",children:"your entity's nonce"})," and store it in the ",(0,i.jsx)(n.code,{children:"NONCE"})," variable. You can do that by running:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"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"})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:""})," is the path to your entity's descriptor, e.g. ",(0,i.jsx)(n.code,{children:"/serverdir/node/entity/"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To vote for the proposal, use the following command to generate a suitable transaction:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["where ",(0,i.jsx)(n.code,{children:"TX_FLAGS"})," refer to previously set base and signer flags as described in the ",(0,i.jsx)(n.a,{href:"/core/oasis-node/cli",children:"Oasis node CLI Tools Setup"})," doc."]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"#installing-oasis-app-231-to-your-ledger",children:"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,i.jsx)(n.code,{children:"governance.CastVote"})," transaction type."]})}),"\n",(0,i.jsxs)(n.p,{children:["To submit the generated transaction, copy ",(0,i.jsx)(n.code,{children:"tx_cast_vote.json"})," to the online Oasis node and submit it from there:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node consensus submit_tx \\\n -a $ADDR \\\n --transaction.file tx_cast_vote.json\n"})}),"\n",(0,i.jsx)(n.h3,{id:"instructions---before-upgrade-system-preparation",children:"Instructions - Before Upgrade System Preparation"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["This upgrade will upgrade ",(0,i.jsx)(n.strong,{children:"Oasis Core"})," to version ",(0,i.jsx)(n.strong,{children:"21.2.8"})," which:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Upgrades the BadgerDB database backend from v2 to v3. See ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#badgerdb-v2-to-v3-migration",children:(0,i.jsx)(n.strong,{children:"BadgerDB v2 to v3 Migration"})})," section for required steps to be done before upgrade."]}),"\n",(0,i.jsxs)(n.li,{children:["Has a check that makes sure the ",(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#increase-file-descriptor-limit",children:"File Descriptor Limit"})," documentation page for details on how to increase the limit on your system."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Stop your node, replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"21.2.8"})," and restart your node."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.admonition,{title:"This is not dump & restore upgrade",type:"caution",children:(0,i.jsxs)(n.p,{children:["For this upgrade, ",(0,i.jsx)(n.strong,{children:"do NOT wipe state"}),"."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Once reaching the designated upgrade epoch, your node will stop and needs to be upgraded to Oasis Core ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.2.8",children:"21.2.8"}),".","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"Otherwise, you need to upgrade your node to Oasis Core 21.2.8 first and then restart it."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["If you use a process manager like ",(0,i.jsx)(n.a,{href:"https://github.com/systemd/systemd",children:"systemd"})," or ",(0,i.jsx)(n.a,{href:"http://supervisord.org",children:"Supervisor"}),", you can configure it to restart the Oasis Node automatically."]})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"The Mainnet's genesis file and the genesis document's hash will remain the same."})}),"\n",(0,i.jsx)(n.h3,{id:"badgerdb-v2-to-v3-migration",children:"BadgerDB v2 to v3 Migration"}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade will upgrade Oasis Core to version ",(0,i.jsx)(n.strong,{children:"21.2.x"})," which includes the new ",(0,i.jsx)(n.a,{href:"https://github.com/dgraph-io/badger",children:(0,i.jsx)(n.strong,{children:"BadgerDB"})})," ",(0,i.jsx)(n.strong,{children:"v3"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"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:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Upon startup, Oasis Node will start migrating all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})," files (Badger v2 files) and start writing Badger v3 DB to files with the ",(0,i.jsx)(n.code,{children:".migrate"})," suffix."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If the migration fails in the middle, Oasis Node will delete all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.migrate"})," files the next time it starts and start the migration (of the remaining ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})]}),"\n",(0,i.jsx)(n.p,{children:"files) again."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["If the migration succeeds, Oasis Node will append the ",(0,i.jsx)(n.code,{children:".backup"})," suffix to all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db"})," files (Badger v2 files) and remove the ",(0,i.jsx)(n.code,{children:".migrate"})," suffix from all ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.migrate"})," files (Badger v3 files)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsxs)(n.p,{children:["The BadgerDB v2 to v3 migration is ",(0,i.jsx)(n.strong,{children:"very I/O intensive"})," (both IOPS and throughput) and ",(0,i.jsx)(n.strong,{children:"may take a couple of hours"})," to complete."]}),(0,i.jsx)(n.p,{children:"To follow its progress, run:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"shopt -s globstar\ndu -h /**/*.badger.db* | sort -h -r\n"})}),(0,i.jsxs)(n.p,{children:["and observe the sizes of various ",(0,i.jsx)(n.code,{children:"*.badger.db*"})," directories."]}),(0,i.jsx)(n.p,{children:"For example, if it outputted the following:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"55G\tdata/tendermint/data/blockstore.badger.db\n37G\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup\n32G\tdata/tendermint/abci-state/mkvs_storage.badger.db\n16G\tdata/tendermint/data/blockstore.badger.db.migration\n2.9G\tdata/tendermint/data/state.badger.db\n62M\tdata/persistent-store.badger.db.backup\n2.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601/ca51b06a054b69f2c18b9781ea42f0b00900de199c1937398514331b0d136ec3/chunks\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601/ca51b06a054b69f2c18b9781ea42f0b00900de199c1937398514331b0d136ec3\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4767601\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601/2ec3a28b1f4a2fcce503f2e80eb5d77b6c0a4d1075e8a14d880ac390338a855e/chunks\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601/2ec3a28b1f4a2fcce503f2e80eb5d77b6c0a4d1075e8a14d880ac390338a855e\n1.1M\tdata/tendermint/abci-state/mkvs_storage.badger.db.backup/checkpoints/4757601\n36K\tdata/persistent-store.badger.db\n20K\tdata/tendermint/data/evidence.badger.db\n"})}),(0,i.jsxs)(n.p,{children:["then the ",(0,i.jsx)(n.code,{children:"mkvs_storage.badger.db"})," was already migrated:"]}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["old BadgerDB v2 directory: ",(0,i.jsx)(n.code,{children:"37G data/tendermint/abci-state/mkvs_storage.badger.db.backup"})]}),"\n",(0,i.jsxs)(n.li,{children:["new BadgerDB v3 directory: ",(0,i.jsx)(n.code,{children:"32G data/tendermint/abci-state/mkvs_storage.badger.db"})]}),"\n"]}),(0,i.jsxs)(n.p,{children:["and now the ",(0,i.jsx)(n.code,{children:"blockstore.badger.db"})," is being migrated:"]}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"current BadgerDB v2 directory:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.code,{children:"55G data/tendermint/data/blockstore.badger.db"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["new BadgerDB v3 directory: ",(0,i.jsx)(n.code,{children:"16G data/tendermint/data/blockstore.badger.db.migration"})]}),"\n"]}),"\n"]}),(0,i.jsx)(n.p,{children:"Note that usually, the new BadgerDB v3 directory is smaller due to less fragmentation."})]}),"\n",(0,i.jsx)(n.h4,{id:"extra-storage-requirements",children:"Extra storage requirements"}),"\n",(0,i.jsx)(n.p,{children:"Your node will thus need to have extra storage space to store both the old and the new BadgerDB files."}),"\n",(0,i.jsxs)(n.p,{children:["To see estimate how much extra space the migration will need, use the ",(0,i.jsx)(n.code,{children:"du"})," tool:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"shopt -s globstar\ndu -h /**/*.badger.db | sort -h -r\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This is an example output from a Mainnet node that uses ",(0,i.jsx)(n.code,{children:"/srv/oasis/node"})," as the ",(0,i.jsx)(n.code,{children:""}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"43G\t/srv/oasis/node/tendermint/data/blockstore.badger.db\n28G\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db\n311M\t/srv/oasis/node/tendermint/data/state.badger.db\n2.0M\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints\n996K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601\n996K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601\n992K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601/ba6218d7be2df31ba6e7201a8585c6435154728e55bbb7df1ffebe683bf60217\n992K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601/1e0bf592bb0d99832b13ad91bc32aed018dfc2639e07b93a254a05f6791a19ac\n984K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4517601/ba6218d7be2df31ba6e7201a8585c6435154728e55bbb7df1ffebe683bf60217/chunks\n984K\t/srv/oasis/node/tendermint/abci-state/mkvs_storage.badger.db/checkpoints/4507601/1e0bf592bb0d99832b13ad91bc32aed018dfc2639e07b93a254a05f6791a19ac/chunks\n148K\t/srv/oasis/node/persistent-store.badger.db\n36K\t/srv/oasis/node/tendermint/data/evidence.badger.db\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["After you've confirmed your node is up and running, you can safely delete all the ",(0,i.jsx)(n.code,{children:"/**/*.badger.db.backup"})," files."]})}),"\n",(0,i.jsx)(n.h4,{id:"extra-memory-requirements",children:"Extra memory requirements"}),"\n",(0,i.jsx)(n.p,{children:"BadgerDB v2 to v3 migration can use a number of Go routines to migrate different database files in parallel."}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"badger.migrate.num_go_routines"}),") if your node has less than 8 GB of RAM."]}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"config.yml"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"# 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"})}),"\n",(0,i.jsx)(n.h3,{id:"installing-oasis-app-231-to-your-ledger",children:"Installing Oasis App 2.3.1 to Your Ledger"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["This manual installation procedure is needed until the latest version of the Oasis App, version 2.3.1, becomes available through ",(0,i.jsx)(n.a,{href:"https://www.ledger.com/ledger-live/",children:"Ledger Live"}),"'s Manager."]})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["Unlike Nano S devices, ",(0,i.jsx)(n.strong,{children:"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."]})}),"\n",(0,i.jsx)(n.h4,{id:"update-firmware-to-version-200",children:"Update Firmware to Version 2.0.0"}),"\n",(0,i.jsxs)(n.p,{children:["First, make sure the firmware on your Nano S is up-to-date. At least ",(0,i.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360010446000-Ledger-Nano-S-firmware-release-notes",children:"version 2.0.0"})," released on May 4, 2021, is required. Follow ",(0,i.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360002731113-Update-Ledger-Nano-S-firmware",children:"Ledger's instructions for updating the firmware on your Nano S"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"install-prerequisites-for-manual-installation",children:"Install Prerequisites for Manual Installation"}),"\n",(0,i.jsx)(n.p,{children:"The manual installation process relies on some tooling that needs to be available on the system:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://www.python.org",children:"Python"})," 3."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://github.com/LedgerHQ/blue-loader-python",children:"Python tools for Ledger Blue, Nano S and Nano X"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Most systems should already have ",(0,i.jsx)(n.a,{href:"https://www.python.org",children:"Python"})," pre-installed."]}),"\n",(0,i.jsxs)(n.p,{children:["To install ",(0,i.jsx)(n.a,{href:"https://github.com/LedgerHQ/blue-loader-python",children:"Python tools for Ledger Blue, Nano S and Nano X"}),", use ",(0,i.jsx)(n.a,{href:"https://pip.pypa.io/en/stable/",children:"pip"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"pip3 install --upgrade ledgerblue\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You might want to install the packages to a ",(0,i.jsx)(n.a,{href:"https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments",children:"Python virtual environment"})," or via so-called ",(0,i.jsx)(n.a,{href:"https://pip.pypa.io/en/stable/user_guide/#user-installs",children:"User install"})," (i.e. isolated to the current user)."]}),"\n",(0,i.jsx)(n.h4,{id:"download-oasis-app-231",children:"Download Oasis App 2.3.1"}),"\n",(0,i.jsxs)(n.p,{children:["Download the ",(0,i.jsx)(n.a,{href:"https://github.com/Zondax/ledger-oasis/releases/download/v2.3.1/installer_s.sh",children:"Oasis App 2.3.1 installer for Nano S"})," from ",(0,i.jsx)(n.a,{href:"https://github.com/Zondax/ledger-oasis",children:"Zondax's Oasis App GitHub repo"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"install-oasis-app-231",children:"Install Oasis App 2.3.1"}),"\n",(0,i.jsx)(n.p,{children:"Make the downloaded installer executable by running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"chmod +x installer_s.sh\n"})}),"\n",(0,i.jsx)(n.p,{children:"Connect you Nano S and unlock it. Then execute the installer:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"./installer_s.sh load\n"})}),"\n",(0,i.jsx)(n.p,{children:"Your Nano S will give you the option to either:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.em,{children:"Deny unsafe manager"}),", or"]}),"\n",(0,i.jsxs)(n.li,{children:["review the ",(0,i.jsx)(n.em,{children:"Public Key"})," and ",(0,i.jsx)(n.em,{children:"Allow unsafe manager"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["First review the public key and ensure it matches the ",(0,i.jsx)(n.code,{children:"Generated random root public key"})," displayed in the terminal."]}),"\n",(0,i.jsxs)(n.p,{children:["Then double press the ",(0,i.jsx)(n.em,{children:"Allow unsafe manager"})," option."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["If there is an existing version of the ",(0,i.jsx)(n.em,{children:"Oasis App"})," installed on your Nano S, you will be prompted with the ",(0,i.jsx)(n.em,{children:"Uninstall Oasis"})," screen, followed by reviewing the ",(0,i.jsx)(n.em,{children:"Identifier"})," (it will depend on the version of the Oasis App you have currently installed) and finally confirming deletion on the ",(0,i.jsx)(n.em,{children:"Confirm action"})," screen."]})}),"\n",(0,i.jsxs)(n.p,{children:["After the new version of the Oasis App has finished loading, you will be prompted with the ",(0,i.jsx)(n.em,{children:"Install app Oasis"})," screen, followed by reviewing the ",(0,i.jsx)(n.em,{children:"Version"}),", ",(0,i.jsx)(n.em,{children:"Identifier"})," and ",(0,i.jsx)(n.em,{children:"Code Identifier"})," screens_._ Ensure the values are as follows:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Version: 2.3.1"}),"\n",(0,i.jsxs)(n.li,{children:["Identifier (",(0,i.jsx)(n.em,{children:"Application full hash"})," on the terminal): ",(0,i.jsx)(n.code,{children:"E0CB424D3B1C2A0F694BCB6E99C3B37C7685399D59DD12D7CF80AF4A487882B1"})]}),"\n",(0,i.jsxs)(n.li,{children:["Code Identifier: ",(0,i.jsx)(n.code,{children:"C17EBE7CD356D01411A02A81C64CDA3E81F193BDA09BEBBD0AEAF75AD7EC35E3"})]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Finally, confirm installation of the new app by double pressing on the ",(0,i.jsx)(n.em,{children:"Perform installation"})," screen. Your Ledger device will ask for your PIN again."]}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.em,{children:"Identifier"})," when installing the app which will NOT match the ",(0,i.jsx)(n.em,{children:"Application full hash"}),' shown on the terminal. However, opening the app will not work and it will "freeze" your Nano S device.']})}),"\n",(0,i.jsx)(n.h4,{id:"verify-installation",children:"Verify Installation"}),"\n",(0,i.jsxs)(n.p,{children:["Open the Oasis App on your Nano S and ensure the ",(0,i.jsx)(n.em,{children:"Version"})," screen shows version 2.3.1."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Starting the manually installed version of the Oasis App will always show the ",(0,i.jsx)(n.em,{children:"This app is not genuine"})," screen, followed by ",(0,i.jsx)(n.em,{children:"Identifier"})," (which should match the Identifier value above) screen. Finally, open the application by double pressing on the ",(0,i.jsx)(n.em,{children:"Open application"})," screen."]})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["After you've signed your ",(0,i.jsx)(n.code,{children:"governance.CastVote"})," transaction, you can safely downgrade Oasis App to the latest official version available via ",(0,i.jsx)(n.a,{href:"https://www.ledger.com/ledger-live/",children:"Ledger Live"}),", version 1.8.2."]}),(0,i.jsx)(n.p,{children:"To do that, just open Ledger Live's Manager and it will prompt you to install version 1.8.2."})]}),"\n",(0,i.jsx)(n.h2,{id:"cobalt-upgrade",children:"2021-04-28 (16:00 UTC) - Cobalt Upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade height:"})," upgrade is scheduled to happen at epoch ",(0,i.jsx)(n.strong,{children:"5046."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Mainnet network to reach this epoch at around 2021-04-28 12:00 UTC."})}),"\n",(0,i.jsx)(n.h3,{id:"instructions---before-upgrade-1",children:"Instructions - Before upgrade"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Make sure you are running the latest Mainnet-compatible Oasis Node version: ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.7",children:"20.12.7"}),".","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["If you are running a different ",(0,i.jsx)(n.strong,{children:"20.12.x"})," Oasis Node version, update to version ",(0,i.jsx)(n.strong,{children:"20.12.7"})," before the upgrade."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Version ",(0,i.jsx)(n.strong,{children:"20.12.7"})," is backwards compatible with other ",(0,i.jsx)(n.strong,{children:"20.12.x"})," releases, so upgrade can be performed at any time by stopping the node and replacing the binary."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["To ensure your node will stop at epoch ",(0,i.jsx)(n.strong,{children:"5046"})," ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-create-proposal",children:"submit the following upgrade descriptor"})," at any time before the upgrade:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'{\n "name": "mainnet-upgrade-2021-04-28",\n "method": "internal",\n "identifier": "mainnet-upgrade-2021-04-28",\n "epoch": 5046\n}\n'})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.h4,{id:"runtime-operators",children:(0,i.jsx)(n.strong,{children:"Runtime operators"})}),"\n",(0,i.jsxs)(n.p,{children:["Following section is relevant only for ",(0,i.jsx)(n.strong,{children:"runtime operators"})," that are running ",(0,i.jsx)(n.strong,{children:"storage"})," nodes for active runtimes on the Mainnet."]}),"\n",(0,i.jsxs)(n.p,{children:["This upgrade requires a runtime storage node migration to be performed ",(0,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Backup your node's data directory"})}),"\n",(0,i.jsx)(n.p,{children:"To prevent irrecoverable runtime storage data corruption/loss in case of a failed storage migration, backup your node's data directory."}),"\n",(0,i.jsxs)(n.p,{children:["For example, to backup the ",(0,i.jsx)(n.code,{children:"/serverdir/node"})," directory using the ",(0,i.jsx)(n.a,{href:"https://rsync.samba.org",children:"rsync"})," tool, run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rsync -a /serverdir/node/ /serverdir/node-BACKUP/\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The storage database on all storage nodes needs to be migrated with the following command (using the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1.1",children:"21.1.1"})," binary):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node storage migrate \\\n --datadir \\\n --runtime.supported \n"})}),"\n",(0,i.jsx)(n.p,{children:"After the migration to v5 completes, you will see an output similar to:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"...\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"})}),"\n",(0,i.jsxs)(n.p,{children:["Take note of the displayed ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h3,{id:"instructions---upgrade-day-1",children:"Instructions - Upgrade day"}),"\n",(0,i.jsxs)(n.p,{children:["Following steps should be performed on ",(0,i.jsx)(n.strong,{children:"2021-04-28"})," only after the network has reached the upgrade epoch and has halted:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Download the genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2021-04-28",children:"Cobalt Upgrade release"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Mainnet state at epoch ",(0,i.jsx)(n.strong,{children:"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."]})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Verify the provided Cobalt upgrade genesis file by comparing it to network state dump. See instructions in the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades#verify-genesis",children:"Handling Network Upgrades"})," guide."]}),"\n",(0,i.jsx)(n.li,{children:"Replace the old genesis file with the new Cobalt upgrade genesis file."}),"\n",(0,i.jsx)(n.li,{children:"Stop your node (if you haven't stopped it already by submitting the upgrade descriptor)."}),"\n",(0,i.jsxs)(n.li,{children:["Replace the old version of Oasis Node with version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v21.1.1",children:"21.1.1"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For more detailed instructions, see the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades",children:"Handling Network Upgrades"})," guide."]})}),"\n",(0,i.jsx)(n.h3,{id:"additional-notes-1",children:"Additional notes"}),"\n",(0,i.jsxs)(n.p,{children:["Examine the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.1.1/CHANGELOG.md",children:"Change Log"})," of the 21.1.1 (and 21.0) releases."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Runtime operators"})}),"\n",(0,i.jsxs)(n.p,{children:["Note the following configuration change in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v21.1.1/CHANGELOG.md#configuration-changes",children:"21.0"})," release."]}),"\n",(0,i.jsxs)(n.admonition,{type:"caution",children:[(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Storage access policy changes"})}),(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"worker.storage.public_rpc.enabled"})," flag set to ",(0,i.jsx)(n.code,{children:"true"}),"."]}),(0,i.jsx)(n.p,{children:"Otherwise, external runtime clients wont be able to connect to any storage nodes."})]}),"\n",(0,i.jsx)(n.h2,{id:"mainnet-upgrade",children:"2020-11-18 (16:00 UTC) - Mainnet"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Block height"})," when Mainnet Beta network stops: ",(0,i.jsx)(n.strong,{children:"702000."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We expect the Mainnet Beta network to reach this block height at around 2020-11-18 13:30 UTC."})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Upgrade window:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Start: ",(0,i.jsx)(n.strong,{children:"2020-11-18T16:00:00Z."})]}),"\n",(0,i.jsxs)(n.li,{children:["End: After nodes representing ",(0,i.jsx)(n.strong,{children:"2/3+ stake"})," do the upgrade."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"instructions",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Download ",(0,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node"})," version ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.2",children:"20.12.2"}),", while continuing to run version 20.10.x."]}),"\n",(0,i.jsx)(n.li,{children:"(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."}),"\n",(0,i.jsxs)(n.li,{children:["Download the Mainnet genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-11-18",children:"2020-11-18 release"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["(optional) Verify the provided Mainnet genesis file by comparing it to network state dump. See instructions in the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades#verify-genesis",children:"Handling Network Upgrades"})," guide."]}),"\n",(0,i.jsx)(n.li,{children:"Replace the old Mainnet Beta genesis file with the Mainnet genesis file."}),"\n",(0,i.jsx)(n.li,{children:"Stop your node."}),"\n",(0,i.jsx)(n.li,{children:"Remove the old 20.10.x version of Oasis Node."}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["Update your node's configuration per instructions in ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#configuration-changes",children:"Configuration changes"})," below."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["This time, we recommend dumping the network state with the upgraded Oasis Node binary so that the genesis file will be in the ",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#canonical-form",children:"canonical form"}),"."]}),(0,i.jsx)(n.p,{children:"The canonical form will make it easier to compare the obtained genesis file with the one provided by us."})]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For more detailed instructions, see the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades",children:"Handling Network Upgrades"})," guide."]})}),"\n",(0,i.jsx)(n.h3,{id:"configuration-changes-1",children:"Configuration changes"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"consensus.tendermint.abci.prune"})," key."]}),"\n",(0,i.jsx)(n.p,{children:"For example, this configuration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"...\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"})}),"\n",(0,i.jsx)(n.p,{children:"Becomes:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"...\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"})}),"\n",(0,i.jsx)(n.h2,{id:"mainnet-beta-upgrade",children:"2020-10-01 - Mainnet Beta"}),"\n",(0,i.jsx)(n.h3,{id:"instructions-1",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Stop your node."}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wipe state"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["Replace the old genesis file with the Mainnet Beta genesis file published in the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/tag/2020-10-01",children:"2020-10-01 release"}),"."]}),"\n",(0,i.jsx)(n.li,{children:"Start your node."}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"You should keep using Oasis Core version 20.10."})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["For more detailed instructions, see the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades",children:"Handling Network Upgrades"})," guide."]})}),"\n",(0,i.jsx)(n.h2,{id:"mainnet-dry-run",children:"2020-09-22 - Mainnet Dry Run"}),"\n",(0,i.jsx)(n.h3,{id:"instructions-2",children:"Instructions"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"This is the initial deployment."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var i=s(6540);const r={},t=i.createContext(r);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a1e8ae9c.5a4cac2b.js b/assets/js/a1e8ae9c.5a4cac2b.js new file mode 100644 index 0000000000..2ecb071431 --- /dev/null +++ b/assets/js/a1e8ae9c.5a4cac2b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9484],{8509:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"operators","navigation":{"previous":{"title":"Eden Upgrade","permalink":"/node/mainnet/eden-upgrade"},"next":{"title":"Damask Upgrade","permalink":"/node/mainnet/previous-upgrades/damask-upgrade"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/a2066b59.882ce97c.js b/assets/js/a2066b59.882ce97c.js new file mode 100644 index 0000000000..132fb71bb4 --- /dev/null +++ b/assets/js/a2066b59.882ce97c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3774],{8208:s=>{s.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"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/a71e7da1.132b9162.js b/assets/js/a71e7da1.132b9162.js new file mode 100644 index 0000000000..456cb698a5 --- /dev/null +++ b/assets/js/a71e7da1.132b9162.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2190],{9546:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var o=t(4848),i=t(8453);const r={},s="Shutting Down a Node",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/shutting-down-a-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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={},c=[];function u(e){const n={admonition:"admonition",code:"code",h1:"h1",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"shutting-down-a-node",children:"Shutting Down a Node"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.p,{children:"The graceful shutdown process involves the following steps:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"Ensure your service manager (e.g. systemd) will not restart the node after\nexit. Otherwise the node may re-register on startup and you will need to wait\nanother epoch for it to expire."}),"\n",(0,o.jsx)(n.li,{children:"Halt the automatic re-registration."}),"\n",(0,o.jsx)(n.li,{children:"Wait for the node's existing registration to expire."}),"\n",(0,o.jsx)(n.li,{children:"Terminate the node binary."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"To have the node gracefully shutdown, run:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"# 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"})}),"\n",(0,o.jsx)(n.admonition,{type:"caution",children:(0,o.jsx)(n.p,{children:"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 for."})})]})}function l(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>a});var o=t(6540);const i={},r=o.createContext(i);function s(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7bd4aaa.f1b88cfd.js b/assets/js/a7bd4aaa.f1b88cfd.js new file mode 100644 index 0000000000..2ab8bf3d69 --- /dev/null +++ b/assets/js/a7bd4aaa.f1b88cfd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7098],{4532:(n,s,e)=>{e.r(s),e.d(s,{default:()=>d});e(6540);var o=e(1003),r=e(2967),i=e(2252),t=e(2831),c=e(1463),a=e(4848);function u(n){const{version:s}=n;return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{version:s.version,tag:(0,r.tU)(s.pluginId,s.version)}),(0,a.jsx)(o.be,{children:s.noIndex&&(0,a.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(n){const{version:s,route:e}=n;return(0,a.jsx)(o.e3,{className:s.className,children:(0,a.jsx)(i.n,{version:s,children:(0,t.v)(e.routes)})})}function d(n){return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(u,{...n}),(0,a.jsx)(l,{...n})]})}}}]); \ No newline at end of file diff --git a/assets/js/a7d941e7.7554295c.js b/assets/js/a7d941e7.7554295c.js new file mode 100644 index 0000000000..6554258e2d --- /dev/null +++ b/assets/js/a7d941e7.7554295c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6635],{784:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var t=a(4848),s=a(8453);const i={title:"ParaTime",description:"Managing ParaTimes"},r="Managing Your ParaTimes",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/paratime.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,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"}},d={},o=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"managing-your-paratimes",children:"Managing Your ParaTimes"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"paratime"})," command lets you manage your ParaTime configurations bound to a\nspecific ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network",children:"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."]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["When running the Oasis CLI for the first time, it will automatically configure\nofficial Oasis ParaTimes running on the ",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"})," and ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"})," networks."]})}),"\n",(0,t.jsx)(n.h2,{id:"add",children:"Add a ParaTime"}),"\n",(0,t.jsxs)(n.p,{children:["Invoke ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.a,{href:"/core/runtime/identifiers",children:"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,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"})," and ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"})," pages."]}),"\n",(0,t.jsx)(n.p,{children:"Each ParaTime also has a native token denomination symbol defined with specific\nnumber of decimal places which you will need to specify."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime add testnet sapphire2 000000000000000000000000000000000000000000000000a6d1e3ebf60dff6d\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"? Description: \n? Denomination symbol: TEST\n? Denomination decimal places: 18\n"})}),"\n",(0,t.jsxs)(n.admonition,{title:"Decimal places of the native and ParaTime token may differ!",type:"danger",children:[(0,t.jsxs)(n.p,{children:["Emerald and Sapphire use ",(0,t.jsx)(n.strong,{children:"18 decimals"})," for compatibility with\nEthereum tooling. The Oasis Mainnet and Testnet consensus layer tokens and the\ntoken native to Cipher have ",(0,t.jsx)(n.strong,{children:"9 decimals"}),"."]}),(0,t.jsx)(n.p,{children:"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!"})]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you configured your network with the ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network#add-local",children:(0,t.jsx)(n.code,{children:"network add-local"})})," command, then all\nregistered ParaTimes of that network will be detected and added to your Oasis\nCLI config automatically."]})}),"\n",(0,t.jsx)(n.h2,{id:"list",children:"List ParaTimes"}),"\n",(0,t.jsxs)(n.p,{children:["Invoke ",(0,t.jsx)(n.code,{children:"paratime list"})," to list all configured ParaTimes across the networks."]}),"\n",(0,t.jsx)(n.p,{children:"For example, at time of writing this section the following ParaTimes were\npreconfigured by the Oasis CLI:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime list\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"NETWORK\tPARATIME \tID \nmainnet\tcipher \t000000000000000000000000000000000000000000000000e199119c992377cb\t\nmainnet\temerald \t000000000000000000000000000000000000000000000000e2eaa99fc008f87f\t\nmainnet\tsapphire (*)\t000000000000000000000000000000000000000000000000f80306c9858e7279\t\ntestnet\tcipher \t0000000000000000000000000000000000000000000000000000000000000000\t\ntestnet\temerald \t00000000000000000000000000000000000000000000000072c8215e60d5bca7\t\ntestnet\tpontusx \t0000000000000000000000000000000000000000000000004febe52eb412b421\t\ntestnet\tsapphire (*)\t000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\t\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.a,{href:"#set-default",children:"default ParaTime"})," for each network is marked with the ",(0,t.jsx)(n.code,{children:"(*)"}),"\nsign."]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"ParaTimes on this list are configured inside your Oasis CLI instance. They\nmay not actually exist on the network."})}),"\n",(0,t.jsx)(n.h2,{id:"remove",children:"Remove a ParaTime"}),"\n",(0,t.jsxs)(n.p,{children:["To remove a configuration of a ParaTime for a specific network, use\n",(0,t.jsx)(n.code,{children:"paratime remove "}),". For example, let's remove the\n",(0,t.jsx)(n.a,{href:"#add",children:"previously added"})," ParaTime:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime list\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"NETWORK\tPARATIME \tID \nmainnet\tcipher \t000000000000000000000000000000000000000000000000e199119c992377cb\t\nmainnet\temerald (*)\t000000000000000000000000000000000000000000000000e2eaa99fc008f87f\t\nmainnet\tsapphire \t000000000000000000000000000000000000000000000000f80306c9858e7279\t\ntestnet\tcipher \t0000000000000000000000000000000000000000000000000000000000000000\t\ntestnet\temerald (*)\t00000000000000000000000000000000000000000000000072c8215e60d5bca7\t\ntestnet\tpontusx \t0000000000000000000000000000000000000000000000004febe52eb412b421\t\ntestnet\tsapphire \t000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\t\ntestnet\tsapphire2 \t000000000000000000000000000000000000000000000000a6d1e3ebf60dff6d\t\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime remove testnet sapphire2\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime list\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"NETWORK\tPARATIME \tID \nmainnet\tcipher \t000000000000000000000000000000000000000000000000e199119c992377cb\t\nmainnet\temerald (*)\t000000000000000000000000000000000000000000000000e2eaa99fc008f87f\t\nmainnet\tsapphire \t000000000000000000000000000000000000000000000000f80306c9858e7279\t\ntestnet\tcipher \t0000000000000000000000000000000000000000000000000000000000000000\t\ntestnet\temerald (*)\t00000000000000000000000000000000000000000000000072c8215e60d5bca7\t\ntestnet\tpontusx \t0000000000000000000000000000000000000000000000004febe52eb412b421\t\ntestnet\tsapphire \t000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\t\n"})}),"\n",(0,t.jsx)(n.h2,{id:"set-default",children:"Set Default ParaTime"}),"\n",(0,t.jsxs)(n.p,{children:["To change the default ParaTime for Oasis CLI transactions on the specific\nnetwork, use ",(0,t.jsx)(n.code,{children:"paratime set-default "}),"."]}),"\n",(0,t.jsx)(n.p,{children:"For example, to set the Cipher ParaTime default on the Testnet, run:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime set-default testnet cipher\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime list\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"NETWORK\tPARATIME \tID \nmainnet\tcipher \t000000000000000000000000000000000000000000000000e199119c992377cb\t\nmainnet\temerald \t000000000000000000000000000000000000000000000000e2eaa99fc008f87f\t\nmainnet\tsapphire (*)\t000000000000000000000000000000000000000000000000f80306c9858e7279\t\ntestnet\tcipher (*) \t0000000000000000000000000000000000000000000000000000000000000000\t\ntestnet\temerald \t00000000000000000000000000000000000000000000000072c8215e60d5bca7\t\ntestnet\tpontusx \t0000000000000000000000000000000000000000000000004febe52eb412b421\t\ntestnet\tsapphire \t000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c\t\n"})}),"\n",(0,t.jsx)(n.h2,{id:"show",children:"Show"}),"\n",(0,t.jsxs)(n.p,{children:["Use ",(0,t.jsx)(n.code,{children:"paratime show "})," providing the block round to print its header and\nother information."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime show 5850612\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime show 5850612 0\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'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'})}),"\n",(0,t.jsx)(n.p,{children:"Encrypted transactions can also be examined, although the data chunk will be\nencrypted:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime show 1078544 0 --network testnet --paratime sapphire\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'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'})}),"\n",(0,t.jsx)(n.h2,{id:"advanced",children:"Advanced"}),"\n",(0,t.jsx)(n.h3,{id:"register",children:"Register a New ParaTime"}),"\n",(0,t.jsxs)(n.p,{children:["ParaTime developers may add a new ParaTime to the network's registry by\ninvoking the ",(0,t.jsx)(n.code,{children:"paratime register "})," command and providing a JSON file\nwith the ParaTime descriptor. You can use the\n",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-id",children:(0,t.jsx)(n.code,{children:"network show"})})," command passing the ParaTime ID to\nsee how descriptors of the currently registered ParaTimes look like."]}),"\n",(0,t.jsxs)(n.p,{children:["To learn more about registering your own ParaTime, check the\n",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#register-runtime",children:"Oasis Core Registry service"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"statistics",children:"Statistics"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.p,{children:"The passed block number should be enumerated based on the round\ninside the ParaTime. The start round can be one of the following:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"If no round given, the validation of the last block will be examined."}),"\n",(0,t.jsxs)(n.li,{children:["If a negative round number ",(0,t.jsx)(n.code,{children:"N"})," is passed, the last ",(0,t.jsx)(n.code,{children:"N"})," blocks will be\nexamined."]}),"\n",(0,t.jsxs)(n.li,{children:["If ",(0,t.jsx)(n.code,{children:"0"})," is given, the oldest block available to the Oasis endpoint will be\nconsidered as a starting block."]}),"\n",(0,t.jsx)(n.li,{children:"A positive number will be considered as a start round."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"At time of writing, the following statistics was available:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime statistics\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"=== 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"})}),"\n",(0,t.jsx)(n.p,{children:"To extend statistics to, say 5 last blocks, you can run:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime statistics -- -5\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"=== 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"})}),"\n",(0,t.jsxs)(n.p,{children:["For further analysis, you can easily export entity statistics to a CSV file by\npassing the ",(0,t.jsx)(n.code,{children:"--output-file"})," parameter and the file name:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis paratime statistics -o stats.csv\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"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!"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>r,x:()=>c});var t=a(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a89bcaa3.6b8c05a8.js b/assets/js/a89bcaa3.6b8c05a8.js new file mode 100644 index 0000000000..9e348a2339 --- /dev/null +++ b/assets/js/a89bcaa3.6b8c05a8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9689],{1565:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>i,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var a=s(4848),o=s(8453);const r={},t="ADR 0016: Consensus Parameters Change Proposal",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0016-consensus-parameters-change-proposal.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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={},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:"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}];function c(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"adr-0016-consensus-parameters-change-proposal",children:"ADR 0016: Consensus Parameters Change Proposal"}),"\n",(0,a.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,a.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,a.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"2022-09-15: Initial version"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,a.jsx)(n.p,{children:"Proposed"}),"\n",(0,a.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,a.jsx)(n.p,{children:"Implement governance proposal which changes consensus parameters only."}),"\n",(0,a.jsx)(n.h2,{id:"implementation",children:"Implementation"}),"\n",(0,a.jsx)(n.h3,{id:"new-proposal",children:"New proposal"}),"\n",(0,a.jsxs)(n.p,{children:["A new type of governance proposal named ",(0,a.jsx)(n.code,{children:"ChangeParametersProposal"})," should be\nadded to the consensus layer. The proposal should contain two non-empty fields:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["the name of the consensus ",(0,a.jsx)(n.code,{children:"Module"})," the changes should be applied to, and,"]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["a CBOR-encoded document ",(0,a.jsx)(n.code,{children:"Changes"})," describing parameter changes."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.code,{children:"Changes"})," are\ncomplete and well-formed and that there is exactly one module to which changes\nwill be applied."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:"// ValidateBasic performs a basic validation on the change parameters proposal.\nfunc (p *ChangeParametersProposal) ValidateBasic() error {\n // Validate that both fields are set.\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The new proposal should be added to the ",(0,a.jsx)(n.code,{children:"ProposalContent"}),". The extension should\nstill allow only one proposal at a time, so we must not forget to update\nthe code responsible for validation."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:'type ProposalContent struct {\n ...\n ChangeParameters *ChangeParametersProposal `json:"change_parameters,omitempty"`\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"parameter-changes",children:"Parameter changes"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,a.jsxs)(n.p,{children:["To prevent invalid proposals being submitted, ",(0,a.jsx)(n.code,{children:"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)."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:"// SanityCheck performs a sanity check on the consensus parameters changes.\nfunc (c *ConsensusParameterChanges) SanityCheck() error {\n // Validate changes.\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"How changes are executed is up to the module implementation."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:"// Apply applies changes to the given consensus parameters.\nfunc (c *ConsensusParameterChanges) Apply(params *ConsensusParameters) error {\n // Apply changes.\n}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"submission",children:"Submission"}),"\n",(0,a.jsxs)(n.p,{children:["When a new ",(0,a.jsx)(n.code,{children:"ChangeParametersProposal"})," is submitted a basic validation is\nperformed first which checks whether the ",(0,a.jsx)(n.code,{children:"Module"})," name and ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["The module should carefully examine the proposal, check whether the proposal\nis well-formed, ",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.h3,{id:"execution",children:"Execution"}),"\n",(0,a.jsxs)(n.p,{children:["If ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.code,{children:"Changes"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["That module should first fetch current consensus parameters, then apply\nproposed ",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:"// SanityCheck performs a sanity check on the consensus parameters.\nfunc (p *ConsensusParameters) SanityCheck() error {\n // Validate parameters.\n}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"how-to-enable-the-new-proposal",children:"How to enable the new proposal"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,a.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,a.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Agile and zero-downtime consensus parameter changes."}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:"Separation of consensus parameter changes and consensus upgrades."}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"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."}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,a.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,a.jsx)(n.p,{children:"No references."})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>l});var a=s(6540);const o={},r=a.createContext(o);function t(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a94703ab.c7415789.js b/assets/js/a94703ab.c7415789.js new file mode 100644 index 0000000000..434e82ea62 --- /dev/null +++ b/assets/js/a94703ab.c7415789.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9048],{2559:(e,t,n)=>{n.r(t),n.d(t,{default:()=>be});var a=n(6540),o=n(4164),i=n(1003),s=n(7559),l=n(4142),r=n(6588),c=n(1312),d=n(3104),u=n(5062);const m={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};var b=n(4848);function h(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),i=(0,a.useRef)(!1),{startScroll:s,cancelScroll:l}=(0,d.gk)();return(0,d.Mq)(((e,n)=>{let{scrollY:a}=e;const s=n?.scrollY;s&&(i.current?i.current=!1:a>=s?(l(),o(!1)):a{e.location.hash&&(i.current=!0,o(!1))})),{shown:n,scrollToTop:()=>s(0)}}({threshold:300});return(0,b.jsx)("button",{"aria-label":(0,c.T)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.A)("clean-btn",s.G.common.backToTopButton,m.backToTopButton,e&&m.backToTopButtonShow),type:"button",onClick:t})}var p=n(3109),x=n(6347),j=n(4581),f=n(6342),_=n(3465);function v(e){return(0,b.jsx)("svg",{width:"20",height:"20","aria-hidden":"true",...e,children:(0,b.jsxs)("g",{fill:"#7a7a7a",children:[(0,b.jsx)("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"}),(0,b.jsx)("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 A={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function g(e){let{onClick:t}=e;return(0,b.jsx)("button",{type:"button",title:(0,c.T)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,c.T)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.A)("button button--secondary button--outline",A.collapseSidebarButton),onClick:t,children:(0,b.jsx)(v,{className:A.collapseSidebarButtonIcon})})}var k=n(5041),C=n(9532);const S=Symbol("EmptyContext"),T=a.createContext(S);function N(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),i=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return(0,b.jsx)(T.Provider,{value:i,children:t})}var I=n(1422),B=n(9169),y=n(8774),w=n(2303);function L(e){let{collapsed:t,categoryLabel:n,onClick:a}=e;return(0,b.jsx)("button",{"aria-label":t?(0,c.T)({id:"theme.DocSidebarItem.expandCategoryAriaLabel",message:"Expand sidebar category '{label}'",description:"The ARIA label to expand the sidebar category"},{label:n}):(0,c.T)({id:"theme.DocSidebarItem.collapseCategoryAriaLabel",message:"Collapse sidebar category '{label}'",description:"The ARIA label to collapse the sidebar category"},{label:n}),"aria-expanded":!t,type:"button",className:"clean-btn menu__caret",onClick:a})}function E(e){let{item:t,onItemClick:n,activePath:i,level:r,index:c,...d}=e;const{items:u,label:m,collapsible:h,className:p,href:x}=t,{docs:{sidebar:{autoCollapseCategories:j}}}=(0,f.p)(),_=function(e){const t=(0,w.A)();return(0,a.useMemo)((()=>e.href&&!e.linkUnlisted?e.href:!t&&e.collapsible?(0,l.Nr)(e):void 0),[e,t])}(t),v=(0,l.w8)(t,i),A=(0,B.ys)(x,i),{collapsed:g,setCollapsed:k}=(0,I.u)({initialState:()=>!!h&&(!v&&t.collapsed)}),{expandedItem:N,setExpandedItem:E}=function(){const e=(0,a.useContext)(T);if(e===S)throw new C.dV("DocSidebarItemsExpandedStateProvider");return e}(),M=function(e){void 0===e&&(e=!g),E(e?null:c),k(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const i=(0,C.ZC)(t);(0,a.useEffect)((()=>{t&&!i&&n&&o(!1)}),[t,i,n,o])}({isActive:v,collapsed:g,updateCollapsed:M}),(0,a.useEffect)((()=>{h&&null!=N&&N!==c&&j&&k(!0)}),[h,N,c,k,j]),(0,b.jsxs)("li",{className:(0,o.A)(s.G.docs.docSidebarItemCategory,s.G.docs.docSidebarItemCategoryLevel(r),"menu__list-item",{"menu__list-item--collapsed":g},p),children:[(0,b.jsxs)("div",{className:(0,o.A)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":A}),children:[(0,b.jsx)(y.A,{className:(0,o.A)("menu__link",{"menu__link--sublist":h,"menu__link--sublist-caret":!x&&h,"menu__link--active":v}),onClick:h?e=>{n?.(t),x?M(!1):(e.preventDefault(),M())}:()=>{n?.(t)},"aria-current":A?"page":void 0,role:h&&!x?"button":void 0,"aria-expanded":h&&!x?!g:void 0,href:h?_??"#":_,...d,children:m}),x&&h&&(0,b.jsx)(L,{collapsed:g,categoryLabel:m,onClick:e=>{e.preventDefault(),M()}})]}),(0,b.jsx)(I.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:g,children:(0,b.jsx)(U,{items:u,tabIndex:g?-1:0,onItemClick:n,activePath:i,level:r+1})})]})}var M=n(6654),H=n(3186);const G={menuExternalLink:"menuExternalLink_NmtK"};function W(e){let{item:t,onItemClick:n,activePath:a,level:i,index:r,...c}=e;const{href:d,label:u,className:m,autoAddBaseUrl:h}=t,p=(0,l.w8)(t,a),x=(0,M.A)(d);return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(i),"menu__list-item",m),children:(0,b.jsxs)(y.A,{className:(0,o.A)("menu__link",!x&&G.menuExternalLink,{"menu__link--active":p}),autoAddBaseUrl:h,"aria-current":p?"page":void 0,to:d,...x&&{onClick:n?()=>n(t):void 0},...c,children:[u,!x&&(0,b.jsx)(H.A,{})]})},u)}const P={menuHtmlItem:"menuHtmlItem_M9Kj"};function R(e){let{item:t,level:n,index:a}=e;const{value:i,defaultStyle:l,className:r}=t;return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(n),l&&[P.menuHtmlItem,"menu__list-item"],r),dangerouslySetInnerHTML:{__html:i}},a)}function D(e){let{item:t,...n}=e;switch(t.type){case"category":return(0,b.jsx)(E,{item:t,...n});case"html":return(0,b.jsx)(R,{item:t,...n});default:return(0,b.jsx)(W,{item:t,...n})}}function F(e){let{items:t,...n}=e;const a=(0,l.Y)(t,n.activePath);return(0,b.jsx)(N,{children:a.map(((e,t)=>(0,b.jsx)(D,{item:e,index:t,...n},t)))})}const U=(0,a.memo)(F),V={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function Y(e){let{path:t,sidebar:n,className:i}=e;const l=function(){const{isActive:e}=(0,k.Mj)(),[t,n]=(0,a.useState)(e);return(0,d.Mq)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return(0,b.jsx)("nav",{"aria-label":(0,c.T)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.A)("menu thin-scrollbar",V.menu,l&&V.menuWithAnnouncementBar,i),children:(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:n,activePath:t,level:1})})})}const K="sidebar_njMd",z="sidebarWithHideableNavbar_wUlq",q="sidebarHidden_VK0M",O="sidebarLogo_isFc";function J(e){let{path:t,sidebar:n,onCollapse:a,isHidden:i}=e;const{navbar:{hideOnScroll:s},docs:{sidebar:{hideable:l}}}=(0,f.p)();return(0,b.jsxs)("div",{className:(0,o.A)(K,s&&z,i&&q),children:[s&&(0,b.jsx)(_.A,{tabIndex:-1,className:O}),(0,b.jsx)(Y,{path:t,sidebar:n}),l&&(0,b.jsx)(g,{onClick:a})]})}const Q=a.memo(J);var X=n(5600),Z=n(2069);const $=e=>{let{sidebar:t,path:n}=e;const a=(0,Z.M)();return(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&a.toggle(),"link"===e.type&&a.toggle()},level:1})})};function ee(e){return(0,b.jsx)(X.GX,{component:$,props:e})}const te=a.memo(ee);function ne(e){const t=(0,j.l)(),n="desktop"===t||"ssr"===t,a="mobile"===t;return(0,b.jsxs)(b.Fragment,{children:[n&&(0,b.jsx)(Q,{...e}),a&&(0,b.jsx)(te,{...e})]})}const ae={expandButton:"expandButton_TmdG",expandButtonIcon:"expandButtonIcon_i1dp"};function oe(e){let{toggleSidebar:t}=e;return(0,b.jsx)("div",{className:ae.expandButton,title:(0,c.T)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,c.T)({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,children:(0,b.jsx)(v,{className:ae.expandButtonIcon})})}const ie={docSidebarContainer:"docSidebarContainer_YfHR",docSidebarContainerHidden:"docSidebarContainerHidden_DPk8",sidebarViewport:"sidebarViewport_aRkj"};function se(e){let{children:t}=e;const n=(0,r.t)();return(0,b.jsx)(a.Fragment,{children:t},n?.name??"noSidebar")}function le(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:i}=e;const{pathname:l}=(0,x.zy)(),[r,c]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{r&&c(!1),!r&&(0,p.O)()&&c(!0),i((e=>!e))}),[i,r]);return(0,b.jsx)("aside",{className:(0,o.A)(s.G.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&c(!0)},children:(0,b.jsx)(se,{children:(0,b.jsxs)("div",{className:(0,o.A)(ie.sidebarViewport,r&&ie.sidebarViewportHidden),children:[(0,b.jsx)(ne,{sidebar:t,path:l,onCollapse:d,isHidden:r}),r&&(0,b.jsx)(oe,{toggleSidebar:d})]})})})}const re={docMainContainer:"docMainContainer_TBSr",docMainContainerEnhanced:"docMainContainerEnhanced_lQrH",docItemWrapperEnhanced:"docItemWrapperEnhanced_JWYK"};function ce(e){let{hiddenSidebarContainer:t,children:n}=e;const a=(0,r.t)();return(0,b.jsx)("main",{className:(0,o.A)(re.docMainContainer,(t||!a)&&re.docMainContainerEnhanced),children:(0,b.jsx)("div",{className:(0,o.A)("container padding-top--md padding-bottom--lg",re.docItemWrapper,t&&re.docItemWrapperEnhanced),children:n})})}const de={docRoot:"docRoot_UBD9",docsWrapper:"docsWrapper_hBAB"};function ue(e){let{children:t}=e;const n=(0,r.t)(),[o,i]=(0,a.useState)(!1);return(0,b.jsxs)("div",{className:de.docsWrapper,children:[(0,b.jsx)(h,{}),(0,b.jsxs)("div",{className:de.docRoot,children:[n&&(0,b.jsx)(le,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:i}),(0,b.jsx)(ce,{hiddenSidebarContainer:o,children:t})]})]})}var me=n(3363);function be(e){const t=(0,l.B5)(e);if(!t)return(0,b.jsx)(me.A,{});const{docElement:n,sidebarName:a,sidebarItems:c}=t;return(0,b.jsx)(i.e3,{className:(0,o.A)(s.G.page.docsDocPage),children:(0,b.jsx)(r.V,{name:a,items:c,children:(0,b.jsx)(ue,{children:n})})})}},3363:(e,t,n)=>{n.d(t,{A:()=>l});n(6540);var a=n(4164),o=n(1312),i=n(1107),s=n(4848);function l(e){let{className:t}=e;return(0,s.jsx)("main",{className:(0,a.A)("container margin-vert--xl",t),children:(0,s.jsx)("div",{className:"row",children:(0,s.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,s.jsx)(i.A,{as:"h1",className:"hero__title",children:(0,s.jsx)(o.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"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/a9e87a2c.96b490ac.js b/assets/js/a9e87a2c.96b490ac.js new file mode 100644 index 0000000000..b5aba1f58c --- /dev/null +++ b/assets/js/a9e87a2c.96b490ac.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5187],{3980:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var s=n(4848),a=n(8453),i=n(5965),r=n(6116);const o={},l="Oasis Network",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"general",previous:{title:"Overview",permalink:"/general/"},next:{title:"Why Oasis?",permalink:"/general/oasis-network/why-oasis"}},d={},h=[{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}];function u(e){const t={h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"oasis-network",children:"Oasis Network"}),"\n",(0,s.jsx)(t.p,{children:"The Oasis Network is a Layer 1 decentralized blockchain network designed to be uniquely scalable, privacy-first and versatile."}),"\n",(0,s.jsx)(t.p,{children:"The Network has two main architectural components, the consensus layer and the ParaTime layer."}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["The ",(0,s.jsx)(t.strong,{children:"consensus layer"})," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."]}),"\n",(0,s.jsxs)(t.li,{children:["The ",(0,s.jsx)(t.strong,{children:"ParaTime layer"})," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Oasis architectural design including ParaTime and consensus layers",src:n(141).A+"",width:"1523",height:"718"})}),"\n",(0,s.jsx)(t.h2,{id:"technology-highlights",children:"Technology Highlights"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Separates consensus and execution into two layers"})," \u2014 the consensus layer and the ParaTime layer \u2014 for better scalability and increased versatility."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["Separation of consensus and execution allows ",(0,s.jsx)(t.strong,{children:"multiple ParaTimes to process transactions in parallel"}),", meaning complex workloads processed on one ParaTime won\u2019t slow down faster, simpler transactions on another."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The ParaTime layer is entirely decentralized, allowing ",(0,s.jsx)(t.strong,{children:"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."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The network\u2019s sophisticated discrepancy detection makes Oasis ",(0,s.jsx)(t.strong,{children:"more efficient than sharding and parachains"})," \u2014 requiring a smaller replication factor for the same level of security."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"benefits-of-the-oasis-network-technology-stack",children:"Benefits of the Oasis Network Technology Stack"}),"\n",(0,s.jsx)(t.h3,{id:"scalability",children:"Scalability"}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h3,{id:"privacy-first",children:"Privacy-First"}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Client, Key Manager, Compute Node diagram",src:n(695).A+""})}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h3,{id:"versatility",children:"Versatility"}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.h3,{id:"learn-more",children:"Learn more"}),"\n",(0,s.jsx)(i.A,{item:(0,r.$)("/general/oasis-network/why-oasis")})]})}function p(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var s=n(4164),a=n(8774),i=n(4142),r=n(5846),o=n(6654),l=n(1312),c=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=n(4848);function u(e){let{href:t,children:n}=e;return(0,h.jsx)(a.A,{href:t,className:(0,s.A)("card padding--lg",d.cardContainer),children:n})}function p(e){let{href:t,icon:n,title:a,description:i}=e;return(0,h.jsxs)(u,{href:t,children:[(0,h.jsxs)(c.A,{as:"h2",className:(0,s.A)("text--truncate",d.cardTitle),title:a,children:[n," ",a]}),i&&(0,h.jsx)("p",{className:(0,s.A)("text--truncate",d.cardDescription),title:i,children:i})]})}function m(e){let{item:t}=e;const n=(0,i.Nr)(t),s=function(){const{selectMessage:e}=(0,r.W)();return t=>e(t,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,h.jsx)(p,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??s(t.items.length)}):null}function f(e){let{item:t}=e;const n=(0,o.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",s=(0,i.cC)(t.docId??void 0);return(0,h.jsx)(p,{href:t.href,icon:n,title:t.label,description:t.description??s?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,h.jsx)(f,{item:t});case"category":return(0,h.jsx)(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},5846:(e,t,n)=>{n.d(t,{W:()=>c});var s=n(6540),a=n(4586);const i=["zero","one","two","few","many","other"];function r(e){return i.filter((t=>e.includes(t)))}const o={locale:"en",pluralForms:r(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,a.A)();return(0,s.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:r(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`),o}}),[e])}function c(){const e=l();return{selectMessage:(t,n)=>function(e,t,n){const s=e.split("|");if(1===s.length)return s[0];s.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${s.length}: ${e}`);const a=n.select(t),i=n.pluralForms.indexOf(a);return s[Math.min(i,s.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>i});var s=n(2252);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,s.r)();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]}},695:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/client-km-compute-e82d4c5748974134adbf78d76ca7bc03.svg"},141:(e,t,n)=>{n.d(t,{A:()=>s});const s=n.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var s=n(6540);const a={},i=s.createContext(a);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ab39d68c.ee142198.js b/assets/js/ab39d68c.ee142198.js new file mode 100644 index 0000000000..5e45b81653 --- /dev/null +++ b/assets/js/ab39d68c.ee142198.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3475],{8713:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var s=r(4848),n=r(8453);const a={},i="Merklized Key-Value Store (MKVS)",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/mkvs.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Authenticated gRPC",permalink:"/core/authenticated-grpc"},next:{title:"Processes",permalink:"/core/processes"}},c={},d=[{value:"Interfaces",id:"interfaces",level:2},{value:"Updates",id:"updates",level:3},{value:"Read Syncer",id:"read-syncer",level:3}];function l(e){const t={a:"a",h1:"h1",h2:"h2",h3:"h3",p:"p",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"merklized-key-value-store-mkvs",children:"Merklized Key-Value Store (MKVS)"}),"\n",(0,s.jsxs)(t.p,{children:["For all places that require an ",(0,s.jsx)(t.a,{href:"https://www.cs.umd.edu/~mwh/papers/gpads.pdf",children:"authenticated data structure (ADS)"})," we provide\nan implementation of a Merklized Key-Value Store, internally implemented as a\nMerklized ",(0,s.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Radix_tree#PATRICIA",children:"Patricia trie"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"interfaces",children:"Interfaces"}),"\n",(0,s.jsx)(t.h3,{id:"updates",children:"Updates"}),"\n",(0,s.jsx)(t.h3,{id:"read-syncer",children:"Read Syncer"})]})}function u(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>i,x:()=>o});var s=r(6540);const n={},a=s.createContext(n);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ab8e36ce.6e6017b5.js b/assets/js/ab8e36ce.6e6017b5.js new file mode 100644 index 0000000000..1bcaf94ebf --- /dev/null +++ b/assets/js/ab8e36ce.6e6017b5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1028],{4642:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var a=s(4848),t=s(8453);const r={description:"Transfer, deposit, withdraw and delegate your ROSE"},i="Manage your Tokens",o={id:"general/manage-tokens/README",title:"Manage your Tokens",description:"Transfer, deposit, withdraw and delegate your ROSE",source:"@site/docs/general/manage-tokens/README.mdx",sourceDirName:"general/manage-tokens",slug:"/general/manage-tokens/",permalink:"/general/manage-tokens/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Transfer, deposit, withdraw and delegate your ROSE"},sidebar:"general",previous:{title:"Frequently Asked Questions",permalink:"/general/oasis-network/faq"},next:{title:"Terminology",permalink:"/general/manage-tokens/terminology"}},l={},d=[{value:"ROSE and the ParaTimes",id:"rose-and-the-paratimes",level:2},{value:"Obtaining ROSE",id:"obtaining-rose",level:2},{value:"The Wallets",id:"the-wallets",level:2},{value:"Official Non-Custodial Wallets",id:"official-non-custodial-wallets",level:3},{value:"MetaMask",id:"metamask",level:3},{value:"Ledger",id:"ledger",level:3},{value:"Custodial Services",id:"custodial-services",level:3},{value:"Account Formats and Signature Schemes",id:"account-formats-and-signature-schemes",level:2},{value:"Check your account",id:"check-your-account",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"manage-your-tokens",children:"Manage your Tokens"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.strong,{children:"native token"})," on Oasis Mainnet is called ",(0,a.jsx)(n.strong,{children:"ROSE"}),". Native tokens are used\nfor:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["proof-of-stake ",(0,a.jsx)(n.strong,{children:"block proposal and validation"}),","]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"governance proposal voting"}),","]}),"\n",(0,a.jsxs)(n.li,{children:["paying out ",(0,a.jsx)(n.strong,{children:"staking rewards"}),","]}),"\n",(0,a.jsxs)(n.li,{children:["paying ",(0,a.jsx)(n.strong,{children:"network gas fees"}),","]}),"\n",(0,a.jsx)(n.li,{children:"dApp-specific use cases."}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"rose-and-the-paratimes",children:"ROSE and the ParaTimes"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network architecture"})," separates between the ",(0,a.jsx)(n.strong,{children:"consensus"})," and the\n",(0,a.jsx)(n.strong,{children:"compute"})," (a.k.a. ParaTime) layer. The consensus layer and each ParaTime\nrunning on the compute layer have their own ",(0,a.jsx)(n.strong,{children:"ledger"})," containing, among othe\ndata, the ",(0,a.jsx)(n.strong,{children:"balances of the accounts"}),"."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Deposits, withdrawals, transfers",src:s(2962).A+"",width:"1523",height:"718"})}),"\n",(0,a.jsxs)(n.p,{children:["Moving tokens from the consensus layer to a ParaTime is called a ",(0,a.jsx)(n.strong,{children:"deposit"})," and\nmoving them from a ParaTime back to the consensus layer is a ",(0,a.jsx)(n.strong,{children:"withdrawal"})," (see\n",(0,a.jsx)(n.a,{href:"/adrs/0003-consensus-runtime-token-transfer",children:"ADR-3"})," for technical specifications)."]}),"\n",(0,a.jsxs)(n.p,{children:["You can ",(0,a.jsx)(n.strong,{children:"transfer"})," tokens from your account to another account only, if both\naccounts are either on the consensus layer or inside the same ParaTime."]}),"\n",(0,a.jsxs)(n.p,{children:["Besides moving the tokens across layers and accounts, you can also ",(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.a,{href:"/general/manage-tokens/staking-and-delegating",children:"delegate\ntokens"})})," to a validator and ",(0,a.jsx)(n.strong,{children:"earn passive income"})," as a reward."]}),"\n",(0,a.jsx)(n.h2,{id:"obtaining-rose",children:"Obtaining ROSE"}),"\n",(0,a.jsxs)(n.p,{children:["The most common way to obtain ROSE is by buying it on a centralized\n",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Cryptocurrency_exchange",children:"cryptocurrency exchange"}),". At time of writing this chapter, ",(0,a.jsx)(n.strong,{children:"all exchanges\nsupported the consensus layer only"}),". This means that you can withdraw\ntokens from the exchange only to ",(0,a.jsx)(n.strong,{children:"your consensus account"}),". Use the ",(0,a.jsx)(n.a,{href:"#official-non-custodial-wallets",children:"ROSE\nWallet"})," to ",(0,a.jsx)(n.strong,{children:"create one"})," and also to ",(0,a.jsx)(n.strong,{children:"deposit\nROSE to Sapphire"}),", if you want to use your tokens in a dApp afterwards."]}),"\n",(0,a.jsxs)(n.p,{children:["An alternative way to obtain ROSE is by swapping another cryptocurrency for\nROSE on a ",(0,a.jsxs)(n.strong,{children:[(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Decentralized_finance#Decentralized_exchanges",children:"decentralized exchange"})," (DEX) running on Sapphire"]}),". In this case,\nthe payout is made to ",(0,a.jsx)(n.strong,{children:"your account on Sapphire"})," directly, and you can use a\nstandard ",(0,a.jsx)(n.a,{href:"#metamask",children:"Ethereum-compatible wallet"})," to manage it."]}),"\n",(0,a.jsx)(n.h2,{id:"the-wallets",children:"The Wallets"}),"\n",(0,a.jsxs)(n.p,{children:["To sign the token-related transactions such as transfers, deposits, withdrawals\nand delegations described above, you need a ",(0,a.jsx)(n.strong,{children:"private key"})," tied to the\ncorresponding account. Your keys are stored in ",(0,a.jsx)(n.em,{children:(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Cryptocurrency_wallet",children:"crypto wallets"})}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"caution",children:(0,a.jsxs)(n.p,{children:["For your own security and peace of mind, please only use the wallets that are\nlisted here. ",(0,a.jsx)(n.strong,{children:"Using unofficial wallets can result in the permanent loss of your\nROSE!"})]})}),"\n",(0,a.jsx)(n.h3,{id:"official-non-custodial-wallets",children:"Official Non-Custodial Wallets"}),"\n",(0,a.jsxs)(n.p,{children:["The Oasis team developed the following ",(0,a.jsx)(n.strong,{children:"non-custodial wallets"})," for you. This\nmeans that the keys for managing the tokens are ",(0,a.jsx)(n.strong,{children:"stored on your device"})," such\nas a laptop or a mobile phone and ",(0,a.jsx)(n.strong,{children:"you are responsible to keep it safe"}),":"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web",children:"ROSE Wallet - Web"})}),": Runs as a web application in your web browser, the\nprivate keys are encrypted with a password and stored inside your Browser's\nlocal store."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/browser-extension",children:"ROSE Wallet - Browser extension"})}),": Runs as an extension to your\nChrome-based browser, the private keys are encrypted with a password and\nstored inside your Browser's encrypted store."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})}),": Runs in a command line, suitable for automation, the private\nkeys are encrypted by a password and stored inside your home folder."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"metamask",children:"MetaMask"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://metamask.io/download/",children:"MetaMask"})," is probably the best-known crypto wallet. However, it is an\n",(0,a.jsx)(n.strong,{children:"EVM-compatible"})," wallet. This means ",(0,a.jsx)(n.strong,{children:"you can only use it to check the account\nbalances and sign transactions on Sapphire and Emerald chains"}),". You cannot use\nit, for example, to sign ",(0,a.jsx)(n.strong,{children:"consensus layer transactions"})," or perform\n",(0,a.jsx)(n.strong,{children:"deposits"})," and ",(0,a.jsx)(n.strong,{children:"withdrawals"})," to and from ParaTimes."]}),"\n",(0,a.jsxs)(n.p,{children:['You can add the Sapphire RPC endpoint by clicking on the "Add to MetaMask"\nbutton next to your preferred Mainnet endpoint provider in the ',(0,a.jsx)(n.a,{href:"/dapp/sapphire/#rpc-endpoints",children:"Sapphire"}),"\nchapter."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Metamask - Adding Sapphire Mainnet Network Configuration",src:s(4053).A+"",width:"363",height:"623"})}),"\n",(0,a.jsx)(n.h3,{id:"ledger",children:"Ledger"}),"\n",(0,a.jsxs)(n.p,{children:["The wallets above are just carefully programmed computer programs that store\nyour keys (in an encrypted form) somewhere on your disk and then use them to\nsign the transactions. However, if your device gets infected with a piece of\nmalicious software (malware, key loggers, screen captures), ",(0,a.jsx)(n.strong,{children:"the password to\ndecrypt your private keys may be obtained and your private keys stolen"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["To mitigate such attacks, a ",(0,a.jsx)(n.strong,{children:"hardware wallet"})," should be used. This is a\nphysical device which stores your private key and which is only accessed when\nyou send the hardware wallet a transaction to be signed. The transaction content\nis then shown on the hardware wallet screen for a user to verify and if the\nuser agrees, the transaction is signed and sent back to your computer or your\nmobile phone for submission to the network. The Oasis team ",(0,a.jsx)(n.strong,{children:"integrated support\nfor Ledger hardware wallets into all ROSE wallets and the Oasis CLI"}),". Check out\na special ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Ledger chapter"})," to learn how to install the Oasis nano app\non your Ledger device."]}),"\n",(0,a.jsx)(n.h3,{id:"custodial-services",children:"Custodial Services"}),"\n",(0,a.jsxs)(n.p,{children:["It is up to you to pick the right strategy for keeping the private key of your\naccount holding your tokens safe. Some users may decide to trust their tokens to\na ",(0,a.jsx)(n.strong,{children:"custody provider"}),". You can read more about those in the\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/custody-providers",children:"Custody providers"})," chapter."]}),"\n",(0,a.jsx)(n.h2,{id:"account-formats-and-signature-schemes",children:"Account Formats and Signature Schemes"}),"\n",(0,a.jsxs)(n.p,{children:["Transactions on the consensus layer must be signed using the ",(0,a.jsx)(n.strong,{children:"ed25519\nsignature scheme"}),". The addresses on the consensus layer use the\n",(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32",children:"Bech-32 encoding"})})," and you can recognize them by a typical ",(0,a.jsx)(n.code,{children:"oasis1"})," prefix."]}),"\n",(0,a.jsxs)(n.p,{children:["ParaTimes can implement arbitrary signature schemes and address encodings. For\nexample, since the Sapphire and Emerald ParaTimes are EVM-compatible, they\nimplement the ",(0,a.jsx)(n.strong,{children:"secp256k1"})," scheme and prefer the ",(0,a.jsx)(n.strong,{children:"hex-encoded"}),"\naddresses and private keys starting with ",(0,a.jsx)(n.code,{children:"0x"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"The table below summarizes the current state of the address formats, signature\nschemes and compatible wallets."}),"\n",(0,a.jsxs)(n.table,{children:[(0,a.jsx)(n.thead,{children:(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.th,{children:"Consensus or ParaTime"}),(0,a.jsx)(n.th,{children:"Address Format"}),(0,a.jsx)(n.th,{children:"Digital Signature Scheme"}),(0,a.jsx)(n.th,{children:"Supported Wallets"})]})}),(0,a.jsxs)(n.tbody,{children:[(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"Consensus"}),(0,a.jsx)(n.td,{children:(0,a.jsx)(n.code,{children:"oasis1"})}),(0,a.jsx)(n.td,{children:"ed25519"}),(0,a.jsx)(n.td,{children:(0,a.jsxs)("ul",{children:[(0,a.jsx)("li",{children:"ROSE Wallet - Web"}),(0,a.jsx)("li",{children:"ROSE Wallet - Browser Extension"}),(0,a.jsx)("li",{children:"Oasis CLI"})]})})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"Sapphire"}),(0,a.jsxs)(n.td,{children:[(0,a.jsx)(n.code,{children:"0x"}),", ",(0,a.jsx)(n.code,{children:"oasis1"})]}),(0,a.jsx)(n.td,{children:"secp256k1, ed25519, sr25519"}),(0,a.jsx)(n.td,{children:(0,a.jsxs)("ul",{children:[(0,a.jsx)("li",{children:"Metamask and other EVM-compatible wallets (transfers only)"}),(0,a.jsx)("li",{children:"ROSE Wallet - Browser Extension"}),(0,a.jsx)("li",{children:"ROSE Wallet - Web (deposits and withdrawals only)"}),(0,a.jsx)("li",{children:"Oasis CLI"})]})})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"Cipher"}),(0,a.jsx)(n.td,{children:(0,a.jsx)(n.code,{children:"oasis1"})}),(0,a.jsx)(n.td,{children:"secp256k1, ed25519, sr25519"}),(0,a.jsx)(n.td,{children:(0,a.jsx)("ul",{children:(0,a.jsx)("li",{children:"Oasis CLI"})})})]}),(0,a.jsxs)(n.tr,{children:[(0,a.jsx)(n.td,{children:"Emerald"}),(0,a.jsxs)(n.td,{children:[(0,a.jsx)(n.code,{children:"0x"}),", ",(0,a.jsx)(n.code,{children:"oasis1"})]}),(0,a.jsx)(n.td,{children:"secp256k1, ed25519, sr25519"}),(0,a.jsx)(n.td,{children:(0,a.jsxs)("ul",{children:[(0,a.jsx)("li",{children:"Metamask and other EVM-compatible wallets (transfers only)"}),(0,a.jsx)("li",{children:"ROSE Wallet - Browser Extension"}),(0,a.jsx)("li",{children:"ROSE Wallet - Web (deposits and withdrawals only)"}),(0,a.jsx)("li",{children:"Oasis CLI"})]})})]})]})]}),"\n",(0,a.jsx)(n.h2,{id:"check-your-account",children:"Check your account"}),"\n",(0,a.jsxs)(n.p,{children:["To check the balance of your consensus account, you can use the\n",(0,a.jsx)(n.a,{href:"https://www.oasisscan.com",children:"Oasis Scan"})," block explorer. Enter your ",(0,a.jsx)(n.code,{children:"oasis1"}),"\naddress at the top and hit enter. For example:"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Account details of entered oasis1 address in Oasis Scan",src:s(926).A+"",width:"1273",height:"958"})}),"\n",(0,a.jsx)(n.p,{children:'The "Amount" is a sum of three values:'}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:'the "Available" tokens that can immediately be transferred,'}),"\n",(0,a.jsx)(n.li,{children:'the "Escrow" tokens that are delegated,'}),"\n",(0,a.jsx)(n.li,{children:'the "Reclaim" tokens that are waiting for the debonding period to pass.'}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:'To check the account\'s deposits and withdrawals navigate to "Transactions" pane\nand press "ParaTime" on the right side, next to the "Consensus" button.\nYou will see all ParaTime-related transactions including deposits, withdrawals,\ntransfers and even smart contract transactions.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Search result of oasis1 address - Account details",src:s(4492).A+"",width:"1626",height:"979"})}),"\n",(0,a.jsx)(n.p,{children:'Furthermore, you can view the transaction details, if you click on a\ntransaction\'s "Tx Hash". Among others, you will see the transaction type, the\n"from", "to" and "amount" fields.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Tx Hash - Transaction details",src:s(5419).A+"",width:"1626",height:"979"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:["Be aware that the ",(0,a.jsx)(n.a,{href:"https://www.oasisscan.com",children:"Oasis Scan Blockchain Explorer"}),"\nis built for consensus layer. If you want to explore Sapphire (0x addresses,\nToken Transfers, Contract Calls, etc.), you have to use the\n",(0,a.jsx)(n.a,{href:"https://explorer.oasis.io/mainnet/sapphire",children:"Sapphire Blockchain Explorer"}),"."]})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},926:(e,n,s)=>{s.d(n,{A:()=>a});const a=s.p+"assets/images/oasisscan_account_details-7d22b004206bda2502eee1ff799f731c.png"},5419:(e,n,s)=>{s.d(n,{A:()=>a});const a=s.p+"assets/images/oasisscan_paratime_tx_details-9769c53959d64e58ffa4a387b78aede5.png"},4492:(e,n,s)=>{s.d(n,{A:()=>a});const a=s.p+"assets/images/oasisscan_paratime_txes-e8560712be9b215cd6aca4ceb52c892f.png"},2962:(e,n,s)=>{s.d(n,{A:()=>a});const a=s.p+"assets/images/transfer_deposit_withdrawal-53746f908d877b4df255879762c41fa5.svg"},4053:(e,n,s)=>{s.d(n,{A:()=>a});const a=s.p+"assets/images/settings-939608ea8571e8881597cf3b86e09c98.png"},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>o});var a=s(6540);const t={},r=a.createContext(t);function i(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aba21aa0.b1904455.js b/assets/js/aba21aa0.b1904455.js new file mode 100644 index 0000000000..52c4c0701b --- /dev/null +++ b/assets/js/aba21aa0.b1904455.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5742],{7093:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/acdeae29.c2ca0f2a.js b/assets/js/acdeae29.c2ca0f2a.js new file mode 100644 index 0000000000..7d525481e2 --- /dev/null +++ b/assets/js/acdeae29.c2ca0f2a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9099],{2453:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>i,metadata:()=>d,toc:()=>h});var a=t(4848),r=t(8453),o=t(5965),s=t(6116);const i={},l="Writing dApps on Emerald",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/emerald/writing-dapps-on-emerald.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Emerald ParaTime",permalink:"/dapp/emerald/"},next:{title:"Tools & Services",permalink:"/dapp/tools/"}},c={},h=[{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 Remix - Ethereum IDE",id:"create-dapp-on-emerald-with-remix---ethereum-ide",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Truffle Support",id:"truffle-support",level:3},{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}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"writing-dapps-on-emerald",children:"Writing dApps on Emerald"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsx)(n.p,{children:"We will walk you through the Hardhat configuration and - for those who prefer\na 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!"}),"\n",(0,a.jsx)(n.h2,{id:"oasis-consensus-layer-and-emerald-paratime",children:"Oasis Consensus Layer and Emerald ParaTime"}),"\n",(0,a.jsxs)(n.p,{children:["Oasis Network consists of the consensus layer and a number of Layer 2 chains\ncalled the ParaTimes (to learn more, check the ",(0,a.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network\nOverview"})," chapter). Emerald is a ParaTime which implements the Ethereum\nVirtual Machine (EVM)."]}),"\n",(0,a.jsxs)(n.p,{children:["The minimum and also expected block time in Emerald is ",(0,a.jsx)(n.strong,{children:"6 seconds"}),". Any\nEmerald transaction will require at least this amount of time to be executed."]}),"\n",(0,a.jsxs)(n.p,{children:["The native Oasis addresses are Bech32-encoded (e.g. ",(0,a.jsx)(n.code,{children:"oasis1qpupfu7e2n6pkezeaw0yhj8mcem8anj64ytrayne"}),")\nwhile Emerald supports both the Bech32-encoded and the Ethereum-compatible\nhex-encoded addresses (e.g. ",(0,a.jsx)(n.code,{children:"0x90adE3B7065fa715c7a150313877dF1d33e777D5"}),"). The\nunderlying algorithm for signing the transactions is ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/EdDSA#Ed25519",children:"Ed25519"})," on the Consensus\nlayer and both ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/EdDSA#Ed25519",children:"Ed25519"})," and ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm",children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["Finally, the ParaTimes are not allowed to directly access your tokens stored in\nConsensus layer addresses. You will need to ",(0,a.jsx)(n.strong,{children:"deposit"})," tokens from your consensus\naccount to Emerald. Consult the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/",children:"How to transfer ROSE into Emerald\nParaTime"})," chapter to learn more."]}),"\n",(0,a.jsx)(n.h2,{id:"testnet-and-mainnet",children:"Testnet and Mainnet"}),"\n",(0,a.jsxs)(n.p,{children:["The Oasis Network currently has, similar to some other blockchains, two major\npublic deployments: the ",(0,a.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"})," and the ",(0,a.jsx)(n.a,{href:"/node/testnet/",children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["The Emerald ParaTime is deployed similarly: the ",(0,a.jsx)(n.a,{href:"/dapp/emerald/#mainnet",children:"Emerald Mainnet"})," is deployed on the Oasis Mainnet\nNetwork while the ",(0,a.jsx)(n.a,{href:"/dapp/emerald/#testnet",children:"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."]}),"\n",(0,a.jsx)(n.admonition,{title:"Never deploy production service on Testnet",type:"danger",children:(0,a.jsxs)(n.p,{children:["Because Testnet state can be wiped in the future, you should ",(0,a.jsx)(n.strong,{children:"never deploy a\nproduction service on the Testnet"}),"!"]})}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["For testing purposes, visit our ",(0,a.jsx)(n.a,{href:"https://faucet.testnet.oasis.io/",children:"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."]})}),"\n",(0,a.jsx)(n.h2,{id:"running-a-private-oasis-network-locally",children:"Running a Private Oasis Network Locally"}),"\n",(0,a.jsxs)(n.p,{children:["For convenient development and testing of your dApps the Oasis team prepared\nthe ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"ghcr.io/oasisprotocol/emerald-localnet"})," Docker image which brings you a complete Oasis\nstack to your desktop. This network is isolated from the Mainnet or Testnet and\nconsists of:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"single Oasis validator node with 1-second block time and 30-second epoch,"}),"\n",(0,a.jsx)(n.li,{children:"single Oasis client node,"}),"\n",(0,a.jsx)(n.li,{children:"three compute nodes running Oasis Emerald,"}),"\n",(0,a.jsx)(n.li,{children:"PostgreSQL instance,"}),"\n",(0,a.jsx)(n.li,{children:"Oasis Web3 gateway with transaction indexer,"}),"\n",(0,a.jsx)(n.li,{children:"helper script which populates initial test accounts for you."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"To run the image, execute:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-localnet\n"})}),"\n",(0,a.jsx)(n.p,{children:"After a while, the tool will show you something like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"emerald-localnet 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"})}),"\n",(0,a.jsxs)(n.p,{children:["Those familiar with local dApp environments will find the output above similar\nto ",(0,a.jsx)(n.code,{children:"geth --dev"})," or ",(0,a.jsx)(n.code,{children:"ganache-cli"})," commands or the ",(0,a.jsx)(n.code,{children:"geth-dev-assistant"})," npm\npackage. ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"})," will spin up a private Oasis Network locally, generate\nand populate test accounts and make the following Web3 endpoints available for\nyou to use:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"http://localhost:8545"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.code,{children:"ws://localhost:8546"})}),"\n"]}),"\n",(0,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsxs)(n.p,{children:["If you prefer using the same mnemonics each time (e.g. for testing purposes)\nor to populate just a single wallet, use ",(0,a.jsx)(n.code,{children:"-to"})," flag and pass the mnemonics or\nthe wallet addresses. For example"]}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:'docker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-localnet -to "bench remain brave curve frozen verify dream margin alarm world repair innocent"\ndocker run -it -p8545:8545 -p8546:8546 ghcr.io/oasisprotocol/emerald-localnet -to "0x75eCF0d4496C2f10e4e9aF3D4d174576Ee9010E2,0xbDA5747bFD65F08deb54cb465eB87D40e51B197E"\n'})})]}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"})," runs in ephemeral mode. Any smart contract and wallet balance\nwill be lost after you quit the Docker container!"]})}),"\n",(0,a.jsx)(n.h2,{id:"create-dapp-on-emerald-with-hardhat",children:"Create dApp on Emerald with Hardhat"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsxs)(n.p,{children:["First, make sure you installed ",(0,a.jsx)(n.a,{href:"https://nodejs.org",children:"Node.js"})," and that you have ",(0,a.jsx)(n.code,{children:"npm"})," and ",(0,a.jsx)(n.code,{children:"npx"}),"\nreadily available. Then run:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"npx hardhat init\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Select the ",(0,a.jsx)(n.code,{children:"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."]}),"\n",(0,a.jsx)(n.p,{children:"To compile, deploy and test the smart contract of your sample project locally,\nmove to your project directory and type:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"$ 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"})}),"\n",(0,a.jsxs)(n.p,{children:["Hardhat already comes with a built-in EVM which is spun up from scratch each\ntime we call ",(0,a.jsx)(n.code,{children:"hardhat test"})," without parameters. It populates 20 accounts with\nETH and registers them to the ",(0,a.jsx)(n.a,{href:"https://docs.ethers.io/v5/",children:"ethers.js"})," instance used in the tests."]}),"\n",(0,a.jsxs)(n.p,{children:["Next, let's look at how to configure Hardhat for Emerald. For convenience, we\nassign the ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"}),", use any of the five generated private keys."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'export PRIVATE_KEY="YOUR_0x_EMERALD_PRIVATE_KEY"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Next, we configure three networks: ",(0,a.jsx)(n.code,{children:"emerald_local"}),", ",(0,a.jsx)(n.code,{children:"emerald_testnet"}),", and\n",(0,a.jsx)(n.code,{children:"emerald_mainnet"}),". Open ",(0,a.jsx)(n.code,{children:"hardhat.config.ts"})," and replace the ",(0,a.jsx)(n.code,{children:"networks"})," field to\nmatch the following:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'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.io",\n accounts:\n process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],\n },\n emerald_mainnet: {\n url: "https://emerald.oasis.io",\n accounts:\n process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [],\n },\n },\n'})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"}),", but is required for Testnet to avoid timeouts. Append the\nfollowing block to the ",(0,a.jsx)(n.code,{children:"config"})," object:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"mocha: {\n timeout: 60000\n}\n"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"geth --dev"})," and ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"}),"\nsupport such mode and the new block will always be mined at least after the 1\nsecond block time elapsed."]})}),"\n",(0,a.jsxs)(n.p,{children:["Now deploy the contract to the local ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"})," Docker container by\nselecting the ",(0,a.jsx)(n.code,{children:"emerald_local"})," network we configured above and run the tests:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"$ 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"})}),"\n",(0,a.jsxs)(n.p,{children:["Next, you can try deploying the contract to the Testnet. Temporarily replace\nyour ",(0,a.jsx)(n.code,{children:"PRIVATE_KEY"})," environment variable with your Testnet one and deploy the\ncontract by using the ",(0,a.jsx)(n.code,{children:"emerald_testnet"})," network. Similarly, you can also\nrun the tests."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'$ 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'})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"https://explorer.oasis.io/mainnet/emerald",children:"Mainnet"}),", ",(0,a.jsx)(n.a,{href:"https://explorer.oasis.io/testnet/emerald",children:"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."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Emerald Block Explorer showing the latest transactions",src:t(2420).A+"",width:"2205",height:"1335"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Emerald Block Explorer showing our account 0x90adE3B7065fa715c7a150313877dF1d33e777D5 used for deploying the smart contract",src:t(7071).A+"",width:"2208",height:"1339"})}),"\n",(0,a.jsxs)(n.p,{children:["Finally, by selecting the ",(0,a.jsx)(n.code,{children:"emerald_mainnet"})," network and the corresponding\nprivate key, we can deploy the contract on the Mainnet:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:'$ 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'})}),"\n",(0,a.jsx)(n.h2,{id:"create-dapp-on-emerald-with-remix---ethereum-ide",children:"Create dApp on Emerald with Remix - Ethereum IDE"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.a,{href:"https://remix.ethereum.org",children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["If you haven't done it yet, first ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/#check-your-account",children:"install the MetaMask extension for your\nbrowser"}),". Import your wallet and configure Emerald Testnet and\nMainnet Networks. If you wish to connect to ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/pkgs/container/emerald-localnet",children:"emerald-localnet"})," container, configure\nthe local network as well."]}),"\n",(0,a.jsx)(n.p,{children:'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.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"The initial example project in Remix - Ethereum IDE",src:t(1830).A+"",width:"2219",height:"1332"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Solidity compiler tab",src:t(9389).A+"",width:"2217",height:"1338"})}),"\n",(0,a.jsx)(n.p,{children:'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.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Metamask transaction confirmation",src:t(6356).A+"",width:"2219",height:"1332"})}),"\n",(0,a.jsx)(n.p,{children:"If everything goes well, your transaction will be deployed using the selected\naccount in the MetaMask and the corresponding Emerald Network."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Successful contract deployment on Emerald Testnet with Remix",src:t(6267).A+"",width:"2219",height:"1332"})}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsx)(n.p,{children:"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%."})}),"\n",(0,a.jsxs)(n.p,{children:["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,a.jsx)(n.a,{href:"https://oasis.io/discord",children:"#emerald-paratime Discord channel"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,a.jsx)(n.h3,{id:"truffle-support",children:"Truffle Support"}),"\n",(0,a.jsx)(n.admonition,{title:"Sunsetting Truffle",type:"info",children:(0,a.jsxs)(n.p,{children:["Per Consensys ",(0,a.jsx)(n.a,{href:"https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat",children:"announcement"}),", Oasis will no longer support Truffle as of\n2023-10-05 and encourage immediate ",(0,a.jsx)(n.a,{href:"https://trufflesuite.com/docs/truffle/how-to/migrate-to-hardhat/",children:"migration"})," to Hardhat. Please see our\nrepository for the archived Truffle ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/docs/blob/207a7b1a42b4afdac70b925e755f5546723e4831/docs/dapp/emerald/writing-dapps-on-emerald.mdx#L330-L570",children:"tutorial"}),"."]})}),"\n",(0,a.jsx)(n.h3,{id:"deployment-of-my-contract-timed-out-on-testnet-or-mainnet",children:"Deployment of my contract timed out on Testnet or Mainnet"}),"\n",(0,a.jsx)(n.p,{children:"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."}),"\n",(0,a.jsxs)(n.p,{children:["Next, check that your ",(0,a.jsx)(n.code,{children:"gasPrice"})," ",(0,a.jsx)(n.strong,{children:"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."]}),"\n",(0,a.jsxs)(n.p,{children:["Finally, consider increasing the ",(0,a.jsx)(n.code,{children:"gasPrice"})," parameter in the Hardhat config\nfile 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."]}),"\n",(0,a.jsx)(n.h3,{id:"execution-of-my-contract-failed-how-do-i-debug-what-went-wrong",children:"Execution of my contract failed. How do I debug what went wrong?"}),"\n",(0,a.jsxs)(n.p,{children:["If you are using Testnet or Mainnet, try to debug your transaction by finding\nit on the Emerald block explorer (",(0,a.jsx)(n.a,{href:"https://explorer.oasis.io/mainnet/emerald",children:"Mainnet"}),", ",(0,a.jsx)(n.a,{href:"https://explorer.oasis.io/testnet/emerald",children:"Testnet"}),"):"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Emerald block explorer showing a failed transaction",src:t(6959).A+"",width:"2219",height:"1332"})}),"\n",(0,a.jsxs)(n.p,{children:["In some cases, the transaction result on Emerald block explorer might be stuck\nat ",(0,a.jsx)(n.code,{children:"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,a.jsx)(n.a,{href:"https://oasisscan.com",children:"Mainnet"}),",\n",(0,a.jsx)(n.a,{href:"https://testnet.oasisscan.com",children:"Testnet"}),") which is primarily a Consensus layer explorer, but\noffers some introspection into ParaTime transactions as well. Once you find your\nfailed Emerald transaction, the ",(0,a.jsx)(n.code,{children:"Status"})," field should contain a more verbose\nerror description, for example:"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Oasis Scan showing the Out of gas error for a transaction on Emerald",src:t(8052).A+"",width:"2219",height:"1332"})}),"\n",(0,a.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,a.jsx)(o.A,{item:(0,s.$)("/node/run-your-node/paratime-client-node")}),"\n",(0,a.jsx)(o.A,{item:(0,s.$)("/node/web3")})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(p,{...e})}):p(e)}},5965:(e,n,t)=>{t.d(n,{A:()=>g});t(6540);var a=t(4164),r=t(8774),o=t(4142),s=t(5846),i=t(6654),l=t(1312),d=t(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:n,children:t}=e;return(0,h.jsx)(r.A,{href:n,className:(0,a.A)("card padding--lg",c.cardContainer),children:t})}function m(e){let{href:n,icon:t,title:r,description:o}=e;return(0,h.jsxs)(p,{href:n,children:[(0,h.jsxs)(d.A,{as:"h2",className:(0,a.A)("text--truncate",c.cardTitle),title:r,children:[t," ",r]}),o&&(0,h.jsx)("p",{className:(0,a.A)("text--truncate",c.cardDescription),title:o,children:o})]})}function u(e){let{item:n}=e;const t=(0,o.Nr)(n),a=function(){const{selectMessage:e}=(0,s.W)();return n=>e(n,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return t?(0,h.jsx)(m,{href:t,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??a(n.items.length)}):null}function f(e){let{item:n}=e;const t=(0,i.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",a=(0,o.cC)(n.docId??void 0);return(0,h.jsx)(m,{href:n.href,icon:t,title:n.label,description:n.description??a?.description})}function g(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(f,{item:n});case"category":return(0,h.jsx)(u,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},5846:(e,n,t)=>{t.d(n,{W:()=>d});var a=t(6540),r=t(4586);const o=["zero","one","two","few","many","other"];function s(e){return o.filter((n=>e.includes(n)))}const i={locale:"en",pluralForms:s(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,r.A)();return(0,a.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:s(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),i}}),[e])}function d(){const e=l();return{selectMessage:(n,t)=>function(e,n,t){const a=e.split("|");if(1===a.length)return a[0];a.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${a.length}: ${e}`);const r=t.select(n),o=t.pluralForms.indexOf(r);return a[Math.min(o,a.length-1)]}(t,n,e)}}},6116:(e,n,t)=>{t.d(n,{$:()=>o});var a=t(2252);function r(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&r(n.items)}}function o(e){const n=(0,a.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)r(n.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]}},2420:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/block_explorer1-300ad8505c206bca6ecb6416836e6770.png"},7071:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/block_explorer2-c07d43edbfeb9e90e1b38710179e9062.png"},6959:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/oasisscan1-024c1033c1ceeff4ca4f4294f544ce9c.png"},8052:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/oasisscan2-00e68913dfa621eb7c5f170e3b2f6378.png"},1830:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/remix1-400bc72123a178beea4c86d2ba9857cd.png"},9389:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/remix2-66fd8dbfe9f2a299501f5f9c75bdd08d.png"},6356:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/remix3-e2db0ab19df6a1aff70c68018b93e897.png"},6267:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/remix4-41183efd0966503c866863efba485d1c.png"},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>i});var a=t(6540);const r={},o=a.createContext(r);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b11f73a1.6899f594.js b/assets/js/b11f73a1.6899f594.js new file mode 100644 index 0000000000..b58113b4d3 --- /dev/null +++ b/assets/js/b11f73a1.6899f594.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7373],{8056:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>p,frontMatter:()=>o,metadata:()=>d,toc:()=>h});var t=a(4848),s=a(8453),i=a(2550),r=a(6116);const o={description:"Web3 gateway for Emerald and Sapphire ParaTimes"},l="Oasis Web3 Gateway for your EVM ParaTime",d={id:"node/web3",title:"Oasis Web3 Gateway for your EVM ParaTime",description:"Web3 gateway for Emerald and Sapphire ParaTimes",source:"@site/docs/node/web3.mdx",sourceDirName:"node",slug:"/node/web3",permalink:"/node/web3",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/web3.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Web3 gateway for Emerald and Sapphire ParaTimes"},sidebar:"operators",previous:{title:"Troubleshooting",permalink:"/node/run-your-node/troubleshooting"},next:{title:"gRPC Proxy",permalink:"/node/grpc"}},c={},h=[{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},{value:"See also",id:"see-also",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"oasis-web3-gateway-for-your-evm-paratime",children:"Oasis Web3 Gateway for your EVM ParaTime"}),"\n",(0,t.jsxs)(n.p,{children:["This guide will walk you through the steps needed to set up the Oasis Web3\ngateway for EVM-compatible ParaTimes, such as ",(0,t.jsx)(n.a,{href:"/dapp/emerald/",children:"Emerald"})," and ",(0,t.jsx)(n.a,{href:"/dapp/sapphire/",children:"Sapphire"}),"."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsx)(n.p,{children:"Each ParaTime requires its own instance of the Web3 gateway!"})}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(n.h3,{id:"hardware",children:"Hardware"}),"\n",(0,t.jsx)(n.p,{children:"In addition to the minimum hardware requirements for running the Oasis node,\nthe following should be added for running the Web3 gateway:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["CPU:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Minimum: 2.0 GHz x86-64 CPU"}),"\n",(0,t.jsx)(n.li,{children:"Recommended: 2.0 GHz x86-64 CPU with 2 cores/vCPUs"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Memory:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Minimum: 4 GB of ECC RAM"}),"\n",(0,t.jsx)(n.li,{children:"Recommended: 8 GB of ECC RAM"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Storage:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Minimum: 300 GB of SSD or NVMe fast storage"}),"\n",(0,t.jsx)(n.li,{children:"Recommended: 500 GB of SSD or NVMe fast storage"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["To put the figures above into perspective, the Web3 gateway for Emerald with\nPostgreSQL encountered ",(0,t.jsx)(n.strong,{children:"210 GB"})," of database growth in ~5 months between\nNov 18, 2021 and Apr 11, 2022 (since the ",(0,t.jsx)(n.a,{href:"https://medium.com/oasis-protocol-project/oasis-emerald-evm-paratime-is-live-on-mainnet-13afe953a4c9",children:"Emerald Mainnet launch"}),")."]})}),"\n",(0,t.jsx)(n.h3,{id:"oasis-paratime-client-node",children:"Oasis ParaTime Client Node"}),"\n",(0,t.jsxs)(n.p,{children:["The Web3 gateway requires a locally deployed ParaTime-enabled Oasis Node.\nFirst, follow the\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node",children:"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 (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.em,{children:"expensive"})," transactions by adding the following to your Oasis node config:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:"title='config.yml'",children:'# ... 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'})}),"\n",(0,t.jsxs)(n.p,{children:["In the config above replace ",(0,t.jsx)(n.code,{children:"{{ ... }}"})," placeholders with actual ParaTime IDs:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ emerald_paratime_id }}"}),":","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Emerald on ",(0,t.jsx)(n.a,{href:"/node/mainnet/#emerald",children:"Mainnet"}),": ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000e2eaa99fc008f87f"})]}),"\n",(0,t.jsxs)(n.li,{children:["Emerald on ",(0,t.jsx)(n.a,{href:"/node/testnet/#emerald",children:"Testnet"}),": ",(0,t.jsx)(n.code,{children:"00000000000000000000000000000000000000000000000072c8215e60d5bca7"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ sapphire_paratime_id }}"}),":","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Sapphire on ",(0,t.jsx)(n.a,{href:"/node/mainnet/#sapphire",children:"Mainnet"}),": ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000f80306c9858e7279"})]}),"\n",(0,t.jsxs)(n.li,{children:["Sapphire on ",(0,t.jsx)(n.a,{href:"/node/testnet/#sapphire",children:"Testnet"}),": ",(0,t.jsx)(n.code,{children:"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"postgresql",children:"PostgreSQL"}),"\n",(0,t.jsxs)(n.p,{children:["The Web3 gateway stores blockchain data in a\n",(0,t.jsx)(n.a,{href:"https://www.postgresql.org/",children:"PostgreSQL"})," database version ",(0,t.jsx)(n.strong,{children:"13.3"})," or higher.\nInstall it by following instructions specific to your operating system and\nenvironment."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"download-oasis-web3-gateway",children:"Download Oasis Web3 Gateway"}),"\n",(0,t.jsxs)(n.p,{children:["Check the required version of the Web3 gateway for the network you will be\ndeploying it to: ",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),". Next, download the Oasis-provided\nbinaries from the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/releases",children:"official GitHub repository"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Alternatively, you can download the source release and compile it yourself.\nConsult the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-web3-gateway/blob/main/README.md#building-and-testing",children:"README.md"})," file for more information."]}),"\n",(0,t.jsx)(n.h2,{id:"running-the-web3-gateway",children:"Running the Web3 Gateway"}),"\n",(0,t.jsx)(n.p,{children:"Copy the content below to the config file of your Web3 gateway."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:"title='gateway.yml'",children:'# 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'})}),"\n",(0,t.jsx)(n.p,{children:"Use the following placeholder values:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ paratime_id }}"}),": The ID of the Emerald or Sapphire ParaTime which you are\nconfiguring the Web3 gateway for (see ",(0,t.jsx)(n.a,{href:"#oasis-paratime-client-node",children:"above"}),")."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ oasis_node_unix_socket }}"}),": Path to the ",(0,t.jsx)(n.code,{children:"internal.sock"})," file created by\nthe Oasis node."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ postgresql_db }}"}),", ",(0,t.jsx)(n.code,{children:"{{ postgresql_user }}"}),", ",(0,t.jsx)(n.code,{children:"{{ postgresql_password }}"}),":\nDatabase name and credentials for your PostgreSQL database."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ chain_id }}"}),": The chain ID of your EVM network:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Emerald on ",(0,t.jsx)(n.a,{href:"/dapp/emerald/#mainnet",children:"Mainnet"}),": ",(0,t.jsx)(n.code,{children:"42262"})]}),"\n",(0,t.jsxs)(n.li,{children:["Emerald on ",(0,t.jsx)(n.a,{href:"/dapp/emerald/#testnet",children:"Testnet"}),": ",(0,t.jsx)(n.code,{children:"42261"})]}),"\n",(0,t.jsxs)(n.li,{children:["Sapphire on ",(0,t.jsx)(n.a,{href:"/dapp/sapphire/#mainnet",children:"Mainnet"}),": ",(0,t.jsx)(n.code,{children:"23294"})]}),"\n",(0,t.jsxs)(n.li,{children:["Sapphire on ",(0,t.jsx)(n.a,{href:"/dapp/sapphire/#testnet",children:"Testnet"}),": ",(0,t.jsx)(n.code,{children:"23295"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsx)(n.p,{children:"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,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"DATABASE__PASSWORD=your_password_here\n"})})]}),"\n",(0,t.jsx)(n.p,{children:"To start the Web3 gateway invoke:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"./oasis-web3-gateway --config gateway.yml\n"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"If your database contains any tables populated by the previous version of the\nWeb3 gateway, migration scripts will automatically be applied upon startup."}),"\n",(0,t.jsx)(n.p,{children:"If you want to migrate the database separately, run:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"./oasis-web3-gateway migrate-db --config gateway.yml\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Above, we are invoking the ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#create-a-user",children:"configure the Web3 gateway as a system service"})," and register it in the service manager for your platform."]})}),"\n",(0,t.jsx)(n.h2,{id:"archive-web3-gateway",children:"Archive Web3 Gateway"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["First, set up an instance of the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/archive-node",children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"8543"}),".\nEnable the proxy for historical blocks by adding the following to your (live)\nWeb3 gateway config and restart it:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:"title='gateway.yml'",children:"# URI of an archive web3 gateway instance for servicing historical queries.\narchive_uri: 'http://localhost:8543'\n"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"Historical estimate gas calls are not supported."})}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsx)(n.h3,{id:"wipe-state-to-force-a-complete-reindex",children:"Wipe state to force a complete reindex"}),"\n",(0,t.jsxs)(n.p,{children:["If you encounter database or hardware issues, you may need to wipe the\ndatabase and reindex all blocks. First, run the ",(0,t.jsx)(n.code,{children:"truncate-db"})," subcommand:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-web3-gateway truncate-db --config gateway.yml --unsafe\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Then, execute the ",(0,t.jsx)(n.code,{children:"oasis-web3-gateway"})," normally to start reindexing the\nblocks."]}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"This will wipe all existing state in the PostgreSQL database and can lead to\nextended downtime while the Web3 Gateway is reindexing the blocks."})}),"\n",(0,t.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsx)(i.A,{items:[(0,r.$)("/node/run-your-node/"),(0,r.$)("/node/grpc")]})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},5965:(e,n,a)=>{a.d(n,{A:()=>f});a(6540);var t=a(4164),s=a(8774),i=a(4142),r=a(5846),o=a(6654),l=a(1312),d=a(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=a(4848);function u(e){let{href:n,children:a}=e;return(0,h.jsx)(s.A,{href:n,className:(0,t.A)("card padding--lg",c.cardContainer),children:a})}function p(e){let{href:n,icon:a,title:s,description:i}=e;return(0,h.jsxs)(u,{href:n,children:[(0,h.jsxs)(d.A,{as:"h2",className:(0,t.A)("text--truncate",c.cardTitle),title:s,children:[a," ",s]}),i&&(0,h.jsx)("p",{className:(0,t.A)("text--truncate",c.cardDescription),title:i,children:i})]})}function m(e){let{item:n}=e;const a=(0,i.Nr)(n),t=function(){const{selectMessage:e}=(0,r.W)();return n=>e(n,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return a?(0,h.jsx)(p,{href:a,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??t(n.items.length)}):null}function g(e){let{item:n}=e;const a=(0,o.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",t=(0,i.cC)(n.docId??void 0);return(0,h.jsx)(p,{href:n.href,icon:a,title:n.label,description:n.description??t?.description})}function f(e){let{item:n}=e;switch(n.type){case"link":return(0,h.jsx)(g,{item:n});case"category":return(0,h.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},2550:(e,n,a)=>{a.d(n,{A:()=>l});a(6540);var t=a(4164),s=a(4142),i=a(5965),r=a(4848);function o(e){let{className:n}=e;const a=(0,s.$S)();return(0,r.jsx)(l,{items:a.items,className:n})}function l(e){const{items:n,className:a}=e;if(!n)return(0,r.jsx)(o,{...e});const l=(0,s.d1)(n);return(0,r.jsx)("section",{className:(0,t.A)("row",a),children:l.map(((e,n)=>(0,r.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,r.jsx)(i.A,{item:e})},n)))})}},5846:(e,n,a)=>{a.d(n,{W:()=>d});var t=a(6540),s=a(4586);const i=["zero","one","two","few","many","other"];function r(e){return i.filter((n=>e.includes(n)))}const o={locale:"en",pluralForms:r(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,s.A)();return(0,t.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:r(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),o}}),[e])}function d(){const e=l();return{selectMessage:(n,a)=>function(e,n,a){const t=e.split("|");if(1===t.length)return t[0];t.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 ${t.length}: ${e}`);const s=a.select(n),i=a.pluralForms.indexOf(s);return t[Math.min(i,t.length-1)]}(a,n,e)}}},6116:(e,n,a)=>{a.d(n,{$:()=>i});var t=a(2252);function s(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&s(n.items)}}function i(e){const n=(0,t.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)s(n.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]}},8453:(e,n,a)=>{a.d(n,{R:()=>r,x:()=>o});var t=a(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b230e4e5.ee29f186.js b/assets/js/b230e4e5.ee29f186.js new file mode 100644 index 0000000000..81e57ac21f --- /dev/null +++ b/assets/js/b230e4e5.ee29f186.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2075],{4825:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var t=i(4848),s=i(8453);const r={},o="ADR 0004: Runtime Governance",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0004-runtime-governance.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},a={},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 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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0004-runtime-governance",children:"ADR 0004: Runtime Governance"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2020-10-07: Add per-role max node limits, minimum required election pool size"}),"\n",(0,t.jsx)(n.li,{children:"2020-09-30: Add entity whitelist admission policy max nodes limit"}),"\n",(0,t.jsx)(n.li,{children:"2020-09-17: Initial draft"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Accepted"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsx)(n.p,{children:"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)."}),"\n",(0,t.jsxs)(n.p,{children:["This proposal extends runtime governance options and enables a path towards\nruntimes that can define their own governance mechanisms. This proposal assumes\nthat ",(0,t.jsx)(n.a,{href:"/adrs/0003-consensus-runtime-token-transfer",children:"ADR 0003"})," has been adopted and runtimes can have their own accounts in the\nstaking module."]}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"runtime-descriptor",children:"Runtime Descriptor"}),"\n",(0,t.jsxs)(n.p,{children:["The runtime descriptor version is bumped to ",(0,t.jsx)(n.code,{children:"2"}),". Version ",(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.h4,{id:"governance-model",children:"Governance Model"}),"\n",(0,t.jsx)(n.p,{children:"This proposal updates the runtime descriptor by adding fields as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"governance_model"})," field can specifiy one of the following governance\nmodels:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsxs)(n.strong,{children:["Entity governance (",(0,t.jsx)(n.code,{children:"GovernanceEntity"}),")."]})," This causes the runtime to behave\nexactly as before, the runtime owner (indicated by ",(0,t.jsx)(n.code,{children:"entity_id"})," in the runtime\ndescriptor) is the only one who can update the runtime descriptor via\n",(0,t.jsx)(n.code,{children:"registry.RegisterRuntime"})," method calls."]}),"\n",(0,t.jsx)(n.p,{children:"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)."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsxs)(n.strong,{children:["Runtime-defined governance (",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"entity_id"}),") is not able to\nperform any updates after the initial registration and such attempts must\nreturn ",(0,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/adrs/0003-consensus-runtime-token-transfer",children:"ADR 0003"}),".\nNote that anyone can delegate the required stake to a runtime in order to\nenable its operation."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsxs)(n.strong,{children:["Consensus layer governance (",(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsx)(n.p,{children:"Runtimes using this governance model are never suspended and do not need to\nprovide stake in escrow."}),"\n",(0,t.jsxs)(n.p,{children:["Runtimes using this governance model cannot be registered/updated via regular\nregistry method calls or runtime messages (doing so must return\n",(0,t.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"entity-whitelist-admission-policy",children:"Entity Whitelist Admission Policy"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["The new ",(0,t.jsx)(n.code,{children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["Each key (roles mask) in the ",(0,t.jsx)(n.code,{children:"max_nodes"})," map must specify a single role,\notherwise the runtime descriptor is rejected with ",(0,t.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["When transforming runtime descriptors from version 1, an entry in the ",(0,t.jsx)(n.code,{children:"entities"}),"\nfield maps to an ",(0,t.jsx)(n.code,{children:"EntityWhitelistConfig"})," structure with ",(0,t.jsx)(n.code,{children:"max_nodes"})," absent,\ndenoting that an unlimited number of nodes is allowed (as before)."]}),"\n",(0,t.jsx)(n.h4,{id:"minimum-required-committee-election-pool-size",children:"Minimum Required Committee Election Pool Size"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,t.jsxs)(n.p,{children:["The value of ",(0,t.jsx)(n.code,{children:"min_pool_size"})," must be non-zero and must be equal to or greater\nthan the corresponding sum of ",(0,t.jsx)(n.code,{children:"group_size"})," and ",(0,t.jsx)(n.code,{children:"group_backup_size"}),". Otherwise\nthe runtime descriptor is rejected with ",(0,t.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["When transforming runtime descriptors from version 1, ",(0,t.jsx)(n.code,{children:"min_pool_size"})," for the\nexecutor committee is computed as ",(0,t.jsx)(n.code,{children:"group_size + group_backup_size"})," while the\n",(0,t.jsx)(n.code,{children:"min_pool_size"})," for the storage committee is equal to ",(0,t.jsx)(n.code,{children:"group_size"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"state",children:"State"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces/updates the following consensus state in the registry\nmodule:"}),"\n",(0,t.jsx)(n.h4,{id:"stored-runtime-descriptors",children:"Stored Runtime Descriptors"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"0x13"})," which previously\ncontained signed runtime descriptors is modified to store plain runtime\ndescriptors."]}),"\n",(0,t.jsx)(n.h3,{id:"genesis-document",children:"Genesis Document"}),"\n",(0,t.jsx)(n.p,{children:"This proposal updates the registry part of the genesis document as follows:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The type of the ",(0,t.jsx)(n.code,{children:"runtimes"})," field is changed to a list of runtime descriptors\n(was a list of ",(0,t.jsx)(n.em,{children:"signed"})," runtime descriptors before)."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The type of the ",(0,t.jsx)(n.code,{children:"suspended_runtimes"})," field is changed to a list of runtime\ndescriptors (was a list of ",(0,t.jsx)(n.em,{children:"signed"})," runtime descriptors before)."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Runtime descriptors must be transformed to support the new fields."}),"\n",(0,t.jsx)(n.h3,{id:"transaction-methods",children:"Transaction Methods"}),"\n",(0,t.jsx)(n.p,{children:"This proposal updates the following transaction methods in the registry module:"}),"\n",(0,t.jsx)(n.h4,{id:"register-runtime",children:"Register Runtime"}),"\n",(0,t.jsx)(n.p,{children:"Runtime registration enables a new runtime to be created or an existing runtime\nto be updated (in case the governance model allows it)."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"registry.RegisterRuntime\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The body of a register runtime transaction must be a ",(0,t.jsx)(n.code,{children:"Runtime"})," descriptor.\nThe signer of the transaction must be the owning entity key."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["Changing the governance model from ",(0,t.jsx)(n.code,{children:"GovernanceEntity"})," to ",(0,t.jsx)(n.code,{children:"GovernanceRuntime"})," is\nallowed. Any other governance model changes are not allowed and must fail with\n",(0,t.jsx)(n.code,{children:"ErrForbidden"}),". Support for other changes is deferred to a consensus layer\ngovernance mechanism not specified by this proposal."]}),"\n",(0,t.jsxs)(n.p,{children:["Using the ",(0,t.jsx)(n.code,{children:"GovernanceRuntime"})," governance model for a runtime of any kind other\nthan ",(0,t.jsx)(n.code,{children:"KindCompute"})," must return ",(0,t.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"messages",children:"Messages"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following runtime messages:"}),"\n",(0,t.jsx)(n.h4,{id:"update-runtime-descriptor",children:"Update Runtime Descriptor"}),"\n",(0,t.jsx)(n.p,{children:"The update runtime descriptor message enables a runtime to update its own\ndescriptor when the current governance model allows it."}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Field name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"update_runtime\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Body:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-golang",children:"type UpdateRuntimeMessage struct {\n registry.Runtime\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["The actions performed when processing the message are the same as those\nperformed when processing the ",(0,t.jsx)(n.code,{children:"registry.RegisterRuntime"})," method call, just made\non the runtime's (instead of an entity's) behalf."]}),"\n",(0,t.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,t.jsx)(n.h4,{id:"registry",children:"Registry"}),"\n",(0,t.jsx)(n.p,{children:"This proposal introduces the following new consensus parameters in the registry\nmodule:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"enable_runtime_governance_models"})," (set of ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"ErrForbidden"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"rust-runtime-support-library",children:"Rust Runtime Support Library"}),"\n",(0,t.jsxs)(n.p,{children:["The Rust runtime support library (",(0,t.jsx)(n.code,{children:"oasis-core-runtime"}),") must be updated to\nsupport the updated and newly needed message structures (the runtime descriptor\nand the update runtime message)."]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtimes can define their governance model, enabling them to become more\ndecentralized while still allowing upgrades."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtimes using the entity whitelist admission policy can limit the number of\nnodes that each entity can register."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Runtimes can specify the minimum size of the compute/storage node pool from\nwhich committees are elected."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"/adrs/0003-consensus-runtime-token-transfer",children:"ADR 0003"})," - Consensus/Runtime Token Transfer"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>d});var t=i(6540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b4883e93.e45a02fc.js b/assets/js/b4883e93.e45a02fc.js new file mode 100644 index 0000000000..b82aeda074 --- /dev/null +++ b/assets/js/b4883e93.e45a02fc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3377],{7034:(e,a,i)=>{i.r(a),i.d(a,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var t=i(4848),n=i(8453);const s={},o="Why Oasis?",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/oasis-network/why-oasis.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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}];function h(e){const a={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,n.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.h1,{id:"why-oasis",children:"Why Oasis?"}),"\n",(0,t.jsx)(a.h2,{id:"network-overview",children:"Network Overview"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Oasis Timeline",src:i(1434).A+"",width:"5744",height:"1070"})}),"\n",(0,t.jsx)(a.h3,{id:"why-the-oasis-network",children:"Why the Oasis Network?"}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsxs)(a.p,{children:[(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsx)(a.h3,{id:"technology-highlights",children:"Technology Highlights"}),"\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.strong,{children:"Separates consensus and execution into two layers"}),", the consensus layer and\nthe ParaTime layer, for better scalability and increased versatility."]}),"\n",(0,t.jsxs)(a.li,{children:["Separation of consensus and execution allows ",(0,t.jsx)(a.strong,{children:"multiple ParaTimes to process\ntransactions in parallel"}),", meaning complex workloads processed on one\nParaTime won\u2019t slow down transactions on another."]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.strong,{children:"The ParaTime layer is entirely decentralized, allowing anyone to register,\ndevelop and deploy their own ParaTime."})," Each ParaTime can be developed in\nisolation to meet the needs of a specific application, such as confidential\ncompute, open or closed committees, and more."]}),"\n",(0,t.jsxs)(a.li,{children:["ParaTimes can be used as a ",(0,t.jsx)(a.strong,{children:"truly scalable and fundamentally cheaper L2\ntechnology"})," since the transaction gas fee and congestion doesn't affect the\nunderlying consensus layer block and the other way around."]}),"\n",(0,t.jsxs)(a.li,{children:["The network\u2019s sophisticated discrepancy detection makes ",(0,t.jsx)(a.strong,{children:"Oasis more efficient\nthan sharding and parachains"}),", requiring a smaller replication factor for the\nsame level of security."]}),"\n",(0,t.jsxs)(a.li,{children:["There are ",(0,t.jsx)(a.strong,{children:"3 ParaTimes"})," built by the Oasis core team and currently deployed\non the network for general availability:","\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.strong,{children:"Sapphire ParaTime, the EVM-Compatible confidential smart contract ParaTime"}),"\nenables confidential computation of the smart contracts written in Solidity\nor other EVM-compatible language. DApp developers can integrate Sapphire for\nprivacy-preserving data storage, governance, and computation into their\napplications with little or no additional work to existing smart contracts\ncode."]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.strong,{children:"Cipher ParaTime, the confidential smart contract ParaTime"}),", was the first\nParaTime deployed by the Oasis team that supports privacy-preserving smart\ncontracts. As with other compute ParaTimes, it boasts high throughput,\ninstant finality, and low fees with added privacy-preserving features.\nCipher enables DEX\u2019s to stop front-running transactions, NFT users to\nprotect their assets privately, and can potentially unlock trillions in\ncredit and lending markets from traditional finance. Cipher executes smart\ncontracts compiled in ",(0,t.jsx)(a.strong,{children:"Oasis Wasm"}),". Currently, we offer tooling for the\n",(0,t.jsx)(a.a,{href:"https://www.rust-lang.org/",children:"Rust programming language"})," which is very rigorous about memory management\nand thus suitable for security-first dApps."]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.strong,{children:"Emerald ParaTime, the EVM-Compatible ParaTime"}),", was built to solve the\nproblems faced by Solidity developers. High fees and low throughput. Emerald\nsolves both of these problems by increasing the throughput of transactions\nto 1,000 per second and reducing fees by 99%+ compared to Ethereum. This\nmeans more users will be able to use and build on the network. Emerald does\nnot support confidential computation."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(a.h2,{id:"new-application-domains",children:"New Application Domains"}),"\n",(0,t.jsx)(a.h3,{id:"scalable-private-defi",children:"Scalable, Private DeFi"}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Scalable, Private DeFi",src:i(5590).A+"",width:"1251",height:"668"})}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:"The Oasis Network is ideal for DeFi applications due to its scalability, instant finality, 99% lower gas fees versus Ethereum, and high throughput."}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Oasis Network in lending market",src:i(3763).A+"",width:"3892",height:"2036"})}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Comparison of networks",src:i(3614).A+"",width:"1274",height:"611"})}),"\n",(0,t.jsx)(a.h3,{id:"data-tokenization--a-responsible-data-economy",children:"Data Tokenization & A Responsible Data Economy"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Data tokenization on the Oasis",src:i(6877).A+"",width:"7118",height:"2794"})}),"\n",(0,t.jsx)(a.p,{children:"Many projects have already begun building apps that leverage data tokenization on the Oasis. Here are just a few examples:"}),"\n",(0,t.jsx)(a.admonition,{title:"Case Study: Binance CryptoSafe Alliance",type:"tip",children:(0,t.jsx)(a.p,{children:"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."})}),"\n",(0,t.jsx)(a.admonition,{title:"Case Study: Fortune 500 Healthcare Provider",type:"tip",children:(0,t.jsx)(a.p,{children:"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."})}),"\n",(0,t.jsx)(a.admonition,{title:"Case Study: Nebula Genomics",type:"tip",children:(0,t.jsx)(a.p,{children:"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."})}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Projects and Partners",src:i(3050).A+"",width:"1298",height:"613"})}),"\n",(0,t.jsx)(a.h2,{id:"technology-overview",children:"Technology Overview"}),"\n",(0,t.jsx)(a.p,{children:"The Oasis Network is a Layer 1, proof-of-stake, decentralized network. It has two main components, the consensus layer and the ParaTime layer."}),"\n",(0,t.jsxs)(a.ol,{children:["\n",(0,t.jsxs)(a.li,{children:["The ",(0,t.jsx)(a.strong,{children:"consensus layer"})," is a scalable, high-throughput, secure, proof-of-stake consensus run by a decentralized set of validator nodes."]}),"\n",(0,t.jsxs)(a.li,{children:["The ",(0,t.jsx)(a.strong,{children:"ParaTime layer"})," hosts many parallel runtimes (ParaTimes), each representing a replicated compute environment with shared state."]}),"\n"]}),"\n",(0,t.jsx)(a.h3,{id:"scalability",children:"Scalability"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Scalability",src:i(141).A+"",width:"1523",height:"718"})}),"\n",(0,t.jsx)(a.h3,{id:"privacy-first",children:"Privacy-First"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Secure enclave",src:i(359).A+"",width:"648",height:"283"})}),"\n",(0,t.jsx)(a.h3,{id:"versatility",children:"Versatility"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.h2,{id:"traction-and-adoption",children:"Traction and Adoption"}),"\n",(0,t.jsx)(a.h3,{id:"the-oasis-ecosystem",children:"The Oasis Ecosystem"}),"\n",(0,t.jsx)(a.p,{children:"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:"}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"The Oasis Ecosystem",src:i(6667).A+"",width:"11564",height:"6597"})}),"\n",(0,t.jsx)(a.h3,{id:"the-defi-ecosystem",children:"The DeFi Ecosystem"}),"\n",(0,t.jsx)(a.p,{children:"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:"}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"The DeFi Ecosystem",src:i(7680).A+"",width:"1200",height:"675"})}),"\n",(0,t.jsx)(a.h3,{id:"the-200m-ecosystem-fund",children:"The $200m Ecosystem Fund"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsxs)(a.p,{children:["If you want to build on Oasis, you can read more about the Ecosystem Fund ",(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/binance-labs-backs-the-oasis-ecosystem-fund-to-support-the-projects-building-on-oasis-network-f6bcb3be6ee4",children:"here"})," or apply to the Ecosystem Fund through this form ",(0,t.jsx)(a.a,{href:"https://airtable.com/shrSyNBumurHhf7cd",children:"here"}),"."]}),"\n",(0,t.jsx)(a.h3,{id:"grants--devaccelerator",children:"Grants & DevAccelerator"}),"\n",(0,t.jsxs)(a.p,{children:["The Oasis Foundation has been working with many talented dev teams via our ",(0,t.jsx)(a.a,{href:"https://oasisprotocol.org/ecosystem#grantsprogram",children:"Grants program"})," to build new applications and integrations on top of the Oasis Network. These include:"]}),"\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://anthem.chorus.one",children:"Anthem (by Chorus One)"})}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-alethea-ai-aac8f854e436",children:"Alethea.ai"}),": A marketplace for AI-generated media"]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-bankex-9bb127f9e449",children:"Bankex"}),": Send digital assets across your social networks"]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-castalise-347f155ab66f",children:"Castalise"}),": Enabling privacy-preserving predictive analytics on pharmaceutical data"]}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://github.com/Chainflow/oasis-mission-control-grant",children:"Chainflow Mission Control"})}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-dead-mans-switch-32d07cdfc057",children:"Dead Man\u2019s Switch"}),": A decentralized, censorship-resistant tool for whistleblowers"]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://luther.ai",children:"Luther.ai:"})," Building artificial intelligence to Retain, Reinforce, Recall and ultimately augment your human memory."]}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://oasis.fish/leaderboard/",children:"Oasis.Fish (by Stakefish)"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.figment.io/",children:"Oasis Hubble (by Figment Networks)"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://oasismonitor.com",children:"Oasis Monitor (by Everstake)"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://oasisscan.com",children:"Oasisscan (by bitcat)"})}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://oasis.smartstake.io",children:"Oasis Smartstake (by Smartstake)"}),": Providing validation services for the Oasis Network"]}),"\n",(0,t.jsx)(a.li,{children:"Oasis Mobile Wallet by RockX"}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-ruyi-health-7c068cfeecea",children:"Ruyi Health"}),": A Secure, Intuitive, and Intelligent Health Management Solution for Stroke Patients and their providers and insurers."]}),"\n",(0,t.jsxs)(a.li,{children:[(0,t.jsx)(a.a,{href:"https://medium.com/oasis-protocol-project/devaccelerator-spotlight-saferate-2dbb99c3a43a",children:"SafeRate"}),": Automatically reduce mortgage payments when neighborhoods home values fall"]}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://github.com/SimplyVC/panic_oasis",children:"SimplyVC Panic Monitoring"})}),"\n"]}),"\n",(0,t.jsx)(a.h3,{id:"community-efforts",children:"Community Efforts"}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.p,{children:"Ambassadors are also growing strong communities worldwide, including Bangladesh, Vietnam, India, Brazil, Korea, Nigeria, Philippines, Russia, China, South Korea, Turkey, and more."}),"\n",(0,t.jsxs)(a.p,{children:["The Oasis Network also has the ",(0,t.jsx)(a.strong,{children:"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."]}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Oasis University Program",src:i(962).A+"",width:"4001",height:"2801"})}),"\n",(0,t.jsx)(a.h3,{id:"contributing-team",children:"Contributing Team"}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Some of the many places contributing team members come from",src:i(4237).A+"",width:"3791",height:"1036"})}),"\n",(0,t.jsx)(a.p,{children:"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."}),"\n",(0,t.jsx)(a.h4,{id:"oasis-foundation",children:(0,t.jsx)(a.a,{href:"https://www.linkedin.com/company/oasisprotocol/",children:"Oasis Foundation"})}),"\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://oasisprotocol.org",children:"See team page on our website"})}),"\n"]}),"\n",(0,t.jsx)(a.h4,{id:"oasis-labs",children:(0,t.jsx)(a.a,{href:"https://www.linkedin.com/company/oasis-labs",children:"Oasis Labs"})}),"\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.linkedin.com/in/dawn-song-51586033/",children:"Dawn Song, Founder"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.linkedin.com/in/peter-gilbert-2b70b1167/",children:"Peter Gilbert, Director of Engineering"})}),"\n"]}),"\n",(0,t.jsx)(a.h3,{id:"press",children:"Press"}),"\n",(0,t.jsx)(a.p,{children:"Over 200 articles have been written since the company came out of stealth mode. Top articles and interviews include:"}),"\n",(0,t.jsxs)(a.ul,{children:["\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.nytimes.com/2019/11/19/technology/artificial-intelligence-dawn-song.html",children:"The New York Times: Building a World Where Data Privacy Exists Online"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.wired.com/story/dawn-song-oasis-labs-data-privacy-wired25/",children:"WIRED: Oasis Labs' Dawn Song on a Safer Way to Protect Your Data"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.technologyreview.com/2019/05/14/239125/how-ai-could-save-lives-without-spilling-secrets/",children:"MIT Technology Review: How AI could save lives without spilling medical secrets"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.yahoo.com/now/web3-users-control-data-says-132837055.html",children:"Yahoo! Finance: Web3 Users will Control Their Data, Says Oasis Ecosystem Head"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://cointelegraph.com/news/first-dex-on-oasis-network-hits-100m-tvl-in-24-hours",children:"Cointelegraph: First DEX on Oasis Network hits $100M TVL in 24 hours "})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://cointelegraph.com/news/binance-labs-backs-200m-oasis-ecosystem-fund",children:"Cointelegraph: Binance Labs backs $200M Oasis Ecosystem Fund "})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.coinspeaker.com/oasis-protocol-partnership-meta/",children:"CoinSpeaker: Oasis Protocol Inks Partnership with Meta to Facilitate AI Computing Applications"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://cointelegraph.com/news/akon-to-sell-historic-dna-data-art-as-nft-on-oasis-network",children:"Cointelegraph: AkoinNFT to Sell Historic DNA Data Art as NFT In Collaboration With Oasis Network "})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.nature.com/articles/d41586-021-01642-3",children:"Nature: How scientists are embracing NFTs "})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://cointelegraph.com/news/concerns-around-data-privacy-are-rising-and-blockchain-is-the-solution",children:"Cointelegraph: Concerns around data privacy are rising, and blockchain is the solution"})}),"\n",(0,t.jsx)(a.li,{children:(0,t.jsx)(a.a,{href:"https://www.coindesk.com/business/2021/10/05/the-educator-entrepreneurs-of-crypto/",children:"Coin Desk: The Educator-Entrepreneurs of Crypto"})}),"\n"]}),"\n",(0,t.jsx)(a.p,{children:"Articles about the Oasis Network have focused on a variety of topics and span across both mainstream and crypto press:"}),"\n",(0,t.jsx)(a.p,{children:(0,t.jsx)(a.img,{alt:"Press",src:i(831).A+"",width:"3632",height:"538"})})]})}function d(e={}){const{wrapper:a}={...(0,n.R)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},141:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/technology_scalability-37484303b278abc340a74baee5027d33.svg"},3614:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/compare_networks-9630fe031fad10dc47c0c56aa1f00d33.png"},6877:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/data_tokenization-3931e375a8cea5a5756f82573ea95223.png"},7680:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/ecosystem-defi-52ce0ac1743d0d251120d3ac98519906.jpg"},6667:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/ecosystem-9c15f2d71858df610097d36faa5e0f71.jpg"},5590:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/features-69565025aa30dbd10c01eed76e58b212.png"},3763:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/lending_market-89baec95cc4d9c2a312f884a6c1c9a78.png"},3050:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/partners-98bce621edbe8c16b650cf27984f15e1.png"},831:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/press_logos-c37908c3371f7230bc2f71ef5729788f.png"},359:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/secure_enclave-685f409cf66aabca221edfab5292e1dc.png"},4237:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/team_logos-343a69f4e7c6b3d857f51f910752efb6.png"},1434:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/timeline-fcb8cf7365a3b7742c563223e08cd070.png"},962:(e,a,i)=>{i.d(a,{A:()=>t});const t=i.p+"assets/images/uni_map-342c7d3df7a918f68531615dfb33b3ee.png"},8453:(e,a,i)=>{i.d(a,{R:()=>o,x:()=>r});var t=i(6540);const n={},s=t.createContext(n);function o(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function r(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b622a7ea.5c4afe06.js b/assets/js/b622a7ea.5c4afe06.js new file mode 100644 index 0000000000..1b97ce571f --- /dev/null +++ b/assets/js/b622a7ea.5c4afe06.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1553],{893:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var i=t(4848),s=t(8453);const o={},r="Modules",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/modules.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"paratime",previous:{title:"Minimal Runtime",permalink:"/paratime/minimal-runtime"},next:{title:"Reproducibility",permalink:"/paratime/reproducibility"}},a={},d=[{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}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"modules",children:"Modules"}),"\n",(0,i.jsxs)(n.p,{children:["As we saw in the ",(0,i.jsx)(n.a,{href:"/paratime/minimal-runtime",children:"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,i.jsx)(n.em,{children:"modules"})," that are composed together to form a\nruntime."]}),"\n",(0,i.jsx)(n.p,{children:"This chapter explores how modules are built."}),"\n",(0,i.jsx)(n.h2,{id:"runtime-trait",children:"Runtime Trait"}),"\n",(0,i.jsxs)(n.p,{children:["Let's briefly revisit the ",(0,i.jsx)(n.code,{children:"Runtime"})," trait which is what brings everything\ntogether. As we saw when ",(0,i.jsx)(n.a,{href:"/paratime/minimal-runtime#runtime-definition",children:"defining the minimal runtime"}),", the trait requires\nimplementing some basic things:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:"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 // Module that provides the core API.\n type Core = modules::core::Module;\n // Module that provides the accounts API.\n type Accounts = modules::accounts::Module;\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"})}),"\n",(0,i.jsx)(n.h3,{id:"version",children:"Version"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"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,i.jsx)(n.a,{href:"https://semver.org/",children:"semantic versioning"})," with the following semantics:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:"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,i.jsx)(n.em,{children:"must"})," be bumped."]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.a,{href:"/core/consensus/services/scheduler",children:"Oasis Core scheduler service"})," will make sure to only schedule nodes which\nare running a compatible version in order to make upgrades easier."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.strong,{children:"minor"})," and ",(0,i.jsx)(n.strong,{children:"patch"})," versions are ignored when determining\ncompatibility and can be used for non-breaking features or fixes."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"list-of-modules",children:"List of Modules"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsx)(n.h3,{id:"genesis-state",children:"Genesis State"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Each module can define its own genesis state format together with the methods\nfor transforming that genesis state into internal persistent state."}),"\n",(0,i.jsx)(n.h2,{id:"module-lifecycle-traits",children:"Module Lifecycle Traits"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.h2,{id:"putting-it-all-together",children:"Putting It All Together"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>l});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b66dccd5.846f3805.js b/assets/js/b66dccd5.846f3805.js new file mode 100644 index 0000000000..12e794a2f9 --- /dev/null +++ b/assets/js/b66dccd5.846f3805.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[890],{6926:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var i=t(4848),s=t(8453);const o={},r="Minimal Runtime",a={id:"paratime/minimal-runtime",title:"Minimal Runtime",description:"This chapter 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/runtime/minimal-runtime.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"minimal-runtime",children:"Minimal Runtime"}),"\n",(0,i.jsxs)(n.p,{children:["This chapter will show you how to quickly create, build and test a minimal\nruntime that allows transfers between accounts by using the ",(0,i.jsx)(n.code,{children:"accounts"})," module\nprovided by the Runtime SDK."]}),"\n",(0,i.jsx)(n.h2,{id:"repository-structure-and-dependencies",children:"Repository Structure and Dependencies"}),"\n",(0,i.jsxs)(n.p,{children:["First we create the basic directory structure for the minimal runtime using\nRust's ",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/cargo",children:(0,i.jsx)(n.code,{children:"cargo"})}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cargo init minimal-runtime\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will create the ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.p,{children:["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\n",(0,i.jsx)(n.code,{children:"rust-toolchain.toml"})," containing the following information:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title="rust-toolchain.toml"',children:'[toolchain]\nchannel = "nightly-2024-07-09"\ncomponents = [ "rustfmt", "clippy" ]\ntargets = [ "x86_64-fortanix-unknown-sgx", "wasm32-unknown-unknown" ]\nprofile = "minimal"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:".cargo/config.toml"})," file with the\nfollowing content:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title=".cargo/config.toml"',children:'[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'})}),"\n",(0,i.jsx)(n.p,{children:"After you complete this guide, the minimal runtime directory structure will look\nas follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"minimal-runtime\n\u251c\u2500\u2500 .cargo\n\u2502 \u2514\u2500\u2500 config.toml # 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.toml # 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"})}),"\n",(0,i.jsx)(n.h2,{id:"runtime-definition",children:"Runtime Definition"}),"\n",(0,i.jsxs)(n.p,{children:["First you need to declare the ",(0,i.jsx)(n.code,{children:"oasis-runtime-sdk"})," as a dependency in order to be\nable to use its features. To do this, edit the ",(0,i.jsx)(n.code,{children:"[dependencies]"})," section in your\n",(0,i.jsx)(n.code,{children:"Cargo.toml"})," to look like the following:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title="Cargo.toml"',children:'[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.8.4" }\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We are using the Git repository directly instead of releasing Rust packages on\ncrates.io."})}),"\n",(0,i.jsxs)(n.p,{children:["After you have declared the dependency on the Runtime SDK the next thing is to\ndefine the minimal runtime. To do this, create ",(0,i.jsx)(n.code,{children:"src/lib.rs"})," with the following\ncontent:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",metastring:'title="src/lib.rs"',children:"//! 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"})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.admonition,{type:"danger",children:(0,i.jsxs)(n.p,{children:["While the test keys are nice for testing they ",(0,i.jsx)(n.strong,{children:"should never be used in\nproduction"})," versions of the runtimes as the private keys are generated from\npublicly known seeds!"]})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"src/main.rs"})," as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",metastring:'title="src/main.rs"',children:"use oasis_runtime_sdk::Runtime;\n\nfn main() {\n minimal_runtime::Runtime::start();\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"building-and-running",children:"Building and Running"}),"\n",(0,i.jsx)(n.p,{children:"In order to build the runtime you can use the regular Cargo build process by\nrunning:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cargo build\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will generate a binary under ",(0,i.jsx)(n.code,{children:"target/debug/minimal-runtime"})," which will\ncontain the runtime."]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.p,{children:"You can also try to run your runtime using:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cargo run\n"})}),"\n",(0,i.jsx)(n.p,{children:"However, this will result in the startup process failing similar to the\nfollowing:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:' 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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"deploying-locally",children:"Deploying Locally"}),"\n",(0,i.jsxs)(n.p,{children:["In order to deploy the newly developed runtime in a local development network,\nyou can use the ",(0,i.jsx)(n.code,{children:"oasis-net-runner"})," provided in Oasis Core. This will set up a\nsmall network of local nodes that will run the runtime."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"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"})}),"\n",(0,i.jsx)(n.p,{children:"After successful startup this should result in the following message being\ndisplayed:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'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'})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"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."})}),"\n",(0,i.jsx)(n.h2,{id:"testing-from-oasis-cli",children:"Testing From Oasis CLI"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"localhost"})," network to the\nOasis CLI and provide the path to the local socket file reported above:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"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"})}),"\n",(0,i.jsx)(n.p,{children:"Now, let's see, if the local network was correctly initialized and the runtime\nis ready:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis network status --network localhost\n"})}),"\n",(0,i.jsxs)(n.p,{children:["If everything is working correctly, you should see the ",(0,i.jsx)(n.code,{children:'"status": "ready"'}),"\nunder the runtime's ",(0,i.jsx)(n.code,{children:'"committee"'})," field after a while and an increasing\n",(0,i.jsx)(n.code,{children:'"latest_round"'})," value:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:' "committee": {\n "status": "ready",\n "active_version": {\n "minor": 1\n },\n "latest_round": 19,\n "latest_height": 302,\n "executor_roles": null,\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["When you restart ",(0,i.jsx)(n.code,{children:"oasis-net-runner"}),", a new ",(0,i.jsx)(n.a,{href:"/core/crypto#chain-domain-separation",children:"chain context"})," will be generated\nand you will have to remove the ",(0,i.jsx)(n.code,{children:"localhost"})," network and add it again to Oasis\nCLI."]})}),"\n",(0,i.jsxs)(n.p,{children:["Now, let's add ",(0,i.jsx)(n.code,{children:"minimal"})," runtime to the wallet. By default, ",(0,i.jsx)(n.code,{children:"oasis-net-runner"}),"\nassigns ID ",(0,i.jsx)(n.code,{children:"8000000000000000000000000000000000000000000000000000000000000000"}),"\nto the first provided runtime."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis paratime add localhost minimal 8000000000000000000000000000000000000000000000000000000000000000\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"? Description: minimal\n? Denomination symbol: TEST\n? Denomination decimal places: 9\n"})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/main/client-sdk/go/testing/testing.go",children:"oasis-sdk testing source"})," for a complete list).\nYou can access the accounts by prepending ",(0,i.jsx)(n.code,{children:"test:"})," literal in front of the test\nuser's name, for example ",(0,i.jsx)(n.code,{children:"test:alice"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account show test:alice --network localhost\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Address: 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"})}),"\n",(0,i.jsx)(n.p,{children:"Sending some TEST in your runtime should also work. Let's send 0.1 TEST to\nBob's address."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 0.1 test:bob --network localhost --account test:alice \n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'Unlock 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'})}),"\n",(0,i.jsx)(n.h2,{id:"testing-from-a-client",children:"Testing From a Client"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["First, create a ",(0,i.jsx)(n.code,{children:"tests"})," directory and move into it, creating a Go module:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"go mod init example.com/oasisprotocol/minimal-runtime-client\ngo mod tidy\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Then create a ",(0,i.jsx)(n.code,{children:"test.go"})," file with the following content:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",metastring:'title="test.go"',children:'package main\n\nimport (\n\t"context"\n\t"fmt"\n\t"os"\n\t"time"\n\n\t"google.golang.org/grpc"\n\t"google.golang.org/grpc/credentials/insecure"\n\n\t"github.com/oasisprotocol/oasis-core/go/common"\n\tcmnGrpc "github.com/oasisprotocol/oasis-core/go/common/grpc"\n\t"github.com/oasisprotocol/oasis-core/go/common/logging"\n\t"github.com/oasisprotocol/oasis-core/go/common/quantity"\n\n\t"github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"\n\t"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/accounts"\n\t"github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"\n\t"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\t// This is the default runtime ID as used in oasis-net-runner. It can\n\t// be changed by using its --fixture.default.runtime.id argument.\n\truntimeIDHex = "8000000000000000000000000000000000000000000000000000000000000000"\n\t// This is the default client node address as set in oasis-net-runner.\n\tnodeAddress = "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\tclient.RuntimeClient\n\n\t// Accounts are the accounts module helpers.\n\tAccounts 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\t// Query the runtime, specifically the accounts module, for the given address\' balances.\n\trsp, err := rc.Accounts.Balances(ctx, client.RoundLatest, address)\n\tif err != nil {\n\t\treturn fmt.Errorf("failed to fetch account balances: %w", err)\n\t}\n\n\tfmt.Printf("=== Balances for %s ===\\n", address)\n\tfor denom, balance := range rsp.Balances {\n\t\tfmt.Printf("%s: %s\\n", denom, balance)\n\t}\n\tfmt.Printf("\\n")\n\n\treturn nil\n}\n\nfunc tokenTransfer() error {\n\t// Initialize logging.\n\tif err := logging.Initialize(os.Stdout, logging.FmtLogfmt, logging.LevelDebug, nil); err != nil {\n\t\treturn fmt.Errorf("unable to initialize logging: %w", err)\n\t}\n\n\t// Decode hex runtime ID into something we can use.\n\tvar runtimeID common.Namespace\n\tif err := runtimeID.UnmarshalHex(runtimeIDHex); err != nil {\n\t\treturn fmt.Errorf("malformed runtime ID: %w", err)\n\t}\n\n\t// Establish a gRPC connection with the client node.\n\tlogger.Info("connecting to local node")\n\tconn, err := cmnGrpc.Dial(nodeAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))\n\tif err != nil {\n\t\treturn fmt.Errorf("failed to establish connection to %s: %w", nodeAddress, err)\n\t}\n\tdefer conn.Close()\n\n\t// Create the runtime client with account module query helpers.\n\tc := client.New(conn, runtimeID)\n\trc := &Client{\n\t\tRuntimeClient: c,\n\t\tAccounts: accounts.NewV1(c),\n\t}\n\n\tctx, cancelFn := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancelFn()\n\n\t// Show initial balances for Alice\'s and Bob\'s accounts.\n\tlogger.Info("dumping initial balances")\n\tif err = showBalances(ctx, rc, testing.Alice.Address); err != nil {\n\t\treturn err\n\t}\n\tif err = showBalances(ctx, rc, testing.Bob.Address); err != nil {\n\t\treturn err\n\t}\n\n\t// Get current nonce for Alice\'s account.\n\tnonce, err := rc.Accounts.Nonce(ctx, client.RoundLatest, testing.Alice.Address)\n\tif err != nil {\n\t\treturn fmt.Errorf("failed to fetch account nonce: %w", err)\n\t}\n\n\t// Perform a transfer from Alice to Bob.\n\tlogger.Info("performing transfer", "nonce", nonce)\n\t// Create a transfer transaction with Bob\'s address as the destination and 10 native base units\n\t// as the amount.\n\ttb := rc.Accounts.Transfer(\n\t\ttesting.Bob.Address,\n\t\ttypes.NewBaseUnits(*quantity.NewFromUint64(10), types.NativeDenomination),\n\t).\n\t\t// Configure gas as set in genesis parameters. We could also estimate it instead.\n\t\tSetFeeGas(100).\n\t\t// Append transaction authentication information using a single signature variant.\n\t\tAppendAuthSignature(testing.Alice.SigSpec, nonce)\n\t// Sign the transaction using the signer. Before a transaction can be submitted it must be\n\t// signed by all configured signers. This will automatically fetch the corresponding chain\n\t// domain separation context for the runtime.\n\tif err = tb.AppendSign(ctx, testing.Alice.Signer); err != nil {\n\t\treturn fmt.Errorf("failed to sign transfer transaction: %w", err)\n\t}\n\t// Submit the transaction and wait for it to be included and a runtime block.\n\tif err = tb.SubmitTx(ctx, nil); err != nil {\n\t\treturn fmt.Errorf("failed to submit transfer transaction: %w", err)\n\t}\n\n\t// Show final balances for Alice\'s and Bob\'s accounts.\n\tlogger.Info("dumping final balances")\n\tif err = showBalances(ctx, rc, testing.Alice.Address); err != nil {\n\t\treturn err\n\t}\n\treturn showBalances(ctx, rc, testing.Bob.Address)\n}\n\nfunc main() {\n\tif err := tokenTransfer(); err != nil {\n\t\tpanic(err)\n\t}\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Fetch the dependencies:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"go get\n"})}),"\n",(0,i.jsx)(n.p,{children:"And build it:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"go build\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The example client will connect to one of the nodes in the network (the ",(0,i.jsx)(n.em,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:"To run the built client do:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"./minimal-runtime-client\n"})}),"\n",(0,i.jsx)(n.p,{children:"The output should be something like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Congratulations, you have successfully built and deployed your first runtime!"}),"\n",(0,i.jsx)(n.admonition,{title:"Example",type:"info",children:(0,i.jsxs)(n.p,{children:["You can view and download complete ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/runtime-sdk/minimal-runtime",children:"runtime example"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/client-sdk/go/minimal-runtime-client",children:"client code in Go"}),"\nfrom the Oasis SDK repository."]})})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var i=t(6540);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b821a83b.559cb9e5.js b/assets/js/b821a83b.559cb9e5.js new file mode 100644 index 0000000000..ce709932de --- /dev/null +++ b/assets/js/b821a83b.559cb9e5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6394],{3623:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var t=o(4848),i=o(8453);const r={},d="Adding or Removing Nodes",s={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/adding-or-removing-nodes.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},a={},l=[{value:"Overview",id:"overview",level:2},{value:"Obtain the ID of your Node",id:"obtain-the-id-of-your-node",level:2},{value:"Download Your Latest Entity Descriptor",id:"download-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:"Submitting Your Entity Registration to the Network",id:"submitting-your-entity-registration-to-the-network",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adding-or-removing-nodes",children:"Adding or Removing Nodes"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Access to a synced node"}),"\n",(0,t.jsx)(n.li,{children:"Access to your entity's private key"}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you just need to temporarily disable your node (e.g. to perform system\nupdates), use ",(0,t.jsx)(n.a,{href:"/node/run-your-node/maintenance/shutting-down-a-node",children:"graceful shutdown"})," instead. This will assure you that your\nentity will not get penalized during node's downtime."]})}),"\n",(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"The process for adding/removing nodes is similar and has the following steps:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Obtain the ID of your running Oasis node"}),"\n",(0,t.jsxs)(n.li,{children:["Download your entity descriptor (",(0,t.jsx)(n.code,{children:"entity.json"}),") from the network registry"]}),"\n",(0,t.jsx)(n.li,{children:"Update the entity descriptor by adding/removing a node"}),"\n",(0,t.jsx)(n.li,{children:"Submitting the updated entity descriptor to the network"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"obtain-the-id-of-your-node",children:"Obtain the ID of your Node"}),"\n",(0,t.jsxs)(n.p,{children:["Connect to your ",(0,t.jsx)(n.code,{children:"server"})," and obtain the ID of your node by running:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis-node control status -a unix:/node/data/internal.sock | jq .identity.node\n"})}),"\n",(0,t.jsx)(n.h2,{id:"download-your-latest-entity-descriptor",children:"Download Your Latest Entity Descriptor"}),"\n",(0,t.jsxs)(n.p,{children:["To ensure that we do not update your entity descriptor (",(0,t.jsx)(n.code,{children:"entity.json"}),")\nincorrectly we should get the latest entity descriptor state from the network.\nFor this operation, you will need to know the base64 encoding of your entity's\npublic key."]}),"\n",(0,t.jsxs)(n.p,{children:["Use ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-id",children:(0,t.jsx)(n.code,{children:"oasis network show"})})," command on your ",(0,t.jsx)(n.code,{children:"localhost"})," to get the latest entity\ndescriptor stored in the network registry. This command is part of ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"}),".\nFor example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis network show xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Now store the obtained JSON as ",(0,t.jsx)(n.code,{children:"entity.json"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"updating-your-entity-descriptor",children:"Updating Your Entity Descriptor"}),"\n",(0,t.jsx)(n.h3,{id:"to-add-a-node",children:"To Add a Node"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.em,{children:"not"}),"\ngive you more voting power nor will it, inherently, provide high availability\nto have multiple nodes."]})}),"\n",(0,t.jsxs)(n.p,{children:["To attach a new node with your entity, add the ID of your node obtained in\nthe ",(0,t.jsx)(n.a,{href:"#obtain-the-id-of-your-node",children:"section above"})," to the ",(0,t.jsx)(n.code,{children:"nodes"})," field in your\n",(0,t.jsx)(n.code,{children:"entity.json"}),". For example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "v": 2,\n "id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=",\n "nodes": [\n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="\n ]\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"In the above entity descriptor 2 nodes are attached to the entity:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["A node with an identity ",(0,t.jsx)(n.code,{children:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="})]}),"\n",(0,t.jsxs)(n.li,{children:["A node with an identity ",(0,t.jsx)(n.code,{children:"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="})]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"to-remove-a-node",children:"To Remove a Node"}),"\n",(0,t.jsxs)(n.p,{children:["To remove node with ID ",(0,t.jsx)(n.code,{children:"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="})," from your\nentity descriptor, simply remove the record from the array in the ",(0,t.jsx)(n.code,{children:"nodes"})," field.\nFor example:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "v": 2,\n "id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=",\n "nodes": [\n "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n ],\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"submitting-your-entity-registration-to-the-network",children:"Submitting Your Entity Registration to the Network"}),"\n",(0,t.jsxs)(n.p,{children:["Finally, to commit the changes on the network, invoke the [",(0,t.jsx)(n.code,{children:"oasis account entity register"}),"] command on your ",(0,t.jsx)(n.code,{children:"localhost"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis account entity register entity.json --account my_entity\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The account used to sign the transaction (",(0,t.jsx)(n.code,{children:"my_entity"})," in the snippet above) must\ncorrespond to the entity ID in ",(0,t.jsx)(n.code,{children:"entity.json"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["If there are no errors, your entity registration should be updated. You can run\nthe ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-id",children:(0,t.jsx)(n.code,{children:"oasis network show"})})," command again to see the changes."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>d,x:()=>s});var t=o(6540);const i={},r=t.createContext(i);function d(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bb3e1595.89646325.js b/assets/js/bb3e1595.89646325.js new file mode 100644 index 0000000000..385354b289 --- /dev/null +++ b/assets/js/bb3e1595.89646325.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9227],{2360:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var t=n(4848),s=n(8453);const i={},r="Develop Oasis Core",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/get-involved/oasis-core.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"getInvolved",previous:{title:"ParaTime Node",permalink:"/get-involved/run-node/paratime-node"},next:{title:"Network Governance",permalink:"/get-involved/network-governance"}},c={},d=[];function l(e){const o={a:"a",admonition:"admonition",h1:"h1",p:"p",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.h1,{id:"develop-oasis-core",children:"Develop Oasis Core"}),"\n",(0,t.jsx)(o.admonition,{type:"info",children:(0,t.jsxs)(o.p,{children:["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,t.jsx)(o.a,{href:"/get-involved/network-governance",children:"please see our governance overview here"}),"."]})}),"\n",(0,t.jsxs)(o.p,{children:["If you wish to contribute either code, documentation or larger enhancement\nproposals, feel free to read our\n",(0,t.jsx)(o.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/master/CONTRIBUTING.md",children:"Oasis Core Contributing Guidelines"}),"."]})]})}function u(e={}){const{wrapper:o}={...(0,s.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>r,x:()=>a});var t=n(6540);const s={},i=t.createContext(s);function r(e){const o=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bcbc0322.cebc9191.js b/assets/js/bcbc0322.cebc9191.js new file mode 100644 index 0000000000..ba2dcae526 --- /dev/null +++ b/assets/js/bcbc0322.cebc9191.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4012],{6544:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>h,contentTitle:()=>c,default:()=>f,frontMatter:()=>d,metadata:()=>u,toc:()=>m});var t=r(4848),i=r(8453),o=r(5965),a=r(6116),s=r(1470),l=r(9365);const d={},c="ParaTime Client Node",u={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/paratime-client-node.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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/"}},h={},m=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"The ParaTime Bundle",id:"the-paratime-bundle",level:3},{value:"Compiling the ParaTime Binary from Source Code",id:"compiling-the-paratime-binary-from-source-code",level:4},{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:"Configuring TEE Paratime Client Node",id:"configuring-tee-paratime-client-node",level:2},{value:"Enabling Expensive Queries",id:"enabling-expensive-queries",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}];function p(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"paratime-client-node",children:"ParaTime Client Node"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["These instructions are for setting up a ",(0,t.jsx)(n.em,{children:"ParaTime client"})," node which only observes ParaTime activity and can submit transactions. If you want to run a ",(0,t.jsx)(n.em,{children:"ParaTime"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"instructions for running a ParaTime node"}),". Similarly, if you want to run a ",(0,t.jsx)(n.em,{children:"validator"})," or a ",(0,t.jsx)(n.em,{children:"non-validator"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"instructions for running a validator node"})," or ",(0,t.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"instructions for running a non-validator node"}),"."]})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you are looking for some concrete ParaTimes that you can run, see ",(0,t.jsx)(n.a,{href:"/get-involved/run-node/paratime-node",children:"the list of ParaTimes and their parameters"}),"."]})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsx)(n.p,{children:"Oasis Core refers to ParaTimes as runtimes internally, so all configuration options will have runtime in their name."})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the ",(0,t.jsx)(n.a,{href:"prerequisites",children:"Prerequisites"})," and ",(0,t.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Run a Non-validator Node"})," sections and have:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Oasis Node binary installed and configured on your system."}),"\n",(0,t.jsxs)(n.li,{children:["The chosen top-level ",(0,t.jsx)(n.code,{children:"/node/"})," working directory prepared. In addition to ",(0,t.jsx)(n.code,{children:"etc"})," and ",(0,t.jsx)(n.code,{children:"data"})," directories, also prepare the following directories:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"bin"}),": This will store binaries needed by Oasis Node for running the ParaTimes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"runtimes"}),": This will store the ParaTime bundles."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsxs)(n.p,{children:["Feel free to name your working directory as you wish, e.g. ",(0,t.jsx)(n.code,{children:"/srv/oasis/"}),"."]}),(0,t.jsx)(n.p,{children:"Just make sure to use the correct working directory path in the instructions below."})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Genesis file copied to ",(0,t.jsx)(n.code,{children:"/node/etc/genesis.json"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["Reading the rest of the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"ParaTime node setup instructions"})," may also be useful."]})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["To speed up bootstraping your new node, we recommend ",(0,t.jsx)(n.a,{href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",children:"copying node's state from your existing node"})," or ",(0,t.jsx)(n.a,{href:"/node/run-your-node/advanced/sync-node-using-state-sync",children:"syncing it using state sync"}),"."]})}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsx)(n.p,{children:"Running a ParaTime client node doesn't require registering an entity or its nodes."}),(0,t.jsx)(n.p,{children:"It also doesn't require having any stake."})]}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsx)(n.p,{children:"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,t.jsx)(n.p,{children:"For example, running a ParaTime client node for an SGX-enabled ParaTime like Cipher doesn't require having SGX on the ParaTime client node."})]}),"\n",(0,t.jsx)(n.h3,{id:"the-paratime-bundle",children:"The ParaTime Bundle"}),"\n",(0,t.jsxs)(n.p,{children:["In order to run a ParaTime node you need to obtain an active ParaTime bundle,\nsee the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),"). The bundle (",(0,t.jsx)(n.code,{children:".orc"}),"\nextension that stands for Oasis Runtime Container) contains all the needed\nParaTime binaries together with the identifier and version metadata to ease\ndeployment."]}),"\n",(0,t.jsx)(n.p,{children:"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)."}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"Like the genesis document, make sure you obtain these from a trusted source."})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.h4,{id:"compiling-the-paratime-binary-from-source-code",children:(0,t.jsx)(n.strong,{children:"Compiling the ParaTime Binary from Source Code"})}),(0,t.jsxs)(n.p,{children:["In case you decide to build the ParaTime binary from source yourself, make sure\nthat you follow our ",(0,t.jsx)(n.a,{href:"../../paratime/reproducibility",children:"guidelines for deterministic compilation"}),"\nto ensure that you receive the exact same binary."]})]}),"\n",(0,t.jsx)(n.h3,{id:"install-paratime-bundle",children:"Install ParaTime Bundle"}),"\n",(0,t.jsxs)(n.p,{children:["For each ParaTime, you need to obtain its bundle and install it to the\n",(0,t.jsx)(n.code,{children:"runtimes"})," subdirectory of your node's working directory."]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["For example, for the ",(0,t.jsx)(n.a,{href:"/node/mainnet/#cipher",children:"Cipher ParaTime"}),",\nyou would have to obtain the ",(0,t.jsx)(n.code,{children:"cipher-paratime.orc"})," bundle and install it to\n",(0,t.jsx)(n.code,{children:"/node/runtimes/cipher-paratime.orc"}),"."]})}),"\n",(0,t.jsx)(n.h3,{id:"install-bubblewrap-sandbox-at-least-version-033",children:"Install Bubblewrap Sandbox (at least version 0.3.3)"}),"\n",(0,t.jsxs)(n.p,{children:["ParaTime client nodes execute ParaTime binaries inside a sandboxed environment provided by ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap",children:"Bubblewrap"}),". In order to install it, please follow these instructions, depending on your distribution:"]}),"\n",(0,t.jsxs)(s.A,{children:[(0,t.jsx)(l.A,{value:"Ubuntu 18.10+",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo apt install bubblewrap\n"})})}),(0,t.jsx)(l.A,{value:"Fedora",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo dnf install bubblewrap\n"})})}),(0,t.jsxs)(l.A,{value:"other",label:"Other Distributions",children:[(0,t.jsxs)(n.p,{children:["On other systems, you can download the latest ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap/releases",children:"source release provided by the Bubblewrap project"})," and build it yourself."]}),(0,t.jsxs)(n.p,{children:["Make sure you have the necessary development tools installed on your system and the ",(0,t.jsx)(n.code,{children:"libcap"})," development headers. On Ubuntu, you can install them with:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo apt install build-essential libcap-dev\n"})}),(0,t.jsxs)(n.p,{children:["After obtaining the Bubblewrap source tarball, e.g. ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap/releases/download/v0.4.1/bubblewrap-0.4.1.tar.xz",children:"bubblewrap-0.4.1.tar.xz"}),", run:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"tar -xf bubblewrap-0.4.1.tar.xz\ncd bubblewrap-0.4.1\n./configure --prefix=/usr\nmake\nsudo make install\n"})}),(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Note that Oasis Node expects Bubblewrap to be installed under ",(0,t.jsx)(n.code,{children:"/usr/bin/bwrap"})," by default."]})})]})]}),"\n",(0,t.jsx)(n.p,{children:"Ensure you have a new enough version by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"bwrap --version\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Ubuntu 18.04 LTS (and earlier) provide overly-old ",(0,t.jsx)(n.code,{children:"bubblewrap"}),". Follow ",(0,t.jsx)(n.em,{children:"Other Distributions"})," section on those systems."]})}),"\n",(0,t.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsxs)(n.p,{children:["In order to configure the ParaTime client node, create the ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file with the following content:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"mode: client\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: info\n cometbft/context: error\n default: info\ngenesis:\n file: /node/etc/genesis.json\np2p:\n seeds:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n - {{ seed_node_address }}\nruntime:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n paths:\n - {{ runtime_orc_path }}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Before using this configuration you should collect the following information to replace the variables present in the configuration file:."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ seed_node_address }}"}),": The seed node address in the form ",(0,t.jsx)(n.code,{children:"ID@IP:port"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["You can find the current Oasis Seed Node address in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ runtime_orc_path }}"}),": Path to the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node#the-paratime-bundle",children:"ParaTime bundle"})," of the form ",(0,t.jsx)(n.code,{children:"/node/runtimes/foo-paratime.orc"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["You can find the current Oasis-supported ParaTimes in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Make sure the ",(0,t.jsx)(n.code,{children:"consensus"})," port (default: ",(0,t.jsx)(n.code,{children:"26656"}),") and ",(0,t.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,t.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,t.jsx)(n.code,{children:"TCP"})," and ",(0,t.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,t.jsx)(n.h2,{id:"configuring-tee-paratime-client-node",children:"Configuring TEE Paratime Client Node"}),"\n",(0,t.jsxs)(n.p,{children:["If your node requires the ability to issue queries that can access confidential\ndata, start by following the ",(0,t.jsx)(n.a,{href:"#configuration",children:"Configuration"})," section to create\nthe ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file. Once the file is set up, add the following\ncontent to the ",(0,t.jsx)(n.code,{children:"runtime"})," part within the ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"# ... sections not relevant are omitted ...\nruntime:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n paths:\n - {{ runtime_orc_path }}\n environment: sgx\n sgx_loader: /node/bin/oasis-core-runtime-loader\n"})}),"\n",(0,t.jsx)(n.p,{children:"Before using this configuration you should collect the following information to\nreplace the variables present in the configuration file:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ runtime_orc_path }}"}),": Path to the\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node#the-paratime-bundle",children:"ParaTime bundle"})," of the form\n",(0,t.jsx)(n.code,{children:"/node/runtimes/foo-paratime.orc"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"enabling-expensive-queries",children:"Enabling Expensive Queries"}),"\n",(0,t.jsxs)(n.p,{children:["In case you need to issue runtime queries that may require more resources to\ncompute (e.g. when running a Web3 Gateway), you need to configure the following\nin your node's ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"# ... sections not relevant are omitted ...\nruntime:\n paths:\n - {{ runtime_orc_path }}\n environment: sgx\n config:\n {{ runtime_id }}:\n estimate_gas_by_simulating_contracts: true\n allowed_queries:\n - all_expensive: true \n"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ runtime_id}}"}),": You can find the ",(0,t.jsx)(n.code,{children:"runtime_id"})," in the Network Parameters\nchapter (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ runtime_orc_path }}"}),": Path to the\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node#the-paratime-bundle",children:"ParaTime bundle"})," of the form\n",(0,t.jsx)(n.code,{children:"/node/runtimes/foo-paratime.orc"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,t.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,t.jsx)(n.h2,{id:"checking-node-status",children:"Checking Node Status"}),"\n",(0,t.jsx)(n.p,{children:"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),"\n",(0,t.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsx)(o.A,{item:(0,a.$)("/node/web3")})]})}function f(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},5965:(e,n,r)=>{r.d(n,{A:()=>x});r(6540);var t=r(4164),i=r(8774),o=r(4142),a=r(5846),s=r(6654),l=r(1312),d=r(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=r(4848);function h(e){let{href:n,children:r}=e;return(0,u.jsx)(i.A,{href:n,className:(0,t.A)("card padding--lg",c.cardContainer),children:r})}function m(e){let{href:n,icon:r,title:i,description:o}=e;return(0,u.jsxs)(h,{href:n,children:[(0,u.jsxs)(d.A,{as:"h2",className:(0,t.A)("text--truncate",c.cardTitle),title:i,children:[r," ",i]}),o&&(0,u.jsx)("p",{className:(0,t.A)("text--truncate",c.cardDescription),title:o,children:o})]})}function p(e){let{item:n}=e;const r=(0,o.Nr)(n),t=function(){const{selectMessage:e}=(0,a.W)();return n=>e(n,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return r?(0,u.jsx)(m,{href:r,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??t(n.items.length)}):null}function f(e){let{item:n}=e;const r=(0,s.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",t=(0,o.cC)(n.docId??void 0);return(0,u.jsx)(m,{href:n.href,icon:r,title:n.label,description:n.description??t?.description})}function x(e){let{item:n}=e;switch(n.type){case"link":return(0,u.jsx)(f,{item:n});case"category":return(0,u.jsx)(p,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},9365:(e,n,r)=>{r.d(n,{A:()=>a});r(6540);var t=r(4164);const i={tabItem:"tabItem_Ymn6"};var o=r(4848);function a(e){let{children:n,hidden:r,className:a}=e;return(0,o.jsx)("div",{role:"tabpanel",className:(0,t.A)(i.tabItem,a),hidden:r,children:n})}},1470:(e,n,r)=>{r.d(n,{A:()=>w});var t=r(6540),i=r(4164),o=r(3104),a=r(6347),s=r(205),l=r(7485),d=r(1682),c=r(9466);function u(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function h(e){const{values:n,children:r}=e;return(0,t.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:r,attributes:t,default:i}}=e;return{value:n,label:r,attributes:t,default:i}}))}(r);return function(e){const n=(0,d.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function m(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:r}=e;const i=(0,a.W6)(),o=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)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 r??null}({queryString:n,groupId:r});return[(0,l.aZ)(o),(0,t.useCallback)((e=>{if(!o)return;const n=new URLSearchParams(i.location.search);n.set(o,e),i.replace({...i.location,search:n.toString()})}),[o,i])]}function f(e){const{defaultValue:n,queryString:r=!1,groupId:i}=e,o=h(e),[a,l]=(0,t.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const t=r.find((e=>e.default))??r[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:o}))),[d,u]=p({queryString:r,groupId:i}),[f,x]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[i,o]=(0,c.Dv)(r);return[i,(0,t.useCallback)((e=>{r&&o.set(e)}),[r,o])]}({groupId:i}),b=(()=>{const e=d??f;return m({value:e,tabValues:o})?e:null})();(0,s.A)((()=>{b&&l(b)}),[b]);return{selectedValue:a,selectValue:(0,t.useCallback)((e=>{if(!m({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),u(e),x(e)}),[u,x,o]),tabValues:o}}var x=r(2303);const b={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var g=r(4848);function j(e){let{className:n,block:r,selectedValue:t,selectValue:a,tabValues:s}=e;const l=[],{blockElementScrollPositionUntilNextRender:d}=(0,o.a_)(),c=e=>{const n=e.currentTarget,r=l.indexOf(n),i=s[r].value;i!==t&&(d(n),a(i))},u=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const r=l.indexOf(e.currentTarget)+1;n=l[r]??l[0];break}case"ArrowLeft":{const r=l.indexOf(e.currentTarget)-1;n=l[r]??l[l.length-1];break}}n?.focus()};return(0,g.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.A)("tabs",{"tabs--block":r},n),children:s.map((e=>{let{value:n,label:r,attributes:o}=e;return(0,g.jsx)("li",{role:"tab",tabIndex:t===n?0:-1,"aria-selected":t===n,ref:e=>l.push(e),onKeyDown:u,onClick:c,...o,className:(0,i.A)("tabs__item",b.tabItem,o?.className,{"tabs__item--active":t===n}),children:r??n},n)}))})}function y(e){let{lazy:n,children:r,selectedValue:i}=e;const o=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=o.find((e=>e.props.value===i));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,g.jsx)("div",{className:"margin-top--md",children:o.map(((e,n)=>(0,t.cloneElement)(e,{key:n,hidden:e.props.value!==i})))})}function v(e){const n=f(e);return(0,g.jsxs)("div",{className:(0,i.A)("tabs-container",b.tabList),children:[(0,g.jsx)(j,{...n,...e}),(0,g.jsx)(y,{...n,...e})]})}function w(e){const n=(0,x.A)();return(0,g.jsx)(v,{...e,children:u(e.children)},String(n))}},5846:(e,n,r)=>{r.d(n,{W:()=>d});var t=r(6540),i=r(4586);const o=["zero","one","two","few","many","other"];function a(e){return o.filter((n=>e.includes(n)))}const s={locale:"en",pluralForms:a(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,i.A)();return(0,t.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:a(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),s}}),[e])}function d(){const e=l();return{selectMessage:(n,r)=>function(e,n,r){const t=e.split("|");if(1===t.length)return t[0];t.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${t.length}: ${e}`);const i=r.select(n),o=r.pluralForms.indexOf(i);return t[Math.min(o,t.length-1)]}(r,n,e)}}},6116:(e,n,r)=>{r.d(n,{$:()=>o});var t=r(2252);function i(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&i(n.items)}}function o(e){const n=(0,t.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)i(n.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]}},8453:(e,n,r)=>{r.d(n,{R:()=>a,x:()=>s});var t=r(6540);const i={},o=t.createContext(i);function a(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/be76d7de.bd7ceafe.js b/assets/js/be76d7de.bd7ceafe.js new file mode 100644 index 0000000000..a9c2439468 --- /dev/null +++ b/assets/js/be76d7de.bd7ceafe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8913],{7719:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var s=t(4848),a=t(8453),i=t(1470),r=t(9365);const o={description:"The Oasis Foundation-managed non-custodial web wallet"},l="ROSE Wallet - Web",c={id:"general/manage-tokens/oasis-wallets/web",title:"ROSE Wallet - Web",description:"The Oasis Foundation-managed non-custodial web wallet",source:"@site/docs/general/manage-tokens/oasis-wallets/web.mdx",sourceDirName:"general/manage-tokens/oasis-wallets",slug:"/general/manage-tokens/oasis-wallets/web",permalink:"/general/manage-tokens/oasis-wallets/web",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/oasis-wallets/web.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"The Oasis Foundation-managed non-custodial web wallet"},sidebar:"general",previous:{title:"ROSE Wallet",permalink:"/general/manage-tokens/oasis-wallets"},next:{title:"Browser Extension",permalink:"/general/manage-tokens/oasis-wallets/browser-extension"}},d={},h=[{value:"Create a New Account",id:"create-a-new-account",level:2},{value:"Account Derivation",id:"account-derivation",level:3},{value:"User Profile",id:"user-profile",level:3},{value:"Import an Existing Account",id:"import-an-existing-account",level:2},{value:"Transfer",id:"transfer",level:2},{value:"Stake",id:"stake",level:2},{value:"ParaTimes",id:"paratimes",level:2},{value:"Buy",id:"buy",level:2},{value:"Account options",id:"account-options",level:2},{value:"My Accounts",id:"my-accounts",level:3},{value:"Contacts",id:"contacts",level:3},{value:"Profile",id:"profile",level:3},{value:"Settings",id:"settings",level:3},{value:"Share your feedback with us",id:"share-your-feedback-with-us",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"rose-wallet---web",children:"ROSE Wallet - Web"}),"\n",(0,s.jsxs)(n.p,{children:["This is the Oasis Foundation-managed non-custodial web wallet for the Oasis\nNetwork. You can access it by visiting ",(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.a,{href:"https://wallet.oasis.io",children:"wallet.oasis.io"})}),"."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Home screen",src:t(590).A+"",width:"1257",height:"970"})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["The wallet was designed to work with any modern browser. In order to use the\n",(0,s.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Ledger hardware wallet"})," though, ",(0,s.jsx)(n.strong,{children:"you\nwill need the WebUSB support"}),". At time of writing, this was only available in\n",(0,s.jsx)(n.a,{href:"https://www.google.com/chrome/",children:"Chrome"})," and other\n",(0,s.jsx)(n.a,{href:"https://www.chromium.org/Home",children:"Chromium"}),"-based browsers."]})}),"\n",(0,s.jsxs)(n.p,{children:["Opening the wallet for the first time will show the ",(0,s.jsx)(n.em,{children:"Home screen"})," where you can\nchoose to ",(0,s.jsx)(n.a,{href:"#create-a-new-account",children:"create a new account"})," or\n",(0,s.jsx)(n.a,{href:"#import-an-existing-account",children:"open an existing one"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"create-a-new-account",children:"Create a New Account"}),"\n",(0,s.jsxs)(n.p,{children:["The next screen is devoted to your mnemonic\u2014",(0,s.jsx)(n.strong,{children:"a unique list of\nwords representing your account(s)"}),". Review the information on this page very\ncarefully. Save your\nmnemonic in the right order in a secure location."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsx)(n.p,{children:"Your mnemonic (i.e. keyphrase) is required to access your wallet. Be sure to\nstore it in a secure location. If you lose or forget your mnemonic, you will\nlose access to your wallet and any token funds contained in it."})}),"\n",(0,s.jsx)(n.admonition,{title:"Never share your mnemonic (i.e. keyphrase)!",type:"danger",children:(0,s.jsx)(n.p,{children:"Anyone with your mnemonic can access your wallet and your tokens."})}),"\n",(0,s.jsx)(n.p,{children:"After you\u2019ve saved your mnemonic, click the \u201cI saved my keyphrase\u201d checkbox and\nthen click on the \u201cImport my wallet\u201d button."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Create a New Wallet",src:t(3242).A+"",width:"1257",height:"970"})}),"\n",(0,s.jsx)(n.p,{children:'Next, you will need to confirm your mnemonic by writing the mnemonic into the\ntext area. The ROSE Wallet will check for any typos and missing words. When\ndone click the "Import my wallet" button.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Confirm your mnemonic",src:t(3825).A+"",width:"1257",height:"970"})}),"\n",(0,s.jsx)(n.h3,{id:"account-derivation",children:"Account Derivation"}),"\n",(0,s.jsxs)(n.p,{children:["If you correctly entered the mnemonic the ",(0,s.jsx)(n.strong,{children:"account derivation popup"}),"\nwill appear containing a list of ",(0,s.jsx)(n.code,{children:"oasis1"})," addresses with their\nbalances on the right. These are the accounts derived from your\nmnemonic based on the ",(0,s.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8 derivation scheme"}),'. Select one or more\naccounts and click the "Open" button to import them into your wallet.']}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Account derivation popup",src:t(9580).A+"",width:"1257",height:"970"})}),"\n",(0,s.jsx)(n.h3,{id:"user-profile",children:"User Profile"}),"\n",(0,s.jsxs)(n.p,{children:['If you want to permanently store the keys of selected accounts, select the\n"Store private keys locally, protected by a password" box. After entering a\npassword below, this will ',(0,s.jsx)(n.strong,{children:"instantiate a profile inside the local store of your\nbrowser to safely store your keys"}),". To access them, you will need to enter the correct\npassword each time you will open the ROSE Wallet - Web."]}),"\n",(0,s.jsxs)(n.p,{children:["Finally, you will be taken to the ",(0,s.jsx)(n.em,{children:"Wallet screen"}),", containing\ninformation about your account balance, recent transactions and more."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"The Wallet screen",src:t(6900).A+"",width:"1319",height:"970"})}),"\n",(0,s.jsx)(n.h2,{id:"import-an-existing-account",children:"Import an Existing Account"}),"\n",(0,s.jsx)(n.p,{children:'On the "Open wallet" page select whether you want to open your\nwallet via a mnemonic, a private key, or a Ledger hardware wallet.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Access an Existing Wallet",src:t(1670).A+"",width:"1329",height:"974"})}),"\n",(0,s.jsxs)(i.A,{children:[(0,s.jsxs)(r.A,{value:"Mnemonic",children:[(0,s.jsx)(n.p,{children:'In the "Enter your keyphrase here" field, enter each word of your mnemonic\nseparated by a space. Then, hit the "Import my wallet" button.'}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Open Wallet via Mnemonic",src:t(9963).A+"",width:"1324",height:"970"})}),(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"#account-derivation",children:"account derivation popup"})," will be shown where\nyou can pick one or more derived accounts to import."]}),(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["The ROSE Wallet uses English mnemonic phrase words as defined in\n",(0,s.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",children:"BIP39"}),".\nYou can find a complete list of all valid phrase words\n",(0,s.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt",children:"here"}),".\nIf you misspelled a word, the wallet will warn you."]})})]}),(0,s.jsxs)(r.A,{value:"Private Key",children:[(0,s.jsx)(n.p,{children:'Paste your Base64-encoded Ed25519 private key in the "Enter your private key\nhere" field and then click on the "Import my wallet" button.'}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Open Wallet via Private Key",src:t(805).A+"",width:"1324",height:"970"})}),(0,s.jsxs)(n.p,{children:['Selecting "Store private keys locally, protected by a password" will instantiate\nthe ',(0,s.jsx)(n.a,{href:"#user-profile",children:"user's profile"}),"."]}),(0,s.jsxs)(n.admonition,{type:"tip",children:[(0,s.jsxs)(n.p,{children:["The 64 bytes long keypair is the preferred format for importing your account. It\nconsists of ",(0,s.jsx)(n.strong,{children:"two 32-byte parts"}),":"]}),(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["The first part is the ",(0,s.jsx)(n.strong,{children:"private key"})," used for signing the transactions\n(e.g. for sending tokens from your account)."]}),"\n",(0,s.jsxs)(n.li,{children:["The second part is a ",(0,s.jsx)(n.strong,{children:"public key"})," used to verify the signatures\nof your transactions and also derive your account's address of the form\n",(0,s.jsx)(n.code,{children:"oasis1..."}),"."]}),"\n"]})]}),(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["If you entered the 64-byte keypair then the wallet checks whether the public\nkey corresponds to its private counterpart. ",(0,s.jsx)(n.strong,{children:"If you mistyped any character, the\nwallet will not allow you to proceed."})]}),(0,s.jsxs)(n.p,{children:["However, if you only typed in the first 32-byte part there is **no error\ndetection possible. It is imperative that you ",(0,s.jsx)(n.strong,{children:"correctly input all characters"}),"\nand not mix similar characters like the big O and 0 or big I and 1! If unsure,\nwe suggest that you perform a test transaction the first time you import your\nwallet from the private key so you can rest assured the key is valid."]})]})]}),(0,s.jsxs)(r.A,{value:"Ledger",children:[(0,s.jsxs)(n.p,{children:["To use the Ledger hardware wallet, make sure you have your Ledger device readily\navailable and have familiarized yourself with the ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",children:"Oasis-specific Ledger usage instructions"}),"."]}),(0,s.jsx)(n.p,{children:'Next, click on the "Select accounts to open". If this is the first time you\'re\nusing Ledger with your browser, a system popup will appear showing the list of\nLedger devices connected to your computer and requesting permission to use it.\nSelect one and then click the "Connect" button.'}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Open Wallet via Ledger",src:t(888).A+"",width:"1327",height:"976"})}),(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"#account-derivation",children:"account derivation popup"})," will be shown next,\nwhere you can pick one or more derived accounts to import."]}),(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsx)(n.p,{children:"To date, only Chromium-based browsers support WebUSB component which is required\nto access your Ledger device."})})]})]}),"\n",(0,s.jsxs)(n.p,{children:["Finally, you will be taken to your ",(0,s.jsx)(n.em,{children:"Wallet screen"}),", containing information about\nyour account balance, recent transactions and more."]}),"\n",(0,s.jsx)(n.h2,{id:"transfer",children:"Transfer"}),"\n",(0,s.jsxs)(i.A,{children:[(0,s.jsxs)(r.A,{value:"Send tokens",children:[(0,s.jsxs)(n.p,{children:["To transfer tokens, open the ",(0,s.jsx)(n.em,{children:"Wallet screen"}),'. Fill in the "Recipient" and\n"Amount" fields and click "Send". A confirmation popup will appear showing\ntransaction details. Carefully review the transaction and click the "Confirm"\nbutton.']}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Transfer confirmation dialog",src:t(2930).A+"",width:"1324",height:"970"})})]}),(0,s.jsxs)(r.A,{value:"Receive tokens",children:[(0,s.jsxs)(n.p,{children:["To receive tokens, open the ",(0,s.jsx)(n.em,{children:"Wallet screen"})," and copy the ",(0,s.jsx)(n.code,{children:"oasis1"})," account\naddress at the top. You can also scan or store a QR code corresponding to your\naccount on the right side of the screen."]}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"The Wallet screen",src:t(6900).A+"",width:"1319",height:"970"})})]})]}),"\n",(0,s.jsx)(n.h2,{id:"stake",children:"Stake"}),"\n",(0,s.jsxs)(n.p,{children:["To ",(0,s.jsx)(n.a,{href:"/general/manage-tokens/staking-and-delegating",children:"stake your tokens"})," open the ",(0,s.jsx)(n.em,{children:"Stake screen"}),".\nThe list of validators will appear, their status, current escrow and the\ncommission fee. Follow the sections below to delegate or undelegate your tokens."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Stake screen",src:t(9045).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsxs)(i.A,{children:[(0,s.jsx)(r.A,{value:"Delegate",children:(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'To delegate tokens, select the preferred validator you wish to delegate your\ntokens to by clicking on it. Fill in the amount and click the "Delegate"\nbutton.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Stake screen: Selected validator",src:t(8213).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'A confirmation popup will appear showing transaction details. Carefully\nreview the transaction and click the "Confirm" button.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Delegate confirmation dialog",src:t(6110).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'In a while, your delegated tokens will appear under the "Active delegations"\ntab.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Active delegations",src:t(3799).A+"",width:"1324",height:"970"})}),"\n"]}),"\n"]})}),(0,s.jsx)(r.A,{value:"Undelegate",children:(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'To undelegate, click on a validator in the "Active delegations" tab, enter\nthe amount of tokens you wish to undelegate and click "Reclaim". You can also\nclick the "Reclaim all" button to undelegate all delegated tokens from this\nvalidator.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Active delegations",src:t(2526).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'A confirmation popup will appear showing transaction details. Carefully review\nthe transaction and click the "Confirm" button.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Undelegate confirmation dialog",src:t(1301).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["In a while, your undelegated tokens will enter the ",(0,s.jsx)(n.strong,{children:"debonding period"}),'. You can\ncheck out all the delegations that are in the debonding period in the "Debonding\ndelegations" tab.']}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Debonding delegations",src:t(3788).A+"",width:"1324",height:"970"})}),"\n"]}),"\n"]})})]}),"\n",(0,s.jsx)(n.h2,{id:"paratimes",children:"ParaTimes"}),"\n",(0,s.jsxs)(n.p,{children:["To move tokens from the consensus layer to a ParaTime (",(0,s.jsx)(n.strong,{children:"deposit"}),") or the\nother way around (",(0,s.jsx)(n.strong,{children:"withdrawal"}),"), open the ",(0,s.jsx)(n.em,{children:"ParaTime screen"}),'. Click on the\n"Deposit to ParaTime" or "Withdraw from ParaTime" button and follow the sections\nbelow.']}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"The ParaTime screen",src:t(5359).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsxs)(i.A,{children:[(0,s.jsx)(r.A,{value:"Deposit",children:(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'Select the ParaTime you wish to deposit your tokens to and click "Next".'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Deposit tokens: Select ParaTime",src:t(3692).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Enter the recipient address in the ParaTime. For EVM-compatible\nParaTimes you will need to enter a hex-encoded address starting with ",(0,s.jsx)(n.code,{children:"0x"})," and\nfor other ParaTimes the Oasis native address starting with ",(0,s.jsx)(n.code,{children:"oasis1"}),'. Click\n"Next".']}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Deposit tokens: Recipient address",src:t(8519).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Enter the amount to deposit."}),"\n",(0,s.jsx)(n.p,{children:'The gas fee and price will automatically be computed. You can toggle the\n"Advanced" button to set it manually.'}),"\n",(0,s.jsx)(n.p,{children:'Finally, click "Next".'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Deposit tokens: Amount",src:t(830).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'Review deposit details, check the "I confirm the amount and the address are\ncorrect" and click the "Deposit" button.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Deposit tokens: Review deposit",src:t(6945).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.p,{children:"Once the deposit transaction is confirmed the tokens will appear on your\nParaTime account."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Deposit tokens: Deposit complete",src:t(7e3).A+"",width:"1324",height:"970"})}),"\n"]}),"\n"]})}),(0,s.jsx)(r.A,{value:"Withdraw",children:(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'Select the ParaTime you wish to withdraw your tokens from and click "Next".'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Withdraw tokens: Select ParaTime",src:t(1296).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Enter the recipient address on the consensus layer below."}),"\n",(0,s.jsxs)(n.p,{children:["If the ParaTime is EVM-compatible you will also need to enter the\n",(0,s.jsx)(n.strong,{children:"hex-encoded private key"})," of the account on the ParaTime which you are\nwithdrawing from. If you are using a ",(0,s.jsx)(n.a,{href:"#user-profile",children:"profile"}),", the ",(0,s.jsx)(n.strong,{children:"private\nkey will be stored for any future withdrawals"}),". For other ParaTimes, the\nwithdrawal transaction will be signed with the ",(0,s.jsx)(n.strong,{children:"private key of your\ncurrently selected account in your wallet"}),"."]}),"\n",(0,s.jsx)(n.p,{children:'Click "Next" to continue.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Withdraw tokens: Recipient address",src:t(4795).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Enter the amount to withdraw."}),"\n",(0,s.jsx)(n.p,{children:'The gas fee and price will automatically be computed. You can toggle the\n"Advanced" button to set it manually.'}),"\n",(0,s.jsx)(n.p,{children:'Finally, click "Next".'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Withdraw tokens: Amount",src:t(3666).A+"",width:"1324",height:"970"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:'Review withdrawal details, check the "I confirm the amount and the address\nare correct" and click the "Withdraw" button.'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Withdraw tokens: Review withdrawal",src:t(13).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.p,{children:"Once the withdrawal transaction is confirmed the tokens will appear on your\nconsensus account."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Withdraw tokens: Withdrawal complete",src:t(8884).A+"",width:"1324",height:"970"})}),"\n"]}),"\n"]})})]}),"\n",(0,s.jsx)(n.h2,{id:"buy",children:"Buy"}),"\n",(0,s.jsxs)(n.p,{children:["You can buy ROSE directly from within the wallet by opening the ",(0,s.jsx)(n.em,{children:"Buy screen"}),".\nThe ROSE Wallet team integrated a 3rd party ",(0,s.jsx)(n.a,{href:"https://transak.com/",children:"Transak"}),"\nservice which performs the necessary KYC, supports various payment methods, buys\nthe tokens on the market and transfers them to your currently selected account."]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Buy tokens directly from the wallet",src:t(6395).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.h2,{id:"account-options",children:"Account options"}),"\n",(0,s.jsx)(n.p,{children:"When you have at least one account opened, click on the account jazz icon in the\ntop-right corner. A popup will appear."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Settings popup",src:t(4692).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.h3,{id:"my-accounts",children:"My Accounts"}),"\n",(0,s.jsx)(n.p,{children:'Select a different account and click "Select" to switch the current account.'}),"\n",(0,s.jsx)(n.h3,{id:"contacts",children:"Contacts"}),"\n",(0,s.jsx)(n.p,{children:"Contains a list of named addresses similar to the address book."}),"\n",(0,s.jsx)(n.h3,{id:"profile",children:"Profile"}),"\n",(0,s.jsxs)(n.p,{children:["Used to change the password or delete your ",(0,s.jsx)(n.a,{href:"#user-profile",children:"profile"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"settings",children:"Settings"}),"\n",(0,s.jsx)(n.p,{children:"You can change the wallet language and toggle between the light and the dark\ntheme."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Account popup: Change theme",src:t(262).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.p,{children:"If you do not have a profile, a sun/moon icon will be shown in the\nlower-left corner."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Toggle between light mode and dark mode, no profile",src:t(4473).A+"",width:"1324",height:"970"})}),"\n",(0,s.jsx)(n.h2,{id:"share-your-feedback-with-us",children:"Share your feedback with us"}),"\n",(0,s.jsxs)(n.p,{children:["If you have any questions or issues using the\n",(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-wallet-web/",children:"ROSE Wallet - Web"}),", you\ncan ",(0,s.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-wallet-web/issues",children:"submit a GitHub issue"}),",\nand the dev team will take a look. You can also connect with us to share your\nfeedback via ",(0,s.jsx)(n.a,{href:"https://oasis.io/discord",children:"Discord"})," or\n",(0,s.jsx)(n.a,{href:"https://t.me/oasisprotocolcommunity",children:"Telegram"}),"."]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>r});t(6540);var s=t(4164);const a={tabItem:"tabItem_Ymn6"};var i=t(4848);function r(e){let{children:n,hidden:t,className:r}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,s.A)(a.tabItem,r),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>v});var s=t(6540),a=t(4164),i=t(3104),r=t(6347),o=t(205),l=t(7485),c=t(1682),d=t(9466);function h(e){return s.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,s.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function u(e){const{values:n,children:t}=e;return(0,s.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:t,attributes:s,default:a}}=e;return{value:n,label:t,attributes:s,default:a}}))}(t);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function p(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const a=(0,r.W6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,l.aZ)(i),(0,s.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(a.location.search);n.set(i,e),a.replace({...a.location,search:n.toString()})}),[i,a])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,i=u(e),[r,l]=(0,s.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const s=t.find((e=>e.default))??t[0];if(!s)throw new Error("Unexpected error: 0 tabValues");return s.value}({defaultValue:n,tabValues:i}))),[c,h]=m({queryString:t,groupId:a}),[g,w]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,i]=(0,d.Dv)(t);return[a,(0,s.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:a}),f=(()=>{const e=c??g;return p({value:e,tabValues:i})?e:null})();(0,o.A)((()=>{f&&l(f)}),[f]);return{selectedValue:r,selectValue:(0,s.useCallback)((e=>{if(!p({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),h(e),w(e)}),[h,w,i]),tabValues:i}}var w=t(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var x=t(4848);function b(e){let{className:n,block:t,selectedValue:s,selectValue:r,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.a_)(),d=e=>{const n=e.currentTarget,t=l.indexOf(n),a=o[t].value;a!==s&&(c(n),r(a))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,x.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.A)("tabs",{"tabs--block":t},n),children:o.map((e=>{let{value:n,label:t,attributes:i}=e;return(0,x.jsx)("li",{role:"tab",tabIndex:s===n?0:-1,"aria-selected":s===n,ref:e=>l.push(e),onKeyDown:h,onClick:d,...i,className:(0,a.A)("tabs__item",f.tabItem,i?.className,{"tabs__item--active":s===n}),children:t??n},n)}))})}function j(e){let{lazy:n,children:t,selectedValue:a}=e;const i=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===a));return e?(0,s.cloneElement)(e,{className:"margin-top--md"}):null}return(0,x.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,s.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function y(e){const n=g(e);return(0,x.jsxs)("div",{className:(0,a.A)("tabs-container",f.tabList),children:[(0,x.jsx)(b,{...n,...e}),(0,x.jsx)(j,{...n,...e})]})}function v(e){const n=(0,w.A)();return(0,x.jsx)(y,{...e,children:h(e.children)},String(n))}},262:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/account-popup-theme-dark-35de04ee7c5c16f57ad9cb3c31f7c5f4.png"},6395:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/buy-731cdec1adebae502b372cf799dcfb1e.png"},3242:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/create_new_wallet_mnemonic1-38b8681e7bfcb96e2f35c6ea81c66400.png"},3825:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/create_new_wallet_mnemonic2-451cacc316cbf85ce52d57e0e6ffa5ae.png"},9580:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/create_new_wallet_select_accounts-a7c877683969a6d60d685e180fdcdf85.png"},8213:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/delegate1-5dc23231b5295a1105cdbc2fe05cb643.png"},6110:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/delegate2-0bcfa6e0aafaeeb26567ca27983c5b7b.png"},3799:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/delegate3-bb0733c0cb1ee723c180e19ad8cd7b82.png"},3692:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/deposit1-ffc383d09d522d55905019dc23c625b9.png"},8519:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/deposit2-cb492dc855a1a94e4ec7f10f0f673c3d.png"},830:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/deposit3-d93d91d93b730749f94b32aeec0c736b.png"},6945:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/deposit4-b9134f051774cf4e3e54937c7bf7a35a.png"},7e3:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/deposit5-f62af89e934740457be2f9ed9d7d6f25.png"},590:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/home-5ec3d62748626a64eb39984984d7008a.png"},1670:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/import_wallet-498120a93d2f76cac5074fc9d70bc07d.png"},888:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/import_wallet_ledger-b18f1448c7cdb73234c04c08df955b26.png"},9963:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/import_wallet_mnemonic-6aa686a800639c41102700240187d2ad.png"},805:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/import_wallet_private_key-7e84a4df8e22b91eee2cb1073c9451d2.png"},4473:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/no-profile-dark-theme-74306637e0c241922b8c7982372540af.png"},5359:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/paratimes-e69d45c9f116673d5250e2c5e2253a28.png"},4692:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/settings-my-accounts-53f9c36b01d46ec195cc497ee62a65d3.png"},9045:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/stake-86196edcc331d1c43f8c237fc9f6798a.png"},2930:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/transfer-d8fb8e130893a73fc982b7fe4e3edf89.png"},2526:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/undelegate1-84aee243b96036b49f330f15f786840a.png"},1301:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/undelegate2-2d8bc2659568544bc805950f74b1db8b.png"},3788:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/undelegate3-8e001bea81c0d7acbec6bc7b0446251c.png"},6900:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/wallet-b8c6aa32364d6e48a645937ed36caa31.png"},1296:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/withdraw1-cab846888c907bfd23795853ca1af848.png"},4795:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/withdraw2-857212a0823e3587a03b806112d7aee4.png"},3666:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/withdraw3-81164f3b2c4f3cb1b590b87dba90a2f3.png"},13:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/withdraw4-fa7a18227b15d6afe180c3301d44e805.png"},8884:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/withdraw5-5c0d0aa06a45f88ffef0c34b380eb53d.png"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var s=t(6540);const a={},i=s.createContext(a);function r(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/be836de1.fde4aa92.js b/assets/js/be836de1.fde4aa92.js new file mode 100644 index 0000000000..84a6dba396 --- /dev/null +++ b/assets/js/be836de1.fde4aa92.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3675],{8477:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Oasis Node","slug":"core/oasis-node","permalink":"/core/oasis-node","sidebar":"oasisCore","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/bede16e2.b1d7538c.js b/assets/js/bede16e2.b1d7538c.js new file mode 100644 index 0000000000..b8fc27a346 --- /dev/null +++ b/assets/js/bede16e2.b1d7538c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4253],{6716:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>h,contentTitle:()=>c,default:()=>x,frontMatter:()=>d,metadata:()=>u,toc:()=>p});var t=r(4848),i=r(8453),o=r(5965),s=r(6116),a=r(1470),l=r(9365);const d={},c="ParaTime Node",u={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/paratime-node.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},h={},p=[{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:"Compiling the ParaTime Binary from Source Code",id:"compiling-the-paratime-binary-from-source-code",level:4},{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:"Bubblewrap Fails to Create Temporary Directory",id:"bubblewrap-fails-to-create-temporary-directory",level:3},{value:"Stake Requirement",id:"stake-requirement",level:3},{value:"Enclave panicked",id:"enclave-panicked",level:3},{value:"See also",id:"see-also",level:2}];function m(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"paratime-node",children:"ParaTime Node"}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["These instructions are for setting up a ",(0,t.jsx)(n.em,{children:"ParaTime"})," node which participates in one or more ParaTime compute committees. If you want to run a ",(0,t.jsx)(n.em,{children:"ParaTime client"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-client-node",children:"instructions for running a ParaTime client node"}),". If you want to run a ",(0,t.jsx)(n.em,{children:"validator"})," node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"instructions for running a validator node"}),". Similarly, if you want to run a non-validator node instead, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"instructions for running a non-validator node"}),"."]})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.p,{children:"For a production setup, we recommend running the ParaTime compute/storage node separately from the validator node (if you run one)."}),(0,t.jsx)(n.p,{children:"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."})]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["If you are looking for some concrete ParaTimes that you can run, see ",(0,t.jsx)(n.a,{href:"/get-involved/run-node/paratime-node",children:"the list of ParaTimes and their parameters"}),"."]})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsx)(n.p,{children:"Oasis Core refers to ParaTimes as runtimes internally, so all configuration options will have runtime in their name."})}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the ",(0,t.jsx)(n.a,{href:"prerequisites",children:"Prerequisites"})," and ",(0,t.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Run a Non-validator Node"})," sections and have:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Oasis Node binary installed and configured on your system."}),"\n",(0,t.jsxs)(n.li,{children:["The chosen top-level ",(0,t.jsx)(n.code,{children:"/node/"})," working directory prepared. In addition to ",(0,t.jsx)(n.code,{children:"etc"})," and ",(0,t.jsx)(n.code,{children:"data"})," directories, also prepare the following directories:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"bin"}),": This will store binaries needed by Oasis Node for running the ParaTimes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"runtimes"}),": This will store the ParaTime bundles."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsxs)(n.p,{children:["Feel free to name your working directory as you wish, e.g. ",(0,t.jsx)(n.code,{children:"/srv/oasis/"}),"."]}),(0,t.jsx)(n.p,{children:"Just make sure to use the correct working directory path in the instructions below."})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Genesis file copied to ",(0,t.jsx)(n.code,{children:"/node/etc/genesis.json"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["Reading the rest of the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"validator node setup instructions"})," may also be useful."]})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["To speed up bootstraping your new node, we recommend ",(0,t.jsx)(n.a,{href:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",children:"copying node's state from your existing node"})," or ",(0,t.jsx)(n.a,{href:"/node/run-your-node/advanced/sync-node-using-state-sync",children:"syncing it using state sync"}),"."]})}),"\n",(0,t.jsx)(n.h3,{id:"stake-requirements",children:"Stake Requirements"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["Current minimum staking requirements for a specific ParaTime are listed on the\nContribute to the Network section\u2014",(0,t.jsx)(n.a,{href:"/get-involved/run-node/paratime-node",children:"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,t.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-native-token",children:"Common Staking Info"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Finally, to stake the tokens, use our ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/account#delegate",children:"Oasis CLI tools"}),". If everything was set\nup correctly, you should see something like below when running ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/account#show",children:(0,t.jsx)(n.code,{children:"oasis account show"})})," command for your entity's account (this is an example for\nTestnet):"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis account show oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve --show-delegations\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"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"})}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsx)(n.p,{children:"The stake requirements may differ from ParaTime to ParaTime and are subject to\nchange in the future."})}),"\n",(0,t.jsx)(n.h3,{id:"register-a-new-entity-or-update-your-entity-registration",children:"Register a New Entity or Update Your Entity Registration"}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsxs)(n.p,{children:["Everything in this section should be done on the ",(0,t.jsx)(n.code,{children:"localhost"})," as there are\nsensitive items that will be created."]})}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If you don't have an entity yet, create a new one by following the\n",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node#initialize-entity",children:"Initialize Entity"})," instructions for validators."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["If you will be running the ParaTime on a new Oasis node, also initialize a\nnew node by following the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node#starting-the-oasis-node",children:"Starting the Oasis Node"})," instructions for\nvalidators."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Now, ",(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node#add-your-node-id-to-the-entity-descriptor",children:"list your node ID"})," in the entity descriptor file ",(0,t.jsx)(n.code,{children:"nodes"})," field."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"/node/run-your-node/validator-node#entity-registration",children:"Register"})," the updated entity descriptor."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"tip",children:[(0,t.jsxs)(n.p,{children:["You will ",(0,t.jsx)(n.a,{href:"#configuration",children:"configure the node"})," to automatically\nregister for the roles it has enabled (i.e. storage and compute roles) via the\n",(0,t.jsx)(n.code,{children:"worker.registration.entity"})," configuration flag."]}),(0,t.jsx)(n.p,{children:"No manual node registration is necessary."})]}),"\n",(0,t.jsxs)(n.admonition,{type:"info",children:[(0,t.jsxs)(n.p,{children:["ParaTime rewards for running the compute node will be sent to your entity\naddress ",(0,t.jsx)(n.strong,{children:"inside the ParaTime"}),". To access the rewards on the consensus layer,\nyou will need to withdraw them first. Use the ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/account#withdraw",children:(0,t.jsx)(n.code,{children:"oasis account withdraw"})}),"\ncommand, for example:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis account withdraw 10\n"})})]}),"\n",(0,t.jsx)(n.h3,{id:"the-paratime-bundle",children:"The ParaTime Bundle"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:".orc"}),"\nextension that stands for Oasis Runtime Container) contains all the needed\nParaTime binaries together with the identifier and version metadata to ease\ndeployment."]}),"\n",(0,t.jsx)(n.p,{children:"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)."}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsx)(n.p,{children:"Like the genesis document, make sure you obtain these from a trusted source."})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.h4,{id:"compiling-the-paratime-binary-from-source-code",children:(0,t.jsx)(n.strong,{children:"Compiling the ParaTime Binary from Source Code"})}),(0,t.jsxs)(n.p,{children:["In case you decide to build the ParaTime binary from source yourself, make sure\nthat you follow our ",(0,t.jsx)(n.a,{href:"/paratime/reproducibility",children:"guidelines for deterministic compilation"}),"\nto ensure that you receive the exact same binary."]}),(0,t.jsx)(n.p,{children:"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."})]}),"\n",(0,t.jsx)(n.h3,{id:"install-oasis-core-runtime-loader",children:"Install Oasis Core Runtime Loader"}),"\n",(0,t.jsxs)(n.p,{children:["For ParaTimes running inside ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node#setting-up-trusted-execution-environment-tee",children:"Intel SGX trusted execution environment"}),", you will need to install the Oasis Core Runtime Loader."]}),"\n",(0,t.jsxs)(n.p,{children:["The Oasis Core Runtime Loader binary (",(0,t.jsx)(n.code,{children:"oasis-core-runtime-loader"}),") is part of Oasis Core binary releases, so make sure you download the appropriate version specified the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,t.jsxs)(n.p,{children:["Install it to ",(0,t.jsx)(n.code,{children:"bin"})," subdirectory of your node's working directory, e.g. ",(0,t.jsx)(n.code,{children:"/node/bin/oasis-core-runtime-loader"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"install-paratime-bundle",children:"Install ParaTime Bundle"}),"\n",(0,t.jsxs)(n.p,{children:["For each ParaTime, you need to obtain its bundle and install it to the\n",(0,t.jsx)(n.code,{children:"runtimes"})," subdirectory of your node's working directory."]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["For example, for the ",(0,t.jsx)(n.a,{href:"/node/mainnet/#cipher",children:"Cipher ParaTime"}),",\nyou would have to obtain the ",(0,t.jsx)(n.code,{children:"cipher-paratime.orc"})," bundle and install it to\n",(0,t.jsx)(n.code,{children:"/node/runtimes/cipher-paratime.orc"}),"."]})}),"\n",(0,t.jsx)(n.h3,{id:"install-bubblewrap-sandbox-at-least-version-033",children:"Install Bubblewrap Sandbox (at least version 0.3.3)"}),"\n",(0,t.jsxs)(n.p,{children:["ParaTime compute nodes execute ParaTime binaries inside a sandboxed environment\nprovided by ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap",children:"Bubblewrap"}),". In order to\ninstall it, please follow these instructions, depending on your distribution. Also\nnote that in case your platform is using AppArmor, you may need to update the\npolicy (see ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#apparmor-profiles",children:"AppArmor profiles"}),")."]}),"\n",(0,t.jsxs)(a.A,{children:[(0,t.jsx)(l.A,{value:"Ubuntu 18.10+",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo apt install bubblewrap\n"})})}),(0,t.jsx)(l.A,{value:"Fedora",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo dnf install bubblewrap\n"})})}),(0,t.jsxs)(l.A,{value:"Other Distributions",children:[(0,t.jsxs)(n.p,{children:["On other systems, you can download the latest ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap/releases",children:"source release provided by the Bubblewrap project"})," and build it yourself."]}),(0,t.jsxs)(n.p,{children:["Make sure you have the necessary development tools installed on your system and the ",(0,t.jsx)(n.code,{children:"libcap"})," development headers. On Ubuntu, you can install them with:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"sudo apt install build-essential libcap-dev\n"})}),(0,t.jsxs)(n.p,{children:["After obtaining the Bubblewrap source tarball, e.g. ",(0,t.jsx)(n.a,{href:"https://github.com/containers/bubblewrap/releases/download/v0.4.1/bubblewrap-0.4.1.tar.xz",children:"bubblewrap-0.4.1.tar.xz"}),", run:"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"tar -xf bubblewrap-0.4.1.tar.xz\ncd bubblewrap-0.4.1\n./configure --prefix=/usr\nmake\nsudo make install\n"})}),(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Note that Oasis Node expects Bubblewrap to be installed under ",(0,t.jsx)(n.code,{children:"/usr/bin/bwrap"})," by default."]})})]})]}),"\n",(0,t.jsx)(n.p,{children:"Ensure you have a new enough version by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"bwrap --version\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Ubuntu 18.04 LTS (and earlier) provide overly-old ",(0,t.jsx)(n.code,{children:"bubblewrap"}),". Follow ",(0,t.jsx)(n.em,{children:"Other Distributions"})," section on those systems."]})}),"\n",(0,t.jsx)(n.h3,{id:"setting-up-trusted-execution-environment-tee",children:"Setting up Trusted Execution Environment (TEE)"}),"\n",(0,t.jsxs)(n.p,{children:["If a ParaTime requires the use of a TEE, then make sure you set up TEE as instructed in the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",children:"Set up trusted execution environment (TEE)"})," doc."]}),"\n",(0,t.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsxs)(n.p,{children:["In order to configure the node create the ",(0,t.jsx)(n.code,{children:"/node/etc/config.yml"})," file with the following content:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"mode: compute\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: info\n cometbft/context: error\n default: info\n\nconsensus:\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 listen_address: tcp://0.0.0.0:26656\n\ngenesis:\n file: /node/etc/genesis.json\n\n# The IAS section is required for ParaTimes which are running inside the\n# Intel SGX Trusted Execution Environment.\nias:\n proxy_addresses:\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\np2p:\n # External P2P configuration.\n port: 9200\n registration:\n addresses:\n # The external IP that is used when registering this node to the\n # network.\n - {{ external_address }}:9200\n seeds:\n # List of seed nodes to connect to.\n # NOTE: You can add additional seed nodes to this list if you want.\n - {{ seed_node_address }}\n\nregistration:\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\nruntime:\n paths:\n # Paths to ParaTime bundles for all of the supported ParaTimes.\n - {{ runtime_orc_path }}\n # The following section is required for ParaTimes which are running inside\n # the Intel SGX Trusted Execution Environment.\n sgx_loader: /node/bin/oasis-core-runtime-loader\n"})}),"\n",(0,t.jsx)(n.p,{children:"Before using this configuration you should collect the following information to replace the variables present in the configuration file:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ external_address }}"}),": The external IP you used when registering this node."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ seed_node_address }}"}),": The seed node address in the form ",(0,t.jsx)(n.code,{children:"ID@IP:port"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["You can find the current Oasis Seed Node address in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ runtime_orc_path }}"}),": Path to the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node#the-paratime-bundle",children:"ParaTime bundle"})," of the form ",(0,t.jsx)(n.code,{children:"/node/runtimes/foo-paratime.orc"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["You can find the current Oasis-supported ParaTimes in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"{{ ias_proxy_address }}"}),": The IAS proxy address in the form ",(0,t.jsx)(n.code,{children:"ID@HOST:port"}),".","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["You can find the current Oasis IAS proxy address in the Network Parameters page (",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,t.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,t.jsxs)(n.li,{children:["If you want, you can also ",(0,t.jsx)(n.a,{href:"/node/run-your-node/ias-proxy",children:"run your own IAS proxy"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["Make sure the ",(0,t.jsx)(n.code,{children:"consensus"})," port (default: ",(0,t.jsx)(n.code,{children:"26656"}),") and ",(0,t.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,t.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,t.jsx)(n.code,{children:"TCP"})," and ",(0,t.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,t.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,t.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,t.jsx)(n.h2,{id:"checking-node-status",children:"Checking Node Status"}),"\n",(0,t.jsx)(n.p,{children:"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["See the general ",(0,t.jsx)(n.a,{href:"/node/run-your-node/troubleshooting",children:"Node troubleshooting"})," and ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#troubleshooting",children:"Set up TEE troubleshooting"})," sections before proceeding with ParaTime node-specific troubleshooting."]}),"\n",(0,t.jsx)(n.h3,{id:"too-old-bubblewrap-version",children:"Too Old Bubblewrap Version"}),"\n",(0,t.jsxs)(n.p,{children:["Double check your installed ",(0,t.jsx)(n.code,{children:"bubblewrap"})," version, and ensure is at least of version ",(0,t.jsx)(n.strong,{children:"0.3.3"}),". For details see the ",(0,t.jsx)(n.a,{href:"#install-bubblewrap-sandbox-at-least-version-033",children:"Install Bubblewrap Sandbox"})," section."]}),"\n",(0,t.jsx)(n.h3,{id:"bubblewrap-sandbox-fails-to-start",children:"Bubblewrap Sandbox Fails to Start"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"bwrap"})," error, like:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{"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'})}),"\n",(0,t.jsxs)(n.p,{children:["In case of ",(0,t.jsx)(n.code,{children:"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:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:" --security-opt apparmor=unconfined \\\n --security-opt seccomp=unconfined \\\n"})}),"\n",(0,t.jsxs)(n.p,{children:["You can also configure an ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/system-configuration#apparmor-profiles",children:"AppArmor profile for Bubblewrap"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"bubblewrap-fails-to-create-temporary-directory",children:"Bubblewrap Fails to Create Temporary Directory"}),"\n",(0,t.jsxs)(n.p,{children:["If the ",(0,t.jsx)(n.code,{children:"/tmp"})," directory is not writable by the user running the node, the\nBubblewrap sandbox may fail to start the ParaTimes. In the logs you will see\nerrors about creating a temporary directory, like:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{"caller":"sandbox.go:546","err":"failed to create temporary directory: mkdir /tmp/oasis-runtime1152692396: read-only file system","level":"error","module":"runtime/host/sandbox","msg":"failed to start runtime","runtime_id":"000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c","ts":"2023-11-09T14:08:50.554629545Z"}\n'})}),"\n",(0,t.jsx)(n.p,{children:"The node might report in the status field that a runtime has not been\nprovisioned yet, like:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'oasis-node control status -a unix:/node/data/internal.sock | grep status\n "status": "waiting for hosted runtime provision",\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This can happen, for example, in Kubernetes, when the ",(0,t.jsx)(n.code,{children:"readOnlyRootFilesystem"}),"\nsetting in a Pod or container security context is set to ",(0,t.jsx)(n.code,{children:"true"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["To resolve the issue, please make sure that the ",(0,t.jsx)(n.code,{children:"/tmp"})," directory is writable by\nthe user running the node. If you are running the node in Kubernetes, you can\nset the ",(0,t.jsx)(n.code,{children:"readOnlyRootFilesystem"})," setting to ",(0,t.jsx)(n.code,{children:"false"}),", or better yet, mount a\ndedicated volume into ",(0,t.jsx)(n.code,{children:"/tmp"}),". It can be very small in size, e.g., ",(0,t.jsx)(n.code,{children:"1 MiB"})," is\nenough."]}),"\n",(0,t.jsx)(n.h3,{id:"stake-requirement",children:"Stake Requirement"}),"\n",(0,t.jsxs)(n.p,{children:["Double check your node entity satisfies the staking requirements for a ParaTime node. For details see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/paratime-node#stake-requirements",children:"Stake Requirements"})," section."]}),"\n",(0,t.jsx)(n.h3,{id:"enclave-panicked",children:"Enclave panicked"}),"\n",(0,t.jsxs)(n.p,{children:["If there is a misconfiguration in the prerequisite ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#bios-configuration",children:"BIOS settings"}),", you can see an error in the logs reporting a\nproblem when running SGX enclaves."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{"component":"ronl","level":"warn","module":"runtime","msg":"runtime execution failed: Enclave panicked: Enclave triggered exception: SgxEnclaveRun { function: EResume, exception_vector: 6, exception_error_code: 0, exception_addr: 0x0 }","runtime_id":"0000000000000000000000000000000000000000000000000000000000000000","runtime_name":"cipher-paratime","ts":"2024-06-03T11:00:43.417403299Z"}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["For example, this can happen if you forget to configure AES instruction set (i.e. the ",(0,t.jsx)(n.code,{children:"CPU AES: ENABLE"})," BIOS setting).\nTo see if your system supports AES instruction set in the CPU run:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:' cpuid -1 | grep "AES"\n'})}),"\n",(0,t.jsx)(n.p,{children:"and look for the following line:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"AES instruction = true\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If the AES instruction is set to ",(0,t.jsx)(n.code,{children:"false"}),", you need to reconfigure you BIOS and set it to ",(0,t.jsx)(n.code,{children:"true"}),".\nYou can do similar inspection for other ",(0,t.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee#bios-configuration",children:"BIOS settings"}),"."]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["You can use the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/tree/main/attestation-tool#readme",children:"attestation tool"})," (at least version 0.3.4) that also checks if the AES instruction set is available."]})}),"\n",(0,t.jsx)(n.h2,{id:"see-also",children:"See also"}),"\n",(0,t.jsx)(o.A,{item:(0,s.$)("/node/web3")})]})}function x(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(m,{...e})}):m(e)}},5965:(e,n,r)=>{r.d(n,{A:()=>f});r(6540);var t=r(4164),i=r(8774),o=r(4142),s=r(5846),a=r(6654),l=r(1312),d=r(1107);const c={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=r(4848);function h(e){let{href:n,children:r}=e;return(0,u.jsx)(i.A,{href:n,className:(0,t.A)("card padding--lg",c.cardContainer),children:r})}function p(e){let{href:n,icon:r,title:i,description:o}=e;return(0,u.jsxs)(h,{href:n,children:[(0,u.jsxs)(d.A,{as:"h2",className:(0,t.A)("text--truncate",c.cardTitle),title:i,children:[r," ",i]}),o&&(0,u.jsx)("p",{className:(0,t.A)("text--truncate",c.cardDescription),title:o,children:o})]})}function m(e){let{item:n}=e;const r=(0,o.Nr)(n),t=function(){const{selectMessage:e}=(0,s.W)();return n=>e(n,(0,l.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:n}))}();return r?(0,u.jsx)(p,{href:r,icon:"\ud83d\uddc3\ufe0f",title:n.label,description:n.description??t(n.items.length)}):null}function x(e){let{item:n}=e;const r=(0,a.A)(n.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",t=(0,o.cC)(n.docId??void 0);return(0,u.jsx)(p,{href:n.href,icon:r,title:n.label,description:n.description??t?.description})}function f(e){let{item:n}=e;switch(n.type){case"link":return(0,u.jsx)(x,{item:n});case"category":return(0,u.jsx)(m,{item:n});default:throw new Error(`unknown item type ${JSON.stringify(n)}`)}}},9365:(e,n,r)=>{r.d(n,{A:()=>s});r(6540);var t=r(4164);const i={tabItem:"tabItem_Ymn6"};var o=r(4848);function s(e){let{children:n,hidden:r,className:s}=e;return(0,o.jsx)("div",{role:"tabpanel",className:(0,t.A)(i.tabItem,s),hidden:r,children:n})}},1470:(e,n,r)=>{r.d(n,{A:()=>w});var t=r(6540),i=r(4164),o=r(3104),s=r(6347),a=r(205),l=r(7485),d=r(1682),c=r(9466);function u(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function h(e){const{values:n,children:r}=e;return(0,t.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:r,attributes:t,default:i}}=e;return{value:n,label:r,attributes:t,default:i}}))}(r);return function(e){const n=(0,d.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,r])}function p(e){let{value:n,tabValues:r}=e;return r.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:r}=e;const i=(0,s.W6)(),o=function(e){let{queryString:n=!1,groupId:r}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!r)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 r??null}({queryString:n,groupId:r});return[(0,l.aZ)(o),(0,t.useCallback)((e=>{if(!o)return;const n=new URLSearchParams(i.location.search);n.set(o,e),i.replace({...i.location,search:n.toString()})}),[o,i])]}function x(e){const{defaultValue:n,queryString:r=!1,groupId:i}=e,o=h(e),[s,l]=(0,t.useState)((()=>function(e){let{defaultValue:n,tabValues:r}=e;if(0===r.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:r}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${r.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const t=r.find((e=>e.default))??r[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:o}))),[d,u]=m({queryString:r,groupId:i}),[x,f]=function(e){let{groupId:n}=e;const r=function(e){return e?`docusaurus.tab.${e}`:null}(n),[i,o]=(0,c.Dv)(r);return[i,(0,t.useCallback)((e=>{r&&o.set(e)}),[r,o])]}({groupId:i}),g=(()=>{const e=d??x;return p({value:e,tabValues:o})?e:null})();(0,a.A)((()=>{g&&l(g)}),[g]);return{selectedValue:s,selectValue:(0,t.useCallback)((e=>{if(!p({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 f=r(2303);const g={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=r(4848);function j(e){let{className:n,block:r,selectedValue:t,selectValue:s,tabValues:a}=e;const l=[],{blockElementScrollPositionUntilNextRender:d}=(0,o.a_)(),c=e=>{const n=e.currentTarget,r=l.indexOf(n),i=a[r].value;i!==t&&(d(n),s(i))},u=e=>{let n=null;switch(e.key){case"Enter":c(e);break;case"ArrowRight":{const r=l.indexOf(e.currentTarget)+1;n=l[r]??l[0];break}case"ArrowLeft":{const r=l.indexOf(e.currentTarget)-1;n=l[r]??l[l.length-1];break}}n?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.A)("tabs",{"tabs--block":r},n),children:a.map((e=>{let{value:n,label:r,attributes:o}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:t===n?0:-1,"aria-selected":t===n,ref:e=>l.push(e),onKeyDown:u,onClick:c,...o,className:(0,i.A)("tabs__item",g.tabItem,o?.className,{"tabs__item--active":t===n}),children:r??n},n)}))})}function y(e){let{lazy:n,children:r,selectedValue:i}=e;const o=(Array.isArray(r)?r:[r]).filter(Boolean);if(n){const e=o.find((e=>e.props.value===i));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:o.map(((e,n)=>(0,t.cloneElement)(e,{key:n,hidden:e.props.value!==i})))})}function v(e){const n=x(e);return(0,b.jsxs)("div",{className:(0,i.A)("tabs-container",g.tabList),children:[(0,b.jsx)(j,{...n,...e}),(0,b.jsx)(y,{...n,...e})]})}function w(e){const n=(0,f.A)();return(0,b.jsx)(v,{...e,children:u(e.children)},String(n))}},5846:(e,n,r)=>{r.d(n,{W:()=>d});var t=r(6540),i=r(4586);const o=["zero","one","two","few","many","other"];function s(e){return o.filter((n=>e.includes(n)))}const a={locale:"en",pluralForms:s(["one","other"]),select:e=>1===e?"one":"other"};function l(){const{i18n:{currentLocale:e}}=(0,i.A)();return(0,t.useMemo)((()=>{try{return function(e){const n=new Intl.PluralRules(e);return{locale:e,pluralForms:s(n.resolvedOptions().pluralCategories),select:e=>n.select(e)}}(e)}catch(n){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${n.message}\n`),a}}),[e])}function d(){const e=l();return{selectMessage:(n,r)=>function(e,n,r){const t=e.split("|");if(1===t.length)return t[0];t.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${t.length}: ${e}`);const i=r.select(n),o=r.pluralForms.indexOf(i);return t[Math.min(o,t.length-1)]}(r,n,e)}}},6116:(e,n,r)=>{r.d(n,{$:()=>o});var t=r(2252);function i(e){for(const n of e){const e=n.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=n),"category"===n.type&&i(n.items)}}function o(e){const n=(0,t.r)();if(!n)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in n.docsSidebars)i(n.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]}},8453:(e,n,r)=>{r.d(n,{R:()=>s,x:()=>a});var t=r(6540);const i={},o=t.createContext(i);function s(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bfa096f2.36a2351f.js b/assets/js/bfa096f2.36a2351f.js new file mode 100644 index 0000000000..eba6da0e67 --- /dev/null +++ b/assets/js/bfa096f2.36a2351f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7873],{3786:o=>{o.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Common Functionality","slug":"core/common-functionality","permalink":"/core/common-functionality","sidebar":"oasisCore","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/c41a84e2.ab1b9770.js b/assets/js/c41a84e2.ab1b9770.js new file mode 100644 index 0000000000..7aa06a7bb6 --- /dev/null +++ b/assets/js/c41a84e2.ab1b9770.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8113],{913:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var t=i(4848),s=i(8453);const a={},c="Runtime Layer",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/README.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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={},d=[{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}];function r(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"runtime-layer",children:"Runtime Layer"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Runtime Layer",src:i(4149).A+""})}),"\n",(0,t.jsxs)(n.p,{children:["The Oasis Core runtime layer enables independent ",(0,t.jsx)(n.em,{children:"runtimes"})," to schedule and\nexecute stateful computations and commit result summaries to the\n",(0,t.jsx)(n.a,{href:"/core/consensus/",children:"consensus layer"}),". In addition to ",(0,t.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"verifying and storing"})," the canonical runtime\nstate summaries the ",(0,t.jsx)(n.a,{href:"/core/consensus/",children:"consensus layer"})," also serves as the ",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry",children:"registry"})," for node and\nruntime metadata, a ",(0,t.jsx)(n.a,{href:"/core/consensus/services/scheduler",children:"scheduler"})," that elects runtime compute committees and a\ncoordinator for ",(0,t.jsx)(n.a,{href:"/core/consensus/services/keymanager",children:"key manager replication"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"runtimes",children:"Runtimes"}),"\n",(0,t.jsxs)(n.p,{children:["A ",(0,t.jsx)(n.em,{children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["In Oasis Core a runtime can be any executable that speaks the\n",(0,t.jsx)(n.a,{href:"/core/runtime/runtime-host-protocol",children:"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."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Runtime Execution",src:i(1029).A+""})}),"\n",(0,t.jsx)(n.p,{children:"In the future this may be expanded with supporting running each runtime in its\nown virtual machine and with other confidential computing technologies."}),"\n",(0,t.jsx)(n.h2,{id:"operation-model",children:"Operation Model"}),"\n",(0,t.jsxs)(n.p,{children:["The relationship between ",(0,t.jsx)(n.a,{href:"/core/consensus/",children:"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).']}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/core/runtime/identifiers",children:"runtime identifier"}),", and then\n",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#register-runtime",children:"register the runtime"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"In addition to compute nodes a runtime also needs storage nodes to store its\nstate."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Both kinds of ",(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#register-node",children:"nodes will register"})," on the consensus layer announcing their\nwillingness to participate in the operation of Runtime A."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["After an ",(0,t.jsx)(n.a,{href:"/core/consensus/services/epochtime",children:"epoch transition"})," the ",(0,t.jsx)(n.a,{href:"/core/consensus/services/scheduler",children:"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,t.jsx)(n.a,{href:"/core/consensus/services/beacon",children:"random beacon"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/core/oasis-node/rpc",children:"client RPC API"})," that encapsulates all this functionality in a ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/runtime/client/api?tab=doc#RuntimeClient.SubmitTx",children:(0,t.jsx)(n.code,{children:"SubmitTx"})}),"\ncall."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["The transactions are batched and proceed through the transaction processing\npipeline. At the end, results are persisted to storage and the\n",(0,t.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"roothash service"})," in the consensus layer finalizes state after verifying\nthat computation was performed correctly and state was correctly persisted."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"The compute nodes are ready to accept the next batch and the process can\nrepeat from step 6."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Note that the above example describes the ",(0,t.jsx)(n.em,{children:"happy path"}),", a scenario where there\nare no failures. Described steps mention things like verifying that computation\nwas performed ",(0,t.jsx)(n.em,{children:"correctly"})," and that state was ",(0,t.jsx)(n.em,{children:"correctly stored"}),". How does the\nconsensus layer actually know that?"]}),"\n",(0,t.jsx)(n.h3,{id:"discrepancy-detection-and-resolution",children:"Discrepancy Detection and Resolution"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"compute-committee-roles-and-commitments",children:"Compute Committee Roles and Commitments"}),"\n",(0,t.jsx)(n.p,{children:"A compute node can be elected into an executor committee and may have one of the\nfollowing roles:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Primary executor node. At any given round a single node is selected among all\nthe primary executor nodes to be a ",(0,t.jsx)(n.em,{children:"transaction scheduler node"})," (roughly equal\nto the role of a ",(0,t.jsx)(n.em,{children:"block proposer"}),")."]}),"\n",(0,t.jsx)(n.li,{children:"Backup executor node. Backup nodes can be activated by the consensus layer in\ncase it determines that there is a discrepancy."}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["The size of the primary and backup executor committees, together with other\nrelated parameters, can be configured on a per-runtime basis. The ",(0,t.jsx)(n.em,{children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["After execution they will sign ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/roothash/api/commitment?tab=doc",children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"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,t.jsx)(n.em,{children:"backups"})," to repeat the\ncomputation."]}),"\n",(0,t.jsx)(n.h3,{id:"storage-receipts",children:"Storage Receipts"}),"\n",(0,t.jsxs)(n.p,{children:["All runtime persistent state is stored by storage nodes. These provide a\n",(0,t.jsx)(n.a,{href:"/core/mkvs",children:"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,t.jsx)(n.a,{href:"/core/consensus/services/roothash",children:"roothash service"})," before\naccepting a commitment from a compute node."]}),"\n",(0,t.jsx)(n.h3,{id:"suspending-runtimes",children:"Suspending Runtimes"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"emitting-messages",children:"Emitting Messages"}),"\n",(0,t.jsxs)(n.p,{children:["Runtimes may ",(0,t.jsx)(n.a,{href:"/core/runtime/messages",children:"emit messages"})," to instruct the consensus layer what to do on their\nbehalf. This makes it possible for runtimes to ",(0,t.jsx)(n.a,{href:"/core/consensus/services/staking#runtime-accounts",children:"own staking accounts"}),"."]})]})}function m(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(r,{...e})}):r(e)}},4149:(e,n,i)=>{i.d(n,{A:()=>t});const t=i.p+"assets/images/oasis-core-runtime-details-4fefa00801807028812dc6d3900d2a38.svg"},1029:(e,n,i)=>{i.d(n,{A:()=>t});const t="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+"},8453:(e,n,i)=>{i.d(n,{R:()=>c,x:()=>o});var t=i(6540);const s={},a=t.createContext(s);function c(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c800e6d8.a9db7dd8.js b/assets/js/c800e6d8.a9db7dd8.js new file mode 100644 index 0000000000..dd056b2c4f --- /dev/null +++ b/assets/js/c800e6d8.a9db7dd8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3667],{4239:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>d,frontMatter:()=>i,metadata:()=>a,toc:()=>o});var s=t(4848),r=t(8453);const i={},c="ADR 0022: Forward-Secret Master Secrets",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0022-keymanager-master-secrets.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,frontMatter:{},sidebar:"adrs",previous:{title:"ADR 0021: Forward-Secret Ephemeral Secrets",permalink:"/adrs/0021-keymanager-ephemeral-secrets"},next:{title:"ADR 0024: Runtime Off-chain Logic (ROFL)",permalink:"/adrs/0024-off-chain-runtime-logic"}},l={},o=[{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}];function h(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-0022-forward-secret-master-secrets",children:"ADR 0022: Forward-Secret Master Secrets"}),"\n",(0,s.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,s.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"2023-04-17: Initial proposal"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Proposed"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsx)(n.p,{children:"The network needs forward-secret master secrets that are generated periodically\nand distributed amongst enclave executors."}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.h3,{id:"key-manager-status",children:"Key manager status"}),"\n",(0,s.jsx)(n.p,{children:"Key manager status will be extended with the following fields:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'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'})}),"\n",(0,s.jsx)(n.h3,{id:"enclave-init-response",children:"Enclave init response"}),"\n",(0,s.jsx)(n.p,{children:"Key manager enclave init response will be extended with the following fields:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'type InitResponse struct {\n ...\n \n NextChecksum []byte `json:"next_checksum,omitempty"`\n NextRSK *signature.PublicKey `json:"next_rsk,omitempty"`\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"master-secrets",children:"Master secrets"}),"\n",(0,s.jsx)(n.p,{children:"The key manager enclave will gain the following additional local RPC methods:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'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'})}),"\n",(0,s.jsx)(n.p,{children:"Remote RPC method for replicating master secret will be extended to support\nreplication of generations and to return a Merkle proof for secret verification."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"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"})}),"\n",(0,s.jsx)(n.p,{children:"Master secret generation will return a signed and encrypted master secret\nfor the requested generation and epoch."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'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'})}),"\n",(0,s.jsx)(n.h3,{id:"checksums",children:"Checksums"}),"\n",(0,s.jsx)(n.p,{children:"Checksum computation will be extended with hash chains:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"checksum_0 = KMAC(generation_0, runtime_id)"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"checksum_N = KMAC(generation_N, checksum_(N-1)) for N > 0"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"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:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.code,{children:"next_checksum = KMAC(secret, prev_checksum)"})}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"master-secret-transaction",children:"Master secret transaction"}),"\n",(0,s.jsxs)(n.p,{children:["Key manager application will be augmented with a ",(0,s.jsx)(n.code,{children:"PublishMasterSecret"}),"\ntransaction which will accept the proposal for the next generation of the master\nsecret if the following conditions are met:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The proposal is intended to be accepted in the upcoming epoch."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Master secret hasn't been proposed in the current epoch."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The rotation period will either expire in the upcoming epoch or has already\nexpired."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The first master secret (generation 0) can be proposed immediately and even\nif the rotation interval is set to 0."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The master secret is encrypted to the majority of the enclaves that form\nthe committee."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The node proposing the secret is a member of the key manager committee."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"If accepted, the next secret can be proposed after the rotation interval\nexpires. Otherwise, the next secret can be proposed in the next epoch."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'MethodPublishMasterSecret = transaction.NewMethodName(\n ModuleName, "PublishMasterSecret", SignedEncryptedMasterSecret{}\n)\n'})}),"\n",(0,s.jsx)(n.h3,{id:"setup",children:"Setup"}),"\n",(0,s.jsx)(n.p,{children:"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."}),"\n",(0,s.jsx)(n.h3,{id:"generation",children:"Generation"}),"\n",(0,s.jsx)(n.p,{children:"Each keymanager will, at a random time in a given epoch:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Check to see if rotation period has expired. If not, go to step 5."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Check to see if another instance has published a proposal for the upcoming\nepoch. If yes, go to step 5."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Execute a local ",(0,s.jsx)(n.code,{children:"generate_master_secret"})," RPC call. The enclave will,\nin-order:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Verify the master secret generation number."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Randomly select a secret."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Use the light client to query the members of the committee."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Encrypt and checksum the selected secret."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Return ",(0,s.jsx)(n.code,{children:"GenerateMasterSecretResponse"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"On failure, go to step 1."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Read ",(0,s.jsx)(n.code,{children:"SignedEncryptedMasterSecret"})," from the response and publish it\nin the consensus layer using ",(0,s.jsx)(n.code,{children:"PublishMasterSecret"})," transaction."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"This key manager instance is DONE."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"replication",children:"Replication"}),"\n",(0,s.jsx)(n.p,{children:"Each key manager will listen for the publication of new master secret proposals\nand will, when a new secret is proposed:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Cancel master secret generation scheduled for the current epoch."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Forward the proposal to the enclave."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The enclave will verify that:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The proposal was published in the consensus layer."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The secret can be decrypted with the enclave's REK key."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The master secret generation number is one greater than the last known\ngeneration."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The checksum computed from the decrypted secret and the last known\nchecksum matches the one in the proposal."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"If all verifications pass, the enclave will:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Decrypt the secret, encrypt it with SGX sealing key and store\nthe ciphertext locally."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Derive the RSK key for the proposed secret and store it in the memory\ntogether with the computed checksum."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Otherwise, go to step 5."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Request enclave to initialize again and use the response to register\nwith the forthcoming checksum and RSK key derived from the proposal."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"This key manager instance is DONE."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"rotation",children:"Rotation"}),"\n",(0,s.jsx)(n.p,{children:"Key manager application will try to rotate the master secret every epoch\nas part of the key manager status generation as follows:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Fetch the latest master secret proposal.\nOn failure, go to step 6."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Verify the master secret generation number and epoch of the proposal.\nOn failure, go to step 6."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Count how many nodes have stored the proposal locally."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Compare the checksum of the proposal to the ",(0,s.jsx)(n.code,{children:"next_checksum"})," field in\nthe init response."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Accept the proposal if the majority of the nodes have replicated\nthe proposed secret and announced ",(0,s.jsx)(n.code,{children:"next_checksum"})," in their init status."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Increment the master secret generation number by 1."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Update the last rotation epoch."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Update the checksum."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Broadcast the new status."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"If the master secret generation number has advanced, the enclaves will\ntry to apply the proposal they stored locally."}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Key manager application is DONE."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"confirmation",children:"Confirmation"}),"\n",(0,s.jsx)(n.p,{children:"Each key manager will listen for the key manager status updates and will,\nwhen the master secret generation number advances:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Send the key manager status to the enclave."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"The enclave will:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Check that the master secret generation number is one greater than\nthe last known generation."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Load locally stored proposal for the next master secret or replicate it\nfrom another enclave."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Use the proposal to compute the next checksum."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Verify the computed checksum against the latest key manager status."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"If checksum matches, the enclave will:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Encrypt the secret with SGX sealing key using master secret generation\nnumber as additional data and store the ciphertext locally."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Update the last known generation number."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Update the latest checksum and RSK key."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Otherwise, go to step 1."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"This key manager instance is DONE."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Runtimes can periodically or on demand re-encrypt their state using\nthe latest generation of the master secret."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Compromise of an enclave cannot reveal master secrets generated after its\nupgrade or obsolescence."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Initialization takes time as all master secrets need to be replicated."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"Number of secrets"}),(0,s.jsx)(n.th,{style:{textAlign:"center"},children:"Replication time"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"10"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"45 sec"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"100"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"52 sec"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"1000"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"2 min 45 sec"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"10000"}),(0,s.jsx)(n.td,{style:{textAlign:"center"},children:"21 min 17 sec"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"Table 1: Local machine benchmarks (without any network overhead)"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Master secret replication response must contain a Merkle proof for secret\nverification."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"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."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Master secrets need to be replicated in reverse order to ensure all\nsecrets are verified against checksum published in the consensus layer."}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>c,x:()=>a});var s=t(6540);const r={},i=s.createContext(r);function c(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:c(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c9130a94.a7a1ab53.js b/assets/js/c9130a94.a7a1ab53.js new file mode 100644 index 0000000000..a8b713beed --- /dev/null +++ b/assets/js/c9130a94.a7a1ab53.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4633],{9218:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var r=n(4848),o=n(8453),s=n(2550),i=n(6116);const a={description:"Build your own ROFL app"},c="Build ROFL App",l={id:"rofl/README",title:"Build ROFL App",description:"Build your own ROFL app",source:"@site/docs/rofl/README.mdx",sourceDirName:"rofl",slug:"/rofl/",permalink:"/rofl/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/rofl/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Build your own ROFL app"},sidebar:"rofl",next:{title:"Prerequisites",permalink:"/rofl/prerequisites"}},d={},u=[];function p(e){const t={a:"a",h1:"h1",p:"p",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"build-rofl-app",children:"Build ROFL App"}),"\n",(0,r.jsx)(t.p,{children:"Runtime OFf-chain Logic (ROFL) apps are a mechanism to augment the deterministic\non-chain backend with verifiable off-chain applications. These applications are\nstateless, have access to the network and can perform expensive and/or\nnon-deterministic computation."}),"\n",(0,r.jsx)(t.p,{children:"ROFL apps run in Trusted Execution Environments (TEEs), similar to the on-chain\nconfidential runtimes. This enables them to securely authenticate to the\non-chain backend which is handled transparently by the framework. Together they\nallow one to implement secure decentralized oracles, bridges, AI agents and\nmore."}),"\n",(0,r.jsxs)(t.p,{children:["This chapter will teach you how to build your own ROFL app with the help of the\n",(0,r.jsx)(t.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/runtime-sdk",children:"Oasis Runtime SDK"}),"."]}),"\n",(0,r.jsx)(s.A,{items:[(0,i.$)("/rofl/prerequisites"),(0,i.$)("/rofl/app")]})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(p,{...e})}):p(e)}},5965:(e,t,n)=>{n.d(t,{A:()=>g});n(6540);var r=n(4164),o=n(8774),s=n(4142),i=n(5846),a=n(6654),c=n(1312),l=n(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var u=n(4848);function p(e){let{href:t,children:n}=e;return(0,u.jsx)(o.A,{href:t,className:(0,r.A)("card padding--lg",d.cardContainer),children:n})}function h(e){let{href:t,icon:n,title:o,description:s}=e;return(0,u.jsxs)(p,{href:t,children:[(0,u.jsxs)(l.A,{as:"h2",className:(0,r.A)("text--truncate",d.cardTitle),title:o,children:[n," ",o]}),s&&(0,u.jsx)("p",{className:(0,r.A)("text--truncate",d.cardDescription),title:s,children:s})]})}function m(e){let{item:t}=e;const n=(0,s.Nr)(t),r=function(){const{selectMessage:e}=(0,i.W)();return t=>e(t,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t}))}();return n?(0,u.jsx)(h,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:t.description??r(t.items.length)}):null}function f(e){let{item:t}=e;const n=(0,a.A)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,s.cC)(t.docId??void 0);return(0,u.jsx)(h,{href:t.href,icon:n,title:t.label,description:t.description??r?.description})}function g(e){let{item:t}=e;switch(t.type){case"link":return(0,u.jsx)(f,{item:t});case"category":return(0,u.jsx)(m,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}},2550:(e,t,n)=>{n.d(t,{A:()=>c});n(6540);var r=n(4164),o=n(4142),s=n(5965),i=n(4848);function a(e){let{className:t}=e;const n=(0,o.$S)();return(0,i.jsx)(c,{items:n.items,className:t})}function c(e){const{items:t,className:n}=e;if(!t)return(0,i.jsx)(a,{...e});const c=(0,o.d1)(t);return(0,i.jsx)("section",{className:(0,r.A)("row",n),children:c.map(((e,t)=>(0,i.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,i.jsx)(s.A,{item:e})},t)))})}},5846:(e,t,n)=>{n.d(t,{W:()=>l});var r=n(6540),o=n(4586);const s=["zero","one","two","few","many","other"];function i(e){return s.filter((t=>e.includes(t)))}const a={locale:"en",pluralForms:i(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,o.A)();return(0,r.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:i(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`),a}}),[e])}function l(){const e=c();return{selectMessage:(t,n)=>function(e,t,n){const r=e.split("|");if(1===r.length)return r[0];r.length>n.pluralForms.length&&console.error(`For locale=${n.locale}, a maximum of ${n.pluralForms.length} plural forms are expected (${n.pluralForms.join(",")}), but the message contains ${r.length}: ${e}`);const o=n.select(t),s=n.pluralForms.indexOf(o);return r[Math.min(s,r.length-1)]}(n,t,e)}}},6116:(e,t,n)=>{n.d(t,{$:()=>s});var r=n(2252);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 s(e){const t=(0,r.r)();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]}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>a});var r=n(6540);const o={},s=r.createContext(o);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c9679863.b72c3f04.js b/assets/js/c9679863.b72c3f04.js new file mode 100644 index 0000000000..85bb113d1f --- /dev/null +++ b/assets/js/c9679863.b72c3f04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8856],{8555:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>h,contentTitle:()=>l,default:()=>x,frontMatter:()=>c,metadata:()=>d,toc:()=>p});var n=t(4848),r=t(8453),i=t(2550),a=t(6116),o=t(1766);const c={},l="Emerald ParaTime",d={id:"dapp/emerald/README",title:"Emerald ParaTime",description:"Emerald is our official ParaTime which executes smart contracts inside the",source:"@site/docs/dapp/emerald/README.mdx",sourceDirName:"dapp/emerald",slug:"/dapp/emerald/",permalink:"/dapp/emerald/",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/emerald/README.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Confidential Hello World",permalink:"/dapp/cipher/confidential-smart-contract"},next:{title:"Writing dApps on Emerald",permalink:"/dapp/emerald/writing-dapps-on-emerald"}},h={},p=[{value:"Chain Information",id:"chain-information",level:2},{value:"Mainnet",id:"mainnet",level:3},{value:"Testnet",id:"testnet",level:3},{value:"RPC Endpoints",id:"rpc-endpoints",level:2},{value:"Block Explorers",id:"block-explorers",level:2},{value:"Indexers",id:"indexers",level:2},{value:"See also",id:"see-also",level:2}];function m(e){const s={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"emerald-paratime",children:"Emerald ParaTime"}),"\n",(0,n.jsxs)(s.p,{children:["Emerald is our official ParaTime which executes smart contracts inside the\n",(0,n.jsx)(s.a,{href:"https://ethereum.org/en/developers/docs/evm/",children:"Ethereum Virtual Machine (EVM)"}),"."]}),"\n",(0,n.jsx)(s.p,{children:"Emerald allows for:"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsx)(s.li,{children:"Full EVM compatibility"}),"\n",(0,n.jsx)(s.li,{children:"Easy integration with EVM-based dApps, such as DeFi, NFT, Metaverse and crypto\ngaming"}),"\n",(0,n.jsx)(s.li,{children:"Scalability: increased throughput of transactions"}),"\n",(0,n.jsx)(s.li,{children:"Low-cost: 99%+ lower fees than Ethereum"}),"\n",(0,n.jsx)(s.li,{children:"6 second finality (1 block)"}),"\n",(0,n.jsx)(s.li,{children:"Cross-chain bridge to enable cross-chain interoperability (upcoming)"}),"\n"]}),"\n",(0,n.jsxs)(s.p,{children:["If you're looking for EVM, but with confidentiality, check out the\n",(0,n.jsx)(s.a,{href:"/dapp/sapphire/",children:"Sapphire ParaTime"}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"chain-information",children:"Chain Information"}),"\n",(0,n.jsx)(s.h3,{id:"mainnet",children:"Mainnet"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Network name: ",(0,n.jsx)(s.code,{children:"emerald"})]}),"\n",(0,n.jsxs)(s.li,{children:["Long network name: ",(0,n.jsx)(s.code,{children:"Oasis Emerald"})]}),"\n",(0,n.jsxs)(s.li,{children:["Chain ID:","\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Hex: ",(0,n.jsx)(s.code,{children:"0xa516"})]}),"\n",(0,n.jsxs)(s.li,{children:["Decimal: ",(0,n.jsx)(s.code,{children:"42262"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"testnet",children:"Testnet"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Network name: ",(0,n.jsx)(s.code,{children:"emerald-testnet"})]}),"\n",(0,n.jsxs)(s.li,{children:["Long network name: ",(0,n.jsx)(s.code,{children:"Oasis Emerald Testnet"})]}),"\n",(0,n.jsxs)(s.li,{children:["Chain ID:","\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Hex: ",(0,n.jsx)(s.code,{children:"0xa515"})]}),"\n",(0,n.jsxs)(s.li,{children:["Decimal: ",(0,n.jsx)(s.code,{children:"42261"})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"rpc-endpoints",children:"RPC Endpoints"}),"\n",(0,n.jsx)(s.admonition,{type:"danger",children:(0,n.jsxs)(s.p,{children:["The RPC endpoint is a ",(0,n.jsx)(s.em,{children:"point of trust"}),". Beside traffic rate limiting, it can\nalso perform censorship or even a man-in-the-middle attack. If you have security\nconsiderations, we strongly recommend that you set up your own ",(0,n.jsx)(s.a,{href:"/node/run-your-node/paratime-client-node",children:"ParaTime client\nnode"})," and the ",(0,n.jsx)(s.a,{href:"/node/web3",children:"Web3-compatible gateway"}),"."]})}),"\n",(0,n.jsx)(s.p,{children:"You can connect to one of the public Web3 gateways below (in alphabetic order):"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Provider"}),(0,n.jsx)(s.th,{children:"Mainnet RPC URLs"}),(0,n.jsx)(s.th,{children:"Testnet RPC URLs"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/",children:"1RPC"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.YH,{rpcs:["https://1rpc.io/oasis/emerald"]})}),(0,n.jsx)(s.td,{children:"N/A"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.YH,{rpcs:["https://emerald.oasis.io","wss://emerald.oasis.io/ws"]})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(o.fm,{rpcs:["https://testnet.emerald.oasis.io","wss://testnet.emerald.oasis.io/ws"]})})]})]})]}),"\n",(0,n.jsx)(s.p,{children:"Public RPCs may have rate limits or traffic restrictions. For professional,\ndedicated RPC endpoints, consider the following providers (in alphabetic order):"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Provider"}),(0,n.jsx)(s.th,{children:"Instructions"}),(0,n.jsx)(s.th,{children:"Pricing"})]})}),(0,n.jsx)(s.tbody,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/",children:"1RPC"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://docs.1rpc.io/guide/how-to-use-1rpc",children:"docs.1rpc.io"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.1rpc.io/#pricing",children:"Pricing"})})]})})]}),"\n",(0,n.jsx)(s.h2,{id:"block-explorers",children:"Block Explorers"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Name/Provider"}),(0,n.jsx)(s.th,{children:"Mainnet URL"}),(0,n.jsx)(s.th,{children:"Testnet URL"}),(0,n.jsx)(s.th,{children:"EIP-3091 compatible"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Explorer"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/emerald",children:"https://explorer.oasis.io/mainnet/emerald"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/emerald",children:"https://explorer.oasis.io/testnet/emerald"})}),(0,n.jsx)(s.td,{children:"Yes"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Scan (",(0,n.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.oasisscan.com/paratimes/000000000000000000000000000000000000000000000000e2eaa99fc008f87f",children:"https://www.oasisscan.com/paratimes/000\u202687f"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://testnet.oasisscan.com/paratimes/00000000000000000000000000000000000000000000000072c8215e60d5bca7",children:"https://testnet.oasisscan.com/paratimes/000\u2026ca7"})}),(0,n.jsx)(s.td,{children:"No"})]})]})]}),"\n",(0,n.jsx)(s.h2,{id:"indexers",children:"Indexers"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Name (Provider)"}),(0,n.jsx)(s.th,{children:"Mainnet URL"}),(0,n.jsx)(s.th,{children:"Testnet URL"}),(0,n.jsx)(s.th,{children:"Documentation"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.covalenthq.com/",children:"Covalent"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.covalenthq.com/v1/oasis-emerald-mainnet"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://www.covalenthq.com/docs/unified-api/",children:"Unified API docs"})})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Nexus (",(0,n.jsx)(s.a,{href:"https://oasisprotocol.org",children:"Oasis Protocol Foundation"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://nexus.oasis.io/v1/"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://testnet.nexus.oasis.io/v1/"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://nexus.oasis.io/v1/spec/v1.html",children:"API"})})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsxs)(s.td,{children:["Oasis Scan (",(0,n.jsx)(s.a,{href:"https://www.bitcat365.com/",children:"Bit Cat"}),")"]}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.oasisscan.com/mainnet/v2"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.code,{children:"https://api.oasisscan.com/testnet/v2"})}),(0,n.jsxs)(s.td,{children:[(0,n.jsx)(s.a,{href:"https://api.oasisscan.com/mainnet/swagger-ui/#/runtime-controller",children:"Mainnet Runtime API"}),", ",(0,n.jsx)(s.a,{href:"https://api.oasisscan.com/testnet/swagger-ui/#/runtime-controller",children:"Testnet Runtime API"})]})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:(0,n.jsx)(s.a,{href:"https://subquery.network",children:"SubQuery Network"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsx)(s.td,{children:(0,n.jsx)(s.em,{children:"N/A"})}),(0,n.jsxs)(s.td,{children:[(0,n.jsx)(s.a,{href:"https://academy.subquery.network/",children:"SubQuery Academy"}),", ",(0,n.jsx)(s.a,{href:"https://academy.subquery.network/quickstart/quickstart.html",children:"QuickStart"}),", ",(0,n.jsx)(s.a,{href:"https://github.com/subquery/ethereum-subql-starter/tree/main/Oasis/oasis-emerald-starter",children:"Starter project"})]})]})]})]}),"\n",(0,n.jsx)(s.admonition,{type:"note",children:(0,n.jsxs)(s.p,{children:["If you are running your own Emerald endpoint, a block explorer, or an indexer\nand wish to be added to these docs, open an issue at\n",(0,n.jsx)(s.a,{href:"https://github.com/oasisprotocol/docs",children:"github.com/oasisprotocol/docs"}),"."]})}),"\n",(0,n.jsx)(s.h2,{id:"see-also",children:"See also"}),"\n",(0,n.jsx)(i.A,{items:[(0,a.$)("/general/manage-tokens/"),(0,a.$)("/node/run-your-node/paratime-node"),(0,a.$)("/node/run-your-node/paratime-client-node"),(0,a.$)("/node/web3"),(0,a.$)("/dapp/sapphire/"),(0,a.$)("/dapp/cipher/")]})]})}function x(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(m,{...e})}):m(e)}},5965:(e,s,t)=>{t.d(s,{A:()=>j});t(6540);var n=t(4164),r=t(8774),i=t(4142),a=t(5846),o=t(6654),c=t(1312),l=t(1107);const d={cardContainer:"cardContainer_fWXF",cardTitle:"cardTitle_rnsV",cardDescription:"cardDescription_PWke"};var h=t(4848);function p(e){let{href:s,children:t}=e;return(0,h.jsx)(r.A,{href:s,className:(0,n.A)("card padding--lg",d.cardContainer),children:t})}function m(e){let{href:s,icon:t,title:r,description:i}=e;return(0,h.jsxs)(p,{href:s,children:[(0,h.jsxs)(l.A,{as:"h2",className:(0,n.A)("text--truncate",d.cardTitle),title:r,children:[t," ",r]}),i&&(0,h.jsx)("p",{className:(0,n.A)("text--truncate",d.cardDescription),title:i,children:i})]})}function x(e){let{item:s}=e;const t=(0,i.Nr)(s),n=function(){const{selectMessage:e}=(0,a.W)();return s=>e(s,(0,c.T)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription.plurals",description:"The default description for a category card in the generated index about how many items this category includes"},{count:s}))}();return t?(0,h.jsx)(m,{href:t,icon:"\ud83d\uddc3\ufe0f",title:s.label,description:s.description??n(s.items.length)}):null}function u(e){let{item:s}=e;const t=(0,o.A)(s.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",n=(0,i.cC)(s.docId??void 0);return(0,h.jsx)(m,{href:s.href,icon:t,title:s.label,description:s.description??n?.description})}function j(e){let{item:s}=e;switch(s.type){case"link":return(0,h.jsx)(u,{item:s});case"category":return(0,h.jsx)(x,{item:s});default:throw new Error(`unknown item type ${JSON.stringify(s)}`)}}},2550:(e,s,t)=>{t.d(s,{A:()=>c});t(6540);var n=t(4164),r=t(4142),i=t(5965),a=t(4848);function o(e){let{className:s}=e;const t=(0,r.$S)();return(0,a.jsx)(c,{items:t.items,className:s})}function c(e){const{items:s,className:t}=e;if(!s)return(0,a.jsx)(o,{...e});const c=(0,r.d1)(s);return(0,a.jsx)("section",{className:(0,n.A)("row",t),children:c.map(((e,s)=>(0,a.jsx)("article",{className:"col col--6 margin-bottom--lg",children:(0,a.jsx)(i.A,{item:e})},s)))})}},5846:(e,s,t)=>{t.d(s,{W:()=>l});var n=t(6540),r=t(4586);const i=["zero","one","two","few","many","other"];function a(e){return i.filter((s=>e.includes(s)))}const o={locale:"en",pluralForms:a(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,r.A)();return(0,n.useMemo)((()=>{try{return function(e){const s=new Intl.PluralRules(e);return{locale:e,pluralForms:a(s.resolvedOptions().pluralCategories),select:e=>s.select(e)}}(e)}catch(s){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${s.message}\n`),o}}),[e])}function l(){const e=c();return{selectMessage:(s,t)=>function(e,s,t){const n=e.split("|");if(1===n.length)return n[0];n.length>t.pluralForms.length&&console.error(`For locale=${t.locale}, a maximum of ${t.pluralForms.length} plural forms are expected (${t.pluralForms.join(",")}), but the message contains ${n.length}: ${e}`);const r=t.select(s),i=t.pluralForms.indexOf(r);return n[Math.min(i,n.length-1)]}(t,s,e)}}},1766:(e,s,t)=>{t.d(s,{KT:()=>i,XV:()=>a,YH:()=>o,fm:()=>c});t(6540);var n=t(4848);const r=e=>(0,n.jsxs)("span",{children:[e.rpcs.map((e=>(0,n.jsxs)("code",{children:[e,(0,n.jsx)("br",{})]},e))),(0,n.jsx)("button",{className:"button button--primary margin-top--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.");const s=Date.now();window.ethereum.request({method:"wallet_addEthereumChain",params:[{chainId:e.chainId,chainName:e.name,nativeCurrency:{name:e.token,symbol:e.token,decimals:18},rpcUrls:e.rpcs,blockExplorerUrls:e.be}]}).then((t=>{const n=Date.now()-s<100;null===t&&n&&alert(`The ${e.name} RPC already added.`)}))},children:"Add to MetaMask"})]}),i=e=>r({name:"Oasis Sapphire",chainId:"0x5afe",token:"ROSE",rpcs:e.rpcs,be:["https://explorer.oasis.io/mainnet/sapphire"]}),a=e=>r({name:"Oasis Sapphire Testnet",chainId:"0x5aff",token:"TEST",rpcs:e.rpcs,be:["https://explorer.oasis.io/testnet/sapphire"]}),o=e=>r({name:"Oasis Emerald",chainId:"0xa516",token:"ROSE",rpcs:e.rpcs,be:["https://explorer.oasis.io/mainnet/emerald"]}),c=e=>r({name:"Oasis Emerald Testnet",chainId:"0xa515",token:"TEST",rpcs:e.rpcs,be:["https://explorer.oasis.io/testnet/emerald"]})},6116:(e,s,t)=>{t.d(s,{$:()=>i});var n=t(2252);function r(e){for(const s of e){const e=s.href;e&&void 0===globalThis.sidebarItemsMap[e]&&(globalThis.sidebarItemsMap[e]=s),"category"===s.type&&r(s.items)}}function i(e){const s=(0,n.r)();if(!s)throw new Error("Unexpected: cant find docsVersion in current context");if(void 0===globalThis.sidebarItemsMap){globalThis.sidebarItemsMap={};for(const e in s.docsSidebars)r(s.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]}},8453:(e,s,t)=>{t.d(s,{R:()=>a,x:()=>o});var n=t(6540);const r={},i=n.createContext(r);function a(e){const s=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function o(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cb5a5574.82cf36f2.js b/assets/js/cb5a5574.82cf36f2.js new file mode 100644 index 0000000000..03e344540c --- /dev/null +++ b/assets/js/cb5a5574.82cf36f2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[529],{3745:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var t=s(4848),i=s(8453);const a={title:"Oasis CLI",description:"Powerful CLI for managing Oasis networks, nodes, tokens and dApps"},r="Oasis Command Line Interface",o={id:"general/manage-tokens/cli/README",title:"Oasis CLI",description:"Powerful CLI for managing Oasis networks, 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/README.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,frontMatter:{title:"Oasis CLI",description:"Powerful CLI for managing Oasis networks, 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"}},l={},c=[];function d(e){const n={a:"a",h1:"h1",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"oasis-command-line-interface",children:"Oasis Command Line Interface"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/cli/releases",children:"GitHub repository"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"It boasts a number of handy features:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Flexible setup:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"supports Mainnet, Testnet, Localnet or any other deployment of the Oasis\nnetwork"}),"\n",(0,t.jsx)(n.li,{children:"consensus layer configuration with arbitrary token"}),"\n",(0,t.jsx)(n.li,{children:"configuration of custom ParaTimes with arbitrary token"}),"\n",(0,t.jsx)(n.li,{children:"connecting to remote (via TCP/IP) or local (Unix socket) Oasis node\ninstance"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Powerful wallet features:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"standard token operations (transfers, allowances, deposits, withdrawals and\nbalance queries)"}),"\n",(0,t.jsx)(n.li,{children:"file-based wallet with password protection"}),"\n",(0,t.jsx)(n.li,{children:"full Ledger hardware wallet support"}),"\n",(0,t.jsx)(n.li,{children:"address book"}),"\n",(0,t.jsx)(n.li,{children:"generation, signing and submitting transactions in non-interactive\n(headless) mode"}),"\n",(0,t.jsx)(n.li,{children:"offline transaction generation for air-gapped machines"}),"\n",(0,t.jsx)(n.li,{children:"transaction encryption with X25519-Deoxys-II envelope"}),"\n",(0,t.jsx)(n.li,{children:"support for Ed25519, Ethereum-compatible Secp256k1 and Sr25519 signature\nschemes"}),"\n",(0,t.jsx)(n.li,{children:"raw, BIP-44, ADR-8 and Ledger's legacy derivation paths"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Node operator features:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Oasis node inspection and healthchecks"}),"\n",(0,t.jsx)(n.li,{children:"network governance transactions"}),"\n",(0,t.jsx)(n.li,{children:"staking reward schedule transactions"}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["Developer features:","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"built-in testing accounts compatible with the Oasis test runner, the Oasis\nCI and the official Sapphire and Emerald Localnet Docker images"}),"\n",(0,t.jsx)(n.li,{children:"Oasis Wasm smart contract code deployment, instantiation, management and\ncalls"}),"\n",(0,t.jsx)(n.li,{children:"debugging tools for deployed Wasm contracts"}),"\n",(0,t.jsx)(n.li,{children:"inspection of blocks, transactions, results and events"}),"\n"]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>o});var t=s(6540);const i={},a=t.createContext(i);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cd9af2e1.bb3884da.js b/assets/js/cd9af2e1.bb3884da.js new file mode 100644 index 0000000000..09d7e732c6 --- /dev/null +++ b/assets/js/cd9af2e1.bb3884da.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1198],{8623:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var t=s(4848),i=s(8453);const r={},c="Transaction Test Vectors",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/test-vectors.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Genesis Document",permalink:"/core/consensus/genesis"},next:{title:"Runtime Layer",permalink:"/core/runtime/"}},a={},d=[{value:"Structure",id:"structure",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"transaction-test-vectors",children:"Transaction Test Vectors"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/core/consensus/services/staking#test-vectors",children:"Staking"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/core/consensus/services/registry#test-vectors",children:"Registry"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/core/consensus/services/governance#test-vectors",children:"Governance"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"structure",children:"Structure"}),"\n",(0,t.jsx)(n.p,{children:"The generated test vectors file is a JSON document which provides an array of\nobjects (test vectors). Each test vector has the following fields:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"kind"})," is a human-readable string describing what kind of a transaction the\ngiven test vector is describing (e.g., ",(0,t.jsx)(n.code,{children:'"Transfer"'}),")."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"signature_context"})," is the ",(0,t.jsx)(n.a,{href:"/core/crypto#domain-separation",children:"domain separation context"})," used for signing the\ntransaction."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"tx"})," is the human-readable ",(0,t.jsx)(n.em,{children:"interpreted"})," unsigned transaction. Its purpose is\nto make it easier for the implementer to understand what the content of the\ntransaction is. ",(0,t.jsxs)(n.strong,{children:["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,t.jsx)(n.a,{href:"/core/encoding",children:"encoded"})," transaction, these would be binary blobs)."]})]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"signed_tx"})," is the human-readable signed transaction to make it easier for the\nimplementer to understand how the ",(0,t.jsx)(n.a,{href:"/core/crypto#envelopes",children:"signature envelope"})," looks like."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"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,t.jsx)(n.strong,{children:"This is what is actually broadcast to the network."})]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"valid"})," is a boolean flag indicating whether the given test vector represents\na valid transaction, including:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"transaction having a valid signature,"}),"\n",(0,t.jsx)(n.li,{children:"transaction being correctly serialized,"}),"\n",(0,t.jsx)(n.li,{children:"transaction passing basic static validation."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.em,{children:["NOTE: Even if a transaction passes basic static validation, it may still\n",(0,t.jsx)(n.strong,{children:"not"})," be a valid transaction on the given network due to invalid nonce, or\ndue to some specific parameters set on the network."]})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"signer_private_key"})," is the Ed25519 private key that was used to sign the\ntransaction in the test vector."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"signer_public_key"})," is the Ed25519 public key corresponding to\n",(0,t.jsx)(n.code,{children:"signer_private_key"}),"."]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>c,x:()=>o});var t=s(6540);const i={},r=t.createContext(i);function c(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ce2c26b3.dbe6360f.js b/assets/js/ce2c26b3.dbe6360f.js new file mode 100644 index 0000000000..d8d82d4fb5 --- /dev/null +++ b/assets/js/ce2c26b3.dbe6360f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9947],{2668:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var t=i(4848),s=i(8453);const a={},r="ADR 0017: ParaTime Application Standard Proposal Process",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0017-app-standards.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},c={},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:"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}];function d(e){const n={a:"a",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"adr-0017-paratime-application-standard-proposal-process",children:"ADR 0017: ParaTime Application Standard Proposal Process"}),"\n",(0,t.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,t.jsx)(n.p,{children:"ADRs"}),"\n",(0,t.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"2022-10-05: Initial version"}),"\n",(0,t.jsx)(n.li,{children:"2022-10-12: Accepted"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,t.jsx)(n.p,{children:"Accepted"}),"\n",(0,t.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,t.jsxs)(n.p,{children:["Applications running within a ParaTime having a novel runtime environment\n(e.g., Sapphire, Cipher) benefit from interoperability standards. For example,\n",(0,t.jsx)(n.a,{href:"https://github.com/ethereum/EIPs",children:"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."]}),"\n",(0,t.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["Although community standards are only proposals, the ",(0,t.jsx)(n.em,{children:"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."]}),"\n",(0,t.jsx)(n.h3,{id:"naming-conventions",children:"Naming Conventions"}),"\n",(0,t.jsx)(n.p,{children:"App standard ADRs shall be referred to as ADR- regardless of the\ntargeted ParaTime."}),"\n",(0,t.jsx)(n.h3,{id:"changes-to-the-adr-template",children:"Changes to the ADR template"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["add a new ",(0,t.jsx)(n.em,{children:"Apps"})," component, which has the ParaTime as its sub-component"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"new-section-requirements",children:"New Section Requirements"}),"\n",(0,t.jsx)(n.h4,{id:"decision-specification--reference-implementation",children:"Decision: Specification & Reference Implementation"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.em,{children:"Decision"})," section gets two new sub-sections:"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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."]}),"\n",(0,t.jsx)(n.h4,{id:"security-considerations",children:"Security Considerations"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h3,{id:"acceptance-requirements",children:"Acceptance Requirements"}),"\n",(0,t.jsxs)(n.p,{children:["Like all ADRs, an Apps component ADR will start as ",(0,t.jsx)(n.em,{children:"Proposed"})," and end up merged\nonce ",(0,t.jsx)(n.em,{children:"Accepted"}),". An application standard ADR following the above format will be\naccepted once:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"there is consensus within the ParaTime's own community that the standard meets\nits design goals"}),"\n",(0,t.jsx)(n.li,{children:"there are no outstanding compatibility or security issues"}),"\n",(0,t.jsx)(n.li,{children:"an ADR repo committer has signed off on the structure and format of the ADR"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"alternatives",children:"Alternatives"}),"\n",(0,t.jsxs)(n.p,{children:["One alternative is to fit the ParaTime-specific application standard proposals\ninto the existing ADR template, but this would cause the ",(0,t.jsx)(n.em,{children:"Decision"})," section to\nbecome overloaded with the necessary information in an ad-hoc way."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.em,{children:"Superseded"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,t.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The community has a rallying point for standard development."}),"\n",(0,t.jsx)(n.li,{children:"We can reuse existing process."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The app standard process might still not be ideal even after this proposal."}),"\n",(0,t.jsx)(n.li,{children:"ADR-NNN naming convention is not forwards compatible."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"We will need to maintain additional ADR process going forward."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://github.com/ethereum/EIPs",children:"Ethereum Improvement Proposals"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.rfc-editor.org/pubprocess/",children:"RFCs"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/ics-template.md",children:"Inter-Chain Standards"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>o});var t=i(6540);const s={},a=t.createContext(s);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ced62d27.2c0433cc.js b/assets/js/ced62d27.2c0433cc.js new file mode 100644 index 0000000000..d276f33e6f --- /dev/null +++ b/assets/js/ced62d27.2c0433cc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6598],{8341:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var i=t(4848),s=t(8453);const a={},r="Application",o={id:"rofl/app",title:"Application",description:"This chapter will show you how to quickly create, build and test a minimal",source:"@site/docs/rofl/app.md",sourceDirName:"rofl",slug:"/rofl/app",permalink:"/rofl/app",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-sdk/edit/main/docs/rofl/app.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"rofl",previous:{title:"Prerequisites",permalink:"/rofl/prerequisites"},next:{title:"Consensus Trust Root",permalink:"/rofl/trust-root"}},c={},l=[{value:"How do ROFL Apps Work?",id:"how-do-rofl-apps-work",level:2},{value:"Repository Structure and Dependencies",id:"repository-structure-and-dependencies",level:2},{value:"App Definition",id:"app-definition",level:2},{value:"Register the App",id:"register-the-app",level:2},{value:"Oracle Contract Definition",id:"oracle-contract-definition",level:2},{value:"Configuring the Oracle Contract Address",id:"configuring-the-oracle-contract-address",level:2},{value:"Building the ROFL App",id:"building-the-rofl-app",level:2},{value:"Updating the ROFL App Policy",id:"updating-the-rofl-app-policy",level:2},{value:"Deploying the ROFL App",id:"deploying-the-rofl-app",level:2},{value:"Checking That the ROFL App is Running",id:"checking-that-the-rofl-app-is-running",level:2},{value:"Checking That the Oracle is Getting Updated",id:"checking-that-the-oracle-is-getting-updated",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"application",children:"Application"}),"\n",(0,i.jsx)(n.p,{children:"This chapter will show you how to quickly create, build and test a minimal\nROFL app that serves as a simple oracle, fetching data from remote sources via\nHTTPS and posting it on chain for aggregation."}),"\n",(0,i.jsx)(n.h2,{id:"how-do-rofl-apps-work",children:"How do ROFL Apps Work?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"ROFL diagram",src:t(6192).A+""})}),"\n",(0,i.jsxs)(n.p,{children:["Each ROFL app runs in its own Trusted Execution Environment (TEE) which is\nprovisioned by an Oasis Node from its ",(0,i.jsx)(n.em,{children:"bundle"})," (a zip archive containing the\nprogram binaries and metadata required for execution). ROFL apps register to\nthe Oasis Network in order to be able to easily authenticate to on-chain smart\ncontracts."]}),"\n",(0,i.jsxs)(n.p,{children:["Inside the TEE, the ROFL app performs important functions that ensure its\nsecurity and enable secure communication with the outside world. This includes\nusing a light client to establish a fresh view of the Oasis consensus layer\nwhich provides a source of rough time and integrity for verification of all\non-chain state. The ROFL app also generates a set of ephemeral cryptographic\nkeys which are used in the process of remote attestation and on-chain\nregistration. These processes ensure that the ROFL app can authenticate to\non-chain modules (e.g. smart contracts running in the ",(0,i.jsx)(n.a,{href:"/dapp/sapphire/",children:"Sapphire runtime"}),") by\nsigning and submitting special transactions."]}),"\n",(0,i.jsx)(n.p,{children:"The ROFL app can then perform arbitrary work and interact with the outside world\nthrough (properly authenticated) network connections. Connections can be\nauthenticated via HTTPS/TLS or use other methods (e.g. light clients for other\nchains)."}),"\n",(0,i.jsxs)(n.p,{children:["As a first step we need to decide which ParaTime the ROFL app will authenticate\nto. This can be any ParaTime which has the ROFL module installed. For the rest\nof this chapter we will be using ",(0,i.jsx)(n.a,{href:"/node/testnet/#sapphire",children:"Sapphire Testnet"})," which has all of the\nrequired functionality."]}),"\n",(0,i.jsx)(n.h2,{id:"repository-structure-and-dependencies",children:"Repository Structure and Dependencies"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["You can find the entire project insite the Oasis SDK repository under\n",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/runtime-sdk/rofl-oracle",children:(0,i.jsx)(n.code,{children:"examples/runtime-sdk/rofl-oracle"})}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["First we create the basic directory structure for the minimal runtime using\nRust's ",(0,i.jsx)(n.a,{href:"https://doc.rust-lang.org/cargo",children:(0,i.jsx)(n.code,{children:"cargo"})}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cargo init rofl-oracle\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will create the ",(0,i.jsx)(n.code,{children:"rofl-oracle"})," 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."]}),"\n",(0,i.jsxs)(n.p,{children:["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\n",(0,i.jsx)(n.code,{children:"rust-toolchain.toml"})," containing the following information:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title="rust-toolchain.toml"',children:'[toolchain]\nchannel = "nightly-2024-07-09"\ncomponents = [ "rustfmt", "clippy" ]\ntargets = [ "x86_64-fortanix-unknown-sgx", "wasm32-unknown-unknown" ]\nprofile = "minimal"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:".cargo/config.toml"})," file with the\nfollowing content:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title=".cargo/config.toml"',children:'[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'})}),"\n",(0,i.jsx)(n.p,{children:"After you complete this guide, the directory structure will look as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rofl-oracle\n\u251c\u2500\u2500 .cargo\n\u2502 \u2514\u2500\u2500 config.toml # 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.toml # Rust toolchain version configuration.\n\u2514\u2500\u2500 src\n \u2514\u2500\u2500 main.rs # The ROFL app definition.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"app-definition",children:"App Definition"}),"\n",(0,i.jsxs)(n.p,{children:["First you need to declare the required dependencies on ",(0,i.jsx)(n.code,{children:"oasis-runtime-sdk"})," and\nrelated crates in order to be able to use the required features. To do this,\nedit the ",(0,i.jsx)(n.code,{children:"[dependencies]"})," section in your ",(0,i.jsx)(n.code,{children:"Cargo.toml"})," to look like the\nfollowing:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",metastring:'title="Cargo.toml"',children:'[package]\nname = "rofl-oracle"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\n# Oasis SDK.\noasis-runtime-sdk = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "runtime-sdk/v0.9.6" }\nmodule-evm = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "runtime-sdk/v0.9.6", package = "oasis-runtime-sdk-evm" }\nrofl-utils = { git = "https://github.com/oasisprotocol/oasis-sdk", tag = "rofl-utils/v0.1.1" }\n\n# Third-party dependencies.\nanyhow = "1.0"\nasync-trait = "0.1.77"\nethabi = { version = "18.0.0", default-features = false, features = ["std"] }\ntokio = { version = "1.38", features = ["rt", "rt-multi-thread"] }\nserde_json = "1.0"\n\n[features]\n# Enables mock SGX in non-SGX builds.\ndebug-mock-sgx = ["oasis-runtime-sdk/debug-mock-sgx"]\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"We are using the Git repository directly instead of releasing Rust packages on\ncrates.io."})}),"\n",(0,i.jsxs)(n.p,{children:["After you have declared the required dependencies the next thing is to define\nthe ROFL app. To do this, create ",(0,i.jsx)(n.code,{children:"src/main.rs"})," with the following content:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",metastring:'title="src/main.rs"',children:'use oasis_runtime_sdk::modules::rofl::app::prelude::*;\n\n/// Address where the oracle contract is deployed.\nconst ORACLE_CONTRACT_ADDRESS: &str = "0x1234845aaB7b6CD88c7fAd9E9E1cf07638805b20"; // TODO: Replace with your contract address.\n\nstruct OracleApp;\n\n#[async_trait]\nimpl App for OracleApp {\n /// Application version.\n const VERSION: Version = sdk::version_from_cargo!();\n\n /// Identifier of the application (used for registrations).\n fn id() -> AppId {\n "rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw".into() // TODO: Replace with your application ID.\n }\n\n /// Return the consensus layer trust root for this runtime; if `None`, consensus layer integrity\n /// verification will not be performed.\n fn consensus_trust_root() -> Option {\n // The trust root below is for Sapphire Testnet at consensus height 22110615.\n Some(TrustRoot {\n height: 22110615,\n hash: "95d1501f9cb88619050a5b422270929164ce739c5d803ed9500285b3b040985e".into(),\n runtime_id: "000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c".into(),\n chain_context: "0b91b8e4e44b2003a7c5e23ddadb5e14ef5345c0ebcb3ddcae07fa2f244cab76"\n .to_string(),\n })\n }\n\n async fn run(self: Arc, _env: Environment) {\n // We are running now!\n println!("Hello ROFL world!");\n }\n\n async fn on_runtime_block(self: Arc, env: Environment, _round: u64) {\n // This gets called for each runtime block. It will not be called again until the previous\n // invocation returns and if invocation takes multiple blocks to run, those blocks will be\n // skipped.\n if let Err(err) = self.run_oracle(env).await {\n println!("Failed to submit observation: {:?}", err);\n }\n }\n}\n\nimpl OracleApp {\n /// Fetch stuff from remote service via HTTPS and publish it on chain.\n async fn run_oracle(self: Arc, env: Environment) -> Result<()> {\n // Fetch data from remote service.\n let observation = tokio::task::spawn_blocking(move || -> Result<_> {\n // Request some data from Coingecko API.\n let rsp: serde_json::Value = rofl_utils::https::agent()\n .get("https://api.coingecko.com/api/v3/simple/price?ids=oasis-network&vs_currencies=USD")\n .call()?\n .body_mut()\n .read_json()?;\n\n // Extract price and convert to integer.\n let price = rsp\n .pointer("/oasis-network/usd")\n .ok_or(anyhow::anyhow!("price not available"))?\n .as_f64()\n .ok_or(anyhow::anyhow!("price malformed"))?;\n let price = (price * 1_000_000.0) as u128;\n\n Ok(price)\n }).await??;\n\n // Prepare the oracle contract call.\n let mut tx = self.new_transaction(\n "evm.Call",\n module_evm::types::Call {\n address: ORACLE_CONTRACT_ADDRESS.parse().unwrap(),\n value: 0.into(),\n data: [\n ethabi::short_signature("submitObservation", &[ethabi::ParamType::Uint(128)])\n .to_vec(),\n ethabi::encode(&[ethabi::Token::Uint(observation.into())]),\n ]\n .concat(),\n },\n );\n tx.set_fee_gas(200_000);\n\n // Submit observation on chain.\n env.client().sign_and_submit_tx(env.signer(), tx).await?;\n\n Ok(())\n }\n}\n\nfn main() {\n OracleApp.start();\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"register-the-app",children:"Register the App"}),"\n",(0,i.jsx)(n.p,{children:"Before the ROFL app can authenticate it needs to be registered as an app on the\nSapphire Testnet. Anyone with enough stake can register an app by using the CLI."}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["In order to obtain TEST tokens needed for registering and running your ROFL\napps use ",(0,i.jsx)(n.a,{href:"https://faucet.testnet.oasis.io/?paratime=sapphire",children:"the faucet"})," or ",(0,i.jsx)(n.a,{href:"/get-involved/#social-media-channels",children:"ask on Discord"}),". To make things easier you should\n",(0,i.jsxs)(n.a,{href:"/general/manage-tokens/cli/wallet",children:["create or import a ",(0,i.jsx)(n.code,{children:"secp256k1-bip44"})," account"]})," that you can also use with the\nEthereum-compatible tooling like Hardhat."]}),(0,i.jsx)(n.p,{children:"To create a ROFL app on Sapphire Testnet you need at least 10,000 TEST."})]}),"\n",(0,i.jsx)(n.p,{children:"Registering a ROFL app assigns it a unique app identifier in the form of:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"rofl1qr98wz5t6q4x8ng6a5l5v7rqlx90j3kcnun5dwht\n"})}),"\n",(0,i.jsx)(n.p,{children:"This identifier can be used by on-chain smart contracts to ensure that they are\ntalking to the right app. During registration the following information is\nassociated with the app:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Administrator address."})," This is the address of the account that is able to\nupdate the app registration. During creation it defaults to the caller of the\nregistration transaction, but it can later be updated if needed."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Policy."})," The policy specifies who is allowed to run instances of your ROFL\napp and defines the app's ",(0,i.jsx)(n.em,{children:"cryptographic identity"}),". This identity must be\nproven each time the app starts through the use of remote attestation. This\nensures that all instances of your app are running the exact same code and are\nrunning in a valid Trusted Execution Environment (TEE)."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Policies can specify various parameters, but for initial registration we will\nspecify a very broad policy which allows anyone to run your ROFL apps. To create\na simple policy, create a file ",(0,i.jsx)(n.code,{children:"policy.yml"})," with the following content:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"# Acceptable remote attestation quotes.\nquotes:\n # Intel SGX/TDX PCS (DCAP) quotes.\n pcs:\n # Maximum age (in days) of the acceptable TCB infos.\n tcb_validity_period: 30\n # Minimum acceptable TCB evaluation data number. This ensures that TCB information\n # provided by the TEE vendor is recent enough and includes relevant TCB recoveries.\n min_tcb_evaluation_data_number: 17\n# Acceptable nodes that can endorse the enclaves.\nendorsements:\n - any: {} # Any node can endorse.\n# Who is paying the transaction fees on behalf of the enclaves.\nfees: endorsing_node # The endorsing node is paying via a fee proxy.\n# How often (in epochs) do the registrations need to be refreshed.\nmax_expiration: 3\n"})}),"\n",(0,i.jsx)(n.p,{children:"To then register a new ROFL app run the CLI as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis rofl create policy.yml --network testnet --paratime sapphire\n"})}),"\n",(0,i.jsx)(n.p,{children:"After signing the transaction and assuming your account has enough funds to\ncover the gas fees and stake required for registration, the CLI will output the\nnewly assigned app identifier in the following form:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Created ROFL application: rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You should use this identifier and replace the placeholder in ",(0,i.jsx)(n.code,{children:"src/main.rs"})," as\nfollows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'fn id() -> AppId {\n "rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw".into()\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"This is it. Before final deployment, after we have built the app binary, we will\nneed to update the app's registration to specify the app's cryptographic\nidentity."}),"\n",(0,i.jsx)(n.h2,{id:"oracle-contract-definition",children:"Oracle Contract Definition"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["While we are using ",(0,i.jsx)(n.a,{href:"/dapp/sapphire/",children:"EVM-based smart contracts"})," in this example, the on-chain\npart can be anything from a ",(0,i.jsx)(n.a,{href:"/dapp/cipher/",children:"WASM-based smart contract"})," to a dedicated\n",(0,i.jsx)(n.a,{href:"/paratime/modules",children:"runtime module"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["We have prepared a simple oracle contract for this example. You can find it by\nchecking out the ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/tree/main/examples/runtime-sdk/rofl-oracle/oracle",children:"prepared example project"})," from the Oasis SDK repository. It\ncontains a simple ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-sdk/blob/main/examples/runtime-sdk/rofl-oracle/oracle/contracts/Oracle.sol",children:"Oracle.sol"})," contract which collects observations from\nauthenticated ROFL app instances, performs trivial aggregation and stores the\nfinal aggregated result. See the ",(0,i.jsx)(n.a,{href:"/dapp/sapphire/quickstart",children:"Sapphire quickstart"})," chapter for more details\non building and deploying Sapphire smart contracts."]}),"\n",(0,i.jsx)(n.p,{children:"Configure the deployment private key and the ROFL app identifier (be sure to use\nthe identifier that you received during registration), then deploy the contract\nby running:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'PRIVATE_KEY="0x..." ROFL_APP_ID="rofl1..." npx hardhat run scripts/deploy.ts --network sapphire-testnet\n'})}),"\n",(0,i.jsx)(n.p,{children:"After successful deployment you will see a message like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Oracle for ROFL app rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw deployed to 0x1234845aaB7b6CD88c7fAd9E9E1cf07638805b20\n"})}),"\n",(0,i.jsx)(n.p,{children:"You can now proceed to building and deploying the ROFL app itself. Remember the\naddress where the oracle contract was deployed to as you will need it in the\nnext step."}),"\n",(0,i.jsx)(n.h2,{id:"configuring-the-oracle-contract-address",children:"Configuring the Oracle Contract Address"}),"\n",(0,i.jsxs)(n.p,{children:["Back in the definition of the ROFL app you will need to specify the address of\nthe oracle contract you deployed in the previous step. To do this, simply update\nthe value of the ",(0,i.jsx)(n.code,{children:"ORACLE_CONTRACT_ADDRESS"})," constant defined at the top of\n",(0,i.jsx)(n.code,{children:"main.rs"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-rust",children:'/// Address where the oracle contract is deployed.\nconst ORACLE_CONTRACT_ADDRESS: &str = "0x1234845aaB7b6CD88c7fAd9E9E1cf07638805b20";\n'})}),"\n",(0,i.jsx)(n.p,{children:"Make sure to use the contract address as output by the deployment script in the\nprevious step."}),"\n",(0,i.jsx)(n.h2,{id:"building-the-rofl-app",children:"Building the ROFL App"}),"\n",(0,i.jsx)(n.p,{children:"In order to quickly build the ROFL app you can use the helpers provided by the\nOasis CLI as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis rofl build sgx --network testnet --paratime sapphire\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This will build the required app binaries using ",(0,i.jsx)(n.code,{children:"cargo"})," and bundle them into\nthe Oasis Runtime Container (ORC) format suitable for deployment to Oasis nodes.\nBy default, the resulting file will be called ",(0,i.jsx)(n.code,{children:"rofl-oracle.orc"}),"."]}),"\n",(0,i.jsx)(n.admonition,{title:"Reproducibility",type:"info",children:(0,i.jsxs)(n.p,{children:["For audit reasons it is very important that ROFL app binaries can be reproduced\nfrom the given source code. This makes it possible to check that the right code\nis actually deployed. In order to support reproducible builds, please see the\n",(0,i.jsx)(n.a,{href:"/paratime/reproducibility",children:"Reproducibility chapter"}),"."]})}),"\n",(0,i.jsx)(n.h2,{id:"updating-the-rofl-app-policy",children:"Updating the ROFL App Policy"}),"\n",(0,i.jsx)(n.p,{children:"Now that the app binaries are available, we need to update the policy with the\ncorrect cryptographic identity of the app. To obtain the identity of the app\nthat was just built run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis rofl identity rofl-oracle.orc\n"})}),"\n",(0,i.jsx)(n.p,{children:"This should output something like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"yg1zKYeLa4QjEj08dkMtNn4JnUmNrpuov4QwC3X9ZBUJFtTP3jZWjgVaV8WjTmoAr2gcg9ymZYoUFM2y9rp1Jw==\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This represents the cryptographic identity of the ROFL app. We now need to\nupdate the policy to ensure that only exact instances of the built app can\nsuccessfully authenticate under our app ID. To do so, update the previously\ngenerated ",(0,i.jsx)(n.code,{children:"policy.yml"})," as follows (using your own app identity):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'# Acceptable remote attestation quotes.\nquotes:\n # Intel SGX/TDX PCS (DCAP) quotes.\n pcs:\n # Maximum age (in days) of the acceptable TCB infos.\n tcb_validity_period: 30\n # Minimum acceptable TCB evaluation data number. This ensures that TCB information\n # provided by the TEE vendor is recent enough and includes relevant TCB recoveries.\n min_tcb_evaluation_data_number: 17\n# Acceptable enclave cryptographic identities.\nenclaves:\n - "yg1zKYeLa4QjEj08dkMtNn4JnUmNrpuov4QwC3X9ZBUJFtTP3jZWjgVaV8WjTmoAr2gcg9ymZYoUFM2y9rp1Jw=="\n# Acceptable nodes that can endorse the enclaves.\nendorsements:\n - any: {} # Any node can endorse.\n# Who is paying the transaction fees on behalf of the enclaves.\nfees: endorsing_node # The endorsing node is paying via a fee proxy.\n# How often (in epochs) do the registrations need to be refreshed.\nmax_expiration: 3\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then to update the on-chain policy, run (using ",(0,i.jsx)(n.em,{children:"your own app identifier"})," instead\nof the placeholder ",(0,i.jsx)(n.code,{children:"rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw"}),"):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis rofl update rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw \\\n --policy policy.yml \\\n --admin self \\\n --network testnet \\\n --paratime sapphire\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"For those interested in the details, the specified cryptographic identity is\nactually based on the MRENCLAVE and MRSIGNER pair used in Intel SGX remote\nattestation. Because the ROFL protocols only use MRENCLAVE for authentication,\na random signer key is generated during build and used to sign the enclave."})}),"\n",(0,i.jsx)(n.h2,{id:"deploying-the-rofl-app",children:"Deploying the ROFL App"}),"\n",(0,i.jsxs)(n.p,{children:["ROFL apps are deployed through Oasis nodes running on systems that support the\ntargeted TEE (e.g. Intel SGX). If you don't have a running node where you could\ndeploy your ROFL app, please first make sure that you have a client node with\nthe Sapphire Testnet runtime configured (see the ",(0,i.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"client node documentation"})," for\ninstructions on setting one up). Note that you need at least version 24.2 of\nOasis Core."]}),"\n",(0,i.jsxs)(n.p,{children:["After your node is set up, update the ",(0,i.jsx)(n.code,{children:"runtime"})," section in your configuration\nas follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"runtime:\n environment: sgx # Required to ensure runtimes run in a TEE.\n sgx_loader: /node/bin/oasis-core-runtime-loader\n paths:\n - /node/runtime/sapphire-paratime.orc\n - /node/runtime/rofl-oracle.orc\n"})}),"\n",(0,i.jsx)(n.p,{children:"Note the appropriate paths to both the latest Sapphire Testnet runtime and the\nROFL app bundle. Before proceeding with the rest of the chapter, please make\nsure that the node is fully synchronized with Sapphire Testnet."}),"\n",(0,i.jsx)(n.p,{children:"The node will also need to cover any transaction fees that are required to\nmaintain registration of the ROFL app. First, determine the address of the node\nyou are connecting to by running the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis-node identity show-address -a unix:/node/data/internal.sock\n"})}),"\n",(0,i.jsx)(n.p,{children:"This should output an address like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis1qp66ryj9caek77kewkxxvjvkzypljhsdgvm5q34d\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You can then ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/account#transfer",children:"transfer some tokens"})," to this address on Sapphire Testnet to make\nsure it will have funds to pay for registration fees:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis account transfer 10 oasis1qp66ryj9caek77kewkxxvjvkzypljhsdgvm5q34d \\\n --network testnet --paratime sapphire\n"})}),"\n",(0,i.jsx)(n.h2,{id:"checking-that-the-rofl-app-is-running",children:"Checking That the ROFL App is Running"}),"\n",(0,i.jsxs)(n.p,{children:["In order to check that the ROFL app is running and has successfully registered\non chain, you can use the following command (using ",(0,i.jsx)(n.em,{children:"your own app identifier"}),"\ninstead of the placeholder ",(0,i.jsx)(n.code,{children:"rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw"}),"):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis rofl show rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw \\\n --network testnet --paratime sapphire\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will output some information about the registered ROFL app, its policy and\nits currently live instances:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'App ID: rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw\nAdmin: oasis1qpwaggvmhwq5uk40clase3knt655nn2tdy39nz2f\nStaked amount: 10000.0 TEST\nPolicy:\n {\n "quotes": {\n "pcs": {\n "tcb_validity_period": 30,\n "min_tcb_evaluation_data_number": 17\n }\n },\n "enclaves": [\n "yg1zKYeLa4QjEj08dkMtNn4JnUmNrpuov4QwC3X9ZBUJFtTP3jZWjgVaV8WjTmoAr2gcg9ymZYoUFM2y9rp1Jw=="\n ],\n "endorsements": [\n {\n "any": {}\n }\n ],\n "fees": 2,\n "max_expiration": 3\n }\n\n=== Instances ===\n- RAK: IPu1O+rQihlydy+V4QmegV9s7debnD+Xr+lNQjofNNQ=\n Node ID: JmwDKc45CJ4sepNFszV/tDGFHBoB9XduO0IMOdts+Lk=\n Expiration: 37408\n'})}),"\n",(0,i.jsx)(n.p,{children:"Here you can see that a single instance of the ROFL app is running on the given\nnode, its public runtime attestation key (RAK) and the epoch at which its\nregistration will expire if not refreshed. ROFL apps must periodically refresh\ntheir registrations to ensure they don't expire."}),"\n",(0,i.jsx)(n.h2,{id:"checking-that-the-oracle-is-getting-updated",children:"Checking That the Oracle is Getting Updated"}),"\n",(0,i.jsxs)(n.p,{children:["In order to check that the oracle is working, you can use the prepared\n",(0,i.jsx)(n.code,{children:"oracle-query"})," task in the Hardhat project. Simply run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'PRIVATE_KEY="0x..." npx hardhat oracle-query 0x1234845aaB7b6CD88c7fAd9E9E1cf07638805b20 --network sapphire-testnet\n'})}),"\n",(0,i.jsx)(n.p,{children:"And you should get an output like the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Using oracle contract deployed at 0x1234845aaB7b6CD88c7fAd9E9E1cf07638805b20\nROFL app: rofl1qp55evqls4qg6cjw5fnlv4al9ptc0fsakvxvd9uw\nThreshold: 1\nLast observation: 62210\nLast update at: 7773504\n"})}),"\n",(0,i.jsx)(n.p,{children:"That's it! Your first ROFL oracle is running!"})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},6192:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/rofl-6f0e9734207a8490d8a0cf83d21f10c1.svg"},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var i=t(6540);const s={},a=i.createContext(s);function r(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cef04ba6.e27d8e88.js b/assets/js/cef04ba6.e27d8e88.js new file mode 100644 index 0000000000..8810bcdbab --- /dev/null +++ b/assets/js/cef04ba6.e27d8e88.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7794],{5966:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var o=s(4848),t=s(8453);const r={},i="ADR 0006: Consensus Governance",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/adrs/edit/main/0006-consensus-governance.md",tags:[],version:"current",lastUpdatedAt:1710755515e3,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"}},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:"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}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-0006-consensus-governance",children:"ADR 0006: Consensus Governance"}),"\n",(0,o.jsx)(n.h2,{id:"component",children:"Component"}),"\n",(0,o.jsx)(n.p,{children:"Oasis Core"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2021-03-30: Update name of the CastVote method's body"}),"\n",(0,o.jsx)(n.li,{children:"2021-01-06: Update API to include Proposals() method"}),"\n",(0,o.jsx)(n.li,{children:"2020-12-08: Updates to match the actual implementation"}),"\n",(0,o.jsx)(n.li,{children:"2020-10-27: Voting period in epochs, min upgrade cancellation difference,\nfailed proposal state"}),"\n",(0,o.jsx)(n.li,{children:"2020-10-16: Initial draft"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Accepted"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.p,{children:"The high-level overview is as follows:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["A proposal is created through a ",(0,o.jsx)(n.em,{children:"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."]}),"\n",(0,o.jsx)(n.p,{children:"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."}),"\n",(0,o.jsx)(n.h3,{id:"state",children:"State"}),"\n",(0,o.jsx)(n.h4,{id:"staking",children:"Staking"}),"\n",(0,o.jsx)(n.p,{children:"This proposal adds the following consensus layer state in the staking module:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsxs)(n.strong,{children:["Governance deposits account balance (",(0,o.jsx)(n.code,{children:"0x59"}),")"]}),", similar to the common pool."]}),"\n"]}),"\n",(0,o.jsx)(n.h4,{id:"governance",children:"Governance"}),"\n",(0,o.jsx)(n.p,{children:"This proposal adds the following consensus layer state in the governance module:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["Next proposal identifier (",(0,o.jsx)(n.code,{children:"0x80"}),")"]})}),"\n",(0,o.jsxs)(n.p,{children:["The next proposal identifier is stored as a CBOR-serialized ",(0,o.jsx)(n.code,{children:"uint64"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["List of proposals (",(0,o.jsx)(n.code,{children:"0x81"}),")"]})}),"\n",(0,o.jsx)(n.p,{children:"Each proposal is stored under a separate storage key with the following key\nformat:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"0x81 \n"})}),"\n",(0,o.jsx)(n.p,{children:"And CBOR-serialized value:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["List of active proposals (",(0,o.jsx)(n.code,{children:"0x82"}),")"]})}),"\n",(0,o.jsx)(n.p,{children:"Each active proposal (one that has not yet closed) is stored under a separate\nstorage key with the following key format:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"0x82 \n"})}),"\n",(0,o.jsx)(n.p,{children:"The value is empty as the proposal ID can be inferred from the key."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["List of votes (",(0,o.jsx)(n.code,{children:"0x83"}),")"]})}),"\n",(0,o.jsx)(n.p,{children:"Each vote is stored under a separate storage key with the following key\nformat:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"0x83 \n"})}),"\n",(0,o.jsx)(n.p,{children:"And CBOR-serialized value:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:"// Vote is a governance vote.\ntype Vote uint8\n\nconst (\n VoteYes Vote = 1\n VoteNo Vote = 2\n VoteAbstain Vote = 3\n)\n"})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["List of pending upgrades (",(0,o.jsx)(n.code,{children:"0x84"}),")"]})}),"\n",(0,o.jsx)(n.p,{children:"Each pending upgrade is stored under a separate storage key with the following\nkey format:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"0x84 \n"})}),"\n",(0,o.jsx)(n.p,{children:"The value is empty as the proposal upgrade descriptor can be obtained via\nproposal that can be inferred from the key."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:(0,o.jsxs)(n.strong,{children:["Parameters (",(0,o.jsx)(n.code,{children:"0x85"}),")"]})}),"\n",(0,o.jsx)(n.p,{children:"Governance consensus parameters."}),"\n",(0,o.jsx)(n.p,{children:"With CBOR-serialized value:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"genesis-document",children:"Genesis Document"}),"\n",(0,o.jsxs)(n.p,{children:["The genesis document needs to be updated to include a ",(0,o.jsx)(n.code,{children:"governance"})," field with\nany initial state (see ",(0,o.jsx)(n.a,{href:"#state",children:(0,o.jsx)(n.em,{children:"State"})}),") and consensus parameters (see ",(0,o.jsx)(n.a,{href:"#consensus-parameters",children:(0,o.jsx)(n.em,{children:"Consensus\nParameters"})}),") for the governance service."]}),"\n",(0,o.jsx)(n.h3,{id:"transaction-methods",children:"Transaction Methods"}),"\n",(0,o.jsx)(n.p,{children:"This proposal adds the following transaction methods in the governance module:"}),"\n",(0,o.jsx)(n.h4,{id:"submit-proposal",children:"Submit Proposal"}),"\n",(0,o.jsx)(n.p,{children:"Proposal submission enables a new consensus layer governance proposal to be\ncreated."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"governance.SubmitProposal\n"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'// 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'})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"upgrade"})," (optional) specifies an upgrade proposal."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"cancel_upgrade"})," (optional) specifies an upgrade cancellation proposal."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Exactly one of the proposal kind fields needs to be non-nil, otherwise the\nproposal is considered malformed."}),"\n",(0,o.jsx)(n.p,{children:"Upon processing any proposal the following steps are first performed:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"The account indicated by the signer is loaded."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["If the account balance is less than ",(0,o.jsx)(n.code,{children:"min_proposal_deposit"}),", the method call\nfails with ",(0,o.jsx)(n.code,{children:"ErrInsufficientBalance"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Upon processing an ",(0,o.jsx)(n.strong,{children:(0,o.jsx)(n.code,{children:"UpgradeProposal"})})," the following steps are then performed:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The upgrade descriptor is checked for basic internal validity. If the check\nfails, the method call fails with ",(0,o.jsx)(n.code,{children:"ErrInvalidArgument"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The upgrade descriptor's ",(0,o.jsx)(n.code,{children:"epoch"})," field is compared with the current epoch. If\nthe specified epoch is not at least ",(0,o.jsx)(n.code,{children:"upgrade_min_epoch_diff"})," epochs ahead of\nthe current epoch, the method call fails with ",(0,o.jsx)(n.code,{children:"ErrUpgradeTooSoon"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The set of pending upgrades is checked to make sure that no upgrades are\ncurrently pending within ",(0,o.jsx)(n.code,{children:"upgrade_min_epoch_diff"})," epochs of the upgrade\ndescriptor's ",(0,o.jsx)(n.code,{children:"epoch"})," field. If there is such an existing upgrade pending, the\nmethod call fails with ",(0,o.jsx)(n.code,{children:"ErrUpgradeAlreadyPending"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Upon processing a ",(0,o.jsx)(n.strong,{children:(0,o.jsx)(n.code,{children:"CancelUpgradeProposal"})})," the following steps are then\nperformed:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"ErrNoSuchUpgrade"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The upgrade descriptor's ",(0,o.jsx)(n.code,{children:"epoch"})," field is compared with the current epoch. If\nthe specified epoch is not at least ",(0,o.jsx)(n.code,{children:"upgrade_cancel_min_epoch_diff"})," epochs\nahead of the current epoch, the method call fails with ",(0,o.jsx)(n.code,{children:"ErrUpgradeTooSoon"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Upon processing any proposal the following steps are then performed:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.code,{children:"min_proposal_deposit"})," base units are transferred from the signer's\naccount to the governance service's ",(0,o.jsx)(n.em,{children:"proposal deposit account"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"The signer's account is saved."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"A new proposal is created and assigned an identifier."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The corresponding ",(0,o.jsx)(n.code,{children:"ProposalSubmittedEvent"})," is emitted with the following\nstructure:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The corresponding ",(0,o.jsx)(n.code,{children:"staking.TransferEvent"})," is emitted, indicating transfer from\nthe submitter's account to the ",(0,o.jsx)(n.em,{children:"proposal deposit account"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h4,{id:"vote",children:"Vote"}),"\n",(0,o.jsx)(n.p,{children:"Voting for submitted consensus layer governance proposals."}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"governance.CastVote\n"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.strong,{children:"Body:"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.p,{children:"Upon processing a vote the following steps are performed:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The entity descriptor corresponding to the transaction signer is fetched. In\ncase no such entity exists, the method call fails with ",(0,o.jsx)(n.code,{children:"ErrNotEligible"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"ErrNotEligible"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The proposal identified by ",(0,o.jsx)(n.code,{children:"id"})," is loaded. If the proposal does not exist,\nthe method call fails with ",(0,o.jsx)(n.code,{children:"ErrNoSuchProposal"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["If the proposal's state is not ",(0,o.jsx)(n.code,{children:"StateActive"}),", the method call fails with\n",(0,o.jsx)(n.code,{children:"ErrVotingIsClosed"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"The vote is added to the list of votes. If the vote already exists, it is\noverwritten."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The corresponding ",(0,o.jsx)(n.code,{children:"VoteEvent"})," is emitted with the following structure:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"queries",children:"Queries"}),"\n",(0,o.jsx)(n.p,{children:"This proposal introduces the following query methods in the governance module:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n",(0,o.jsx)(n.h3,{id:"tallying",children:"Tallying"}),"\n",(0,o.jsxs)(n.p,{children:["In ",(0,o.jsx)(n.code,{children:"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:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"A mapping of current validator entity addresses to their respective active\nescrow balances is prepared."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["A results mapping from ",(0,o.jsx)(n.code,{children:"Vote"})," to number of votes is initialized in the\nproposal's ",(0,o.jsx)(n.code,{children:"results"})," field."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"invalid_votes"})," field is incremented for each such vote."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In case the percentage of votes relative to the total voting power is less\nthan ",(0,o.jsx)(n.code,{children:"quorum"}),", the proposal is rejected."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In case the percentage of ",(0,o.jsx)(n.code,{children:"VoteYes"})," votes relative to all valid votes is less\nthan ",(0,o.jsx)(n.code,{children:"threshold"}),", the proposal is rejected."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"Otherwise the proposal is passed."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The proposal's status is changed to either ",(0,o.jsx)(n.code,{children:"StatePassed"})," or ",(0,o.jsx)(n.code,{children:"StateRejected"}),"\nand the proposal is saved."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsx)(n.p,{children:"The proposal is removed from the list of active proposals."}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["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.jsx)(n.code,{children:"StateFailed"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["The corresponding ",(0,o.jsx)(n.code,{children:"ProposalFinalizedEvent"})," is emitted with the following\nstructure:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'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'})}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In case the proposal has been passed, the deposit is transferred back to the\nproposal submitter and a corresponding ",(0,o.jsx)(n.code,{children:"staking.TransferEvent"})," is emitted,\nindicating transfer from the ",(0,o.jsx)(n.em,{children:"proposal deposit account"})," to the submitter's\naccount."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In case the proposal has been rejected, the deposit is transferred to the\ncommon pool and a corresponding ",(0,o.jsx)(n.code,{children:"staking.TransferEvent"})," is emitted,\nindicating transfer from the ",(0,o.jsx)(n.em,{children:"proposal deposit account"})," to the common pool\naccount."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"proposal-content-execution",children:"Proposal Content Execution"}),"\n",(0,o.jsxs)(n.p,{children:["After any proposal is successfully executed the corresponding\n",(0,o.jsx)(n.code,{children:"ProposalExecutedEvent"})," is emitted with the following structure:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-golang",children:'type ProposalExecutedEvent struct {\n // ID is the unique identifier of a proposal.\n ID uint64 `json:"id"`\n}\n'})}),"\n",(0,o.jsx)(n.h4,{id:"upgrade-proposal",children:"Upgrade Proposal"}),"\n",(0,o.jsxs)(n.p,{children:["The set of pending upgrades is checked to make sure that no upgrades are\ncurrently pending within ",(0,o.jsx)(n.code,{children:"upgrade_min_epoch_diff"})," of the upgrade descriptor's\n",(0,o.jsx)(n.code,{children:"epoch"})," field. If there is such an existing pending upgrade the upgrade proposal\nexecution fails."]}),"\n",(0,o.jsxs)(n.p,{children:["When an upgrade proposal is executed, a new entry is added to the list of\npending upgrades using ",(0,o.jsx)(n.code,{children:"epoch"})," as ",(0,o.jsx)(n.code,{children:""}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["On each epoch transition (as part of ",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsx)(n.h4,{id:"cancel-upgrade-proposal",children:"Cancel Upgrade Proposal"}),"\n",(0,o.jsxs)(n.p,{children:["When a cancel upgrade proposal is executed, the proposal identified by\n",(0,o.jsx)(n.code,{children:"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."]}),"\n",(0,o.jsx)(n.h3,{id:"consensus-parameters",children:"Consensus Parameters"}),"\n",(0,o.jsx)(n.p,{children:"This proposal introduces the following new consensus parameters in the\ngovernance module:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"gas_costs"})," (transaction.Costs) are the governance transaction gas costs."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"min_proposal_deposit"})," (base units) specifies the number of base units that\nare deposited when creating a new proposal."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"voting_period"})," (epochs) specifies the number of epochs after which the voting\nfor a proposal is closed and the votes are tallied."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"threshold"})," (uint8: [0,100]) specifies the minimum percentage of ",(0,o.jsx)(n.code,{children:"VoteYes"}),"\nvotes in order for a proposal to be accepted."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"The following parameter sanity checks are introduced:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Product of ",(0,o.jsx)(n.code,{children:"quorum"})," and ",(0,o.jsx)(n.code,{children:"threshold"})," must be 2/3+."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.code,{children:"voting_period"})," must be less than ",(0,o.jsx)(n.code,{children:"upgrade_min_epoch_diff"})," and\n",(0,o.jsx)(n.code,{children:"upgrade_cancel_min_epoch_diff"}),"."]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"The consensus layer can coordinate on upgrades."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"})]})}function p(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>a});var o=s(6540);const t={},r=o.createContext(t);function i(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d089813a.f2be1fb1.js b/assets/js/d089813a.f2be1fb1.js new file mode 100644 index 0000000000..3f4a2c2f53 --- /dev/null +++ b/assets/js/d089813a.f2be1fb1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8599],{8083:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var t=n(4848),r=n(8453);const i={},o="Runtime Messages",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/runtime/messages.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Runtime IDs",permalink:"/core/runtime/identifiers"},next:{title:"Oasis Node",permalink:"/core/oasis-node"}},a={},d=[{value:"Supported Messages",id:"supported-messages",level:2},{value:"Staking Method Call",id:"staking-method-call",level:3},{value:"Limits",id:"limits",level:2}];function l(e){const s={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"runtime-messages",children:"Runtime Messages"}),"\n",(0,t.jsxs)(s.p,{children:["In order to enable runtimes to perform actions in the consensus layer on their\nbehalf, they can emit ",(0,t.jsx)(s.em,{children:"messages"})," in each round."]}),"\n",(0,t.jsx)(s.h2,{id:"supported-messages",children:"Supported Messages"}),"\n",(0,t.jsx)(s.p,{children:"The following sections describe the methods supported by the consensus roothash\nservice."}),"\n",(0,t.jsx)(s.h3,{id:"staking-method-call",children:"Staking Method Call"}),"\n",(0,t.jsxs)(s.p,{children:["The staking method call message enables a runtime to call one of the supported\n",(0,t.jsx)(s.a,{href:"/core/consensus/services/staking#methods",children:"staking service methods"}),"."]}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.strong,{children:"Field name:"})}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{children:"staking\n"})}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.strong,{children:"Body:"})}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-golang",children:'type StakingMessage struct {\n cbor.Versioned\n\n Transfer *staking.Transfer `json:"transfer,omitempty"`\n Withdraw *staking.Withdraw `json:"withdraw,omitempty"`\n}\n'})}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.strong,{children:"Fields:"})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"v"})," must be set to ",(0,t.jsx)(s.code,{children:"0"}),"."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"transfer"})," indicates that the ",(0,t.jsxs)(s.a,{href:"/core/consensus/services/staking#transfer",children:[(0,t.jsx)(s.code,{children:"staking.Transfer"})," method"]})," should be executed."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"withdraw"})," indicates that the ",(0,t.jsxs)(s.a,{href:"/core/consensus/services/staking#withdraw",children:[(0,t.jsx)(s.code,{children:"staking.Withdraw"})," method"]})," should be executed."]}),"\n"]}),"\n",(0,t.jsx)(s.p,{children:"Exactly one of the supported method fields needs to be non-nil, otherwise the\nmessage is considered malformed."}),"\n",(0,t.jsx)(s.h2,{id:"limits",children:"Limits"}),"\n",(0,t.jsxs)(s.p,{children:["The maximum number of runtime messages that can be emitted in a single round is\nlimited by the ",(0,t.jsx)(s.code,{children:"executor.max_messages"})," option in the runtime descriptor. Its\nupper bound is the ",(0,t.jsxs)(s.a,{href:"/core/consensus/services/roothash#consensus-parameters",children:[(0,t.jsx)(s.code,{children:"max_messages"})," consensus parameter"]})," of the roothash service."]})]})}function h(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>o,x:()=>c});var t=n(6540);const r={},i=t.createContext(r);function o(e){const s=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),t.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d18a0ae3.9c6b09e6.js b/assets/js/d18a0ae3.9c6b09e6.js new file mode 100644 index 0000000000..be65f01b07 --- /dev/null +++ b/assets/js/d18a0ae3.9c6b09e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6650],{4366:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>c,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var i=s(4848),t=s(8453);const a={},r="Handling Network Upgrades",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/maintenance/handling-network-upgrades.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},d={},l=[{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}];function h(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"handling-network-upgrades",children:"Handling Network Upgrades"}),"\n",(0,i.jsxs)(n.p,{children:["Changes between the major consensus network versions are backward and forward\nbreaking. You have to always run ",(0,i.jsx)(n.strong,{children:"a specific version of the Oasis Core to\nfetch and validate the blocks matching the specific consensus network version"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There are two kinds of consensus network upgrades that can occur:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.em,{children:"Seamless upgrade"}),": on-chain upgrade without resetting the consensus state or\nchanging the genesis document (e.g. ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#2022-04-04-upgrade",children:"Testnet upgrade 2022-04-04"}),", ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#2021-08-31-upgrade",children:"Mainnet\nupgrade 2021-08-31"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.em,{children:"Dump & restore upgrade"}),": requires wiping state and starting the upgraded\nnetwork from a fresh genesis document (e.g. ",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log#damask-upgrade",children:"Mainnet upgrade 2022-04-11\n(Damask)"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/upgrade-log#2022-03-03-upgrade",children:"Testnet upgrade 2022-03-03"}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The specific Oasis Core version requirements also impact the way how you\n",(0,i.jsx)(n.strong,{children:"initially sync your node with the network"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"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."}),"\n",(0,i.jsx)(n.li,{children:"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)."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For example, at time of writing this guide in order to sync your node from\nscratch on the ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet Network Parameters"})," you needed to do the\nfollowing:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Download the genesis document and run Oasis Core 22.0.x which synced\nblocks from epoch 14209 through (excluding) upgrade epoch 15056."}),"\n",(0,i.jsx)(n.li,{children:"Wait until the node automatically stopped, then upgrade to Oasis Core\n22.2.x which synced the blocks from epoch 15056 onwards."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["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\nNetwork Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"reaching-upgrade-epoch",children:"Reaching Upgrade Epoch"}),"\n",(0,i.jsxs)(n.p,{children:["Once a ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#governance-cast-vote",children:"governance proposal"})," is accepted the node will automatically stop when\nreaching the ",(0,i.jsx)(n.strong,{children:"upgrade epoch"})," specified in the proposal. The node will\nwrite something like this in the log:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{"caller":"mux.go:426","level":"debug","module":"abci-mux","msg":"dispatching halt hooks for upgrade","ts":"2022-05-06T13:11:41.721994647Z"}\n'})}),"\n",(0,i.jsx)(n.p,{children:"and on the error output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"panic: upgrade: reached upgrade epoch\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The state of the network at the upgrade epoch height will be automatically\nexported into a genesis file located in\n",(0,i.jsx)(n.code,{children:"/exports/genesis--at-.json"}),",\nwhere ",(0,i.jsx)(n.code,{children:"CHAIN_ID"})," is the chain ID of the network and ",(0,i.jsx)(n.code,{children:"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."]}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"While waiting for the network upgrade epoch, you can check the current height\nand epoch by running:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})}),(0,i.jsxs)(n.p,{children:["and observe the value of the ",(0,i.jsx)(n.code,{children:"consensus.latest_height"})," and\n",(0,i.jsx)(n.code,{children:"consensus.latest_epoch"})," fields respectively."]})]}),"\n",(0,i.jsxs)(n.p,{children:["Once the upgrade epoch is reached, follow the instructions in the corresponding\n",(0,i.jsx)(n.a,{href:"/node/mainnet/upgrade-log",children:"upgrade log"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"preparing-new-genesis-file-and-wiping-state",children:"Preparing New Genesis File and Wiping State"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"patching-dumped-state",children:"Patching Dumped State"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.code,{children:"genesis_dump.json"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node debug fix-genesis --genesis.file genesis--at-.json --genesis.new_file genesis_dump.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Other parts of the genesis need to be updated manually, as described in each\nupgrade's ",(0,i.jsx)(n.em,{children:"Proposed State Changes"})," section (e.g. ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/damask-upgrade#proposed-state-changes",children:"Damask upgrade's Proposed\nState Changes"}),", ",(0,i.jsx)(n.a,{href:"/node/mainnet/previous-upgrades/cobalt-upgrade#proposed-state-changes",children:"Cobalt upgrade's Proposed State Changes"}),")."]}),"\n",(0,i.jsx)(n.h3,{id:"verify-genesis",children:"Download and Verify the Provided Genesis File"}),"\n",(0,i.jsxs)(n.p,{children:["In addition, download the new genesis file linked in the Network Parameters\npage (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),") and save it as ",(0,i.jsx)(n.code,{children:"/node/etc/genesis.json"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Compare the dumped state with the downloaded genesis file:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"diff --unified=3 genesis_dump.json genesis.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you obtain the same result, then you have successfully verified the provided\ngenesis file!"}),"\n",(0,i.jsx)(n.h4,{id:"example-diff-for-mainnet-beta-to-mainnet-network-upgrade",children:"Example diff for Mainnet Beta to Mainnet network upgrade"}),"\n",(0,i.jsxs)(n.p,{children:["Let's look at what ",(0,i.jsx)(n.code,{children:"diff"})," returned before performing manual changes to the\ngenesis file for the Mainnet network upgrade:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-diff",children:'--- 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'})}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"Let's break down the diff and explain what has changed."}),"\n",(0,i.jsx)(n.p,{children:"The following genesis file fields will always change on a network upgrade:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"chain_id"}),": A unique ID of the network. Mainnet upgrades follow a pattern ",(0,i.jsx)(n.code,{children:"oasis-1"}),", ",(0,i.jsx)(n.code,{children:"oasis-2"}),", ..."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"genesis_time"}),": Time from which the genesis file is valid."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"halt_epoch"}),": The epoch when the node will stop functioning. We set this to\nintentionally force an upgrade."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The following fields were a particular change in this upgrade:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"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,i.jsx)(n.a,{href:"/general/oasis-network/token-metrics-and-distribution",children:"Token\nMetrics and Distribution"})," doc."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"staking.params.disable_transfers"}),": This field was removed to enable token\ntransfers."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"staking.common_pool"}),": This field represents the Common Pool. Its balance was\nincreased by 450M ROSE to fund increased staking rewards."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"staking.ledger.oasis1qrad7s7nqm4gvyzr8yt2rdk0ref489rn3vn400d6"}),": This field\ncorresponds to the Community and Ecosystem Wallet. Its ",(0,i.jsx)(n.code,{children:"general.balance"})," was\nreduced by 450M ROSE and transferred to the Common Pool to fund increased\nstaking rewards."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"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,i.jsx)(n.em,{children:"\u201d"}),(0,i.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,i.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,i.jsx)(n.em,{children:"\u201d [submitted by Oasis Community Member Daniyar Borangaziyev]."})]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/node/genesis-doc#parameters",children:"Genesis Document"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"wiping-state",children:"Wiping State"}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsxs)(n.p,{children:["We do not suggest that you wipe ",(0,i.jsx)(n.em,{children:"all"})," state. You might lose node identities and\nkeys if you do it this way."]})}),"\n",(0,i.jsxs)(n.p,{children:["The process is described in the\n",(0,i.jsx)(n.a,{href:"/node/run-your-node/maintenance/wiping-node-state#state-wipe-and-keep-node-identity",children:"Wiping Node State"}),"\ndocument."]}),"\n",(0,i.jsx)(n.h2,{id:"updating-paratimes",children:"Updating ParaTimes"}),"\n",(0,i.jsxs)(n.p,{children:["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 ",(0,i.jsx)(n.a,{href:"/general/manage-tokens/cli/network#show-paratimes",children:(0,i.jsx)(n.code,{children:"oasis network show paratimes"})})," command below queries the\nregistry and extracts the version information for the Paratime\n",(0,i.jsx)(n.code,{children:"00000000000000000000000000000000000000000000000072c8215e60d5bca7"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis network show paratimes \\| \njq 'select(.id==\"00000000000000000000000000000000000000000000000072c8215e60d5bca7\") | .deployments'\n"})}),"\n",(0,i.jsx)(n.p,{children:"At time of writing the Emerald ParaTime on Testnet has the following record:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'[\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'})}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.strong,{children:"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."]}),"\n",(0,i.jsx)(n.p,{children:"Oasis node supports configuring multiple versions of ParaTime bundles, for\nexample:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"runtime:\n paths:\n - /path/to/emerald-paratime-7.1.0-testnet.orc\n - /path/to/emerald-paratime-8.0.0-testnet.orc\n"})}),"\n",(0,i.jsx)(n.p,{children:"The node will then automatically run the correct version of the ParaTime as\nspecified in the registry."}),"\n",(0,i.jsx)(n.h2,{id:"start-your-node",children:"Start Your Node"}),"\n",(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Oasis Node"})," like this:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,i.jsx)(n.h2,{id:"clean-up",children:"Clean Up"}),"\n",(0,i.jsxs)(n.p,{children:["After you're comfortable with your node deployment, you can remove the old\nOasis Core version and the intermediate\n",(0,i.jsx)(n.code,{children:"genesis--at-.json"})," and ",(0,i.jsx)(n.code,{children:"genesis_dump.json"})," files."]})]})}function c(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>o});var i=s(6540);const t={},a=i.createContext(t);function r(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d632a858.925d9633.js b/assets/js/d632a858.925d9633.js new file mode 100644 index 0000000000..33b4428bcb --- /dev/null +++ b/assets/js/d632a858.925d9633.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[4074],{736:(t,e,o)=>{o.r(e),o.d(e,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=o(4848),n=o(8453);const s={description:"How to build your first dApp on OPL"},r="Overview",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/introduction.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},l={},d=[{value:"Getting Started",id:"getting-started",level:2}];function c(t){const e={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,n.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"overview",children:"Overview"}),"\n",(0,i.jsxs)(e.p,{children:["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,i.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Secret_ballot",children:"secret ballot"}),"\ndApp that can only be built with the Oasis Privacy Layer."]}),"\n",(0,i.jsxs)(e.p,{children:["Why is this important? ",(0,i.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Secret_ballot",children:"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."]}),"\n",(0,i.jsx)(e.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,i.jsx)(e.p,{children:"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."}),"\n",(0,i.jsx)(e.p,{children:"By the end of this tutorial, we will have:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["written smart contracts using the OPL ",(0,i.jsx)(e.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/OPL.sol",children:"library"})]}),"\n",(0,i.jsxs)(e.li,{children:["used ",(0,i.jsx)(e.a,{href:"https://hardhat.org/docs",children:"Hardhat"})," development environment for OPL"]}),"\n",(0,i.jsxs)(e.li,{children:["used ",(0,i.jsx)(e.a,{href:"https://github.com/wighawag/hardhat-deploy",children:"Hardhat Deploy"})," to deploy\nsmarts contracts to a testnet."]}),"\n",(0,i.jsxs)(e.li,{children:["used ",(0,i.jsx)(e.a,{href:"https://www.pinata.cloud",children:"Pinata"}),"\nto store simple JSON data. Not everything has to go on a blockchain."]}),"\n",(0,i.jsxs)(e.li,{children:["used ",(0,i.jsx)(e.a,{href:"https://im-docs.celer.network/developer/celer-im-overview",children:"Celer"})," to\npass messages cross multiple chains"]}),"\n",(0,i.jsxs)(e.li,{children:["built a simple ",(0,i.jsx)(e.a,{href:"https://vuejs.org/guide/introduction.html",children:"Vue.JS"}),"\napp to interact with our dApp through ",(0,i.jsx)(e.a,{href:"https://docs.metamask.io/wallet",children:"MetaMask"}),"."]}),"\n"]})]})}function h(t={}){const{wrapper:e}={...(0,n.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(c,{...t})}):c(t)}},8453:(t,e,o)=>{o.d(e,{R:()=>r,x:()=>a});var i=o(6540);const n={},s=i.createContext(n);function r(t){const e=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(n):t.components||n:r(t.components),i.createElement(s.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/d941f4da.13e80170.js b/assets/js/d941f4da.13e80170.js new file mode 100644 index 0000000000..a3be949395 --- /dev/null +++ b/assets/js/d941f4da.13e80170.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7984],{6601:(e,s,r)=>{r.r(s),r.d(s,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>h});var t=r(4848),n=r(8453);const a={},i="Release Process",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/release-process.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Processes",permalink:"/core/processes"},next:{title:"Versioning",permalink:"/core/versioning"}},l={},h=[{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}];function c(e){const s={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,n.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"release-process",children:"Release Process"}),"\n",(0,t.jsx)(s.p,{children:"The following steps should be followed when preparing a release."}),"\n",(0,t.jsx)(s.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(s.p,{children:"Our release process relies on some tooling that needs to be available on a\nmaintainer's system:"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://www.python.org/",children:"Python"})," 3.6+."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/towncrier",children:"Oasis' towncrier fork"}),"."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.a,{href:"https://github.com/lgiordani/punch",children:"Punch"})," 2.0.x."]}),"\n"]}),"\n",(0,t.jsxs)(s.p,{children:["Most systems should already have ",(0,t.jsx)(s.a,{href:"https://www.python.org/",children:"Python"})," pre-installed."]}),"\n",(0,t.jsxs)(s.p,{children:["To install ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/towncrier",children:"Oasis' towncrier fork"})," and ",(0,t.jsx)(s.a,{href:"https://github.com/lgiordani/punch",children:"Punch"}),", use ",(0,t.jsx)(s.a,{href:"https://pip.pypa.io/en/stable/",children:"pip"}),":"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"pip3 install --upgrade \\\n https://github.com/oasisprotocol/towncrier/archive/oasis-master.tar.gz \\\n punch.py~=2.0.0\n"})}),"\n",(0,t.jsxs)(s.p,{children:["You might want to install the packages to a ",(0,t.jsx)(s.a,{href:"https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments",children:"Python virtual environment"})," or\nvia so-called ",(0,t.jsx)(s.a,{href:"https://pip.pypa.io/en/stable/user_guide/#user-installs",children:"User install"})," (i.e. isolated to the current user)."]}),"\n",(0,t.jsx)(s.h2,{id:"tooling",children:"Tooling"}),"\n",(0,t.jsxs)(s.p,{children:["Our ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Make_(software)",children:"Make"})," tooling has some targets that automate parts of the release process\nand try to make it less error-prone:"]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"changelog"}),": Bumps project's version with the ",(0,t.jsx)(s.a,{href:"https://github.com/lgiordani/punch",children:"Punch"})," utility and assembles\nthe ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md",children:"Change Log"})," from the ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md",children:"Change Log Fragments"})," using the\n",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/towncrier",children:"towncrier"})," utility."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"release-tag"}),": After performing a bunch of sanity checks, it tags the git\norigin remote's release branch's ",(0,t.jsx)(s.code,{children:"HEAD"})," with the ",(0,t.jsx)(s.code,{children:"v"})," tag and\npushes it to the remote."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"release-stable-branch"}),": Creates and pushes a stable branch for the current\nrelease."]}),"\n"]}),"\n",(0,t.jsxs)(s.p,{children:["Note that all above targets depend on the ",(0,t.jsx)(s.code,{children:"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."]}),"\n",(0,t.jsxs)(s.p,{children:["The version of the Oasis Core's next release is computed automatically using\nthe ",(0,t.jsx)(s.a,{href:"https://github.com/lgiordani/punch",children:"Punch"})," utility according to the project's ",(0,t.jsx)(s.a,{href:"/core/versioning",children:"Versioning"})," scheme."]}),"\n",(0,t.jsxs)(s.p,{children:["The ",(0,t.jsx)(s.code,{children:"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."]}),"\n",(0,t.jsx)(s.p,{children:"To customize the release process, one can set the following environment\nvariables:"}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"GIT_ORIGIN_REMOTE"})," (default: ",(0,t.jsx)(s.code,{children:"origin"}),"): Name of the git remote pointing to\nthe canonical upstream git repository."]}),"\n",(0,t.jsxs)(s.li,{children:[(0,t.jsx)(s.code,{children:"RELEASE_BRANCH"})," (default: ",(0,t.jsx)(s.code,{children:"master"}),"): Name of the branch where to tag the next\nrelease."]}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"preparing-a-regular-release",children:"Preparing a Regular Release"}),"\n",(0,t.jsx)(s.h3,{id:"bump-protocol-versions",children:"Bump Protocol Versions"}),"\n",(0,t.jsxs)(s.p,{children:["Before a release, make sure that the proper protocol versions were bumped\ncorrectly (see ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go",children:(0,t.jsx)(s.code,{children:"go/common/version/version.go"})}),"). If not, make a pull request\nthat bumps the respective version(s) before proceeding with the release process."]}),"\n",(0,t.jsx)(s.h3,{id:"prepare-the-change-log",children:"Prepare the Change Log"}),"\n",(0,t.jsxs)(s.p,{children:["Before a release, all ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md",children:"Change Log fragments"})," should be assembled into a new\nsection of the ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md",children:"Change Log"})," using the ",(0,t.jsx)(s.code,{children:"changelog"})," ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Make_(software)",children:"Make"})," target."]}),"\n",(0,t.jsxs)(s.p,{children:["Create a new branch, e.g. ",(0,t.jsx)(s.code,{children:"changelog"}),", and then run ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Make_(software)",children:"Make"}),":"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"git checkout -b changelog\nmake changelog\n"})}),"\n",(0,t.jsx)(s.p,{children:"Review the staged changes and make appropriate adjustment to the Change Log\n(e.g. re-order entries, make formatting/spelling fixes, ...)."}),"\n",(0,t.jsxs)(s.p,{children:["Replace the ",(0,t.jsx)(s.code,{children:""})," strings in the protocol versions table just below the\nnext version's heading with appropriate protocol versions as defined in\n",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go",children:"go/common/version/version.go"})," file."]}),"\n",(0,t.jsx)(s.p,{children:"For example:"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{style:{textAlign:"left"},children:"Protocol"}),(0,t.jsx)(s.th,{style:{textAlign:"center"},children:"Version"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{style:{textAlign:"left"},children:"Consensus"}),(0,t.jsx)(s.td,{style:{textAlign:"center"},children:"4.0.0"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{style:{textAlign:"left"},children:"Runtime Host"}),(0,t.jsx)(s.td,{style:{textAlign:"center"},children:"2.0.0"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{style:{textAlign:"left"},children:"Runtime Committee"}),(0,t.jsx)(s.td,{style:{textAlign:"center"},children:"2.0.0"})]})]})]}),"\n",(0,t.jsx)(s.p,{children:"After you are content with the changes, commit them, push them to the origin\nand make a pull request."}),"\n",(0,t.jsx)(s.p,{children:"Once the pull request had been reviewed and merged, proceed to the next step."}),"\n",(0,t.jsx)(s.h3,{id:"tag-next-release",children:"Tag Next Release"}),"\n",(0,t.jsxs)(s.p,{children:["To create a signed git tag from the latest commit in origin remote's ",(0,t.jsx)(s.code,{children:"master"}),"\nbranch, use:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"make release-tag\n"})}),"\n",(0,t.jsx)(s.p,{children:"This command will perform a bunch of sanity checks to prevent common errors\nwhile tagging the next release."}),"\n",(0,t.jsx)(s.p,{children:"After those checks have passed, it will ask for confirmation before proceeding."}),"\n",(0,t.jsx)(s.h3,{id:"ensure-github-release-was-published",children:"Ensure GitHub Release Was Published"}),"\n",(0,t.jsxs)(s.p,{children:["After the tag with the next release is pushed to the ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"canonical git repository"}),",\nthe GitHub Actions ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/.github/workflows/release.yml",children:"Release manager workflow"})," is triggered which uses the\n",(0,t.jsx)(s.a,{href:"https://goreleaser.com/",children:"GoReleaser"})," tool to automatically build the binaries, prepare archives and\nchecksums, and publish a GitHub Release that accompanies the versioned git tag."]}),"\n",(0,t.jsxs)(s.p,{children:["Browse to ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases",children:"Oasis Core's releases page"})," and make sure the new release is properly\npublished."]}),"\n",(0,t.jsxs)(s.h3,{id:"create-stableyyminorx-branch",children:["Create ",(0,t.jsx)(s.code,{children:"stable/YY.MINOR.x"})," Branch"]}),"\n",(0,t.jsx)(s.p,{children:"To prepare a new stable branch from the new release tag and push it to the\norigin remote, use:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"make release-stable-branch\n"})}),"\n",(0,t.jsx)(s.p,{children:"This command will perform sanity checks to prevent common errors."}),"\n",(0,t.jsx)(s.p,{children:"After those checks have passed, it will ask for confirmation before proceeding."}),"\n",(0,t.jsx)(s.h2,{id:"preparing-a-bugfixstable-release",children:"Preparing a Bugfix/Stable Release"}),"\n",(0,t.jsxs)(s.p,{children:["As mentioned in the ",(0,t.jsx)(s.a,{href:"/core/versioning",children:"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."]}),"\n",(0,t.jsxs)(s.p,{children:["Set the ",(0,t.jsx)(s.code,{children:"RELEASE_BRANCH"})," environment variable to the name of the stable branch\nof the ",(0,t.jsx)(s.code,{children:"YY.MINOR"})," release you want to back-port the changes to, e.g.\n",(0,t.jsx)(s.code,{children:"stable/21.2.x"}),", and export it:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:'export RELEASE_BRANCH="stable/21.2.x"\n'})}),"\n",(0,t.jsx)(s.h3,{id:"back-port-changes",children:"Back-port Changes"}),"\n",(0,t.jsxs)(s.p,{children:["Create a new branch, e.g. ",(0,t.jsx)(s.code,{children:"backport-foo-${RELEASE_BRANCH#stable/}"}),", from the\n",(0,t.jsx)(s.code,{children:"${RELEASE_BRANCH}"})," branch:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"git checkout -b backport-foo-${RELEASE_BRANCH#stable/} ${RELEASE_BRANCH}\n"})}),"\n",(0,t.jsxs)(s.p,{children:["After back-porting all the desired changes, push it to the origin and make a\npull request against the ",(0,t.jsx)(s.code,{children:"${RELEASE_BRANCH}"})," branch."]}),"\n",(0,t.jsx)(s.h3,{id:"prepare-change-log-for-bugfixstable-release",children:"Prepare Change Log for Bugfix/Stable Release"}),"\n",(0,t.jsxs)(s.p,{children:["As with a regular release, the back-ported changes should include the\ncorresponding ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/.changelog/README.md",children:"Change Log Fragments"})," that need to be assembled into a new\nsection of the ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/CHANGELOG.md",children:"Change Log"})," using the ",(0,t.jsx)(s.code,{children:"changelog"})," ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Make_(software)",children:"Make"})," target."]}),"\n",(0,t.jsxs)(s.p,{children:["Create a new branch, e.g. ",(0,t.jsx)(s.code,{children:"changelog-${RELEASE_BRANCH#stable/}"}),", from the\n",(0,t.jsx)(s.code,{children:"${RELEASE_BRANCH}"})," branch:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"git checkout -b changelog-${RELEASE_BRANCH#stable/} ${RELEASE_BRANCH}\n"})}),"\n",(0,t.jsxs)(s.p,{children:["Then run ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Make_(software)",children:"Make"}),"'s ",(0,t.jsx)(s.code,{children:"changelog"})," target:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"make changelog\n"})}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsxs)(s.em,{children:["NOTE: The ",(0,t.jsx)(s.code,{children:"changelog"})," Make target will bump the ",(0,t.jsx)(s.code,{children:"MICRO"})," part of the version\nautomatically."]})}),"\n",(0,t.jsxs)(s.p,{children:["Replace the ",(0,t.jsx)(s.code,{children:""})," strings in the protocol versions table just below the\nnext version's heading with appropriate protocol versions as defined in\n",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/common/version/version.go",children:"go/common/version/version.go"})," file."]}),"\n",(0,t.jsxs)(s.p,{children:["After reviewing the staged changes, commit them, push the changes to the origin\nand make a pull request against the ",(0,t.jsx)(s.code,{children:"${RELEASE_BRANCH}"})," branch."]}),"\n",(0,t.jsx)(s.p,{children:"Once the pull request had been reviewed and merged, proceed to the next step."}),"\n",(0,t.jsx)(s.h3,{id:"tag-bugfixstable-release",children:"Tag Bugfix/Stable Release"}),"\n",(0,t.jsxs)(s.p,{children:["As with a regular release, create a signed git tag from the latest commit in\norigin remote's release branch by running the ",(0,t.jsx)(s.code,{children:"release-tag"})," Make target:"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"make release-tag\n"})}),"\n",(0,t.jsx)(s.p,{children:"After the sanity checks have passed, it will ask for confirmation before\nproceeding."}),"\n",(0,t.jsx)(s.h3,{id:"ensure-github-release-for-bugfixstable-release-was-published",children:"Ensure GitHub Release for Bugfix/Stable Release Was Published"}),"\n",(0,t.jsxs)(s.p,{children:["Similar to a regular release, after the tag with the next release is pushed to\nthe ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"canonical git repository"}),", the GitHub Actions ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/.github/workflows/release.yml",children:"Release manager workflow"})," is\ntriggered which uses the ",(0,t.jsx)(s.a,{href:"https://goreleaser.com/",children:"GoReleaser"})," tool to automatically build a new release."]}),"\n",(0,t.jsxs)(s.p,{children:["Browse to ",(0,t.jsx)(s.a,{href:"https://github.com/oasisprotocol/oasis-core/releases",children:"Oasis Core's releases page"})," and make sure the new bugfix/stable\nrelease is properly published."]})]})}function d(e={}){const{wrapper:s}={...(0,n.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,s,r)=>{r.d(s,{R:()=>i,x:()=>o});var t=r(6540);const n={},a=t.createContext(n);function i(e){const s=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function o(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),t.createElement(a.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d95a60a6.4e1a4f98.js b/assets/js/d95a60a6.4e1a4f98.js new file mode 100644 index 0000000000..450b0ae98c --- /dev/null +++ b/assets/js/d95a60a6.4e1a4f98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[443],{9159:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var t=s(4848),i=s(8453);const a={},r="Upgrade to Mainnet",o={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/mainnet/previous-upgrades/mainnet-upgrade.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Cobalt Upgrade",permalink:"/node/mainnet/previous-upgrades/cobalt-upgrade"},next:{title:"Upgrade Log",permalink:"/node/mainnet/upgrade-log"}},d={},l=[{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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",input:"input",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"upgrade-to-mainnet",children:"Upgrade to Mainnet"}),"\n",(0,t.jsxs)(n.p,{children:["This document provides an overview of the proposed criteria and changes to upgrade from Mainnet Beta to Mainnet. This has been ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/community/discussions/1",children:"reviewed and approved by community members and validators of the Oasis Network"})," and is being reproduced and summarized here for easy access."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsx)(n.p,{children:"As proposed by the community, the upgrade from Mainnet Beta to Mainnet will kick off on November 18, 2020 at 16:00 UTC."})}),"\n",(0,t.jsx)(n.h2,{id:"criteria-for-mainnet",children:"Criteria for Mainnet"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{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."]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","Beta network runs successfully for at least 10 days."]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{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."]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","At least 50 validators run on the Network.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.em,{children:"Throughout Mainnet Beta there have been between 75 and 77 active validators on the network."})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","There are NO Oasis Protocol Foundation or Oasis Labs nodes serving as validators."]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","At least one block explorer exists to track network stability, transactions, and validator activity.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.em,{children:"There is much more. See"})," ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/docs/blob/0aeeb93a6e7c9001925923661e4eb3340ec4fb4b/docs/general/community-resources/community-made-resources.md#block-explorers--validator-leaderboards-block-explorers-validator-leaderboards",children:(0,t.jsx)(n.em,{children:"Block Explorers & Validator Leaderboards"})})," ",(0,t.jsx)(n.em,{children:"part of our docs."})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","At least one qualified custodian supports the native ROSE token.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.em,{children:"Currently, Anchorage and Finoa support the ROSE token. See"})," ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/holding-rose-tokens/custody-providers",children:(0,t.jsx)(n.em,{children:"Custody Providers"})})," ",(0,t.jsx)(n.em,{children:"part of our docs."})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",checked:!0,disabled:!0})," ","At least one web wallet or hardware wallet supports native ROSE token.","\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.em,{children:"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,t.jsx)(n.a,{href:"../../../general/manage-tokens/holding-rose-tokens/",children:(0,t.jsx)(n.em,{children:"3rd Party Wallets"})})," ",(0,t.jsx)(n.em,{children:"and"})," ",(0,t.jsx)(n.a,{href:"../../../general/manage-tokens/oasis-wallets",children:(0,t.jsx)(n.em,{children:"Oasis Wallets"})})," ",(0,t.jsx)(n.em,{children:"parts of our docs."})]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"mechanics-of-upgrading-to-mainnet",children:"Mechanics of Upgrading to Mainnet"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"proposed-changes-from-mainnet-beta-to-mainnet",children:"Proposed Changes From Mainnet Beta to Mainnet"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"/general/oasis-network/token-metrics-and-distribution",children:"Token Metrics and Distribution"})," doc)."]}),"\n",(0,t.jsxs)(n.admonition,{type:"info",children:[(0,t.jsx)(n.p,{children:"The following parts of the genesis file will be updated:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"height"})})," will remain the same as at the time of the snapshot of Mainnet Beta, i.e. ",(0,t.jsx)(n.code,{children:"702000"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"genesis_time"})})," will be set to ",(0,t.jsx)(n.code,{children:"2020-11-18T16:00:00Z"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"chain_id"})})," will be set to ",(0,t.jsx)(n.code,{children:"oasis-1"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"halt_epoch"})})," will be set to ",(0,t.jsx)(n.code,{children:"9940"})," (approximately 1 year from Mainnet launch)."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"staking.params.disable_transfers"})})," will be omitted (or set to",(0,t.jsx)(n.code,{children:"false)"}),"to enable transfers."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"staking.params.reward_schedule"})})," will be updated to reflect the updated reward schedule as mentioned above."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"staking.common_pool"})})," will be increased by 450M ROSE to fund increased staking rewards."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"staking.ledger.oasis1qrad7s7nqm4gvyzr8yt2rdk0ref489rn3vn400d6"})}),", which corresponds to the Community and Ecosystem Wallet, will have its ",(0,t.jsx)(n.code,{children:"general.balance"})," reduced by 450M ROSE to ",(0,t.jsx)(n.code,{children:"1183038701000000000"})," and transferred to the Common Pool to fund increased staking rewards."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:(0,t.jsx)(n.code,{children:"extra_data"})})," will be set back to the value in the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/mainnet-artifacts/releases/download/2020-10-01/genesis.json",children:"Mainnet Beta genesis file"})," to include the Oasis network's genesis quote: ",(0,t.jsx)(n.em,{children:"\u201d"}),(0,t.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F",children:(0,t.jsx)(n.em,{children:"Quis custodiet ipsos custodes?"})}),(0,t.jsx)(n.em,{children:"\u201d [submitted by Oasis Community Member Daniyar Borangaziyev]:"})]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-diff",children:' "extra_data": {\n "quote": "UXVpcyBjdXN0b2RpZXQgaXBzb3MgY3VzdG9kZXM/IFtzdWJtaXR0ZWQgYnkgT2FzaXMgQ29tbXVuaXR5IE1lbWJlciBEYW5peWFyIEJvcmFuZ2F6aXlldl0="\n }\n'})}),"\n"]}),"\n"]})]}),"\n",(0,t.jsxs)(n.p,{children:["See the updated ",(0,t.jsx)(n.a,{href:"/node/mainnet/",children:"Network Parameters"})," for the published Mainnet genesis file."]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["For more detailed instructions how to verify the provided Mainnet genesis file by comparing it to network state dump, see the ",(0,t.jsx)(n.a,{href:"/node/run-your-node/maintenance/handling-network-upgrades#example-diff-for-mainnet-beta-to-mainnet-network-upgrade",children:"Handling Network Upgrades"})," guide."]})}),"\n",(0,t.jsxs)(n.p,{children:["Mainnet will use ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/releases/tag/v20.12.2",children:(0,t.jsx)(n.strong,{children:"Oasis Core 20.12.2"})}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"mainnet-launch-support",children:"Mainnet Launch Support"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["For any additional support, please reach out via the ",(0,t.jsxs)(n.a,{href:"/get-involved/",children:[(0,t.jsx)(n.strong,{children:"#node-operators"})," channel at the Oasis Network Community server on Discord"]})," with your questions, comments, and feedback related to Mainnet."]}),"\n",(0,t.jsxs)(n.p,{children:["To follow the network, please use one of the many community block explorers including ",(0,t.jsx)(n.a,{href:"https://www.oasisscan.com/",children:"oasisscan.com"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>o});var t=s(6540);const i={},a=t.createContext(i);function r(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/db582d92.1e5791b0.js b/assets/js/db582d92.1e5791b0.js new file mode 100644 index 0000000000..bf49d433df --- /dev/null +++ b/assets/js/db582d92.1e5791b0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3729],{792:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>l});var r=i(4848),t=i(8453);const o={},s="Key Manager Node",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/keymanager-node/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},a={},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}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"key-manager-node",children:"Key Manager Node"}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["These instructions are for setting up a ",(0,r.jsx)(n.em,{children:"key manager"})," node. Key manager nodes run a special runtime that provides confidentiality to other ParaTimes. If you want to run a ",(0,r.jsx)(n.em,{children:"validator"})," node instead, see the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"instructions for running a validator node"}),". Similarly, if you want to run a ",(0,r.jsx)(n.em,{children:"ParaTime"})," node instead, see the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"instructions for running a ParaTime node"}),"."]})}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsx)(n.p,{children:"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."})}),"\n",(0,r.jsx)(n.p,{children:"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."}),"\n",(0,r.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the ",(0,r.jsx)(n.a,{href:"../prerequisites",children:"Prerequisites"})," and ",(0,r.jsx)(n.a,{href:"/node/run-your-node/non-validator-node",children:"Run a Non-validator Node"})," sections and have:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Oasis Node binary installed on your system and a dedicated non-root user that will run your Oasis Node."}),"\n",(0,r.jsxs)(n.li,{children:["The chosen top-level ",(0,r.jsx)(n.code,{children:"/node/"})," working directory prepared (feel free to name it as you wish, e.g. ",(0,r.jsx)(n.code,{children:"/srv/oasis/"}),") with:","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"etc"}),": This will store the node configuration and genesis file."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"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,r.jsx)(n.code,{children:"rwx------"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"bin"}),": This will store binaries needed by Oasis Node for running the ParaTimes."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"runtimes"}),": This will store the ParaTime bundles."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["Downloaded or compiled the correct versions of everything according to Network Parameters page (",(0,r.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,r.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),").","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The genesis file copied to ",(0,r.jsx)(n.code,{children:"/node/etc/genesis.json"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The binaries needed by Oasis Node for running the ParaTimes copied to ",(0,r.jsx)(n.code,{children:"/node/bin/"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The key manager ParaTime bundle (",(0,r.jsx)(n.code,{children:".orc"})," extension) copied to ",(0,r.jsx)(n.code,{children:"/node/runtimes/"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["Initialized a new node and updated your entity registration by following the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node#register-a-new-entity-or-update-your-entity-registration",children:"Register a New Entity or Update Your Entity Registration"})," instructions.","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The entity descriptor file copied to ",(0,r.jsx)(n.code,{children:"/node/etc/entity.json"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["Reading the rest of the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/validator-node",children:"validator node setup instructions"})," and ",(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"ParaTime node setup instructions"})," may also be useful."]})}),"\n",(0,r.jsx)(n.h3,{id:"setting-up-trusted-execution-environment-tee",children:"Setting up Trusted Execution Environment (TEE)"}),"\n",(0,r.jsxs)(n.p,{children:["The key manager ParaTime requires the use of a TEE. See the ",(0,r.jsx)(n.a,{href:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",children:"Set up trusted execution environment"})," doc for instructions on how to set it up before proceeding."]}),"\n",(0,r.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,r.jsxs)(n.p,{children:["In order to configure the node create the ",(0,r.jsx)(n.code,{children:"/node/etc/config.yml"})," file with the following content:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'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'})}),"\n",(0,r.jsxs)(n.p,{children:["Before using this configuration you should collect the following information to replace the ",(0,r.jsx)(n.code,{children:"{{ ... }}"})," variables present in the configuration file:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"{{ external_address }}"}),": The external IP you used when registering this node."]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"{{ seed_node_address }}"}),": The seed node address in the form ",(0,r.jsx)(n.code,{children:"ID@IP:port"}),".","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can find the current Oasis Seed Node address in the Network Parameters page (",(0,r.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,r.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"{{ keymanager_runtime_orc_path }}"}),": Path to the key manager ",(0,r.jsx)(n.a,{href:"/node/run-your-node/paratime-node#the-paratime-bundle",children:"ParaTime bundle"})," of the form ",(0,r.jsx)(n.code,{children:"/node/runtimes/foo-paratime.orc"}),".","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can find the current Oasis-supported key manager ParaTime in the Network Parameters page (",(0,r.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,r.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"{{ keymanager_runtime_id }}"}),": Runtime identified for the key manager ParaTime.","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can find the current Oasis-supported key manager ParaTime identifiers in the Network Parameters page (",(0,r.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,r.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"{{ ias_proxy_address }}"}),": The IAS proxy address in the form ",(0,r.jsx)(n.code,{children:"ID@HOST:port"}),".","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["You can find the current Oasis IAS proxy address in the Network Parameters page (",(0,r.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,r.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")."]}),"\n",(0,r.jsxs)(n.li,{children:["If you want, you can also ",(0,r.jsx)(n.a,{href:"/node/run-your-node/ias-proxy",children:"run your own IAS proxy"}),"."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsxs)(n.p,{children:["Make sure the ",(0,r.jsx)(n.code,{children:"consensus"})," port (default: ",(0,r.jsx)(n.code,{children:"26656"}),") and ",(0,r.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,r.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,r.jsx)(n.code,{children:"TCP"})," and ",(0,r.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,r.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,r.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,r.jsx)(n.h2,{id:"checking-node-status",children:"Checking Node Status"}),"\n",(0,r.jsx)(n.p,{children:"To ensure that your node is properly connected with the network, you can run the following command after the node has started:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"oasis-node control status -a unix:/node/data/internal.sock\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>d});var r=i(6540);const t={},o=r.createContext(t);function s(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/dcfcc267.91bf4ea5.js b/assets/js/dcfcc267.91bf4ea5.js new file mode 100644 index 0000000000..7760c044dd --- /dev/null +++ b/assets/js/dcfcc267.91bf4ea5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[223],{6545:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>p,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var s=t(4848),o=t(8453);const r={},i="Running Tests",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/development-setup/running-tests.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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"}},c={},d=[{value:"Tests",id:"tests",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}];function u(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"running-tests",children:"Running Tests"}),"\n",(0,s.jsxs)(n.p,{children:["Before proceeding, make sure to look at the ",(0,s.jsx)(n.a,{href:"/core/development-setup/prerequisites",children:"prerequisites"})," required for running\nan Oasis Core environment followed by ",(0,s.jsx)(n.a,{href:"/core/development-setup/building",children:"build instructions"})," for the respective\nenvironment (non-SGX or SGX). The following sections assume that you have\nsuccessfully completed the required build steps."]}),"\n",(0,s.jsx)(n.h2,{id:"tests",children:"Tests"}),"\n",(0,s.jsx)(n.p,{children:"After you've built everything, you can use the following commands to run tests."}),"\n",(0,s.jsx)(n.p,{children:"To run all unit tests:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make test-unit\n"})}),"\n",(0,s.jsx)(n.p,{children:"To run end-to-end tests locally:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make test-e2e\n"})}),"\n",(0,s.jsx)(n.p,{children:"To run all tests:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make test\n"})}),"\n",(0,s.jsx)(n.p,{children:"To execute tests using SGX set the following environmental variable before\nrunning the tests:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"export OASIS_TEE_HARDWARE=intel-sgx\n"})}),"\n",(0,s.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,s.jsxs)(n.p,{children:["Check the console output for mentions of a path of the form\n",(0,s.jsx)(n.code,{children:"/tmp/oasis-test-runnerXXXXXXXXX"})," (where each ",(0,s.jsx)(n.code,{children:"X"})," is a digit).\nThat's the log directory. Start with coarsest-level debug output in\n",(0,s.jsx)(n.code,{children:"console.log"})," files:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"cat $(find /tmp/oasis-test-runnerXXXXXXXXX -name console.log) | less\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For even more output, check the other ",(0,s.jsx)(n.code,{children:"*.log"})," files."]})]})}function p(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>l});var s=t(6540);const o={},r=s.createContext(o);function i(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/de2ae66a.25854425.js b/assets/js/de2ae66a.25854425.js new file mode 100644 index 0000000000..cffff6ed40 --- /dev/null +++ b/assets/js/de2ae66a.25854425.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[55],{9322:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var i=s(4848),o=s(8453);const t={},c="Genesis Document",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/genesis.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Key Manager",permalink:"/core/consensus/services/keymanager"},next:{title:"Transaction Test Vectors",permalink:"/core/consensus/test-vectors"}},a={},d=[{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}];function h(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"genesis-document",children:"Genesis Document"}),"\n",(0,i.jsxs)(n.p,{children:["The genesis document contains a set of parameters that outline the initial state\nof the ",(0,i.jsx)(n.a,{href:"/core/consensus/",children:"consensus layer"})," and its services."]}),"\n",(0,i.jsxs)(n.p,{children:["For more details about the actual genesis document's API, see\n",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/genesis/api",children:"genesis API documentation"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"genesis-documents-hash",children:"Genesis Document's Hash"}),"\n",(0,i.jsx)(n.p,{children:"The genesis document's hash is computed as:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"Base16(SHA512-256(CBOR()))\n"})}),"\n",(0,i.jsx)(n.p,{children:"where:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Base16()"})," represents the hex encoding function,"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"SHA512-256()"})," represents the SHA-512/256 hash function as described in\n",(0,i.jsx)(n.a,{href:"/core/crypto#hash-functions",children:"Cryptography"})," documentation,"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"CBOR()"})," represents the ",(0,i.jsx)(n.em,{children:"canonical"})," CBOR encoding function as described in\n",(0,i.jsx)(n.a,{href:"/core/encoding",children:"Serialization"})," documentation, and"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:""})," represents a given genesis document."]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["This should not be confused with a SHA-1 or a SHA-256 checksum of a\n",(0,i.jsx)(n.a,{href:"#genesis-file",children:"genesis file"})," that is used to check if the downloaded genesis file is correct."]})}),"\n",(0,i.jsxs)(n.p,{children:["This hash is also used for ",(0,i.jsx)(n.a,{href:"/core/crypto#chain-domain-separation",children:"chain domain separation"})," as the last\npart of the ",(0,i.jsx)(n.a,{href:"/core/crypto#domain-separation",children:"domain separation"})," context."]}),"\n",(0,i.jsx)(n.h2,{id:"genesis-file",children:"Genesis File"}),"\n",(0,i.jsx)(n.p,{children:"A genesis file is a JSON file corresponding to a serialized genesis document."}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["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,i.jsx)(n.a,{href:"/node/genesis-doc",children:"Genesis File Overview"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"canonical-form",children:"Canonical Form"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.em,{children:"canonical"})," form of a genesis file is the pretty-printed JSON file with\n2-space indents ending with a newline, where:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Struct fields are encoded in the order in which they are defined in the\ncorresponding struct definitions."}),"\n",(0,i.jsxs)(n.p,{children:["The genesis document is defined by the ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/genesis/api#Document",children:(0,i.jsx)(n.code,{children:"genesis/api.Document"})})," struct which\ncontains pointers to other structs defining the genesis state of all\n",(0,i.jsx)(n.a,{href:"/core/consensus/",children:"consensus layer"})," services."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Maps have their keys converted to strings which are then encoded in\nlexicographical order."}),"\n",(0,i.jsxs)(n.p,{children:["This is Go's default behavior. For more details, see\n",(0,i.jsx)(n.a,{href:"https://golang.org/pkg/encoding/json/#Marshal",children:(0,i.jsx)(n.code,{children:"encoding/json.Marshal()"})}),"'s documentation."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["This should not be confused with the ",(0,i.jsx)(n.em,{children:"canonical"})," CBOR encoding of the genesis\ndocument that is used to derive the domain separation context as described\nin the ",(0,i.jsx)(n.a,{href:"#genesis-documents-hash",children:"Genesis Document's Hash"})," section."]})}),"\n",(0,i.jsxs)(n.p,{children:["This form is used to enable simple diffing/patching with the standard Unix tools\n(i.e. ",(0,i.jsx)(n.code,{children:"diff"}),"/",(0,i.jsx)(n.code,{children:"patch"}),")."]})]})}function l(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>c,x:()=>r});var i=s(6540);const o={},t=i.createContext(o);function c(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e0bef5df.f0beb8e9.js b/assets/js/e0bef5df.f0beb8e9.js new file mode 100644 index 0000000000..5009662c49 --- /dev/null +++ b/assets/js/e0bef5df.f0beb8e9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5714],{3538:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"Services","slug":"core/consensus/services","permalink":"/core/consensus/services","sidebar":"oasisCore","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/e27d89bb.03681ab5.js b/assets/js/e27d89bb.03681ab5.js new file mode 100644 index 0000000000..dc5bc594c3 --- /dev/null +++ b/assets/js/e27d89bb.03681ab5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7754],{238:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>a});var i=s(4848),t=s(8453);const r={},o="Registry",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/registry.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Staking",permalink:"/core/consensus/services/staking"},next:{title:"Committee Scheduler",permalink:"/core/consensus/services/scheduler"}},d={},a=[{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}];function h(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"registry",children:"Registry"}),"\n",(0,i.jsx)(n.p,{children:"The registry service is responsible for managing a registry of runtime, entity\nand node public keys and metadata."}),"\n",(0,i.jsxs)(n.p,{children:["The service interface definition lives in ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/registry/api",children:(0,i.jsx)(n.code,{children:"go/registry/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc",children:"consensus service API documentation"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsx)(n.p,{children:"The registry service manages different kinds of resources which are described\nfrom a high level perspective in this chapter."}),"\n",(0,i.jsx)(n.h3,{id:"entities-and-nodes",children:"Entities and Nodes"}),"\n",(0,i.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"/core/consensus/services/staking",children:"stake"})," on\nthe network."]}),"\n",(0,i.jsx)(n.p,{children:"Currently, an entity can own the following types of resources:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"nodes and"}),"\n",(0,i.jsx)(n.li,{children:"runtimes."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"/core/consensus/services/staking#delegation",children:"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)."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"runtimes",children:"Runtimes"}),"\n",(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.a,{href:"/core/runtime/",children:"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.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime",children:["the ",(0,i.jsx)(n.code,{children:"Runtime"})," structure"]}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The chosen governance model indicates how the runtime descriptor can be updated\nin the future."}),"\n",(0,i.jsx)(n.p,{children:"There are currently three supported governance models:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Entity governance"})," where the runtime owner is the only one who can update\nthe runtime descriptor via ",(0,i.jsx)(n.code,{children:"registry.RegisterRuntime"})," method calls."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Runtime-defined governance"})," where the runtime itself is the only one who\ncan update the runtime descriptor by emitting a runtime message."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Consensus layer governance"})," where only the consensus layer itself can\nupdate the runtime descriptor through network governance."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,i.jsx)(n.p,{children:"The following sections describe the methods supported by the consensus registry\nservice."}),"\n",(0,i.jsx)(n.h3,{id:"register-entity",children:"Register Entity"}),"\n",(0,i.jsxs)(n.p,{children:["Entity registration enables a new entity to be created. A new register entity\ntransaction can be generated using ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterEntityTx",children:(0,i.jsx)(n.code,{children:"NewRegisterEntityTx"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"registry.RegisterEntity\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The body of a register entity transaction must be a ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#SignedEntity",children:(0,i.jsx)(n.code,{children:"SignedEntity"})})," structure,\nwhich is a ",(0,i.jsx)(n.a,{href:"/core/crypto#envelopes",children:"signed envelope"})," containing an ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#Entity",children:(0,i.jsx)(n.code,{children:"Entity"})})," descriptor. The\nsigner of the entity MUST be the same as the signer of the transaction."]}),"\n",(0,i.jsxs)(n.p,{children:["Registering an entity may require sufficient stake in the entity's\n",(0,i.jsx)(n.a,{href:"/core/consensus/services/staking#escrow",children:"escrow account"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"deregister-entity",children:"Deregister Entity"}),"\n",(0,i.jsxs)(n.p,{children:["Entity deregistration enables an existing entity to be removed. A new deregister\nentity transaction can be generated using ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewDeregisterEntityTx",children:(0,i.jsx)(n.code,{children:"NewDeregisterEntityTx"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"registry.DeregisterEntity\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The body of a register entity transaction must be ",(0,i.jsx)(n.code,{children:"nil"}),". The entity is implied\nto be the signer of the transaction."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.em,{children:"If an entity still has either nodes or runtimes registered, it is not possible\nto deregister an entity and such a transaction will fail."})}),"\n",(0,i.jsx)(n.h3,{id:"register-node",children:"Register Node"}),"\n",(0,i.jsxs)(n.p,{children:["Node registration enables a new node to be created. A new register node\ntransaction can be generated using ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterNodeTx",children:(0,i.jsx)(n.code,{children:"NewRegisterNodeTx"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"registry.RegisterNode\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The body of a register entity transaction must be a ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#MultiSignedNode",children:(0,i.jsx)(n.code,{children:"MultiSignedNode"})}),"\nstructure, which is a ",(0,i.jsx)(n.a,{href:"/core/crypto#envelopes",children:"multi-signed envelope"})," containing a ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/node?tab=doc#Node",children:(0,i.jsx)(n.code,{children:"Node"})}),"\ndescriptor. The signer of the transaction MUST be the node identity key."]}),"\n",(0,i.jsxs)(n.p,{children:["The owning entity MUST have the given node identity public key whitelisted in\nthe ",(0,i.jsx)(n.code,{children:"Nodes"})," field in its ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/entity?tab=doc#Entity",children:(0,i.jsx)(n.code,{children:"Entity"})})," descriptor."]}),"\n",(0,i.jsx)(n.p,{children:"The node descriptor structure MUST be signed by all the following keys:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Node identity key."}),"\n",(0,i.jsx)(n.li,{children:"Consensus key."}),"\n",(0,i.jsx)(n.li,{children:"TLS key."}),"\n",(0,i.jsx)(n.li,{children:"P2P key."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Registering a node may require sufficient stake in the owning entity's\n",(0,i.jsx)(n.a,{href:"/core/consensus/services/staking#escrow",children:"escrow account"}),". There are two kinds of thresholds that the node may need to\nsatisfy:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Global thresholds are the same for all runtimes and are defined by the\nconsensus parameters (see ",(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#ConsensusParameters.Thresholds",children:[(0,i.jsx)(n.code,{children:"Thresholds"})," in staking consensus parameters"]}),")."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["In ",(0,i.jsx)(n.em,{children:"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.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime.Staking",children:[(0,i.jsx)(n.code,{children:"Staking"})," field"]})," in the runtime descriptor."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h3,{id:"unfreeze-node",children:"Unfreeze Node"}),"\n",(0,i.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewUnfreezeNodeTx",children:(0,i.jsx)(n.code,{children:"NewUnfreezeNodeTx"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"registry.UnfreezeNode\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Body:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:'type UnfreezeNode struct {\n NodeID signature.PublicKey `json:"node_id"`\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"node_id"})," specifies the node identifier of the node to thaw."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The transaction signer MUST be the entity key that owns the node."}),"\n",(0,i.jsxs)(n.p,{children:["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.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/staking/api?tab=doc#ConsensusParameters.Slashing",children:[(0,i.jsx)(n.code,{children:"Slashing"})," in staking consensus parameters"]}),")."]}),"\n",(0,i.jsx)(n.h3,{id:"register-runtime",children:"Register Runtime"}),"\n",(0,i.jsxs)(n.p,{children:["Runtime registration enables a new runtime to be created. A new register\nruntime transaction can be generated using ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#NewRegisterRuntimeTx",children:(0,i.jsx)(n.code,{children:"NewRegisterRuntimeTx"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"registry.RegisterRuntime\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The body of a register runtime transaction must be a ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/registry/api?tab=doc#Runtime",children:(0,i.jsx)(n.code,{children:"Runtime"})})," descriptor.\nThe signer of the transaction MUST be the owning entity key."]}),"\n",(0,i.jsxs)(n.p,{children:["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.jsx)(n.a,{href:"/core/consensus/services/staking#escrow",children:"escrow account"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Changing the governance model from entity governance to runtime governance is\nallowed. Any other governance model changes are not allowed."}),"\n",(0,i.jsx)(n.h2,{id:"events",children:"Events"}),"\n",(0,i.jsx)(n.h2,{id:"test-vectors",children:"Test Vectors"}),"\n",(0,i.jsxs)(n.p,{children:["To generate test vectors for various registry ",(0,i.jsx)(n.a,{href:"/core/consensus/transactions",children:"transactions"}),", run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make -C go registry/gen_vectors\n"})}),"\n",(0,i.jsxs)(n.p,{children:["For more information about the structure of the test vectors see the section\non ",(0,i.jsx)(n.a,{href:"/core/consensus/test-vectors",children:"Transaction Test Vectors"}),"."]})]})}function l(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>c});var i=s(6540);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e27f323d.3a2a4ae1.js b/assets/js/e27f323d.3a2a4ae1.js new file mode 100644 index 0000000000..4414283bc9 --- /dev/null +++ b/assets/js/e27f323d.3a2a4ae1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8639],{5562:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>d,default:()=>u,frontMatter:()=>c,metadata:()=>l,toc:()=>h});var r=n(4848),s=n(8453),i=n(1470),a=n(9365);const c={},d="Oasis Privacy Layer",l={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/dapp/opl/README.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"developers",previous:{title:"Security",permalink:"/dapp/sapphire/security"},next:{title:"Overview",permalink:"/dapp/opl/introduction"}},o={},h=[{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}];function x(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"oasis-privacy-layer",children:"Oasis Privacy Layer"}),"\n",(0,r.jsx)(t.p,{children:"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."}),"\n",(0,r.jsxs)(t.p,{children:["By using ",(0,r.jsx)(t.a,{href:"https://www.npmjs.com/package/@oasisprotocol/sapphire-contracts",children:"a Solidity library"}),"\nthat integrates ",(0,r.jsx)(t.a,{href:"https://oasisprotocol.org/sapphire",children:"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."]}),"\n",(0,r.jsxs)(t.p,{children:["For more information about OPL and to catch the latest news, please visit the\n",(0,r.jsx)(t.a,{href:"https://oasisprotocol.org/opl",children:"official OPL page"}),"."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Oasis Privacy Layer diagram",src:n(7127).A+"",width:"1081",height:"1081"})}),"\n",(0,r.jsxs)(t.p,{children:["The user submits a transaction on the Home network to a contract which uses\n",(0,r.jsx)(t.code,{children:"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."]}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"Transaction Flow",src:n(8117).A+"",width:"1124",height:"387"})}),"\n",(0,r.jsx)(t.p,{children:"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."}),"\n",(0,r.jsx)(t.h2,{id:"quickstart",children:"Quickstart"}),"\n",(0,r.jsx)(t.p,{children:"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."}),"\n",(0,r.jsxs)(t.p,{children:["Start by adding the ",(0,r.jsx)(t.a,{href:"http://npmjs.com/package/@oasisprotocol/sapphire-contracts",children:(0,r.jsx)(t.code,{children:"@oasisprotocol/sapphire-contracts"})})," NPM package to your\nHardhat project so you can import ",(0,r.jsx)(t.code,{children:"OPL.sol"}),":"]}),"\n",(0,r.jsxs)(i.A,{groupId:"npm2yarn",children:[(0,r.jsx)(a.A,{value:"npm",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"npm install @oasisprotocol/sapphire-contracts\n"})})}),(0,r.jsx)(a.A,{value:"pnpm",label:"pnpm",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"pnpm add @oasisprotocol/sapphire-contracts\n"})})}),(0,r.jsx)(a.A,{value:"yarn",label:"Yarn",children:(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",children:"yarn add @oasisprotocol/sapphire-contracts\n"})})})]}),"\n",(0,r.jsxs)(t.p,{children:["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.jsx)(t.code,{children:"secretExample"}),"\nhandler. Use the constructor to provide the Sapphire contract with the location\n(address and chain) of the contract on the Home network:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-solidity",children:'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'})}),"\n",(0,r.jsxs)(t.p,{children:["Then on the other chain, define your contract which can be called via\n",(0,r.jsx)(t.code,{children:"triggerExample"})," to send a message to the contract on Sapphire using the\n",(0,r.jsx)(t.code,{children:"postMessage"})," interface."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-solidity",children:'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'})}),"\n",(0,r.jsxs)(t.p,{children:["After a few minutes the bridge will detect and then the executor will invoke the\n",(0,r.jsx)(t.code,{children:"SapphireContract.on_example"})," method."]}),"\n",(0,r.jsx)(t.h2,{id:"monitoring",children:"Monitoring"}),"\n",(0,r.jsx)(t.p,{children:"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."}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://api.celerscan.com/scan/searchByTxHash?tx=0x",children:"https://api.celerscan.com/scan/searchByTxHash?tx=0x"}),"..."]}),"\n",(0,r.jsxs)(t.p,{children:["For details of the response format, see the ",(0,r.jsx)(t.a,{href:"https://im-docs.celer.network/developer/development-guide/query-im-tx-status",children:"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."]}),"\n",(0,r.jsx)(t.h2,{id:"mainnet-deployment",children:"Mainnet Deployment"}),"\n",(0,r.jsxs)(t.p,{children:["It is necessary to run a ",(0,r.jsx)(t.a,{href:"https://im-docs.celer.network/developer/development-guide/message-executor",children:"Message Executor"})," which monitors the Celer ",(0,r.jsx)(t.em,{children:"State\nGuardian Network"})," (SGN) for cross-chain messages and then submits the proof\non-chain to deliver them to the target contract."]}),"\n",(0,r.jsxs)(t.p,{children:["If you are participating in a Hackathon or Grant, ",(0,r.jsx)(t.a,{href:"https://form.typeform.com/to/RsiUR9Xz",children:"please fill out the relay\nrequest form"})," to be allowed to use the\nshared Message Executor."]}),"\n",(0,r.jsx)(t.h2,{id:"supported-networks",children:"Supported Networks"}),"\n",(0,r.jsx)(t.h3,{id:"mainnets",children:"Mainnets"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Name"}),(0,r.jsx)(t.th,{children:"Int ID"}),(0,r.jsx)(t.th,{children:"Hex ID"}),(0,r.jsx)(t.th,{children:"autoswitch name"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Ape"}),(0,r.jsx)(t.td,{children:"16350"}),(0,r.jsx)(t.td,{children:"0x3fde"}),(0,r.jsx)(t.td,{children:"ape"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Arbitrum Nova"}),(0,r.jsx)(t.td,{children:"42170"}),(0,r.jsx)(t.td,{children:"0xa4ba"}),(0,r.jsx)(t.td,{children:"arbitrum-nova"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Arbitrum One"}),(0,r.jsx)(t.td,{children:"42161"}),(0,r.jsx)(t.td,{children:"a4b1"}),(0,r.jsx)(t.td,{children:"arbitrum-one"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Astar"}),(0,r.jsx)(t.td,{children:"592"}),(0,r.jsx)(t.td,{children:"0x250"}),(0,r.jsx)(t.td,{children:"astar"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Aurora"}),(0,r.jsx)(t.td,{children:"1313161554"}),(0,r.jsx)(t.td,{children:"0x4e454152"}),(0,r.jsx)(t.td,{children:"aurora"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Avalanche"}),(0,r.jsx)(t.td,{children:"43114"}),(0,r.jsx)(t.td,{children:"0xa86a"}),(0,r.jsx)(t.td,{children:"avalanche"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Binance Smart Chain"}),(0,r.jsx)(t.td,{children:"56"}),(0,r.jsx)(t.td,{children:"0x38"}),(0,r.jsx)(t.td,{children:"bsc"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Ethereum"}),(0,r.jsx)(t.td,{children:"1"}),(0,r.jsx)(t.td,{children:"0x1"}),(0,r.jsx)(t.td,{children:"ethereum"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Fantom"}),(0,r.jsx)(t.td,{children:"250"}),(0,r.jsx)(t.td,{children:"0xfa"}),(0,r.jsx)(t.td,{children:"fantom"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Filecoin"}),(0,r.jsx)(t.td,{children:"314"}),(0,r.jsx)(t.td,{children:"0x13a"}),(0,r.jsx)(t.td,{children:"filecoin"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Milkomeda C1"}),(0,r.jsx)(t.td,{children:"2001"}),(0,r.jsx)(t.td,{children:"0x7d1"}),(0,r.jsx)(t.td,{children:"milkomeda"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Moonriver"}),(0,r.jsx)(t.td,{children:"1285"}),(0,r.jsx)(t.td,{children:"0x505"}),(0,r.jsx)(t.td,{children:"moonriver"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Polygon"}),(0,r.jsx)(t.td,{children:"137"}),(0,r.jsx)(t.td,{children:"0x89"}),(0,r.jsx)(t.td,{children:"polygon"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Sapphire"}),(0,r.jsx)(t.td,{children:"23294"}),(0,r.jsx)(t.td,{children:"0x5afe"}),(0,r.jsx)(t.td,{children:"sapphire"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Syscoin"}),(0,r.jsx)(t.td,{children:"57"}),(0,r.jsx)(t.td,{children:"0x39"}),(0,r.jsx)(t.td,{children:"syscoin"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Polygon zkEVM"}),(0,r.jsx)(t.td,{children:"1101"}),(0,r.jsx)(t.td,{children:"0x44d"}),(0,r.jsx)(t.td,{children:"polygon-zkevm"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Optimism"}),(0,r.jsx)(t.td,{children:"10"}),(0,r.jsx)(t.td,{children:"0xa"}),(0,r.jsx)(t.td,{children:"optimism"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"zkSync Era"}),(0,r.jsx)(t.td,{children:"324"}),(0,r.jsx)(t.td,{children:"0x144"}),(0,r.jsx)(t.td,{children:"zksync-era"})]})]})]}),"\n",(0,r.jsx)(t.h3,{id:"testnets",children:"Testnets"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Name"}),(0,r.jsx)(t.th,{children:"Int ID"}),(0,r.jsx)(t.th,{children:"Hex ID"}),(0,r.jsx)(t.th,{children:"autoswitch name"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Arbitrum Testnet"}),(0,r.jsx)(t.td,{children:"421611"}),(0,r.jsx)(t.td,{children:"0x66eeb"}),(0,r.jsx)(t.td,{children:"arbitrum-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Avalanche C-Chain Fuji Testnet"}),(0,r.jsx)(t.td,{children:"43113"}),(0,r.jsx)(t.td,{children:"0xa869"}),(0,r.jsx)(t.td,{children:"avalanche-fuji"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"BSC Testnet"}),(0,r.jsx)(t.td,{children:"97"}),(0,r.jsx)(t.td,{children:"0x61"}),(0,r.jsx)(t.td,{children:"bsc-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"ConsenSys zkEVM Testnet"}),(0,r.jsx)(t.td,{children:"59140"}),(0,r.jsx)(t.td,{children:"0xe704"}),(0,r.jsx)(t.td,{children:"zkevm-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Dexalot Testnet"}),(0,r.jsx)(t.td,{children:"432201"}),(0,r.jsx)(t.td,{children:"0x69849"}),(0,r.jsx)(t.td,{children:"dexalot-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Fantom Testnet"}),(0,r.jsx)(t.td,{children:"4002"}),(0,r.jsx)(t.td,{children:"0xfa2"}),(0,r.jsx)(t.td,{children:"fantom-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Filecoin Hyperspace Testnet"}),(0,r.jsx)(t.td,{children:"3141"}),(0,r.jsx)(t.td,{children:"0xc45"}),(0,r.jsx)(t.td,{children:"filecoin-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"FNCY Testnet"}),(0,r.jsx)(t.td,{children:"923018"}),(0,r.jsx)(t.td,{children:"0xe158a"}),(0,r.jsx)(t.td,{children:"fncy-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Godwoken Testnet"}),(0,r.jsx)(t.td,{children:"71401"}),(0,r.jsx)(t.td,{children:"0x116e9"}),(0,r.jsx)(t.td,{children:"godwoken-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Goerli Testnet"}),(0,r.jsx)(t.td,{children:"5"}),(0,r.jsx)(t.td,{children:"0x5"}),(0,r.jsx)(t.td,{children:"goerli"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Polygon Mumbai Testnet"}),(0,r.jsx)(t.td,{children:"80001"}),(0,r.jsx)(t.td,{children:"0x13881"}),(0,r.jsx)(t.td,{children:"polygon-mumbai"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Polygon zkEVM Testnet"}),(0,r.jsx)(t.td,{children:"1442"}),(0,r.jsx)(t.td,{children:"0x5a2"}),(0,r.jsx)(t.td,{children:"zkevm-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Sapphire Testnet"}),(0,r.jsx)(t.td,{children:"23295"}),(0,r.jsx)(t.td,{children:"0x5aff"}),(0,r.jsx)(t.td,{children:"sapphire-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Scroll Alpha Testnet"}),(0,r.jsx)(t.td,{children:"534353"}),(0,r.jsx)(t.td,{children:"0x82751"}),(0,r.jsx)(t.td,{children:"scroll-testnet"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"Shibuya Testnet"}),(0,r.jsx)(t.td,{children:"81"}),(0,r.jsx)(t.td,{children:"0x51"}),(0,r.jsx)(t.td,{children:"shibuya-testnet"})]})]})]}),"\n",(0,r.jsx)(t.p,{children:"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!"})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(x,{...e})}):x(e)}},9365:(e,t,n)=>{n.d(t,{A:()=>a});n(6540);var r=n(4164);const s={tabItem:"tabItem_Ymn6"};var i=n(4848);function a(e){let{children:t,hidden:n,className:a}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.A)(s.tabItem,a),hidden:n,children:t})}},1470:(e,t,n)=>{n.d(t,{A:()=>w});var r=n(6540),s=n(4164),i=n(3104),a=n(6347),c=n(205),d=n(7485),l=n(1682),o=n(9466);function h(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((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)??[]}function x(e){const{values:t,children:n}=e;return(0,r.useMemo)((()=>{const e=t??function(e){return h(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:s}}=e;return{value:t,label:n,attributes:r,default:s}}))}(n);return function(e){const t=(0,l.X)(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 u(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function p(e){let{queryString:t=!1,groupId:n}=e;const s=(0,a.W6)(),i=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,d.aZ)(i),(0,r.useCallback)((e=>{if(!i)return;const t=new URLSearchParams(s.location.search);t.set(i,e),s.replace({...s.location,search:t.toString()})}),[i,s])]}function j(e){const{defaultValue:t,queryString:n=!1,groupId:s}=e,i=x(e),[a,d]=(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(!u({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:i}))),[l,h]=p({queryString:n,groupId:s}),[j,m]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[s,i]=(0,o.Dv)(n);return[s,(0,r.useCallback)((e=>{n&&i.set(e)}),[n,i])]}({groupId:s}),f=(()=>{const e=l??j;return u({value:e,tabValues:i})?e:null})();(0,c.A)((()=>{f&&d(f)}),[f]);return{selectedValue:a,selectValue:(0,r.useCallback)((e=>{if(!u({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);d(e),h(e),m(e)}),[h,m,i]),tabValues:i}}var m=n(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var g=n(4848);function b(e){let{className:t,block:n,selectedValue:r,selectValue:a,tabValues:c}=e;const d=[],{blockElementScrollPositionUntilNextRender:l}=(0,i.a_)(),o=e=>{const t=e.currentTarget,n=d.indexOf(t),s=c[n].value;s!==r&&(l(t),a(s))},h=e=>{let t=null;switch(e.key){case"Enter":o(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(0,g.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,s.A)("tabs",{"tabs--block":n},t),children:c.map((e=>{let{value:t,label:n,attributes:i}=e;return(0,g.jsx)("li",{role:"tab",tabIndex:r===t?0:-1,"aria-selected":r===t,ref:e=>d.push(e),onKeyDown:h,onClick:o,...i,className:(0,s.A)("tabs__item",f.tabItem,i?.className,{"tabs__item--active":r===t}),children:n??t},t)}))})}function v(e){let{lazy:t,children:n,selectedValue:s}=e;const i=(Array.isArray(n)?n:[n]).filter(Boolean);if(t){const e=i.find((e=>e.props.value===s));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,g.jsx)("div",{className:"margin-top--md",children:i.map(((e,t)=>(0,r.cloneElement)(e,{key:t,hidden:e.props.value!==s})))})}function y(e){const t=j(e);return(0,g.jsxs)("div",{className:(0,s.A)("tabs-container",f.tabList),children:[(0,g.jsx)(b,{...t,...e}),(0,g.jsx)(v,{...t,...e})]})}function w(e){const t=(0,m.A)();return(0,g.jsx)(y,{...e,children:h(e.children)},String(t))}},8117:(e,t,n)=>{n.d(t,{A:()=>r});const r=n.p+"assets/images/opl-contract-flow.mmd-a7b41e513987dc5c2d364b283a8147ec.svg"},7127:(e,t,n)=>{n.d(t,{A:()=>r});const r=n.p+"assets/images/privacy-layer-diagram-5b87a6dff417d5a4074bd6fdee9dce7e.png"},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>c});var r=n(6540);const s={},i=r.createContext(s);function a(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e2e2c701.9f8ff47d.js b/assets/js/e2e2c701.9f8ff47d.js new file mode 100644 index 0000000000..c4bcfe1ba1 --- /dev/null +++ b/assets/js/e2e2c701.9f8ff47d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8600],{4747:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var t=s(4848),o=s(8453);const i={},a="Key Manager",r={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/consensus/services/keymanager.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,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}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"key-manager",children:"Key Manager"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["The service interface definition lives in ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/tree/master/go/keymanager/api",children:(0,t.jsx)(n.code,{children:"go/keymanager/api"})}),". It defines the\nsupported queries and transactions. For more information you can also check out\nthe ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc",children:"consensus service API documentation"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"policies",children:"Policies"}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#PolicySGX",children:"policy document"})," specifies the following access control policies that are\nenforced by the key manager runtime based on the calling enclave identity:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"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."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsx)(n.h2,{id:"methods",children:"Methods"}),"\n",(0,t.jsx)(n.h3,{id:"update-policy",children:"Update Policy"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#NewUpdatePolicyTx",children:(0,t.jsx)(n.code,{children:"NewUpdatePolicyTx"})}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Method name:"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"keymanager.UpdatePolicy\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The body of an update policy transaction must be a ",(0,t.jsx)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/keymanager/api?tab=doc#SignedPolicySGX",children:(0,t.jsx)(n.code,{children:"SignedPolicySGX"})})," which is\na signed key manager access control policy. The signer of the transaction must\nbe the key manager runtime's owning entity."]}),"\n",(0,t.jsx)(n.h2,{id:"events",children:"Events"})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>r});var t=s(6540);const o={},i=t.createContext(o);function a(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e607d64f.19867e6a.js b/assets/js/e607d64f.19867e6a.js new file mode 100644 index 0000000000..3ee3e39035 --- /dev/null +++ b/assets/js/e607d64f.19867e6a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1081],{8199:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var t=s(4848),a=s(8453),r=s(1470),i=s(9365);const o={description:"Submitting transactions without paying for fees"},l="Gasless Transactions",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/gasless.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"Submitting transactions without paying for fees"},sidebar:"developers",previous:{title:"View-Call Authentication",permalink:"/dapp/sapphire/authentication"},next:{title:"Contract Addresses and Deployments",permalink:"/dapp/sapphire/addresses"}},d={},h=[{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}];function p(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",section:"section",strong:"strong",sup:"sup",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"gasless-transactions",children:"Gasless Transactions"}),"\n",(0,t.jsxs)(n.p,{children:["When you submit a transaction to a blockchain, you need to pay certain fee\n(called ",(0,t.jsx)(n.em,{children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["In this chapter we will learn how the user signs and sends their transaction to\na ",(0,t.jsx)(n.em,{children:"relayer"}),". The relayer then wraps the original signed transaction into a new\n",(0,t.jsx)(n.em,{children:"meta-transaction"})," (see ",(0,t.jsx)(n.a,{href:"https://eips.ethereum.org/EIPS/eip-2771",children:"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."]}),"\n",(0,t.jsxs)(n.p,{children:["Oasis Sapphire supports two transaction relaying methods: The ",(0,t.jsx)(n.strong,{children:"on-chain\nsigner"})," exposes the Oasis-specific contract state encryption functionality\nwhile the ",(0,t.jsx)(n.strong,{children:"gas station network"})," method is a standardized approach known in\nother blockchains as well."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsx)(n.p,{children:"The gas station network implementation on Sapphire is still in early beta. Some\nfeatures such as the browser support are not fully implemented yet."})}),"\n",(0,t.jsx)(n.h2,{id:"on-chain-signer",children:"On-Chain Signer"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.a,{href:"https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md",children:"EIP-155"})," format. These steps are executed as a confidential call. Finally,\nthe user submits the generated transaction to the network."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Diagram of the On-Chain Signing",src:s(9922).A+""})}),"\n",(0,t.jsx)(n.h3,{id:"eip155signer",children:"EIP155Signer"}),"\n",(0,t.jsxs)(n.p,{children:["To sign a transaction, the Sapphire's ",(0,t.jsx)(n.code,{children:"EIP155Signer"})," library bundled along the\n",(0,t.jsx)(n.code,{children:"@oasisprotocol/sapphire-contract"})," package comes with the following helper which\nreturns a raw, RLP-encoded, signed transaction ready to be broadcast:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-solidity",children:"function sign(address publicAddress, bytes32 secretKey, EthTx memory transaction) internal view returns (bytes memory);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"publicAddress"})," and ",(0,t.jsx)(n.code,{children:"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,t.jsx)(n.code,{children:"nonce"})," field in the following struct:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-solidity",children:"struct EthereumKeypair {\n address addr;\n bytes32 secret;\n uint64 nonce;\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The last ",(0,t.jsx)(n.code,{children:"transaction"})," parameter in the ",(0,t.jsx)(n.code,{children:"sign()"})," function is the transaction\nencoded in a format based on ",(0,t.jsx)(n.a,{href:"https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md",children:"EIP-155"}),". This can either be the original user's\ntransaction or a meta-transaction."]}),"\n",(0,t.jsx)(n.h3,{id:"gasless-proxy-contract",children:"Gasless Proxy Contract"}),"\n",(0,t.jsxs)(n.p,{children:["The following snippet is a complete ",(0,t.jsx)(n.em,{children:"Gasless"})," contract for wrapping the user's\ntransactions (",(0,t.jsx)(n.code,{children:"makeProxyTx()"}),") and executing them (",(0,t.jsx)(n.code,{children:"proxy()"}),"). The signer's\nprivate key containing enough balance to cover transaction fees should be\nprovided in the constructor."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-solidity",children:'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'})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["The snippet above only runs on Sapphire Mainnet, Testnet or Localnet.\n",(0,t.jsx)(n.code,{children:"EIP155Signer.sign()"})," is not supported on other EVM chains."]})}),"\n",(0,t.jsx)(n.h3,{id:"simple-gasless-commenting-dapp",children:"Simple Gasless Commenting dApp"}),"\n",(0,t.jsx)(n.p,{children:"Let's see how we can implement on-chain signer for a gasless commenting dApp\nlike this:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-solidity",children:"contract CommentBox {\n string[] public comments;\n\n function comment(string memory commentText) external {\n comments.push(commentText);\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Then, the TypeScript code on a client side for submitting a comment in a gasless\nfashion would look like this:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const CommentBox = await ethers.getContractFactory(\"CommentBox\");\nconst commentBox = await CommentBox.deploy();\nawait commentBox.waitForDeployment();\nconst Gasless = await ethers.getContractFactory(\"Gasless\");\nconst gasless = await Gasless.deploy();\nawait gasless.waitForDeployment();\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.JsonRpcProvider(ethers.provider.connection);\nconst plainResp = await plainProvider.sendTransaction(tx);\n\nconst receipt = await ethers.provider.getTransactionReceipt(plainResp.hash);\nif (!receipt || receipt.status != 1) throw new Error('tx failed');\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"Example",type:"info",children:(0,t.jsxs)(n.p,{children:["You can download a complete on-chain signer example based on the above snippets\nfrom the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/tree/main/examples/onchain-signer",children:"Sapphire ParaTime examples"})," repository."]})}),"\n",(0,t.jsx)(n.h3,{id:"gasless-proxy-in-production",children:"Gasless Proxy in Production"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsx)(n.h4,{id:"confidentiality",children:"Confidentiality"}),"\n",(0,t.jsxs)(n.p,{children:["Both the inner- and the meta-transaction are stored on-chain unencrypted. Use\n",(0,t.jsx)(n.code,{children:"Sapphire.encrypt()"})," and ",(0,t.jsx)(n.code,{children:"Sapphire.decrypt()"})," call on the inner-transaction with\nan encryption key generated and stored inside a confidential contract state."]}),"\n",(0,t.jsx)(n.h4,{id:"gas-cost-and-gas-limit",children:"Gas Cost and Gas Limit"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"Never let gas cost\nand limit to be freely defined by the user, since they can drain your relayer's\naccount."})]}),"\n",(0,t.jsx)(n.h4,{id:"allowed-transactions",children:"Allowed Transactions"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"only\nallow calls to this contract address"}),"."]}),"\n",(0,t.jsx)(n.h4,{id:"access-control",children:"Access Control"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.code,{children:"makeProxyTx()"})," should simulate the execution of the inner-transaction\nand generate the meta-transaction only if it inner-transaction succeeded."]}),"\n",(0,t.jsx)(n.h4,{id:"multiple-signers",children:"Multiple Signers"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"pool of signers"}),". When the\ntransaction is relayed, don't forget to reimburse the signer of the transaction!"]}),"\n",(0,t.jsx)(n.admonition,{title:"Example",type:"info",children:(0,t.jsxs)(n.p,{children:["All the above points are considered in the ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/demo-voting",children:"Demo Voting dApp"}),".\nYou can explore the code and also try out a deployed gasless version of the\nvoting dApp on the ",(0,t.jsx)(n.a,{href:"https://playground.oasis.io/demo-voting",children:"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."]})}),"\n",(0,t.jsx)(n.h2,{id:"gas-station-network",children:"Gas Station Network"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://docs.opengsn.org",children:"Gas Station Network"})," (GSN) was adapted to work with\nSapphire in a forked ",(0,t.jsx)(n.code,{children:"@oasislabs/opengsn-cli"})," package. The diagram below\nillustrates a flow for signing a transaction by using a GSN",(0,t.jsx)(n.sup,{children:(0,t.jsx)(n.a,{href:"#user-content-fn-1",id:"user-content-fnref-1","data-footnote-ref":!0,"aria-describedby":"footnote-label",children:"1"})}),"."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Diagram of the Gas Station Network Flow",src:s(3108).A+"",width:"1624",height:"927"})}),"\n",(0,t.jsx)(n.h3,{id:"package-install",children:"Package Install"}),"\n",(0,t.jsxs)(n.p,{children:["Starting with an empty folder, let us install the\n",(0,t.jsx)(n.a,{href:"https://github.com/oasislabs/gsn",children:"Oasis fork of the GSN command line tool"})," by\nusing the following commands:"]}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(i.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm init\nnpm install -D @oasislabs/opengsn-cli\n"})})}),(0,t.jsx)(i.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm init\npnpm add -D @oasislabs/opengsn-cli\n"})})}),(0,t.jsx)(i.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn init\nyarn add --dev @oasislabs/opengsn-cli\n"})})})]}),"\n",(0,t.jsxs)(n.p,{children:["Next, we will export our hex-encoded private key (",(0,t.jsx)(n.strong,{children:"without"})," the leading ",(0,t.jsx)(n.code,{children:"0x"}),")\nfor deploying the gas station network as an environment variable:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"export PRIVATE_KEY=...\n"})}),"\n",(0,t.jsx)(n.h3,{id:"deploy-gsn",children:"Deploy GSN"}),"\n",(0,t.jsxs)(n.p,{children:["Deploy GSN relaying contracts along with the test paymaster using a\ntest token. Use the address of your account as ",(0,t.jsx)(n.code,{children:"--burnAddress"})," and\n",(0,t.jsx)(n.code,{children:"--devAddress"})," parameters:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npx gsn deploy --network sapphire-testnet --burnAddress 0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204 --devAddress 0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204 --testToken true --testPaymaster true --yes --privateKeyHex $PRIVATE_KEY\n"})}),"\n",(0,t.jsx)(n.p,{children:"After the command finishes successfully, you should find the addreses of\ndeployed contracts at the end:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:" 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"})}),"\n",(0,t.jsx)(n.h3,{id:"start-gsn-relay-server",children:"Start GSN Relay Server"}),"\n",(0,t.jsx)(n.p,{children:"Now we are ready to start our own relay server by using the following command.\nUse the newly deployed:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"RelayHub"})," address for ",(0,t.jsx)(n.code,{children:"--relayHubAddress"}),","]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"TestToken"})," address for ",(0,t.jsx)(n.code,{children:"--managerStakeTokenAddress"}),","]}),"\n",(0,t.jsxs)(n.li,{children:["address of your account for ",(0,t.jsx)(n.code,{children:"--owner-address"})]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npx gsn relayer-run --relayHubAddress 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --managerStakeTokenAddress 0x6Ed21672c0c26Daa32943F7b1cA1f1d0ABdbac66 --ownerAddress '0xfA3AC9f65C9D75EE3978ab76c6a1105f03156204' --ethereumNodeUrl 'https://testnet.sapphire.oasis.io' --workdir .\n"})}),"\n",(0,t.jsx)(n.h3,{id:"fund-and-register-gsn-relay-server",children:"Fund and Register GSN Relay Server"}),"\n",(0,t.jsxs)(n.p,{children:["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,t.jsx)(n.strong,{children:"5 tokens"}),". Use the ",(0,t.jsx)(n.code,{children:"RelayHub"})," and ",(0,t.jsx)(n.code,{children:"Paymaster"})," addresses for ",(0,t.jsx)(n.code,{children:"--hub"}),"\nand ",(0,t.jsx)(n.code,{children:"--paymaster"})," values:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npx gsn paymaster-fund --network sapphire-testnet --hub 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --paymaster 0x8C06261f58a024C958d42df89be7195c8690008d --privateKeyHex $PRIVATE_KEY --amount 5000000000000000000\n"})}),"\n",(0,t.jsx)(n.p,{children:"You can check the balance of the paymaster by running:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npx gsn paymaster-balance --network sapphire-testnet --hub 0xc4423AB6133B06e4e60D594Ac49abE53374124b3 --paymaster 0x8C06261f58a024C958d42df89be7195c8690008d\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, we need to register the relay server with the your desired ",(0,t.jsx)(n.code,{children:"relayUrl"})," by\nstaking the ",(0,t.jsx)(n.code,{children:"token"})," the relayHub requires."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npx gsn relayer-register --network sapphire-testnet --relayUrl 'http://localhost:8090' --token 0x6Ed21672c0c26Daa32943F7b1cA1f1d0ABdbac66 --wrap true --privateKeyHex $PRIVATE_KEY\n"})}),"\n",(0,t.jsx)(n.p,{children:"After this step, your relay server should be ready to take incoming relay\nrequests and forward them to the relay hub on Sapphire Testnet."}),"\n",(0,t.jsx)(n.h3,{id:"send-testing-relayed-requests",children:"Send Testing Relayed Requests:"}),"\n",(0,t.jsx)(n.p,{children:"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:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Forwarder"})," as ",(0,t.jsx)(n.code,{children:"--to"}),","]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Paymaster"})," as ",(0,t.jsx)(n.code,{children:"--paymaster"}),","]}),"\n",(0,t.jsxs)(n.li,{children:["your account address as ",(0,t.jsx)(n.code,{children:"--from"})]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Parameters matching our deployment would be:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"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"})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["More detailed explanations of these GSN commands and parameters can be found on\nthe ",(0,t.jsx)(n.a,{href:"https://docs.opengsn.org/javascript-client/gsn-helpers.html",children:"upstream OpenGSN website"}),"."]})}),"\n",(0,t.jsx)(n.h3,{id:"writing-a-gsn-enabled-smart-contract",children:"Writing a GSN-enabled Smart Contract"}),"\n",(0,t.jsx)(n.p,{children:"First, install the OpenGSN contracts package:"}),"\n",(0,t.jsxs)(r.A,{groupId:"npm2yarn",children:[(0,t.jsx)(i.A,{value:"npm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm install -D @opengsn/contracts@3.0.0-beta.2\n"})})}),(0,t.jsx)(i.A,{value:"pnpm",label:"pnpm",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"pnpm add -D @opengsn/contracts@3.0.0-beta.2\n"})})}),(0,t.jsx)(i.A,{value:"yarn",label:"Yarn",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"yarn add --dev @opengsn/contracts@3.0.0-beta.2\n"})})})]}),"\n",(0,t.jsxs)(n.p,{children:["Then follow the remainder of the steps from the\n",(0,t.jsx)(n.a,{href:"https://docs.opengsn.org/contracts/#receiving-a-relayed-call",children:"upstream OpenGSN docs"}),"."]}),"\n","\n",(0,t.jsxs)(n.section,{"data-footnotes":!0,className:"footnotes",children:[(0,t.jsx)(n.h2,{className:"sr-only",id:"footnote-label",children:"Footnotes"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{id:"user-content-fn-1",children:["\n",(0,t.jsxs)(n.p,{children:["The GSN flow diagram is courtesy of ",(0,t.jsx)(n.a,{href:"https://github.com/opengsn/docs",children:"OpenGSN documentation"}),". ",(0,t.jsx)(n.a,{href:"#user-content-fnref-1","data-footnote-backref":"","aria-label":"Back to reference 1",className:"data-footnote-backref",children:"\u21a9"})]}),"\n"]}),"\n"]}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},9365:(e,n,s)=>{s.d(n,{A:()=>i});s(6540);var t=s(4164);const a={tabItem:"tabItem_Ymn6"};var r=s(4848);function i(e){let{children:n,hidden:s,className:i}=e;return(0,r.jsx)("div",{role:"tabpanel",className:(0,t.A)(a.tabItem,i),hidden:s,children:n})}},1470:(e,n,s)=>{s.d(n,{A:()=>w});var t=s(6540),a=s(4164),r=s(3104),i=s(6347),o=s(205),l=s(7485),c=s(1682),d=s(9466);function h(e){return t.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,t.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function p(e){const{values:n,children:s}=e;return(0,t.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:s,attributes:t,default:a}}=e;return{value:n,label:s,attributes:t,default:a}}))}(s);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,s])}function u(e){let{value:n,tabValues:s}=e;return s.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:s}=e;const a=(0,i.W6)(),r=function(e){let{queryString:n=!1,groupId:s}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!s)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 s??null}({queryString:n,groupId:s});return[(0,l.aZ)(r),(0,t.useCallback)((e=>{if(!r)return;const n=new URLSearchParams(a.location.search);n.set(r,e),a.replace({...a.location,search:n.toString()})}),[r,a])]}function g(e){const{defaultValue:n,queryString:s=!1,groupId:a}=e,r=p(e),[i,l]=(0,t.useState)((()=>function(e){let{defaultValue:n,tabValues:s}=e;if(0===s.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!u({value:n,tabValues:s}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${s.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const t=s.find((e=>e.default))??s[0];if(!t)throw new Error("Unexpected error: 0 tabValues");return t.value}({defaultValue:n,tabValues:r}))),[c,h]=m({queryString:s,groupId:a}),[g,x]=function(e){let{groupId:n}=e;const s=function(e){return e?`docusaurus.tab.${e}`:null}(n),[a,r]=(0,d.Dv)(s);return[a,(0,t.useCallback)((e=>{s&&r.set(e)}),[s,r])]}({groupId:a}),f=(()=>{const e=c??g;return u({value:e,tabValues:r})?e:null})();(0,o.A)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,t.useCallback)((e=>{if(!u({value:e,tabValues:r}))throw new Error(`Can't select invalid tab value=${e}`);l(e),h(e),x(e)}),[h,x,r]),tabValues:r}}var x=s(2303);const f={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var y=s(4848);function b(e){let{className:n,block:s,selectedValue:t,selectValue:i,tabValues:o}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,r.a_)(),d=e=>{const n=e.currentTarget,s=l.indexOf(n),a=o[s].value;a!==t&&(c(n),i(a))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const s=l.indexOf(e.currentTarget)+1;n=l[s]??l[0];break}case"ArrowLeft":{const s=l.indexOf(e.currentTarget)-1;n=l[s]??l[l.length-1];break}}n?.focus()};return(0,y.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,a.A)("tabs",{"tabs--block":s},n),children:o.map((e=>{let{value:n,label:s,attributes:r}=e;return(0,y.jsx)("li",{role:"tab",tabIndex:t===n?0:-1,"aria-selected":t===n,ref:e=>l.push(e),onKeyDown:h,onClick:d,...r,className:(0,a.A)("tabs__item",f.tabItem,r?.className,{"tabs__item--active":t===n}),children:s??n},n)}))})}function j(e){let{lazy:n,children:s,selectedValue:a}=e;const r=(Array.isArray(s)?s:[s]).filter(Boolean);if(n){const e=r.find((e=>e.props.value===a));return e?(0,t.cloneElement)(e,{className:"margin-top--md"}):null}return(0,y.jsx)("div",{className:"margin-top--md",children:r.map(((e,n)=>(0,t.cloneElement)(e,{key:n,hidden:e.props.value!==a})))})}function v(e){const n=g(e);return(0,y.jsxs)("div",{className:(0,a.A)("tabs-container",f.tabList),children:[(0,y.jsx)(b,{...n,...e}),(0,y.jsx)(j,{...n,...e})]})}function w(e){const n=(0,x.A)();return(0,y.jsx)(v,{...e,children:h(e.children)},String(n))}},3108:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/gasless-gsn-flow-ce9d704c33063bf100cc9d483f696a95.jpg"},9922:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/gasless-on-chain-signer-3f3b75e0b9fddb83e45c51d52ee5a8bd.svg"},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>o});var t=s(6540);const a={},r=t.createContext(a);function i(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e6c3daa2.c91c6ce2.js b/assets/js/e6c3daa2.c91c6ce2.js new file mode 100644 index 0000000000..c75ad550c7 --- /dev/null +++ b/assets/js/e6c3daa2.c91c6ce2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6704],{5466:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>i,toc:()=>d});var t=s(4848),r=s(8453);const a={description:"How to setup your Ledger hardware wallet"},o="Ledger Hardware Wallet",i={id:"general/manage-tokens/holding-rose-tokens/ledger-wallet",title:"Ledger Hardware Wallet",description:"How to setup your Ledger hardware wallet",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/holding-rose-tokens/ledger-wallet.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"How to setup your Ledger hardware wallet"},sidebar:"general",previous:{title:"Custody Providers & Protocols",permalink:"/general/manage-tokens/holding-rose-tokens/custody-providers"},next:{title:"How to Transfer ETH/ERC20 to Emerald ParaTime",permalink:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime"}},l={},d=[{value:"Setup your Ledger device and Install Oasis App",id:"setup-your-ledger-device-and-install-oasis-app",level:2},{value:"Connect to your wallet",id:"connect-to-your-wallet",level:2},{value:"ROSE Wallet",id:"rose-wallet",level:3},{value:"Oasis CLI",id:"oasis-cli",level:3},{value:"Signing the transaction",id:"signing-the-transaction",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"ledger-hardware-wallet",children:"Ledger Hardware Wallet"}),"\n",(0,t.jsxs)(n.p,{children:["This is a general documentation that will help users setup the ",(0,t.jsx)(n.a,{href:"https://www.ledger.com",children:"Ledger"})," hadware\nwallet on the Oasis Network. Ledger Live 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,t.jsx)(n.a,{href:"https://wallet.oasis.io",children:"ROSE Wallet - Web"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"setup-your-ledger-device-and-install-oasis-app",children:"Setup your Ledger device and Install Oasis App"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["To use your ",(0,t.jsx)(n.a,{href:"https://www.ledger.com",children:"Ledger"})," wallet to hold your ROSE tokens, you will have to\ninstall ",(0,t.jsx)(n.a,{href:"https://github.com/Zondax/ledger-oasis",children:"Oasis app"})," on your Ledger wallet via ",(0,t.jsx)(n.a,{href:"https://www.ledger.com/ledger-live/",children:"Ledger Live"}),'\'s Manager. Click\non the "My Ledger" button. Then, you need to connect your Ledger to your\ncomputer and unlock it with your PIN code.']}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Unlock ledger",src:s(3989).A+"",width:"1920",height:"1051"})}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.p,{children:"The Oasis app requires an up-to-date firmware on your Ledger wallet:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["At least ",(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360014980580-Ledger-Nano-X-firmware-release-notes",children:"version 2.0.0"})," released on Oct 21, 2021 on a Nano X device."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["At least ",(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360010446000-Ledger-Nano-S-firmware-release-notes",children:"version 2.1.0"})," released on Nov 30, 2021 on a Nano S device."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["At least ",(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/4494540771997-Ledger-Nano-S-Plus-Firmware-Release-Notes",children:"version 1.0.4"})," released on Sep 27, 2022 on a Nano S Plus device."]}),"\n"]}),"\n"]}),(0,t.jsx)(n.p,{children:"Follow Ledger's instructions for updating the firmware on your Ledger wallet:"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360013349800",children:"Nano X"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/360002731113-Update-Ledger-Nano-S-firmware",children:"Nano S"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://support.ledger.com/hc/en-us/articles/4445777839901-Update-Ledger-Nano-S-Plus-firmware",children:"Nano S Plus"})}),"\n"]})]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Next, allow the Ledger Manager on your Ledger device. Then you will be able\nto open the App catalog and search for ",(0,t.jsx)(n.code,{children:"oasis"}),":"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.img,{alt:"Allow Ledger Manager",src:s(712).A+"",width:"1920",height:"1051"}),"\n",(0,t.jsx)(n.img,{alt:"Search app in catalog..",src:s(6362).A+"",width:"1920",height:"1051"})]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Install the ",(0,t.jsx)(n.strong,{children:"Oasis"})," Nano app."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Install the Oasis Nano app",src:s(5244).A+"",width:"1920",height:"1051"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:'After the installation is complete, take your Ledger device, navigate to the\nOasis app and use both buttons to open it. Your Ledger device is ready when\nyou will see the "Oasis Ready" message.'}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"Oasis Ready",src:s(5407).A+"",width:"640",height:"480"})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["The Oasis app will use the ",(0,t.jsx)(n.a,{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",children:"BIP 39"})," mnemonic seed stored secretly on your\nLedger hardware wallet to generate the private & public key pairs for your\nOasis accounts. ",(0,t.jsx)(n.strong,{children:"Make sure you backed up the mnemonic when you first\ninitialized your Ledger device!"})]}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsxs)(n.p,{children:["For security, the ROSE Wallet uses a ",(0,t.jsx)(n.strong,{children:"different mnemonic to private key\nderivation path"})," by default for your Ledger accounts (known as ",(0,t.jsx)(n.em,{children:"Ledger"})," or\n",(0,t.jsx)(n.em,{children:"ed25519-legacy"}),") and for the accounts stored on a disk or inside a browser\n(also known as ",(0,t.jsx)(n.a,{href:"/adrs/0008-standard-account-key-generation",children:"ADR-8"}),"). If you find yourself in a situation where your Ledger\ndevice does not function anymore, you have the backup mnemonic available, and\nyou urgently need to access your funds, use the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/tools/tree/main/unmnemonic",children:"Oasis unmnemonic tool"})})," to\n",(0,t.jsx)(n.strong,{children:"derive the private key from your Ledger mnemonic"}),". Checkout out this\n",(0,t.jsx)(n.a,{href:"/general/manage-tokens/faq#i-lost-my-ledger-or-my-ledger-is-broken-i-urgently-need-to-access-my-assets-can-i-import-ledger-mnemonic-into-rose-wallet",children:"FAQ section"})," to download it and learn more."]})}),"\n",(0,t.jsx)(n.h2,{id:"connect-to-your-wallet",children:"Connect to your wallet"}),"\n",(0,t.jsx)(n.h3,{id:"rose-wallet",children:"ROSE Wallet"}),"\n",(0,t.jsx)(n.p,{children:"This is a simpler option since it offers a nice UI for connecting your Ledger to\na web application or a browser extension. Check out the following sections\ncorresponding to your wallet for instructions:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/web#import-an-existing-account",children:"ROSE Wallet - Web: Import Ledger account"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/general/manage-tokens/oasis-wallets/browser-extension#ledger",children:"ROSE Wallet - Browser extension: Ledger"})}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsx)(n.p,{children:"At time of writing, signing the ParaTime transactions is not yet supported by\nthe ROSE Wallet - Web or the Browser extension."})}),"\n",(0,t.jsx)(n.h3,{id:"oasis-cli",children:"Oasis CLI"}),"\n",(0,t.jsx)(n.p,{children:"This is a more powerful option that allows performing not just token-related\ntasks (transferring, staking, ParaTime deposits, withdrawals and transfers), but\nalso generating and/or signing raw transactions, multi-signatures, network\ngovernance operations etc."}),"\n",(0,t.jsxs)(n.p,{children:["Ledger is supported by the ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," out of the box. You can add a new Ledger\naccount to the Oasis CLI by invoking the ",(0,t.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#create",children:(0,t.jsx)(n.code,{children:"oasis wallet create"})})," command and\nadding the ",(0,t.jsx)(n.code,{children:"--kind ledger"})," parameter. For\nexample:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"oasis wallet create logan --kind ledger\n"})}),"\n",(0,t.jsx)(n.h2,{id:"signing-the-transaction",children:"Signing the transaction"}),"\n",(0,t.jsxs)(n.p,{children:["Once your Ledger account is registered to the wallet on your computer, you can\nuse it to sign the transactions. After confirming the transaction on your\ncomputer, the transaction details ",(0,t.jsx)(n.strong,{children:"will appear on your Ledger screen"}),"\nwhere you will need to ",(0,t.jsx)(n.strong,{children:"carefully review transaction details and make sure they\nmatch the ones on your computer"}),'. Then, navigate to the screen where you will\nsee the "APPROVE" button. Use the two buttons to approve your transaction.']}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"ROSE Wallet - Web -> Ledger -> Approve TX",src:s(2757).A+"",width:"1280",height:"960"})}),"\n",(0,t.jsx)(n.p,{children:"The signed transaction will be sent back to your computer and submitted to the\nnetwork."})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},2757:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/ledger_oasis_approve-107bae9057a413cc91850ab7cceb910e.jpg"},5407:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg"},712:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/live_allow_ledger_manager-0d550bcf5c975eaef183b78baa74b269.png"},6362:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/live_search_apps-0c74d0a0063a45242988e15770c01176.png"},5244:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/live_search_results_oasis_install-320e7861a97fc5b72575c82d0edbcde8.png"},3989:(e,n,s)=>{s.d(n,{A:()=>t});const t=s.p+"assets/images/live_unlock_ledger-ef4071262dfbba6f5c0544a7efd15b5e.png"},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>i});var t=s(6540);const r={},a=t.createContext(r);function o(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e6f41e1e.851cc106.js b/assets/js/e6f41e1e.851cc106.js new file mode 100644 index 0000000000..2fbfe39cb2 --- /dev/null +++ b/assets/js/e6f41e1e.851cc106.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[564],{355:(e,s,d)=>{d.r(s),d.d(s,{assets:()=>i,contentTitle:()=>a,default:()=>x,frontMatter:()=>c,metadata:()=>n,toc:()=>h});var r=d(4848),t=d(8453);const c={description:"List of Standard Contract Addresses"},a="Contract Addresses and Deployments",n={id:"dapp/sapphire/addresses",title:"Contract Addresses and Deployments",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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/sapphire-paratime/edit/main/docs/addresses.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"List of Standard Contract Addresses"},sidebar:"developers",previous:{title:"Gasless Transactions",permalink:"/dapp/sapphire/gasless"},next:{title:"Deployment Patterns",permalink:"/dapp/sapphire/deployment"}},i={},h=[{value:"Standard Contract Addresses",id:"standard-contract-addresses",level:2},{value:"Celer cBridge Tokens (Mainnet)",id:"celer-cbridge-tokens-mainnet",level:2},{value:"Celer cBridge Tokens (Testnet)",id:"celer-cbridge-tokens-testnet",level:2},{value:"Deployments",id:"deployments",level:2}];function l(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h1,{id:"contract-addresses-and-deployments",children:"Contract Addresses and Deployments"}),"\n",(0,r.jsx)(s.h2,{id:"standard-contract-addresses",children:"Standard Contract Addresses"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Name"}),(0,r.jsx)(s.th,{children:"Mainnet Address"}),(0,r.jsx)(s.th,{children:"Testnet Address"}),(0,r.jsx)(s.th,{children:"Verify"}),(0,r.jsx)(s.th,{children:"Source"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://multicall3.com/",children:"Multicall V3"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0xcA11bde05977b3631167028862bE2a173976CA11"})}),(0,r.jsx)(s.td,{children:"-"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://sourcify.dev/#/lookup/0xcA11bde05977b3631167028862bE2a173976CA11",children:"Mainnet"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/mds1/multicall/blob/main/src/Multicall3.sol",children:"Multicall3.sol"})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://wrose.oasis.io/",children:"Wrapped ROSE"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.code,{children:"0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94"})}),(0,r.jsxs)(s.td,{children:[(0,r.jsx)(s.a,{href:"https://sourcify.dev/#/lookup/0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3",children:"Mainnet"}),", ",(0,r.jsx)(s.a,{href:"https://sourcify.dev/#/lookup/0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94",children:"Testnet"})]}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/oasisprotocol/sapphire-paratime/blob/main/contracts/contracts/WrappedROSE.sol",children:"WrappedROSE.sol"})})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"celer-cbridge-tokens-mainnet",children:"Celer cBridge Tokens (Mainnet)"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Source Chain"}),(0,r.jsx)(s.th,{children:"Token Name"}),(0,r.jsx)(s.th,{children:"Source Address"}),(0,r.jsx)(s.th,{children:"Dest. Chain"}),(0,r.jsx)(s.th,{children:"Dest Address"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Ethereum Mainnet (1)"}),(0,r.jsx)(s.td,{children:"OCEAN"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://etherscan.io/address/0x967da4048cD07aB37855c090aAF366e4ce1b9F48",children:(0,r.jsx)(s.code,{children:"0x967da4048cD07aB37855c090aAF366e4ce1b9F48"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x39d22B78A7651A76Ffbde2aaAB5FD92666Aca520",children:(0,r.jsx)(s.code,{children:"0x39d22B78A7651A76Ffbde2aaAB5FD92666Aca520"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Ethereum Mainnet (1)"}),(0,r.jsx)(s.td,{children:"USDC"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",children:(0,r.jsx)(s.code,{children:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x2c2E3812742Ab2DA53a728A09F5DE670Aba584b6",children:(0,r.jsx)(s.code,{children:"0x2c2E3812742Ab2DA53a728A09F5DE670Aba584b6"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Ethereum Mainnet (1)"}),(0,r.jsx)(s.td,{children:"USDT"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://etherscan.io/address/0xdAC17F958D2ee523a2206206994597C13D831ec7",children:(0,r.jsx)(s.code,{children:"0xdAC17F958D2ee523a2206206994597C13D831ec7"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xE48151964556381B33f93E05E36381Fd53Ec053E",children:(0,r.jsx)(s.code,{children:"0xE48151964556381B33f93E05E36381Fd53Ec053E"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Ethereum Mainnet (1)"}),(0,r.jsx)(s.td,{children:"WBTC"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://etherscan.io/address/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",children:(0,r.jsx)(s.code,{children:"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xE9533976C590200E32d95C53f06AE12d292cFc47",children:(0,r.jsx)(s.code,{children:"0xE9533976C590200E32d95C53f06AE12d292cFc47"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Ethereum Mainnet (1)"}),(0,r.jsx)(s.td,{children:"WETH"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",children:(0,r.jsx)(s.code,{children:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xfc6b18d694F2D137dB762B152736Ba098F9808d9",children:(0,r.jsx)(s.code,{children:"0xfc6b18d694F2D137dB762B152736Ba098F9808d9"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"BNB Chain (56)"}),(0,r.jsx)(s.td,{children:"BNB"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://bscscan.com/address/0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",children:(0,r.jsx)(s.code,{children:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xe95E3a9f1a45B5EDa71781448F6047d7B7e31cbF",children:(0,r.jsx)(s.code,{children:"0xe95E3a9f1a45B5EDa71781448F6047d7B7e31cbF"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Polygon PoS (137)"}),(0,r.jsx)(s.td,{children:"MATIC"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://polygonscan.com/address/0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",children:(0,r.jsx)(s.code,{children:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xa349005a68FA33e8DACAAa850c45175bbcD49B19",children:(0,r.jsx)(s.code,{children:"0xa349005a68FA33e8DACAAa850c45175bbcD49B19"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Oasis Sapphire (23294)"}),(0,r.jsx)(s.td,{children:"wROSE"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3",children:(0,r.jsx)(s.code,{children:"0x8Bc2B030b299964eEfb5e1e0b36991352E56D2D3"})})}),(0,r.jsx)(s.td,{children:"BNB Chain (56)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://bscscan.com/address/0xF00600eBC7633462BC4F9C61eA2cE99F5AAEBd4a",children:(0,r.jsx)(s.code,{children:"0xF00600eBC7633462BC4F9C61eA2cE99F5AAEBd4a"})})})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"celer-cbridge-tokens-testnet",children:"Celer cBridge Tokens (Testnet)"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Source Chain"}),(0,r.jsx)(s.th,{children:"Token Name"}),(0,r.jsx)(s.th,{children:"Source Address"}),(0,r.jsx)(s.th,{children:"Dest. Chain"}),(0,r.jsx)(s.th,{children:"Dest Address"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Goerli (5)"}),(0,r.jsx)(s.td,{children:"USDT"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://goerli.etherscan.io/address/0xf4B2cbc3bA04c478F0dC824f4806aC39982Dce73",children:(0,r.jsx)(s.code,{children:"0xf4B2cbc3bA04c478F0dC824f4806aC39982Dce73"})})}),(0,r.jsx)(s.td,{children:"Oasis Sapphire Testnet (23295)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://testnet.explorer.sapphire.oasis.dev/address/0xa55C7E1274bE5db2275a0BDd055f81e8263b7954",children:(0,r.jsx)(s.code,{children:"0xa55C7E1274bE5db2275a0BDd055f81e8263b7954"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Oasis Sapphire Testnet (23295)"}),(0,r.jsx)(s.td,{children:"wROSE"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://testnet.explorer.sapphire.oasis.dev/address/0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94",children:(0,r.jsx)(s.code,{children:"0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94"})})}),(0,r.jsx)(s.td,{children:"BSC Testnet (97)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://testnet.bscscan.com/address/0x26a6f43BaEDD1767c283e2555A9E1236E5aE3A55",children:(0,r.jsx)(s.code,{children:"0x26a6f43BaEDD1767c283e2555A9E1236E5aE3A55"})})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:"Oasis Sapphire Testnet (23295)"}),(0,r.jsx)(s.td,{children:"wROSE"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://testnet.explorer.sapphire.oasis.dev/address/0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94",children:(0,r.jsx)(s.code,{children:"0xB759a0fbc1dA517aF257D5Cf039aB4D86dFB3b94"})})}),(0,r.jsx)(s.td,{children:"Polygon Mumbai (80001)"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://mumbai.polygonscan.com/address/0xE9533976C590200E32d95C53f06AE12d292cFc47",children:(0,r.jsx)(s.code,{children:"0xE9533976C590200E32d95C53f06AE12d292cFc47"})})})]})]})]}),"\n",(0,r.jsx)(s.h2,{id:"deployments",children:"Deployments"}),"\n",(0,r.jsxs)(s.table,{children:[(0,r.jsx)(s.thead,{children:(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.th,{children:"Name"}),(0,r.jsx)(s.th,{children:"Mainnet Address"}),(0,r.jsx)(s.th,{children:"Testnet Address"}),(0,r.jsx)(s.th,{children:"Source"})]})}),(0,r.jsxs)(s.tbody,{children:[(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://im-docs.celer.network/developer/development-guide/message-executor",children:"Celer IM Executor"})}),(0,r.jsx)(s.td,{children:"Multiple executors available"}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/sapphire/address/0x9C850D230FFFaCEf1E2D1741a00080856630e455",children:(0,r.jsx)(s.code,{children:"0x9C850D230FFFaCEf1E2D1741a00080856630e455"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/celer-network/im-executor",children:"Message Executor"})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://im-docs.celer.network/developer/development-guide/message-executor",children:"Celer MessageBus"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D",children:(0,r.jsx)(s.code,{children:"0x9Bb46D5100d2Db4608112026951c9C965b233f4D"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/sapphire/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D",children:(0,r.jsx)(s.code,{children:"0x9Bb46D5100d2Db4608112026951c9C965b233f4D"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/celer-network/sgn-v2-contracts/blob/6af81b55a13a7aacab9a4d92a38d374d46c0fdbf/contracts/message/messagebus/MessageBus.sol",children:"Message bus"})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/safe-global/safe-singleton-factory/",children:"Safe Singleton Factory"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",children:(0,r.jsx)(s.code,{children:"0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/sapphire/address/0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",children:(0,r.jsx)(s.code,{children:"0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/safe-global/safe-singleton-factory/",children:"Singleton Factory"})})]}),(0,r.jsxs)(s.tr,{children:[(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://docs.bandchain.org/",children:"Band Oracle"})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/mainnet/sapphire/address/0xDA7a001b254CD22e46d3eAB04d937489c93174C3",children:(0,r.jsx)(s.code,{children:"0xDA7a001b254CD22e46d3eAB04d937489c93174C3"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://explorer.oasis.io/testnet/sapphire/address/0x0c2362c9A0586Dd7295549C65a4A5e3aFE10a88A",children:(0,r.jsx)(s.code,{children:"0x0c2362c9A0586Dd7295549C65a4A5e3aFE10a88A"})})}),(0,r.jsx)(s.td,{children:(0,r.jsx)(s.a,{href:"https://github.com/bandprotocol/band-std-reference-contracts-solidity",children:"Oracle"})})]})]})]})]})}function x(e={}){const{wrapper:s}={...(0,t.R)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,s,d)=>{d.d(s,{R:()=>a,x:()=>n});var r=d(6540);const t={},c=r.createContext(t);function a(e){const s=r.useContext(c);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function n(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),r.createElement(c.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e793830e.e9b8e6e7.js b/assets/js/e793830e.e9b8e6e7.js new file mode 100644 index 0000000000..fc1b6cbfde --- /dev/null +++ b/assets/js/e793830e.e9b8e6e7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5801],{6326:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>t,toc:()=>a});var d=o(4848),s=o(8453);const i={},r="Seed Node",t={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/seed-node.md",tags:[],version:"current",lastUpdatedAt:172612742e4,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"}},c={},a=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(n.h1,{id:"seed-node",children:"Seed Node"}),"\n",(0,d.jsx)(n.p,{children:"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."}),"\n",(0,d.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,d.jsxs)(n.p,{children:["Before following this guide, make sure you've followed the ",(0,d.jsx)(n.a,{href:"/node/run-your-node/prerequisites/oasis-node",children:"Prerequisites Guide"})," and understand how to use the ",(0,d.jsx)(n.code,{children:"oasis-node"})," binary."]}),"\n",(0,d.jsx)(n.h3,{id:"creating-a-working-directory",children:"Creating a Working Directory"}),"\n",(0,d.jsxs)(n.p,{children:["We will be creating the following directory structure inside a chosen top-level ",(0,d.jsx)(n.code,{children:"/node"})," (feel free to name your directories however you wish) directory:"]}),"\n",(0,d.jsxs)(n.ul,{children:["\n",(0,d.jsxs)(n.li,{children:["\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.code,{children:"etc"}),": This will store the node configuration and genesis file."]}),"\n"]}),"\n",(0,d.jsxs)(n.li,{children:["\n",(0,d.jsxs)(n.p,{children:[(0,d.jsx)(n.code,{children:"data"}),": This will store the data directory needed by the running ",(0,d.jsx)(n.code,{children:"oasis-node"})," binary, including the complete blockchain state."]}),"\n",(0,d.jsxs)(n.p,{children:["The directory permissions should be ",(0,d.jsx)(n.code,{children:"rwx------"}),"."]}),"\n"]}),"\n"]}),"\n",(0,d.jsx)(n.p,{children:"To create the directory structure, use the following command:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-text",children:"mkdir -m700 -p /node/{etc,data}\n"})}),"\n",(0,d.jsx)(n.h3,{id:"copying-the-genesis-file",children:"Copying the Genesis File"}),"\n",(0,d.jsxs)(n.p,{children:["The latest genesis file can be found in the Network Parameters page (",(0,d.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,d.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),"). You should download the latest ",(0,d.jsx)(n.code,{children:"genesis.json"})," file and copy it to the ",(0,d.jsx)(n.code,{children:"/node/etc"})," directory we just created."]}),"\n",(0,d.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,d.jsx)(n.admonition,{type:"info",children:(0,d.jsx)(n.p,{children:"This will configure the given node to only act as a seed node."})}),"\n",(0,d.jsxs)(n.p,{children:["In order to configure the node create the ",(0,d.jsx)(n.code,{children:"/node/etc/config.yml"})," file with the following content:"]}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-yaml",children:"mode: seed\ncommon:\n data_dir: /node/data\n log:\n format: JSON\n level:\n cometbft: info\n cometbft/context: error\n default: info\n\ngenesis:\n file: /node/etc/genesis.json\n"})}),"\n",(0,d.jsx)(n.admonition,{type:"caution",children:(0,d.jsxs)(n.p,{children:["Make sure the ",(0,d.jsx)(n.code,{children:"consensus"})," port (default: ",(0,d.jsx)(n.code,{children:"26656"}),") and ",(0,d.jsx)(n.code,{children:"p2p.port"})," (default: ",(0,d.jsx)(n.code,{children:"9200"}),") are exposed and publicly\naccessible on the internet (for ",(0,d.jsx)(n.code,{children:"TCP"})," and ",(0,d.jsx)(n.code,{children:"UDP"})," traffic)."]})}),"\n",(0,d.jsx)(n.h2,{id:"starting-the-oasis-node",children:"Starting the Oasis Node"}),"\n",(0,d.jsx)(n.p,{children:"You can start the node by running the following command:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"oasis-node --config /node/etc/config.yml\n"})}),"\n",(0,d.jsx)(n.h3,{id:"seed-node-address",children:"Seed node address"}),"\n",(0,d.jsx)(n.p,{children:"To get the seed node Tendermint identity, run the following command:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"oasis-node identity tendermint show-node-address --datadir /node/data/\n"})}),"\n",(0,d.jsx)(n.h3,{id:"share-seed-node-address",children:"Share seed node address"}),"\n",(0,d.jsx)(n.p,{children:"Nodes can now use your seed node by specifying it via a configuration flag:"}),"\n",(0,d.jsx)(n.pre,{children:(0,d.jsx)(n.code,{className:"language-bash",children:"--consensus.tendermint.p2p.seed @:26656\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,d.jsx)(n,{...e,children:(0,d.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>t});var d=o(6540);const s={},i=d.createContext(s);function r(e){const n=d.useContext(i);return d.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),d.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e7b1111d.bebfd2b6.js b/assets/js/e7b1111d.bebfd2b6.js new file mode 100644 index 0000000000..bbb7c5dcb9 --- /dev/null +++ b/assets/js/e7b1111d.bebfd2b6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[6037],{4575:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"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","sidebar":"operators","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/e7c70926.57f0099e.js b/assets/js/e7c70926.57f0099e.js new file mode 100644 index 0000000000..0ffec405eb --- /dev/null +++ b/assets/js/e7c70926.57f0099e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5084],{7627:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"3rd Party Wallets and Services","description":"There is a number of 3rd party services, tools and wallets out there which support the Oasis network. Some of them are categorized below. Keep in mind that these products were developed by 3rd parties and the Oasis Protocol Foundation cannot be held responsible for any security vulnerabilities or malicious activity.","slug":"general/manage-tokens/holding-rose-tokens","permalink":"/general/manage-tokens/holding-rose-tokens","sidebar":"general","navigation":{"previous":{"title":"Browser Extension","permalink":"/general/manage-tokens/oasis-wallets/browser-extension"},"next":{"title":"Custody Providers & Protocols","permalink":"/general/manage-tokens/holding-rose-tokens/custody-providers"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/e9951844.ee49c8fe.js b/assets/js/e9951844.ee49c8fe.js new file mode 100644 index 0000000000..6063e2f24d --- /dev/null +++ b/assets/js/e9951844.ee49c8fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5592],{6443:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=s(4848),t=s(8453);const o={},r="Cryptography",a={id:"core/crypto",title:"Cryptography",description:"Hash Functions",source:"@site/docs/core/crypto.md",sourceDirName:"core",slug:"/core/crypto",permalink:"/core/crypto",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/crypto.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Encoding",permalink:"/core/encoding"},next:{title:"Authenticated gRPC",permalink:"/core/authenticated-grpc"}},c={},d=[{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}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"cryptography",children:"Cryptography"}),"\n",(0,i.jsx)(n.h2,{id:"hash-functions",children:"Hash Functions"}),"\n",(0,i.jsxs)(n.p,{children:["In most places where cryptographic hashes are required, we use the SHA-512/256\nhash function as specified in ",(0,i.jsx)(n.a,{href:"https://csrc.nist.gov/publications/detail/fips/180/4/final",children:"FIPS 180-4"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"signatures",children:"Signatures"}),"\n",(0,i.jsxs)(n.p,{children:["All cryptographic signatures are made using the Ed25519 (pure) scheme specified\nin ",(0,i.jsx)(n.a,{href:"https://tools.ietf.org/html/rfc8032",children:"RFC 8032"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"domain-separation",children:"Domain Separation"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"The message to be signed is computed as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"M := H(Context || Message)\n"})}),"\n",(0,i.jsx)(n.p,{children:"Where:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"H"})," is the SHA-512/256 cryptographic hash function."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Context"})," is the domain separation context string."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Message"})," is the original message."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The Ed25519 signature is then computed over ",(0,i.jsx)(n.code,{children:"M"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["NOTE: While using something like Ed25519ph/ctx as specified by ",(0,i.jsx)(n.a,{href:"https://tools.ietf.org/html/rfc8032",children:"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."]})}),"\n",(0,i.jsx)(n.h4,{id:"contexts",children:"Contexts"}),"\n",(0,i.jsx)(n.p,{children:"All of the domain separation contexts used in Oasis Core use the following\nconvention:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["They start with the string ",(0,i.jsx)(n.code,{children:"oasis-core/"}),","]}),"\n",(0,i.jsx)(n.li,{children:"followed by the general module name,"}),"\n",(0,i.jsxs)(n.li,{children:["followed by the string ",(0,i.jsx)(n.code,{children:": "}),","]}),"\n",(0,i.jsx)(n.li,{children:"followed by a use case description."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The maximum length of a domain separation context is 255 bytes to be compatible\nwith the length defined in ",(0,i.jsx)(n.a,{href:"https://tools.ietf.org/html/rfc8032",children:"RFC 8032"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The Go implementation maintains a registry of all used contexts to make sure\nthey are not reused incorrectly."}),"\n",(0,i.jsx)(n.h4,{id:"chain-domain-separation",children:"Chain Domain Separation"}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.p,{children:"For all domain separation contexts where chain domain separation is required,\nwe use the following additional convention:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"The context is as specified by the convention in the section above,"}),"\n",(0,i.jsxs)(n.li,{children:["followed by the string ",(0,i.jsx)(n.code,{children:"for chain"}),","]}),"\n",(0,i.jsxs)(n.li,{children:["followed by the ",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-documents-hash",children:"genesis document's hash"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"envelopes",children:"Envelopes"}),"\n",(0,i.jsx)(n.p,{children:"There are currently two kinds of envelopes that are used when signing CBOR\nmessages:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/signature?tab=doc#Signed",children:["Single signature envelope (",(0,i.jsx)(n.code,{children:"Signed"}),")"]})," contains the CBOR-serialized blob in\nthe ",(0,i.jsx)(n.code,{children:"untrusted_raw_value"})," field and a single ",(0,i.jsx)(n.code,{children:"signature"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.a,{href:"https://pkg.go.dev/github.com/oasisprotocol/oasis-core/go/common/crypto/signature?tab=doc#MultiSigned",children:["Multiple signature envelope (",(0,i.jsx)(n.code,{children:"MultiSigned"}),")"]})," contains the CBOR-serialized\nblob in the ",(0,i.jsx)(n.code,{children:"untrusted_raw_value"})," field and multiple signatures in the\n",(0,i.jsx)(n.code,{children:"signatures"})," field."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The envelopes are themselves CBOR-encoded. While no separate test vectors are\nprovided, ",(0,i.jsx)(n.a,{href:"/core/consensus/test-vectors",children:"those used for transactions"})," can be used as a reference."]}),"\n",(0,i.jsx)(n.h2,{id:"standard-account-key-generation",children:"Standard Account Key Generation"}),"\n",(0,i.jsxs)(n.p,{children:["When generating an ",(0,i.jsx)(n.a,{href:"/core/consensus/services/staking#accounts",children:"account"}),"'s private/public key pair, follow ",(0,i.jsx)(n.a,{href:"https://github.com/oasisprotocol/adrs/blob/master/0008-standard-account-key-generation.md",children:"ADR 0008:\nStandard Account Key Generation"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>a});var i=s(6540);const t={},o=i.createContext(t);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ea8b28d2.c197a81f.js b/assets/js/ea8b28d2.c197a81f.js new file mode 100644 index 0000000000..d6247b98ef --- /dev/null +++ b/assets/js/ea8b28d2.c197a81f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[1927],{4374:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>t,toc:()=>c});var o=s(4848),a=s(8453);const r={title:"Address book",description:"Storing your blockchain contacts for future use"},d="Address Book",t={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/cli/edit/master/docs/addressbook.md",tags:[],version:"current",lastUpdatedAt:1715850376e3,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={},c=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"address-book",children:"Address Book"}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.code,{children:"addressbook"}),"\ncommand to ",(0,o.jsx)(n.strong,{children:"name the address and store it in your address book"}),". Entries\nin your address book are behaving similarly to the\n",(0,o.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet",children:"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."]}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsx)(n.p,{children:"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."})}),"\n",(0,o.jsx)(n.h2,{id:"add",children:"Add a New Entry"}),"\n",(0,o.jsxs)(n.p,{children:["Use ",(0,o.jsx)(n.code,{children:"addressbook add
"})," to name the address and store it in your\naddress book."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook add mike oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook add meghan 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1\n"})}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.code,{children:"2.5 TEST"})," to ",(0,o.jsx)(n.code,{children:"meghan"})," on Sapphire\nTestnet:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis account transfer 2.5 meghan\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"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"})}),"\n",(0,o.jsx)(n.h2,{id:"list",children:"List Entries"}),"\n",(0,o.jsxs)(n.p,{children:["You can list all entries in your address book by invoking ",(0,o.jsx)(n.code,{children:"addressbook list"}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook list\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"NAME \tADDRESS \nmeghan\t0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \t\nmike \toasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\t\n"})}),"\n",(0,o.jsx)(n.h2,{id:"show",children:"Show Entry Details"}),"\n",(0,o.jsxs)(n.p,{children:["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,o.jsx)(n.code,{children:"addressbook show "}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook show meghan\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"Name: meghan\nEthereum address: 0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1\nNative address: oasis1qrjzcve7y6qp3nqs3n7ghavw68vkdh3epcv64ega\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook show mike\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"Name: mike\nNative address: oasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\n"})}),"\n",(0,o.jsx)(n.h2,{id:"rename",children:"Rename an Entry"}),"\n",(0,o.jsxs)(n.p,{children:["You can always rename the entry in your address book by using\n",(0,o.jsx)(n.code,{children:"addressbook rename "}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook list\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"NAME \tADDRESS \nmeghan\t0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \t\nmike \toasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\t\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook rename mike mark\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook list\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"NAME \tADDRESS \nmark \toasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\t\nmeghan\t0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \t\n"})}),"\n",(0,o.jsx)(n.h2,{id:"remove",children:"Remove an Entry"}),"\n",(0,o.jsxs)(n.p,{children:["To delete an entry from your address book invoke\n",(0,o.jsx)(n.code,{children:"addressbook remove "}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook list\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"NAME \tADDRESS \nmeghan\t0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1 \t\nmike \toasis1qrtrpg56l6y2cfudwtgfuxmq5e5cyhffcsfpdqvw\t\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook remove mike\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-shell",children:"oasis addressbook list\n"})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"NAME \tADDRESS \nmeghan\t0xBe8B38ED9b0794e7ab9EbEfC1e710b4F4EC6F6C1\t\n"})})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>t});var o=s(6540);const a={},r=o.createContext(a);function d(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:d(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/eb341911.b02e7da2.js b/assets/js/eb341911.b02e7da2.js new file mode 100644 index 0000000000..1f173ad0c7 --- /dev/null +++ b/assets/js/eb341911.b02e7da2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[823],{6206:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>a,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=s(4848),i=s(8453);const o={},t="Versioning",c={id:"core/versioning",title:"Versioning",description:"Oasis Core",source:"@site/docs/core/versioning.md",sourceDirName:"core",slug:"/core/versioning",permalink:"/core/versioning",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/versioning.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Release Process",permalink:"/core/release-process"},next:{title:"Security",permalink:"/core/SECURITY"}},d={},l=[{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}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"versioning",children:"Versioning"}),"\n",(0,r.jsx)(n.h2,{id:"oasis-core",children:"Oasis Core"}),"\n",(0,r.jsxs)(n.p,{children:["Oasis Core (as a whole) uses a ",(0,r.jsx)(n.a,{href:"http://calver.org",children:"CalVer"})," (calendar versioning) scheme with the\nfollowing format:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"YY.MINOR[.MICRO][-MODIFIER]\n"})}),"\n",(0,r.jsx)(n.p,{children:"where:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"YY"})," represents short year (e.g. ",(0,r.jsx)(n.code,{children:"19"}),", ",(0,r.jsx)(n.code,{children:"20"}),", ",(0,r.jsx)(n.code,{children:"21"}),", ...),"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"MINOR"})," represents the minor version starting with zero (e.g. ",(0,r.jsx)(n.code,{children:"0"}),", ",(0,r.jsx)(n.code,{children:"1"}),", ",(0,r.jsx)(n.code,{children:"2"}),",\n",(0,r.jsx)(n.code,{children:"3"}),", ...),"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"MICRO"}),' represents (optional) final number in the version (sometimes referred\nto as the "patch" segment) (e.g. ',(0,r.jsx)(n.code,{children:"0"}),", ",(0,r.jsx)(n.code,{children:"1"}),", ",(0,r.jsx)(n.code,{children:"2"}),", ",(0,r.jsx)(n.code,{children:"3"}),", ...)."]}),"\n",(0,r.jsxs)(n.p,{children:["If the ",(0,r.jsx)(n.code,{children:"MICRO"})," version is ",(0,r.jsx)(n.code,{children:"0"}),", it will be omitted."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"MODIFIER"})," represents (optional) build metadata, e.g. ",(0,r.jsx)(n.code,{children:"git8c01382"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"YY"})," version must be bumped after each new calendar year."]}),"\n",(0,r.jsxs)(n.p,{children:["When a regularly scheduled release is made, the ",(0,r.jsx)(n.code,{children:"MINOR"})," version should be\nbumped."]}),"\n",(0,r.jsxs)(n.p,{children:["If there is a major fix that we want to back-port from an upcoming next release\nand release it, then the ",(0,r.jsx)(n.code,{children:"MICRO"})," version should be bumped."]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"MODIFIER"})," should be used to denote a build from an untagged (and\npotentially unclean) git source. It should be of the form:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"gitCOMMIT_SHA[+dirty]\n"})}),"\n",(0,r.jsx)(n.p,{children:"where:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"COMMIT_SHA"})," represents the current commit\u2019s abbreviated SHA."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"+dirty"})," part is optional and is only present if there are uncommitted\nchanges in the working directory."]}),"\n",(0,r.jsx)(n.h2,{id:"protocols-consensus-runtime-host-runtime-committee",children:"Protocols (Consensus, Runtime Host, Runtime Committee)"}),"\n",(0,r.jsxs)(n.p,{children:["Oasis Core\u2019s protocol versions use ",(0,r.jsx)(n.a,{href:"https://semver.org/",children:"SemVer"})," (semantic versioning) 2.0.0 with the\nfollowing format:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-text",children:"MAJOR.MINOR.PATCH\n"})}),"\n",(0,r.jsx)(n.p,{children:"where:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"MAJOR"})," represents the major version,"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"MINOR"})," represents the minor version,"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"PATCH"})," represents the patch version."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Whenever a backward-incompatible change is made to a protocol, the ",(0,r.jsx)(n.code,{children:"MAJOR"}),"\nversion must be bumped."]}),"\n",(0,r.jsxs)(n.p,{children:["If a new release adds a protocol functionality in a backwards compatible manner,\nthe ",(0,r.jsx)(n.code,{children:"MINOR"})," version must be bumped."]}),"\n",(0,r.jsxs)(n.p,{children:["When only backwards compatible bug fixes are made to a protocol, the ",(0,r.jsx)(n.code,{children:"PATCH"}),"\nversion should be bumped."]}),"\n",(0,r.jsx)(n.h3,{id:"version-100",children:"Version 1.0.0"}),"\n",(0,r.jsxs)(n.p,{children:["With the release of ",(0,r.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core/blob/v20.10/CHANGELOG.md",children:"Oasis Core 20.10"}),", we bumped the protocol versions to\nversion 1.0.0 which ",(0,r.jsx)(n.a,{href:"https://semver.org/#how-do-i-know-when-to-release-100",children:"signified that they are ready for production use"}),"."]})]})}function a(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var r=s(6540);const i={},o=r.createContext(i);function t(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f57ebf67.f746b865.js b/assets/js/f57ebf67.f746b865.js new file mode 100644 index 0000000000..05654805f8 --- /dev/null +++ b/assets/js/f57ebf67.f746b865.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[7793],{2176:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var i=s(4848),o=s(8453);const r={},t="Troubleshooting",d={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/troubleshooting.md",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Remote Signer for Oasis Node Keys",permalink:"/node/run-your-node/advanced/remote-signer"},next:{title:"Web3 Gateway",permalink:"/node/web3"}},l={},c=[{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:"Node directory Ownership",id:"node-directory-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}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",mdxAdmonitionTitle:"mdxAdmonitionTitle",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsx)(n.mdxAdmonitionTitle,{children:(0,i.jsx)(n.strong,{children:"BEFORE YOU BEGIN TROUBLESHOOTING"})}),(0,i.jsx)(n.p,{children:"Before you begin troubleshooting we suggest you check all of the following:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Check that your current binary version is the latest listed on the Network Parameters page (",(0,i.jsx)(n.a,{href:"/node/mainnet/",children:"Mainnet"}),", ",(0,i.jsx)(n.a,{href:"/node/testnet/",children:"Testnet"}),")"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Check the version on your localhost using ",(0,i.jsx)(n.code,{children:"oasis-node --version"})]}),"\n",(0,i.jsxs)(n.li,{children:["Check the version on your server using ",(0,i.jsx)(n.code,{children:"oasis-node --version"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"If upgrading, make sure that you've wiped state (unless that is explicitly not required)"}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"If you're doing anything with the entity:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Do you have the latest genesis?"}),"\n",(0,i.jsx)(n.li,{children:"Do you have the correct private key (or Ledger device)."}),"\n",(0,i.jsxs)(n.li,{children:["If you're signing a transaction:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Do you sufficient account balance to make the transaction?","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Run ",(0,i.jsx)(n.code,{children:"oasis-node stake account info"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["Are you using the correct nonce?","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Run ",(0,i.jsx)(n.code,{children:"oasis-node stake account info"})]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"If you're generating a transaction:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Do you have the latest genesis?"}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"If you're submitting a transaction:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Do you have the latest genesis?"}),"\n",(0,i.jsx)(n.li,{children:"Is your node synced? If not, the transaction will fail to run properly"}),"\n"]}),"\n"]}),"\n"]})]}),"\n",(0,i.jsx)(n.h2,{id:"running-a-node",children:"Running a Node"}),"\n",(0,i.jsx)(n.h3,{id:"invalid-permissions",children:"Invalid Permissions"}),"\n",(0,i.jsx)(n.h4,{id:"permissions-for-node-and-entity",children:"Permissions for node and entity"}),"\n",(0,i.jsx)(n.p,{children:"Error Message:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"common/Mkdir: path '/node/data' has invalid permissions: -rwxr-xr-x\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"entity"})," and ",(0,i.jsx)(n.code,{children:"node"})," directories both need to have permissions ",(0,i.jsx)(n.code,{children:"rwx------"}),". Make sure you initialize the directory with correct permissions or change them using ",(0,i.jsx)(n.code,{children:"chmod"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"mkdir --mode 700 --parents {entity,node}\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"chmod 700 /node/data\nchmod 700 /node/etc\n"})}),"\n",(0,i.jsx)(n.h4,{id:"permissions-for-pem-files",children:"Permissions for .pem files"}),"\n",(0,i.jsx)(n.p,{children:"Error Message example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"signature/signer/file: invalid PEM file permissions 700 on /node/data/identity.pem\n"})}),"\n",(0,i.jsxs)(n.p,{children:["All ",(0,i.jsx)(n.code,{children:".pem"})," files should have the permissions ",(0,i.jsx)(n.code,{children:"600"}),". You can set the permissions for all ",(0,i.jsx)(n.code,{children:".pem"})," files in a directory using the following command:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"chmod -R 600 /path/*.pem\n"})}),"\n",(0,i.jsx)(n.h4,{id:"node-directory-ownership",children:"Node directory Ownership"}),"\n",(0,i.jsxs)(n.p,{children:["Another possible cause of permission issues is not giving ownership of your ",(0,i.jsx)(n.code,{children:"node/"})," to the user running the node (e.g. ",(0,i.jsx)(n.code,{children:"docker-host"})," or replace with your user):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"chown -R docker-host:docker-host /node\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In general, to avoid problems when running docker, specify the user when running ",(0,i.jsx)(n.code,{children:"docker"})," commands by adding the flag ",(0,i.jsx)(n.code,{children:"--user $(id -u):$(id -g)"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"cannot-find-file",children:"Cannot Find File"}),"\n",(0,i.jsx)(n.p,{children:"Error Message examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"no such file or directory\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:"file does not exist\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["More often than you'd expect, this error is the result of setting the path incorrectly. You may have left something like ",(0,i.jsx)(n.code,{children:"--genesis.file $GENESIS_FILE_PATH"})," in the command without setting ",(0,i.jsx)(n.code,{children:"$GENESIS_FILE_PATH"})," first, or set the path incorrectly. Check that ",(0,i.jsx)(n.code,{children:"echo $GENESIS_FILE_PATH"})," matches your expectation or provide a path in the command."]}),"\n",(0,i.jsx)(n.p,{children:"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."}),"\n",(0,i.jsx)(n.h2,{id:"staking-and-registering",children:"Staking and Registering"}),"\n",(0,i.jsx)(n.h3,{id:"transaction-out-of-gas",children:"Transaction Out of Gas"}),"\n",(0,i.jsx)(n.p,{children:"Error message:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-text",children:'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'})}),"\n",(0,i.jsxs)(n.p,{children:["The docs are now updated to show that you need to add ",(0,i.jsx)(n.code,{children:"--stake.transaction.fee.gas"})," and ",(0,i.jsx)(n.code,{children:"--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,i.jsx)(n.code,{children:"--nonce"})," flag."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>d});var i=s(6540);const o={},r=i.createContext(o);function t(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f8012949.9f2c0c8c.js b/assets/js/f8012949.9f2c0c8c.js new file mode 100644 index 0000000000..92701b91de --- /dev/null +++ b/assets/js/f8012949.9f2c0c8c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[9610],{5164:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>l});var t=i(4848),s=i(8453);const r={},o="Security",c={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/SECURITY.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Versioning",permalink:"/core/versioning"}},a={},l=[{value:"Specifications",id:"specifications",level:2},{value:"Contract Computational/Data Integrity",id:"contract-computationaldata-integrity",level:2},{value:"CometBFT",id:"cometbft",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}];function d(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"security",children:"Security"}),"\n",(0,t.jsxs)(n.p,{children:["At ",(0,t.jsx)(n.a,{href:"https://oasisprotocol.org/",children:"Oasis Foundation"}),", we take security very seriously and we deeply appreciate\nany effort to discover and fix vulnerabilities in ",(0,t.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-core",children:"Oasis Core"})," and other\nprojects powering the ",(0,t.jsx)(n.a,{href:"/general/oasis-network/",children:"Oasis Network"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["We prefer that security reports be sent through our ",(0,t.jsx)(n.a,{href:"https://oasisprotocol.org/security",children:"private bug bounty program\nlinked on our website"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"We sketch out the general classification of the kinds of errors\nbelow. This is not intended to be an exhaustive list."}),"\n",(0,t.jsx)(n.h2,{id:"specifications",children:"Specifications"}),"\n",(0,t.jsxs)(n.p,{children:["Our ",(0,t.jsx)(n.a,{href:"https://oasisprotocol.org/papers",children:"papers"})," specify what we are building. Additional designs and\nspecifications may be made available later."]}),"\n",(0,t.jsx)(n.p,{children:"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."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Conceptual errors."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Ambiguities, inconsistencies, or incorrect statements."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Mismatch between specifications and implementation of any subsystems\n/ modules, when the implementation is considered complete."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"contract-computationaldata-integrity",children:"Contract Computational/Data Integrity"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Race conditions / non-determinism. These may introduce a denial of\nservice opportunity, or a way to force the system into slow path /\nrecovery mode."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Conditions under which compute nodes may cause a bogus transaction\nresult to be accepted (committed to the blockchain) by the system."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"cometbft",children:"CometBFT"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["CometBFT has its own vulnerability disclosure policy and bug\nbounty, so in general issues in the core CometBFT code should be\nreported\n",(0,t.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/master/SECURITY.md",children:"there"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Oasis Core code that misuses CometBFT code, i.e., in violation of\nAPI/contract, would definitely be in scope."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"discrepancy-detection",children:"Discrepancy Detection"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Situations where a discrepant computation is not detected."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Situations where a discrepancy occurs but no receipts are\ngenerated/retained for blame assignment / slashing after slow-path\nrecovery."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"storage",children:"Storage"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"We use immutable authenticated data structures."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Undetected mutations. E.g., situations where a conceptually\nimmutable data structure can be changed without updating hashes\n(and thus getting a new ID)."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Missing/incomplete ADS proof generation or verification."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Availability failures. Potential DoS, e.g., malformed requests that\ncause node panics, etc."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"contract-confidentiality",children:"Contract Confidentiality"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"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."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"TEE misuse, model failures."}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"availability",children:"Availability"}),"\n",(0,t.jsx)(n.p,{children:"Bugs that create a potential for DOS or DDOS attack, e.g.:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Amplification attacks."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Failstop crashes / panics."}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Deadlocks / livelocks."}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>c});var t=i(6540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f923b8a9.91363a0d.js b/assets/js/f923b8a9.91363a0d.js new file mode 100644 index 0000000000..6edeae3599 --- /dev/null +++ b/assets/js/f923b8a9.91363a0d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[3397],{73:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>m,frontMatter:()=>i,metadata:()=>c,toc:()=>h});var a=t(4848),r=t(8453),o=t(1470),s=t(9365);const i={description:"The Oasis Foundation-managed non-custodial browser extension wallet"},l="ROSE Wallet - Browser Extension",c={id:"general/manage-tokens/oasis-wallets/browser-extension",title:"ROSE Wallet - Browser Extension",description:"The Oasis Foundation-managed non-custodial browser extension wallet",source:"@site/docs/general/manage-tokens/oasis-wallets/browser-extension.mdx",sourceDirName:"general/manage-tokens/oasis-wallets",slug:"/general/manage-tokens/oasis-wallets/browser-extension",permalink:"/general/manage-tokens/oasis-wallets/browser-extension",draft:!1,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/general/manage-tokens/oasis-wallets/browser-extension.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{description:"The Oasis Foundation-managed non-custodial browser extension wallet"},sidebar:"general",previous:{title:"Web",permalink:"/general/manage-tokens/oasis-wallets/web"},next:{title:"3rd Party Wallets and Services",permalink:"/general/manage-tokens/holding-rose-tokens"}},d={},h=[{value:"Installation",id:"installation",level:2},{value:"Create a New Account",id:"create-a-new-account",level:2},{value:"Import an Existing Account",id:"import-an-existing-account",level:2},{value:"Ledger",id:"ledger",level:2},{value:"Transfer",id:"transfer",level:2},{value:"Stake",id:"stake",level:2},{value:"ParaTimes",id:"paratimes",level:2}];function u(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"rose-wallet---browser-extension",children:"ROSE Wallet - Browser Extension"}),"\n",(0,a.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsxs)(n.p,{children:["Currently, the ",(0,a.jsx)(n.a,{href:"https://github.com/oasisprotocol/oasis-wallet-ext",children:"ROSE Wallet - Browser Extension"}),"\n",(0,a.jsx)(n.strong,{children:"only supports"})," ",(0,a.jsx)(n.a,{href:"https://www.google.com/chrome/",children:(0,a.jsx)(n.strong,{children:"Chrome"})})," or other\n",(0,a.jsx)(n.a,{href:"https://www.chromium.org/Home",children:"Chromium"}),"-based browsers."]})}),"\n",(0,a.jsxs)(n.p,{children:["You can install the ROSE Wallet - Browser Extension by heading to the\n",(0,a.jsx)(n.a,{href:"https://chrome.google.com/webstore/detail/oasis-wallet/ppdadbejkmjnefldpcdjhnkpbjkikoip",children:"Chrome Web Store"}),"."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"ROSE Wallet Extension - chrome web store",src:t(6589).A+"",width:"2266",height:"1339"})}),"\n",(0,a.jsxs)(n.p,{children:["Next, either ",(0,a.jsx)(n.a,{href:"#create-a-new-account",children:"create a new wallet"})," or\n",(0,a.jsx)(n.a,{href:"#import-an-existing-account",children:"restore your existing one"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"create-a-new-account",children:"Create a New Account"}),"\n",(0,a.jsxs)(n.p,{children:["Enter the ",(0,a.jsx)(n.strong,{children:"new wallet password"}),'. You will need to enter this password each\ntime you open the wallet and after some time when the wallet automatically\nlocks. Click "Next".']}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Create new wallet: Enter password",src:t(4524).A+"",width:"445",height:"600"})}),"\n",(0,a.jsx)(n.p,{children:'The newly generated mnemonic is shown to you. Carefully back it up. You will\nneed this mnemonic, to migrate the wallet to another device or to restore it, if\nyou uninstall your web browser. Click on the "Confirm backup" button.'}),"\n",(0,a.jsx)(n.admonition,{type:"caution",children:(0,a.jsxs)(n.p,{children:["Your mnemonic phrase is required to access your wallet. Be sure to ",(0,a.jsx)(n.strong,{children:"store it in\na secure location"}),". If you lose or forget your mnemonic phrase, you will lose\naccess to your wallet and any token funds contained in it."]})}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"Never share your mnemonic keyphrase"}),". Anyone with your keyphrase can access\nyour wallet and your tokens."]})}),"\n",(0,a.jsxs)(n.p,{children:['Now reenter the mnemonic words as a proof that you backed up the mnemonic and\nclick on the "Confirm" button. Once done, you will see your balance on the\n',(0,a.jsx)(n.strong,{children:"Oasis consensus layer"}),"."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Account history",src:t(9168).A+"",width:"456",height:"604"})}),"\n",(0,a.jsx)(n.h2,{id:"import-an-existing-account",children:"Import an Existing Account"}),"\n",(0,a.jsx)(n.p,{children:"In the top-right corner, click your account icon to open the Account management\nmenu."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Account Management - Importing Accounts",src:t(4014).A+"",width:"456",height:"604"})}),"\n",(0,a.jsx)(n.p,{children:'Click "Import" and select the:'}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:'"Oasis Private Key" to import your existing Oasis private key to be used by\nCipher ParaTime; or'}),"\n",(0,a.jsx)(n.li,{children:'"Ethereum-compatible Private Key" to import your existing Ethereum Account to\nbe used by the EVM-compatible Sapphire or Emerald.'}),"\n"]}),"\n",(0,a.jsx)(n.admonition,{type:"info",children:(0,a.jsx)(n.p,{children:"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 ROSE Wallet - Browser Extension."})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Importing Ethereum-compatible Account with Private Key",src:t(7057).A+"",width:"456",height:"608"})}),"\n",(0,a.jsx)(n.p,{children:'Fill in the "Account name" that will appear later in the Account Management screen.'}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Imported Account Name",src:t(1143).A+"",width:"455",height:"604"})}),"\n",(0,a.jsx)(n.p,{children:"Next, paste your Base64-encoded Oasis or hex-encoded Ethereum private key."}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["You will need to import ",(0,a.jsx)(n.strong,{children:"the private key and not the mnemonics"}),". You can\nderive a private key from the mnemonics with BIP39\u2192BIP44 converter. For example\nby ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#import",children:"importing"})," the mnemonic into the Oasis CLI and\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/wallet#export",children:"exporting it"}),"."]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Entering Ethereum address Private Key (BIP44)",src:t(1918).A+"",width:"458",height:"607"})}),"\n",(0,a.jsx)(n.p,{children:'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.'}),"\n",(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsxs)(n.p,{children:["In older versions of the ROSE 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,a.jsx)(n.strong,{children:"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 withdrawing ROSE to. The signature schemes are\nincompatible (the consensus layer only supports Ed25519) and those tokens will\nnot be accessible anymore!"})]})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Account Management - Accounts Overview",src:t(5386).A+"",width:"456",height:"604"})}),"\n",(0,a.jsx)(n.h2,{id:"ledger",children:"Ledger"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Plug your Ledger device into your computer and log into the Oasis app on-device"}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Oasis App Ready on Ledger Nano S connected to your device",src:t(5407).A+"",width:"640",height:"480"})}),"\n",(0,a.jsxs)(n.ol,{start:"2",children:["\n",(0,a.jsx)(n.li,{children:"Open the Oasis Chrome Extension Wallet and click the account icon on the top\nright. Select Ledger on the bottom right of the app."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Unlock your ROSE Wallet Browser Extension",src:t(1844).A+"",width:"752",height:"1202"})}),"\n",(0,a.jsxs)(n.ol,{start:"4",children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:'Follow user onboarding flow clicking "Next" as you move forward with set up.'}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsx)(n.p,{children:'You\'ll see a pop-up in your Chrome Browser asking you to select which device\nto connect. Click on your Ledger device. Then click "Connect".'}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsx)(n.p,{children:"You may need to resize the pop up window to see all buttons."})}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Confirm your Ledger device and Import",src:t(751).A+"",width:"747",height:"1200"})}),"\n",(0,a.jsxs)(n.ol,{start:"6",children:["\n",(0,a.jsx)(n.li,{children:'Follow the next onboarding steps to upload the correct Ledger account, clicking "Confirm" when complete.'}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Confirm your account(s) from Ledger for Import",src:t(8086).A+"",width:"748",height:"1200"})}),"\n",(0,a.jsxs)(n.ol,{start:"7",children:["\n",(0,a.jsx)(n.li,{children:"Use your Ledger to send, receive and stake on the Oasis Network!"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"transfer",children:"Transfer"}),"\n",(0,a.jsxs)(o.A,{children:[(0,a.jsx)(s.A,{value:"Send",children:(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Click the avatar on the top right corner"}),"\n",(0,a.jsx)(n.li,{children:"Pick an account you want to transfer tokens out of"}),"\n",(0,a.jsx)(n.li,{children:'Click "Send"'}),"\n",(0,a.jsx)(n.li,{children:'Type in the token amount under "Amount"'}),"\n",(0,a.jsx)(n.li,{children:"Type in the Receiver\u2019s wallet address"}),"\n",(0,a.jsx)(n.li,{children:'Click "Next"'}),"\n",(0,a.jsx)(n.li,{children:'Check the "Send Details"; if everything looks good to you, click "Confirm"'}),"\n",(0,a.jsx)(n.li,{children:"Wait for a couple of seconds, and you\u2019ll get a status update of your transaction"}),"\n",(0,a.jsx)(n.li,{children:"Go back to the Account page, and you\u2019ll see the transfer has gone through"}),"\n"]})}),(0,a.jsx)(s.A,{value:"Receive",children:(0,a.jsx)(n.p,{children:"Click \u2018Receive\u2019 on the Account page, and you\u2019ll get the QR code as well as the\nwallet address in text format"})})]}),"\n",(0,a.jsx)(n.h2,{id:"stake",children:"Stake"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:'Click "Staking" on the Account main page'}),"\n",(0,a.jsx)(n.li,{children:'Go to "Validator node", and select a node you want to delegate your tokens to.'}),"\n",(0,a.jsx)(n.li,{children:'Click into the node you want to delegate your tokens to, and click "Add Escrow"'}),"\n",(0,a.jsx)(n.li,{children:'Fill in the amount you want to delegate under "Amount" and click "Next"'}),"\n",(0,a.jsx)(n.li,{children:'Check the "Delegate info", if everything looks good to you, click "Confirm"'}),"\n",(0,a.jsx)(n.li,{children:'Go to "My delegate" and you will see which node you just delegated tokens to and by how much'}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"paratimes",children:"ParaTimes"}),"\n",(0,a.jsxs)(n.p,{children:["Switch to the ",(0,a.jsx)(n.em,{children:"ParaTimes tab"})," to deposit and withdraw ROSE to or from the\nParaTimes."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"The ParaTimes tab",src:t(7704).A+"",width:"457",height:"607"})}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["At time of writing, depositing and withdrawing ROSE to and from ParaTimes\nworks only for the accounts ",(0,a.jsx)(n.strong,{children:"imported from the private key or the mnemonic"}),".\nIf you want to use a hardware wallet, please use the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"}),"."]})}),"\n",(0,a.jsxs)(o.A,{children:[(0,a.jsxs)(s.A,{value:"Deposit",children:[(0,a.jsx)(n.p,{children:'For the sake of demonstration, we\'ll continue with the Sapphire ParaTime, but\nthe Emerald or Cipher ParaTimes work just as well. Under the Sapphire label\nclick on the "To ParaTime" button.'}),(0,a.jsx)(n.p,{children:'Fill in the "Amount" of ROSE that you want to transfer to Sapphire 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,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Sending ROSE to Sapphire",src:t(2106).A+"",width:"456",height:"604"})}),(0,a.jsx)(n.p,{children:"If everything goes well, you will see a successful ParaTime transaction in your\naccount history."}),(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Account history",src:t(9168).A+"",width:"456",height:"604"})})]}),(0,a.jsxs)(s.A,{value:"Withdraw",children:[(0,a.jsxs)(n.p,{children:["You can withdraw your ROSE from the ParaTime back to your consensus account by first\nselecting your ParaTime account in the ",(0,a.jsx)(n.em,{children:"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 consensus layer address and confirm\nthe withdrawal. In a few moments you will have your ROSE accessible on the\nconsensus layer.']}),(0,a.jsx)(n.admonition,{type:"danger",children:(0,a.jsxs)(n.p,{children:["If you want to transfer ROSE to an exchange and you currently have them\ndeposited on Sapphire, ",(0,a.jsx)(n.strong,{children:"we strongly recommend that you withdraw ROSE\nto your ROSE 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,a.jsxs)(n.admonition,{type:"tip",children:[(0,a.jsxs)(n.p,{children:["Advanced users (e.g. those running ParaTime ",(0,a.jsx)(n.a,{href:"/node/run-your-node/paratime-node",children:"compute nodes"}),") may need to\nwithdraw ROSE from ParaTimes stored in their ",(0,a.jsx)(n.code,{children:"oasis1"})," accounts, for example to\nclaim their ParaTime execution rewards. The ROSE Wallet - Browser Extension does\nnot support such withdrawals. Use the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/account#withdraw",children:(0,a.jsx)(n.code,{children:"oasis account withdraw"})})," command which\nis part of the ",(0,a.jsx)(n.a,{href:"/general/manage-tokens/cli/",children:"Oasis CLI"})," instead, for example:"]}),(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-shell",children:"oasis account withdraw 10\n"})})]})]})]}),"\n",(0,a.jsxs)(n.p,{children:["You can check the balance of your consensus and ParaTime accounts by opening the\n",(0,a.jsx)(n.em,{children:"Account Management"})," screen and selecting the corresponding account. Then click\non the back arrow. The ",(0,a.jsx)(n.em,{children:"Wallet"})," tab will show you the balance on the consensus\nlayer and for ParaTimes navigate to the ",(0,a.jsx)(n.em,{children:"ParaTimes tab"}),". There you will notice\nthe available amount of ROSE per each ParaTime."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"ROSE balance in Sapphire",src:t(2248).A+"",width:"456",height:"604"})}),"\n",(0,a.jsxs)(n.p,{children:["For EVM-compatible ParaTimes, you can as well verify the balance in\n",(0,a.jsx)(n.a,{href:"/general/manage-tokens/#metamask",children:"Metamask"})," or a built-in wallet in the Brave browser:"]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.img,{alt:"Metamask - Received ROSE",src:t(8765).A+"",width:"364",height:"607"})})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(u,{...e})}):u(e)}},9365:(e,n,t)=>{t.d(n,{A:()=>s});t(6540);var a=t(4164);const r={tabItem:"tabItem_Ymn6"};var o=t(4848);function s(e){let{children:n,hidden:t,className:s}=e;return(0,o.jsx)("div",{role:"tabpanel",className:(0,a.A)(r.tabItem,s),hidden:t,children:n})}},1470:(e,n,t)=>{t.d(n,{A:()=>v});var a=t(6540),r=t(4164),o=t(3104),s=t(6347),i=t(205),l=t(7485),c=t(1682),d=t(9466);function h(e){return a.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,a.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function u(e){const{values:n,children:t}=e;return(0,a.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:t,attributes:a,default:r}}=e;return{value:n,label:t,attributes:a,default:r}}))}(t);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function m(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:t}=e;const r=(0,s.W6)(),o=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)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 t??null}({queryString:n,groupId:t});return[(0,l.aZ)(o),(0,a.useCallback)((e=>{if(!o)return;const n=new URLSearchParams(r.location.search);n.set(o,e),r.replace({...r.location,search:n.toString()})}),[o,r])]}function g(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,o=u(e),[s,l]=(0,a.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!m({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const a=t.find((e=>e.default))??t[0];if(!a)throw new Error("Unexpected error: 0 tabValues");return a.value}({defaultValue:n,tabValues:o}))),[c,h]=p({queryString:t,groupId:r}),[g,x]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[r,o]=(0,d.Dv)(t);return[r,(0,a.useCallback)((e=>{t&&o.set(e)}),[t,o])]}({groupId:r}),w=(()=>{const e=c??g;return m({value:e,tabValues:o})?e:null})();(0,i.A)((()=>{w&&l(w)}),[w]);return{selectedValue:s,selectValue:(0,a.useCallback)((e=>{if(!m({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),h(e),x(e)}),[h,x,o]),tabValues:o}}var x=t(2303);const w={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var f=t(4848);function y(e){let{className:n,block:t,selectedValue:a,selectValue:s,tabValues:i}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,o.a_)(),d=e=>{const n=e.currentTarget,t=l.indexOf(n),r=i[t].value;r!==a&&(c(n),s(r))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,f.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,r.A)("tabs",{"tabs--block":t},n),children:i.map((e=>{let{value:n,label:t,attributes:o}=e;return(0,f.jsx)("li",{role:"tab",tabIndex:a===n?0:-1,"aria-selected":a===n,ref:e=>l.push(e),onKeyDown:h,onClick:d,...o,className:(0,r.A)("tabs__item",w.tabItem,o?.className,{"tabs__item--active":a===n}),children:t??n},n)}))})}function b(e){let{lazy:n,children:t,selectedValue:r}=e;const o=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=o.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return(0,f.jsx)("div",{className:"margin-top--md",children:o.map(((e,n)=>(0,a.cloneElement)(e,{key:n,hidden:e.props.value!==r})))})}function j(e){const n=g(e);return(0,f.jsxs)("div",{className:(0,r.A)("tabs-container",w.tabList),children:[(0,f.jsx)(y,{...n,...e}),(0,f.jsx)(b,{...n,...e})]})}function v(e){const n=(0,x.A)();return(0,f.jsx)(j,{...e,children:h(e.children)},String(n))}},9168:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/account_history-8cb60b00f32ab450bfa579f4e19a79a8.png"},4014:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/accounts1-e6156dbb8ecdafc396eb0def137a062e.png"},5386:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/accounts2-374ff3f5128e7f6683c4f5e5ef7cb7d0.png"},6589:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/chrome_web_store-567139994ac68a1da47074c041cbe959.png"},4524:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/create_wallet-6f84ae326fa8da9fbeae3cb443992027.png"},2106:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/deposit-d0f6ca5b1c65739f54bbfa7867959334.png"},7057:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/import-8dc1af399466eba46658807f9d041223.png"},1143:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/import2-6d7311fead222a1018d2cff955b43d6e.png"},1918:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/import3-33c28731c0ceaa30a8621945d48227eb.png"},1844:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/ledger1-00e350e8cc5168c58d3dbd56d72f0357.png"},751:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/ledger2-ace8c17920abf877d4c68f40c1854eb3.png"},8086:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/ledger3-bd9f503231d12dec0764340d7695cb5a.png"},7704:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/paratimes-ba19a88dd7d5bcb85ecce1a4ba286380.png"},2248:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/paratimes2-718728090a646032557a7a9260a4c7fc.png"},5407:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/ledger_oasis_ready-c62f41645274a3f3f88e16f932cdbb35.jpg"},8765:(e,n,t)=>{t.d(n,{A:()=>a});const a=t.p+"assets/images/account-069b6ef007c33f2910379fbf63d87e8d.png"},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>i});var a=t(6540);const r={},o=a.createContext(r);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fdfc1f73.be3439c1.js b/assets/js/fdfc1f73.be3439c1.js new file mode 100644 index 0000000000..c075b88983 --- /dev/null +++ b/assets/js/fdfc1f73.be3439c1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[2035],{6466:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>u,contentTitle:()=>l,default:()=>p,frontMatter:()=>a,metadata:()=>c,toc:()=>d});var r=s(4848),t=s(8453),i=s(1470),o=s(9365);const a={},l="System Configuration",c={id:"node/run-your-node/prerequisites/system-configuration",title:"System Configuration",description:"This page outlines the modifications necessary that should be made to 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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/docs/edit/main/docs/node/run-your-node/prerequisites/system-configuration.mdx",tags:[],version:"current",lastUpdatedAt:172612742e4,frontMatter:{},sidebar:"operators",previous:{title:"Install the Oasis Node",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"}},u={},d=[{value:"Create a user",id:"create-a-user",level:2},{value:"Increase file descriptor limit",id:"increase-file-descriptor-limit",level:2},{value:"AppArmor profiles",id:"apparmor-profiles",level:2},{value:"Example snippets for different setups",id:"example-snippets-for-different-setups",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"system-configuration",children:"System Configuration"}),"\n",(0,r.jsx)(n.p,{children:"This page outlines the modifications necessary that should be made to the\nconfiguration of the system where you are running an Oasis Node instance. To\nprepare the system for running an Oasis Node, we will guide you through the\nprocess of creating a dedicated user account, increasing the file descriptor\nlimit and optional AppArmor profiles."}),"\n",(0,r.jsx)(n.h2,{id:"create-a-user",children:"Create a user"}),"\n",(0,r.jsxs)(n.p,{children:["Nothing in Oasis Node requires elevated privileges, so running the Oasis Node\nwith root privileges is not allowed. Attempting to run the ",(0,r.jsx)(n.code,{children:"oasis-node"})," process\nas the root user will terminate immediately on startup. You will need to\ncreate a dedicated user account to manage the Oasis Node processes."]}),"\n",(0,r.jsx)(n.p,{children:"To create a new user run as root:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"adduser oasis\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If you have an existing data directory, change its ownership to the ",(0,r.jsx)(n.code,{children:"oasis"}),"\nuser. If not, you may skip this step."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"chown -R oasis /node/data\n"})}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:["Adjust the user as appropriate to your setup. For example, setting the ",(0,r.jsx)(n.code,{children:"oasis"}),"\nuser's Shell to ",(0,r.jsx)(n.code,{children:"/usr/sbin/nologin"})," prevents (accidentally) logging in as this\nuser. See the following examples on how to create a user on different systems."]}),(0,r.jsxs)(i.A,{children:[(0,r.jsxs)(o.A,{value:"Ubuntu",children:[(0,r.jsx)(n.p,{children:"As root, run:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"adduser --system oasis --shell /usr/sbin/nologin\n"})})]}),(0,r.jsxs)(o.A,{value:"Fedora",children:[(0,r.jsx)(n.p,{children:"As root, run:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"useradd -r -s /usr/sbin/nologin\n"})})]}),(0,r.jsxs)(o.A,{value:"Ansible",children:[(0,r.jsx)(n.p,{children:"Add the following task to your playbook:"}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yml",children:"- name: Create oasis user\n ansible.builtin.user:\n name: oasis\n comment: Oasis Services user\n system: yes\n shell: /usr/sbin/nologin\n"})})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"increase-file-descriptor-limit",children:"Increase file descriptor limit"}),"\n",(0,r.jsx)(n.p,{children:"Make sure that the user under which you are running your Oasis Node has a\nhigh-enough file descriptor limit as the databases can have many opened files.\nRunning out of file descriptors can lead to the node stopping unexpectedly."}),"\n",(0,r.jsx)(n.p,{children:"You can check the file descriptor limit by running the following as the same\nuser that will run the Oasis Node:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"ulimit -n\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If this number is lower than 102400 you should consider increasing it by\nupdating your system configuration. You can configure ",(0,r.jsx)(n.em,{children:"temporary"})," limits by\nrunning:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"ulimit -n 102400\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This limit will only apply to any processes started from the same shell after\nthe command was executed. If you want to make the change ",(0,r.jsx)(n.em,{children:"permanent"}),", you have\nthe following options:"]}),"\n",(0,r.jsxs)(i.A,{children:[(0,r.jsxs)(o.A,{value:"systemd",children:[(0,r.jsxs)(n.p,{children:["In case you are running your Oasis Node process via\n",(0,r.jsx)(n.a,{href:"https://systemd.io/",children:"systemd"}),", you can add the following directive under the\n",(0,r.jsx)(n.code,{children:"[Service]"})," section:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"LimitNOFILE=102400\n"})})]}),(0,r.jsxs)(o.A,{value:"Docker",children:[(0,r.jsxs)(n.p,{children:["If you are running the Oasis Node via ",(0,r.jsx)(n.a,{href:"https://www.docker.com/",children:"Docker"})," you can\npass the following option to ",(0,r.jsx)(n.code,{children:"docker run"})," in order to increase the limit to\ndesired values:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"--ulimit nofile=102400:1048576\n"})})]}),(0,r.jsxs)(o.A,{value:"limits.conf",children:[(0,r.jsxs)(n.p,{children:["As ",(0,r.jsx)(n.code,{children:"root"}),", create a system-wide ",(0,r.jsx)(n.em,{children:"resource limits"})," configuration File in\n",(0,r.jsx)(n.code,{children:"/etc/security/limits.d/99-oasis-node.conf"})," with content similar to the\nfollowing example:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"* soft nofile 102400\n* hard nofile 1048576\n"})}),(0,r.jsxs)(n.p,{children:["You can replace ",(0,r.jsx)(n.code,{children:"*"})," with the name of the user that is running the Oasis Node in\ncase you only want to change the limits for that particular user."]}),(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsx)(n.p,{children:"The change above will increase the limit for all processes and not just the\nOasis Node."})}),(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsx)(n.p,{children:"In order for the changes to take effect a system restart may be required."})})]})]}),"\n",(0,r.jsx)(n.h2,{id:"apparmor-profiles",children:"AppArmor profiles"}),"\n",(0,r.jsx)(n.p,{children:"In case your system is using AppArmor and is restricting unprivileged user namespace\ncreation, you may need to allow them for Bubblewrap (the sandbox that Oasis Node is\nusing to execute runtimes)."}),"\n",(0,r.jsxs)(n.p,{children:["You can use the following policy in ",(0,r.jsx)(n.code,{children:"/etc/apparmor.d/bwrap"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"abi ,\ninclude \n\nprofile bwrap /usr/bin/bwrap flags=(unconfined) {\n userns,\n\n # Site-specific additions and overrides. See local/README for details.\n include if exists \n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"Then reload AppArmor policies by running:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"sudo systemctl reload apparmor.service\n"})}),"\n",(0,r.jsx)(n.h2,{id:"example-snippets-for-different-setups",children:"Example snippets for different setups"}),"\n",(0,r.jsxs)(n.p,{children:["You may find the following snippets helpful in case you are running ",(0,r.jsx)(n.code,{children:"oasis-node"}),"\nprocess with systemd, Docker or runit."]}),"\n",(0,r.jsxs)(i.A,{children:[(0,r.jsxs)(o.A,{value:"systemd",children:[(0,r.jsxs)(n.p,{children:["Add a ",(0,r.jsxs)(n.a,{href:"https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=",children:[(0,r.jsx)(n.code,{children:"User"})," directive"]})," to the Oasis service's systemd unit file:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"...\nUser=oasis\n...\n"})}),(0,r.jsxs)(n.p,{children:["Below can be found a simple systemd unit file for ",(0,r.jsx)(n.code,{children:"oasis-node"})," that can be used\nas a starting point."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-ini",children:"[Unit]\nDescription=Oasis Node\nAfter=network.target\n\n[Service]\nType=simple\nUser=oasis\nWorkingDirectory=/node/data\nExecStart=/node/bin/oasis-node --config /node/etc/config.yml\nRestart=on-failure\nRestartSec=3\nLimitNOFILE=1024000\n\n[Install]\nWantedBy=multi-user.target\n"})})]}),(0,r.jsxs)(o.A,{value:"Docker",children:[(0,r.jsxs)(n.p,{children:["Add ",(0,r.jsxs)(n.a,{href:"https://docs.docker.com/engine/reference/builder/#user",children:[(0,r.jsx)(n.code,{children:"USER"})," instruction"]})," to your Oasis service's Dockerfile:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"...\nUSER oasis\n...\n"})})]}),(0,r.jsxs)(o.A,{value:"runit",children:[(0,r.jsxs)(n.p,{children:["Wrap the invocation in a ",(0,r.jsxs)(n.a,{href:"http://smarden.org/runit/chpst.8.html",children:[(0,r.jsx)(n.code,{children:"chpst"})," command"]}),":"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"chpst -u oasis oasis-node ...\n"})})]})]})]})}function p(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},9365:(e,n,s)=>{s.d(n,{A:()=>o});s(6540);var r=s(4164);const t={tabItem:"tabItem_Ymn6"};var i=s(4848);function o(e){let{children:n,hidden:s,className:o}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,r.A)(t.tabItem,o),hidden:s,children:n})}},1470:(e,n,s)=>{s.d(n,{A:()=>w});var r=s(6540),t=s(4164),i=s(3104),o=s(6347),a=s(205),l=s(7485),c=s(1682),u=s(9466);function d(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(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)??[]}function h(e){const{values:n,children:s}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return d(e).map((e=>{let{props:{value:n,label:s,attributes:r,default:t}}=e;return{value:n,label:s,attributes:r,default:t}}))}(s);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,s])}function p(e){let{value:n,tabValues:s}=e;return s.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:s}=e;const t=(0,o.W6)(),i=function(e){let{queryString:n=!1,groupId:s}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!s)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 s??null}({queryString:n,groupId:s});return[(0,l.aZ)(i),(0,r.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(t.location.search);n.set(i,e),t.replace({...t.location,search:n.toString()})}),[i,t])]}function f(e){const{defaultValue:n,queryString:s=!1,groupId:t}=e,i=h(e),[o,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:s}=e;if(0===s.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:s}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${s.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=s.find((e=>e.default))??s[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[c,d]=m({queryString:s,groupId:t}),[f,x]=function(e){let{groupId:n}=e;const s=function(e){return e?`docusaurus.tab.${e}`:null}(n),[t,i]=(0,u.Dv)(s);return[t,(0,r.useCallback)((e=>{s&&i.set(e)}),[s,i])]}({groupId:t}),g=(()=>{const e=c??f;return p({value:e,tabValues:i})?e:null})();(0,a.A)((()=>{g&&l(g)}),[g]);return{selectedValue:o,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),d(e),x(e)}),[d,x,i]),tabValues:i}}var x=s(2303);const g={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var j=s(4848);function y(e){let{className:n,block:s,selectedValue:r,selectValue:o,tabValues:a}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,i.a_)(),u=e=>{const n=e.currentTarget,s=l.indexOf(n),t=a[s].value;t!==r&&(c(n),o(t))},d=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const s=l.indexOf(e.currentTarget)+1;n=l[s]??l[0];break}case"ArrowLeft":{const s=l.indexOf(e.currentTarget)-1;n=l[s]??l[l.length-1];break}}n?.focus()};return(0,j.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,t.A)("tabs",{"tabs--block":s},n),children:a.map((e=>{let{value:n,label:s,attributes:i}=e;return(0,j.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:d,onClick:u,...i,className:(0,t.A)("tabs__item",g.tabItem,i?.className,{"tabs__item--active":r===n}),children:s??n},n)}))})}function b(e){let{lazy:n,children:s,selectedValue:t}=e;const i=(Array.isArray(s)?s:[s]).filter(Boolean);if(n){const e=i.find((e=>e.props.value===t));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,j.jsx)("div",{className:"margin-top--md",children:i.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==t})))})}function v(e){const n=f(e);return(0,j.jsxs)("div",{className:(0,t.A)("tabs-container",g.tabList),children:[(0,j.jsx)(y,{...n,...e}),(0,j.jsx)(b,{...n,...e})]})}function w(e){const n=(0,x.A)();return(0,j.jsx)(v,{...e,children:d(e.children)},String(n))}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>a});var r=s(6540);const t={},i=r.createContext(t);function o(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ffcff7f9.7aed29ca.js b/assets/js/ffcff7f9.7aed29ca.js new file mode 100644 index 0000000000..bd52995382 --- /dev/null +++ b/assets/js/ffcff7f9.7aed29ca.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[5638],{1367:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>c,metadata:()=>a,toc:()=>r});var i=s(4848),o=s(8453);const c={},t="oasis-node CLI",a={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,unlisted:!1,editUrl:"https://github.com/oasisprotocol/oasis-core/edit/stable/22.2.x/docs/oasis-node/cli.md",tags:[],version:"current",lastUpdatedAt:1715584634e3,frontMatter:{},sidebar:"oasisCore",previous:{title:"Metrics",permalink:"/core/oasis-node/metrics"},next:{title:"Common Functionality",permalink:"/core/common-functionality"}},d={},r=[{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}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.h1,{id:"oasis-node-cli",children:[(0,i.jsx)(n.code,{children:"oasis-node"})," CLI"]}),"\n",(0,i.jsx)(n.h2,{id:"control",children:(0,i.jsx)(n.code,{children:"control"})}),"\n",(0,i.jsx)(n.h3,{id:"status",children:(0,i.jsx)(n.code,{children:"status"})}),"\n",(0,i.jsx)(n.p,{children:"Run"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node control status\n"})}),"\n",(0,i.jsx)(n.p,{children:"to get information like the following (example taken from a runtime compute\nnode):"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\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 ]\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": 2000000000\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 "addresses": [\n "Kj8ANHwfMzcWoA1vx0OMhn4oGv8Y0vc46xMOdQUIh5c=@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'})}),"\n",(0,i.jsx)(n.h2,{id:"genesis",children:(0,i.jsx)(n.code,{children:"genesis"})}),"\n",(0,i.jsx)(n.h3,{id:"check",children:(0,i.jsx)(n.code,{children:"check"})}),"\n",(0,i.jsxs)(n.p,{children:["To check if a given ",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-file",children:"genesis file"})," is valid, run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node genesis check --genesis.file /path/to/genesis.json\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["This also checks if the genesis file is in the ",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#canonical-form",children:"canonical form"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"dump",children:(0,i.jsx)(n.code,{children:"dump"})}),"\n",(0,i.jsxs)(n.p,{children:["To dump the state of the network at a specific block height, e.g. 717600, to a\n",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-file",children:"genesis file"}),", run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node genesis dump \\\n --address unix:/path/to/node/internal.sock \\\n --genesis.file /path/to/genesis_dump.json \\\n --height 717600\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"You must only run the following command after the given block height has been\nreached on the network."})}),"\n",(0,i.jsx)(n.h3,{id:"init",children:(0,i.jsx)(n.code,{children:"init"})}),"\n",(0,i.jsxs)(n.p,{children:["To initialize a new ",(0,i.jsx)(n.a,{href:"/core/consensus/genesis#genesis-file",children:"genesis file"})," with the given chain id and ",(0,i.jsx)(n.a,{href:"/core/consensus/services/staking#tokens-and-base-units",children:"staking token\nsymbol"}),", run:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:'oasis-node genesis init --genesis.file /path/to/genesis.json \\\n --chain.id "name-of-my-network" \\\n --staking.token_symbol TEST\n'})}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["You can set a lot of parameters for the various ",(0,i.jsx)(n.a,{href:"/core/consensus/",children:"consensus layer services"}),"."]}),(0,i.jsx)(n.p,{children:"To see the full list, run:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node genesis init --help\n"})})]}),"\n",(0,i.jsx)(n.h2,{id:"stake",children:(0,i.jsx)(n.code,{children:"stake"})}),"\n",(0,i.jsx)(n.h3,{id:"account",children:(0,i.jsx)(n.code,{children:"account"})}),"\n",(0,i.jsx)(n.h4,{id:"info",children:(0,i.jsx)(n.code,{children:"info"})}),"\n",(0,i.jsx)(n.p,{children:"Run"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node stake account info \\\n --stake.account.address \\\n --address unix:/path/to/node/internal.sock\n"})}),"\n",(0,i.jsx)(n.p,{children:"to get staking information for a specific account:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"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"})}),"\n",(0,i.jsx)(n.h3,{id:"pubkey2address",children:(0,i.jsx)(n.code,{children:"pubkey2address"})}),"\n",(0,i.jsx)(n.p,{children:"Run"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"oasis-node stake pubkey2address --public_key \n"})}),"\n",(0,i.jsx)(n.p,{children:"to get staking account address from an entity or node public key. Example\nresponse:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"oasis1qqncl383h8458mr9cytatygctzwsx02n4c5f8ed7\n"})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>a});var i=s(6540);const o={},c=i.createContext(o);function t(e){const n=i.useContext(c);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),i.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.1a9ee234.js b/assets/js/main.1a9ee234.js new file mode 100644 index 0000000000..490601dd71 --- /dev/null +++ b/assets/js/main.1a9ee234.js @@ -0,0 +1,2 @@ +/*! For license information please see main.1a9ee234.js.LICENSE.txt */ +(self.webpackChunkdocs_oasis_io=self.webpackChunkdocs_oasis_io||[]).push([[8792],{5391:(e,t,n)=>{"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;to});const o=function(){for(var e,t,n=0,o="";n{"use strict";n.d(t,{A:()=>p});n(6540);var r=n(3259),o=n.n(r),a=n(4054);const i={"00eda7cc":[()=>n.e(4754).then(n.bind(n,2268)),"@site/docs/core/development-setup/deploying-a-runtime.md",2268],"03741c42":[()=>n.e(367).then(n.bind(n,2296)),"@site/docs/core/README.md",2296],"041ef302":[()=>Promise.all([n.e(1869),n.e(3722)]).then(n.bind(n,8076)),"@site/docs/paratime/README.mdx",8076],"047b4156":[()=>n.e(5296).then(n.bind(n,450)),"@site/docs/node/run-your-node/advanced/copy-state-from-one-node-to-the-other.md",450],"049d1767":[()=>n.e(2005).then(n.bind(n,9738)),"@site/docs/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime.md",9738],"04a64f04":[()=>Promise.all([n.e(1869),n.e(5616)]).then(n.bind(n,6142)),"@site/docs/dapp/opl/build.md",6142],"05c525ec":[()=>n.e(7329).then(n.bind(n,7897)),"@site/docs/core/consensus/services/roothash.md",7897],"06ddcc68":[()=>n.e(7205).then(n.t.bind(n,8640,19)),"@generated/docusaurus-plugin-content-docs/default/p/node-run-your-node-advanced-446.json",8640],"06f6e027":[()=>n.e(9267).then(n.t.bind(n,1788,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-processes-452.json",1788],"07b8cc2d":[()=>Promise.all([n.e(1869),n.e(9874)]).then(n.bind(n,6074)),"@site/docs/node/run-your-node/advanced/remote-signer.mdx",6074],"0da7eee9":[()=>n.e(5567).then(n.bind(n,8449)),"@site/docs/rofl/prerequisites.md",8449],"0e099be9":[()=>n.e(192).then(n.bind(n,802)),"@site/docs/dapp/opl/host.md",802],"0e9cd926":[()=>n.e(7943).then(n.bind(n,6176)),"@site/docs/adrs/0020-governance-delegator-votes.md",6176],"0f0ebacb":[()=>n.e(7556).then(n.bind(n,1738)),"@site/docs/paratime/reproducibility.md",1738],"0f921af1":[()=>n.e(9861).then(n.bind(n,8432)),"@site/docs/general/manage-tokens/cli/account.md",8432],"0f92291a":[()=>n.e(8593).then(n.bind(n,3917)),"@site/docs/get-involved/README.md",3917],10244602:[()=>Promise.all([n.e(1869),n.e(4518)]).then(n.bind(n,7446)),"@site/docs/general/manage-tokens/faq.mdx",7446],"10bc4617":[()=>n.e(3095).then(n.bind(n,5309)),"@site/docs/core/consensus/services/epochtime.md",5309],"138e0e15":[()=>n.e(4921).then(n.t.bind(n,1597,19)),"@generated/@easyops-cn/docusaurus-search-local/default/__plugin.json",1597],"14eb3368":[()=>Promise.all([n.e(1869),n.e(6969)]).then(n.bind(n,5847)),"@theme/DocCategoryGeneratedIndexPage",5847],17896441:[()=>Promise.all([n.e(1869),n.e(8401)]).then(n.bind(n,5113)),"@theme/DocItem",5113],"1a4e3797":[()=>Promise.all([n.e(1869),n.e(2138)]).then(n.bind(n,1283)),"@theme/SearchPage",1283],"1a50dc2d":[()=>Promise.all([n.e(1869),n.e(7903)]).then(n.bind(n,2455)),"@site/docs/dapp/opl/setup.md",2455],"1a9d3710":[()=>n.e(8263).then(n.bind(n,1399)),"@site/docs/get-involved/token-delivery-and-kyc.md",1399],"1d621f19":[()=>n.e(1939).then(n.bind(n,1254)),"@site/docs/node/genesis-doc.md",1254],"1dbb95b6":[()=>Promise.all([n.e(8509),n.e(6938)]).then(n.bind(n,9497)),"@site/docs/general/oasis-network/token-metrics-and-distribution.mdx",9497],"1df235ce":[()=>n.e(952).then(n.bind(n,8317)),"@site/docs/dapp/cipher/confidential-smart-contract.md",8317],"1e60058c":[()=>n.e(713).then(n.bind(n,140)),"@site/docs/core/consensus/README.md",140],"1fa6bbb5":[()=>n.e(2684).then(n.bind(n,3589)),"@site/docs/core/consensus/services/beacon.md",3589],"20d2542b":[()=>n.e(9508).then(n.bind(n,3453)),"@site/docs/core/development-setup/prerequisites.md",3453],"210fedca":[()=>n.e(9221).then(n.bind(n,8949)),"@site/docs/node/run-your-node/maintenance/wiping-node-state.md",8949],"220011ce":[()=>n.e(1353).then(n.bind(n,3688)),"@site/docs/dapp/opl/enclave.md",3688],"2287f371":[()=>n.e(5797).then(n.bind(n,9633)),"@site/docs/adrs/0021-keymanager-ephemeral-secrets.md",9633],"24323d06":[()=>n.e(1229).then(n.bind(n,2796)),"@site/docs/core/authenticated-grpc.md",2796],26373622:[()=>Promise.all([n.e(1869),n.e(7162)]).then(n.bind(n,3049)),"@site/docs/dapp/sapphire/guide.mdx",3049],"277e601e":[()=>n.e(6698).then(n.bind(n,6014)),"@site/docs/node/mainnet/previous-upgrades/cobalt-upgrade.md",6014],"27f9eba8":[()=>n.e(4827).then(n.bind(n,7220)),"@site/docs/get-involved/delegation-policy.md",7220],"29c77900":[()=>n.e(9194).then(n.bind(n,9865)),"@site/docs/node/run-your-node/prerequisites/stake-requirements.md",9865],"2c58cae2":[()=>n.e(7460).then(n.bind(n,2389)),"@site/docs/dapp/cipher/prerequisites.md",2389],"2c7b4985":[()=>n.e(5365).then(n.t.bind(n,651,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-high-level-components-cc3.json",651],"2d94235f":[()=>n.e(2230).then(n.bind(n,5284)),"@site/docs/dapp/tools/README.md",5284],"2e8d1096":[()=>n.e(2458).then(n.bind(n,5795)),"@site/docs/adrs/0003-consensus-runtime-token-transfer.md",5795],"2ea67962":[()=>n.e(5653).then(n.bind(n,2048)),"@site/docs/node/run-your-node/prerequisites/oasis-node.md",2048],30129561:[()=>n.e(1662).then(n.bind(n,8931)),"@site/docs/core/runtime/runtime-host-protocol.md",8931],"30beaf32":[()=>Promise.all([n.e(1869),n.e(4139)]).then(n.bind(n,5806)),"@site/docs/dapp/sapphire/quickstart.mdx",5806],"34c89262":[()=>n.e(7194).then(n.bind(n,5502)),"@site/docs/adrs/0015-vrf-per-block-entropy.md",5502],"35e64e57":[()=>n.e(4447).then(n.bind(n,2865)),"@site/docs/node/mainnet/eden-upgrade.md",2865],"370b1912":[()=>n.e(1376).then(n.bind(n,2710)),"@site/docs/adrs/0012-runtime-message-results.md",2710],"393bd7b1":[()=>n.e(6380).then(n.t.bind(n,9502,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-development-setup-running-tests-and-development-networks-f58.json",9502],"3ae86dfc":[()=>n.e(1915).then(n.bind(n,8395)),"@site/docs/core/encoding.md",8395],"3b03afbf":[()=>n.e(8398).then(n.t.bind(n,3621,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-development-setup-d77.json",3621],"3bc542c3":[()=>n.e(5596).then(n.bind(n,7191)),"@site/docs/general/manage-tokens/holding-rose-tokens/custody-providers.md",7191],"3bfc3ca9":[()=>Promise.all([n.e(1869),n.e(2425)]).then(n.bind(n,5709)),"@site/docs/node/grpc.mdx",5709],"3e5e0bf3":[()=>n.e(2530).then(n.bind(n,5658)),"@site/docs/adrs/0007-improved-random-beacon.md",5658],"3fb4947e":[()=>n.e(1053).then(n.bind(n,3536)),"@site/docs/core/oasis-node/metrics.md",3536],"4079c408":[()=>n.e(7010).then(n.bind(n,9952)),"@site/docs/adrs/0013-runtime-upgrades.md",9952],"409fc1d8":[()=>n.e(1502).then(n.bind(n,3334)),"@site/docs/adrs/0011-incoming-runtime-messages.md",3334],"414b6464":[()=>n.e(1644).then(n.bind(n,1517)),"@site/docs/node/testnet/README.md",1517],"433ff9f9":[()=>n.e(4411).then(n.bind(n,9009)),"@site/docs/general/manage-tokens/cli/network.md",9009],"4414cbb7":[()=>n.e(4918).then(n.bind(n,6052)),"@site/docs/node/mainnet/README.md",6052],"4a27219a":[()=>n.e(3746).then(n.bind(n,9214)),"@site/docs/node/run-your-node/maintenance/refreshing-certificates.md",9214],"4ae0b297":[()=>n.e(8121).then(n.bind(n,4695)),"@site/docs/dapp/cipher/hello-world.md",4695],"4c52944b":[()=>n.e(2792).then(n.bind(n,647)),"@site/docs/paratime/prerequisites.md",647],"4c58f4a9":[()=>Promise.all([n.e(1869),n.e(1139)]).then(n.bind(n,2945)),"@site/docs/dapp/sapphire/security.md",2945],"4daae886":[()=>n.e(5456).then(n.bind(n,1494)),"@site/docs/adrs/0008-standard-account-key-generation.md",1494],"527e04fa":[()=>n.e(8905).then(n.bind(n,3963)),"@site/docs/core/runtime/identifiers.md",3963],"52c9072e":[()=>n.e(4166).then(n.t.bind(n,9250,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-development-setup-build-environment-setup-and-building-5f4.json",9250],"5334ec61":[()=>n.e(8025).then(n.bind(n,8316)),"@site/docs/core/development-setup/building.md",8316],"533aa3d4":[()=>n.e(319).then(n.bind(n,3010)),"@site/docs/node/mainnet/previous-upgrades/damask-upgrade.md",3010],"5583c17b":[()=>Promise.all([n.e(1869),n.e(7513)]).then(n.bind(n,2991)),"@site/docs/dapp/sapphire/browser.md",2991],"562f786c":[()=>n.e(7386).then(n.bind(n,4753)),"@site/docs/rofl/trust-root.md",4753],"59b1a96c":[()=>Promise.all([n.e(1869),n.e(4485)]).then(n.bind(n,3398)),"@site/docs/README.mdx",3398],"5a14fd4c":[()=>n.e(9555).then(n.bind(n,9138)),"@site/docs/adrs/0010-vrf-elections.md",9138],"5da91464":[()=>n.e(4839).then(n.bind(n,4129)),"@site/docs/node/run-your-node/archive-node.md",4129],"5e95c892":[()=>n.e(9647).then(n.bind(n,7121)),"@theme/DocsRoot",7121],"60d875af":[()=>Promise.all([n.e(1869),n.e(436)]).then(n.bind(n,6502)),"@site/docs/node/run-your-node/README.mdx",6502],"6602e166":[()=>n.e(8063).then(n.t.bind(n,7435,19)),"@generated/docusaurus-plugin-content-docs/default/p/get-involved-run-node-d28.json",7435],"6629c45f":[()=>n.e(5820).then(n.t.bind(n,7691,19)),"@generated/docusaurus-plugin-content-docs/default/p/index.json",7691],"6ac8b2ab":[()=>n.e(3132).then(n.bind(n,2082)),"@site/docs/adrs/0009-ed25519-semantics.md",2082],"6b19e4d7":[()=>Promise.all([n.e(1869),n.e(9589)]).then(n.bind(n,3076)),"@site/docs/dapp/sapphire/README.mdx",3076],"6de7ad9b":[()=>Promise.all([n.e(1869),n.e(87)]).then(n.bind(n,9972)),"@site/docs/dapp/opl/frontend.md",9972],"6e63ac1c":[()=>n.e(7189).then(n.bind(n,536)),"@site/docs/dapp/sapphire/deployment.md",536],"6ea13540":[()=>n.e(8186).then(n.bind(n,6743)),"@site/docs/adrs/0001-tm-multi-root-apphash.md",6743],"714fd338":[()=>n.e(3343).then(n.bind(n,5416)),"@site/docs/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee.md",5416],"71d6bec9":[()=>n.e(1894).then(n.bind(n,5381)),"@site/docs/dapp/tools/band.md",5381],"72e396cc":[()=>n.e(9743).then(n.bind(n,5700)),"@site/docs/node/run-your-node/sentry-node.md",5700],"72efe815":[()=>n.e(5028).then(n.bind(n,7004)),"@site/docs/node/run-your-node/ias-proxy.md",7004],"72f44a45":[()=>n.e(3902).then(n.bind(n,8700)),"@site/docs/general/oasis-network/faq.md",8700],"7327d54c":[()=>n.e(622).then(n.bind(n,5330)),"@site/docs/get-involved/network-governance.md",5330],"736ce571":[()=>n.e(210).then(n.bind(n,9817)),"@site/docs/node/run-your-node/prerequisites/hardware-recommendations.md",9817],"74cc02ce":[()=>Promise.all([n.e(1869),n.e(6350)]).then(n.bind(n,7725)),"@site/docs/general/README.mdx",7725],"767aa429":[()=>n.e(472).then(n.bind(n,7978)),"@site/docs/general/manage-tokens/cli/wallet.md",7978],"7687a514":[()=>Promise.all([n.e(1869),n.e(1538)]).then(n.bind(n,8542)),"@site/docs/dapp/cipher/README.mdx",8542],"777245c5":[()=>n.e(4551).then(n.bind(n,6661)),"@site/docs/core/consensus/services/governance.md",6661],79102774:[()=>Promise.all([n.e(1869),n.e(3684)]).then(n.bind(n,2383)),"@site/docs/node/run-your-node/validator-node.mdx",2383],"7b1f3817":[()=>n.e(7532).then(n.bind(n,100)),"@site/docs/adrs/0002-go-modules-compatible-git-tags.md",100],"7bee5ea1":[()=>n.e(4938).then(n.bind(n,6557)),"@site/docs/general/manage-tokens/terminology.md",6557],"7ca72da4":[()=>n.e(8660).then(n.bind(n,3873)),"@site/docs/core/bigint.md",3873],"7da689db":[()=>Promise.all([n.e(1869),n.e(1420)]).then(n.bind(n,5754)),"@site/docs/get-involved/run-node/paratime-node.mdx",5754],"82c34158":[()=>n.e(9737).then(n.bind(n,4271)),"@site/docs/dapp/sapphire/authentication.md",4271],85011861:[()=>n.e(5403).then(n.bind(n,6995)),"@site/docs/general/manage-tokens/cli/transaction.md",6995],"87030e10":[()=>n.e(9673).then(n.bind(n,6093)),"@site/docs/adrs/0024-off-chain-runtime-logic.md",6093],"8786ced4":[()=>n.e(5214).then(n.bind(n,7494)),"@site/docs/adrs/0014-runtime-signing-tx-with-hardware-wallet.md",7494],"885a74d0":[()=>n.e(7964).then(n.bind(n,7248)),"@site/docs/core/development-setup/oasis-net-runner.md",7248],"886d3d06":[()=>n.e(9206).then(n.bind(n,1270)),"@site/docs/general/manage-tokens/cli/setup.md",1270],"8b083473":[()=>n.e(598).then(n.bind(n,666)),"@site/docs/core/oasis-node/rpc.md",666],"8f21ad56":[()=>n.e(2676).then(n.bind(n,1968)),"@site/docs/node/testnet/upgrade-log.md",1968],"8fa03331":[()=>n.e(8104).then(n.bind(n,1960)),"@site/docs/node/run-your-node/advanced/sync-node-using-state-sync.md",1960],"904dacd1":[()=>n.e(3993).then(n.bind(n,6082)),"@site/docs/node/run-your-node/keymanager-node/signing-key-manager-policy.md",6082],"916ebde8":[()=>n.e(6627).then(n.t.bind(n,9625,19)),"@generated/docusaurus-plugin-content-docs/default/p/general-manage-tokens-oasis-wallets-285.json",9625],"917d8c1f":[()=>n.e(6202).then(n.bind(n,103)),"@site/docs/core/development-setup/single-validator-node-network.md",103],"919a9404":[()=>n.e(64).then(n.bind(n,6075)),"@site/docs/adrs/0005-runtime-compute-slashing.md",6075],"94ed66ea":[()=>n.e(6205).then(n.bind(n,2960)),"@site/docs/core/consensus/services/scheduler.md",2960],"977c4838":[()=>Promise.all([n.e(1869),n.e(9628)]).then(n.bind(n,7715)),"@site/docs/node/README.mdx",7715],"9795c642":[()=>n.e(7444).then(n.bind(n,8339)),"@site/docs/get-involved/run-node/validator-node.md",8339],"994ee662":[()=>n.e(2625).then(n.bind(n,3796)),"@site/docs/general/manage-tokens/staking-and-delegating.md",3796],"9ba66431":[()=>n.e(1117).then(n.bind(n,9328)),"@site/docs/core/consensus/services/staking.md",9328],"9e0d9849":[()=>n.e(5783).then(n.t.bind(n,3682,19)),"@generated/docusaurus-plugin-content-docs/default/p/node-run-your-node-prerequisites-f4c.json",3682],"9fa9d380":[()=>Promise.all([n.e(1869),n.e(9051)]).then(n.bind(n,1025)),"@site/docs/node/run-your-node/non-validator-node.mdx",1025],"9fda2e12":[()=>Promise.all([n.e(1869),n.e(8537)]).then(n.bind(n,3744)),"@site/docs/dapp/README.mdx",3744],a02c83e6:[()=>n.e(6391).then(n.bind(n,5535)),"@site/docs/core/consensus/transactions.md",5535],a11d2c44:[()=>n.e(1432).then(n.bind(n,7648)),"@site/docs/node/run-your-node/keymanager-node/key-manager-upgrade.md",7648],a14fc975:[()=>n.e(1527).then(n.bind(n,1819)),"@site/docs/node/mainnet/upgrade-log.md",1819],a1e8ae9c:[()=>n.e(9484).then(n.t.bind(n,8509,19)),"@generated/docusaurus-plugin-content-docs/default/p/node-mainnet-previous-upgrades-a09.json",8509],a2066b59:[()=>n.e(3774).then(n.t.bind(n,8208,19)),"@generated/docusaurus-plugin-content-docs/default/p/adrs-dbd.json",8208],a71e7da1:[()=>n.e(2190).then(n.bind(n,9546)),"@site/docs/node/run-your-node/maintenance/shutting-down-a-node.md",9546],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,4532)),"@theme/DocVersionRoot",4532],a7d941e7:[()=>n.e(6635).then(n.bind(n,784)),"@site/docs/general/manage-tokens/cli/paratime.md",784],a89bcaa3:[()=>n.e(9689).then(n.bind(n,1565)),"@site/docs/adrs/0016-consensus-parameters-change-proposal.md",1565],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,2559)),"@theme/DocRoot",2559],a9e87a2c:[()=>Promise.all([n.e(1869),n.e(5187)]).then(n.bind(n,3980)),"@site/docs/general/oasis-network/README.mdx",3980],ab39d68c:[()=>n.e(3475).then(n.bind(n,8713)),"@site/docs/core/mkvs.md",8713],ab8e36ce:[()=>n.e(1028).then(n.bind(n,4642)),"@site/docs/general/manage-tokens/README.mdx",4642],aba21aa0:[()=>n.e(5742).then(n.t.bind(n,7093,19)),"@generated/docusaurus-plugin-content-docs/default/__plugin.json",7093],acdeae29:[()=>Promise.all([n.e(1869),n.e(9099)]).then(n.bind(n,2453)),"@site/docs/dapp/emerald/writing-dapps-on-emerald.mdx",2453],b11f73a1:[()=>Promise.all([n.e(1869),n.e(7373)]).then(n.bind(n,8056)),"@site/docs/node/web3.mdx",8056],b230e4e5:[()=>n.e(2075).then(n.bind(n,4825)),"@site/docs/adrs/0004-runtime-governance.md",4825],b4883e93:[()=>n.e(3377).then(n.bind(n,7034)),"@site/docs/general/oasis-network/why-oasis.md",7034],b622a7ea:[()=>n.e(1553).then(n.bind(n,893)),"@site/docs/paratime/modules.md",893],b66dccd5:[()=>n.e(890).then(n.bind(n,6926)),"@site/docs/paratime/minimal-runtime.md",6926],b821a83b:[()=>n.e(6394).then(n.bind(n,3623)),"@site/docs/node/run-your-node/maintenance/adding-or-removing-nodes.md",3623],bb3e1595:[()=>n.e(9227).then(n.bind(n,2360)),"@site/docs/get-involved/oasis-core.md",2360],bcbc0322:[()=>Promise.all([n.e(1869),n.e(4012)]).then(n.bind(n,6544)),"@site/docs/node/run-your-node/paratime-client-node.mdx",6544],be76d7de:[()=>Promise.all([n.e(1869),n.e(8913)]).then(n.bind(n,7719)),"@site/docs/general/manage-tokens/oasis-wallets/web.mdx",7719],be836de1:[()=>n.e(3675).then(n.t.bind(n,8477,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-oasis-node-96d.json",8477],bede16e2:[()=>Promise.all([n.e(1869),n.e(4253)]).then(n.bind(n,6716)),"@site/docs/node/run-your-node/paratime-node.mdx",6716],bfa096f2:[()=>n.e(7873).then(n.t.bind(n,3786,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-common-functionality-3bb.json",3786],c41a84e2:[()=>n.e(8113).then(n.bind(n,913)),"@site/docs/core/runtime/README.md",913],c800e6d8:[()=>n.e(3667).then(n.bind(n,4239)),"@site/docs/adrs/0022-keymanager-master-secrets.md",4239],c9130a94:[()=>Promise.all([n.e(1869),n.e(4633)]).then(n.bind(n,9218)),"@site/docs/rofl/README.mdx",9218],c9679863:[()=>Promise.all([n.e(1869),n.e(8856)]).then(n.bind(n,8555)),"@site/docs/dapp/emerald/README.mdx",8555],cb5a5574:[()=>n.e(529).then(n.bind(n,3745)),"@site/docs/general/manage-tokens/cli/README.md",3745],cd9af2e1:[()=>n.e(1198).then(n.bind(n,8623)),"@site/docs/core/consensus/test-vectors.md",8623],ce2c26b3:[()=>n.e(9947).then(n.bind(n,2668)),"@site/docs/adrs/0017-app-standards.md",2668],ced62d27:[()=>n.e(6598).then(n.bind(n,8341)),"@site/docs/rofl/app.md",8341],cef04ba6:[()=>n.e(7794).then(n.bind(n,5966)),"@site/docs/adrs/0006-consensus-governance.md",5966],d089813a:[()=>n.e(8599).then(n.bind(n,8083)),"@site/docs/core/runtime/messages.md",8083],d18a0ae3:[()=>n.e(6650).then(n.bind(n,4366)),"@site/docs/node/run-your-node/maintenance/handling-network-upgrades.md",4366],d632a858:[()=>n.e(4074).then(n.bind(n,736)),"@site/docs/dapp/opl/introduction.md",736],d941f4da:[()=>n.e(7984).then(n.bind(n,6601)),"@site/docs/core/release-process.md",6601],d95a60a6:[()=>n.e(443).then(n.bind(n,9159)),"@site/docs/node/mainnet/previous-upgrades/mainnet-upgrade.md",9159],db582d92:[()=>n.e(3729).then(n.bind(n,792)),"@site/docs/node/run-your-node/keymanager-node/README.md",792],dcfcc267:[()=>n.e(223).then(n.bind(n,6545)),"@site/docs/core/development-setup/running-tests.md",6545],de2ae66a:[()=>n.e(55).then(n.bind(n,9322)),"@site/docs/core/consensus/genesis.md",9322],e0bef5df:[()=>n.e(5714).then(n.t.bind(n,3538,19)),"@generated/docusaurus-plugin-content-docs/default/p/core-consensus-services-f15.json",3538],e27d89bb:[()=>n.e(7754).then(n.bind(n,238)),"@site/docs/core/consensus/services/registry.md",238],e27f323d:[()=>Promise.all([n.e(1869),n.e(8639)]).then(n.bind(n,5562)),"@site/docs/dapp/opl/README.md",5562],e2e2c701:[()=>n.e(8600).then(n.bind(n,4747)),"@site/docs/core/consensus/services/keymanager.md",4747],e607d64f:[()=>Promise.all([n.e(1869),n.e(1081)]).then(n.bind(n,8199)),"@site/docs/dapp/sapphire/gasless.md",8199],e6c3daa2:[()=>n.e(6704).then(n.bind(n,5466)),"@site/docs/general/manage-tokens/holding-rose-tokens/ledger-wallet.md",5466],e6f41e1e:[()=>n.e(564).then(n.bind(n,355)),"@site/docs/dapp/sapphire/addresses.md",355],e793830e:[()=>n.e(5801).then(n.bind(n,6326)),"@site/docs/node/run-your-node/seed-node.md",6326],e7b1111d:[()=>n.e(6037).then(n.t.bind(n,4575,19)),"@generated/docusaurus-plugin-content-docs/default/p/node-run-your-node-maintenance-c49.json",4575],e7c70926:[()=>n.e(5084).then(n.t.bind(n,7627,19)),"@generated/docusaurus-plugin-content-docs/default/p/general-manage-tokens-holding-rose-tokens-e35.json",7627],e9951844:[()=>n.e(5592).then(n.bind(n,6443)),"@site/docs/core/crypto.md",6443],ea8b28d2:[()=>n.e(1927).then(n.bind(n,4374)),"@site/docs/general/manage-tokens/cli/addressbook.md",4374],eb341911:[()=>n.e(823).then(n.bind(n,6206)),"@site/docs/core/versioning.md",6206],f57ebf67:[()=>n.e(7793).then(n.bind(n,2176)),"@site/docs/node/run-your-node/troubleshooting.md",2176],f8012949:[()=>n.e(9610).then(n.bind(n,5164)),"@site/docs/core/SECURITY.md",5164],f923b8a9:[()=>Promise.all([n.e(1869),n.e(3397)]).then(n.bind(n,73)),"@site/docs/general/manage-tokens/oasis-wallets/browser-extension.mdx",73],fdfc1f73:[()=>Promise.all([n.e(1869),n.e(2035)]).then(n.bind(n,6466)),"@site/docs/node/run-your-node/prerequisites/system-configuration.mdx",6466],ffcff7f9:[()=>n.e(5638).then(n.bind(n,1367)),"@site/docs/core/oasis-node/cli.md",1367]};var s=n(4848);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("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%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("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",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(6921),u=n(3102);function d(e,t){if("*"===e)return o()({loading:l,loader:()=>n.e(2237).then(n.bind(n,2237)),modules:["@theme/NotFound"],webpack:()=>[2237],render(e,t){const n=e.default;return(0,s.jsx)(u.W,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},p=[],f=[],m=(0,c.A)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));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 i=o;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;delete o.__context;const l=o.__props;return delete o.__props,(0,s.jsx)(u.W,{value:i,children:(0,s.jsx)(a,{...o,...l,...n})})}})}const p=[{path:"/search",component:d("/search","822"),exact:!0},{path:"/",component:d("/","154"),routes:[{path:"/",component:d("/","2f3"),routes:[{path:"/",component:d("/","3de"),routes:[{path:"/adrs",component:d("/adrs","e33"),exact:!0,sidebar:"adrs"},{path:"/adrs/0001-tm-multi-root-apphash",component:d("/adrs/0001-tm-multi-root-apphash","5b8"),exact:!0,sidebar:"adrs"},{path:"/adrs/0002-go-modules-compatible-git-tags",component:d("/adrs/0002-go-modules-compatible-git-tags","d77"),exact:!0,sidebar:"adrs"},{path:"/adrs/0003-consensus-runtime-token-transfer",component:d("/adrs/0003-consensus-runtime-token-transfer","0dc"),exact:!0,sidebar:"adrs"},{path:"/adrs/0004-runtime-governance",component:d("/adrs/0004-runtime-governance","3b9"),exact:!0,sidebar:"adrs"},{path:"/adrs/0005-runtime-compute-slashing",component:d("/adrs/0005-runtime-compute-slashing","67d"),exact:!0,sidebar:"adrs"},{path:"/adrs/0006-consensus-governance",component:d("/adrs/0006-consensus-governance","331"),exact:!0,sidebar:"adrs"},{path:"/adrs/0007-improved-random-beacon",component:d("/adrs/0007-improved-random-beacon","bf8"),exact:!0,sidebar:"adrs"},{path:"/adrs/0008-standard-account-key-generation",component:d("/adrs/0008-standard-account-key-generation","3a4"),exact:!0,sidebar:"adrs"},{path:"/adrs/0009-ed25519-semantics",component:d("/adrs/0009-ed25519-semantics","e61"),exact:!0,sidebar:"adrs"},{path:"/adrs/0010-vrf-elections",component:d("/adrs/0010-vrf-elections","5c4"),exact:!0,sidebar:"adrs"},{path:"/adrs/0011-incoming-runtime-messages",component:d("/adrs/0011-incoming-runtime-messages","b6e"),exact:!0,sidebar:"adrs"},{path:"/adrs/0012-runtime-message-results",component:d("/adrs/0012-runtime-message-results","330"),exact:!0,sidebar:"adrs"},{path:"/adrs/0013-runtime-upgrades",component:d("/adrs/0013-runtime-upgrades","565"),exact:!0,sidebar:"adrs"},{path:"/adrs/0014-runtime-signing-tx-with-hardware-wallet",component:d("/adrs/0014-runtime-signing-tx-with-hardware-wallet","e92"),exact:!0,sidebar:"adrs"},{path:"/adrs/0015-vrf-per-block-entropy",component:d("/adrs/0015-vrf-per-block-entropy","e77"),exact:!0,sidebar:"adrs"},{path:"/adrs/0016-consensus-parameters-change-proposal",component:d("/adrs/0016-consensus-parameters-change-proposal","1e4"),exact:!0,sidebar:"adrs"},{path:"/adrs/0017-app-standards",component:d("/adrs/0017-app-standards","44f"),exact:!0,sidebar:"adrs"},{path:"/adrs/0020-governance-delegator-votes",component:d("/adrs/0020-governance-delegator-votes","d09"),exact:!0,sidebar:"adrs"},{path:"/adrs/0021-keymanager-ephemeral-secrets",component:d("/adrs/0021-keymanager-ephemeral-secrets","120"),exact:!0,sidebar:"adrs"},{path:"/adrs/0022-keymanager-master-secrets",component:d("/adrs/0022-keymanager-master-secrets","02a"),exact:!0,sidebar:"adrs"},{path:"/adrs/0024-off-chain-runtime-logic",component:d("/adrs/0024-off-chain-runtime-logic","1cd"),exact:!0,sidebar:"adrs"},{path:"/core/",component:d("/core/","e3c"),exact:!0,sidebar:"oasisCore"},{path:"/core/authenticated-grpc",component:d("/core/authenticated-grpc","236"),exact:!0,sidebar:"oasisCore"},{path:"/core/bigint",component:d("/core/bigint","72d"),exact:!0},{path:"/core/common-functionality",component:d("/core/common-functionality","45b"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/",component:d("/core/consensus/","0b4"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/genesis",component:d("/core/consensus/genesis","da0"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services",component:d("/core/consensus/services","3da"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/beacon",component:d("/core/consensus/services/beacon","0db"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/epochtime",component:d("/core/consensus/services/epochtime","e8d"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/governance",component:d("/core/consensus/services/governance","a5b"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/keymanager",component:d("/core/consensus/services/keymanager","0fd"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/registry",component:d("/core/consensus/services/registry","bd1"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/roothash",component:d("/core/consensus/services/roothash","214"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/scheduler",component:d("/core/consensus/services/scheduler","114"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/services/staking",component:d("/core/consensus/services/staking","21e"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/test-vectors",component:d("/core/consensus/test-vectors","977"),exact:!0,sidebar:"oasisCore"},{path:"/core/consensus/transactions",component:d("/core/consensus/transactions","be4"),exact:!0,sidebar:"oasisCore"},{path:"/core/crypto",component:d("/core/crypto","277"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup",component:d("/core/development-setup","816"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/build-environment-setup-and-building",component:d("/core/development-setup/build-environment-setup-and-building","ae9"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/building",component:d("/core/development-setup/building","e22"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/deploying-a-runtime",component:d("/core/development-setup/deploying-a-runtime","39d"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/oasis-net-runner",component:d("/core/development-setup/oasis-net-runner","068"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/prerequisites",component:d("/core/development-setup/prerequisites","d49"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/running-tests",component:d("/core/development-setup/running-tests","7e0"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/running-tests-and-development-networks",component:d("/core/development-setup/running-tests-and-development-networks","e49"),exact:!0,sidebar:"oasisCore"},{path:"/core/development-setup/single-validator-node-network",component:d("/core/development-setup/single-validator-node-network","3cf"),exact:!0,sidebar:"oasisCore"},{path:"/core/encoding",component:d("/core/encoding","c77"),exact:!0,sidebar:"oasisCore"},{path:"/core/high-level-components",component:d("/core/high-level-components","40b"),exact:!0,sidebar:"oasisCore"},{path:"/core/mkvs",component:d("/core/mkvs","914"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node",component:d("/core/oasis-node","db3"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/cli",component:d("/core/oasis-node/cli","b77"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/metrics",component:d("/core/oasis-node/metrics","bd4"),exact:!0,sidebar:"oasisCore"},{path:"/core/oasis-node/rpc",component:d("/core/oasis-node/rpc","2c6"),exact:!0,sidebar:"oasisCore"},{path:"/core/processes",component:d("/core/processes","54e"),exact:!0,sidebar:"oasisCore"},{path:"/core/release-process",component:d("/core/release-process","e37"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/",component:d("/core/runtime/","ac5"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/identifiers",component:d("/core/runtime/identifiers","cbe"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/messages",component:d("/core/runtime/messages","14e"),exact:!0,sidebar:"oasisCore"},{path:"/core/runtime/runtime-host-protocol",component:d("/core/runtime/runtime-host-protocol","2c7"),exact:!0,sidebar:"oasisCore"},{path:"/core/SECURITY",component:d("/core/SECURITY","650"),exact:!0,sidebar:"oasisCore"},{path:"/core/versioning",component:d("/core/versioning","723"),exact:!0,sidebar:"oasisCore"},{path:"/dapp/",component:d("/dapp/","44e"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/",component:d("/dapp/cipher/","55a"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/confidential-smart-contract",component:d("/dapp/cipher/confidential-smart-contract","35b"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/hello-world",component:d("/dapp/cipher/hello-world","1f9"),exact:!0,sidebar:"developers"},{path:"/dapp/cipher/prerequisites",component:d("/dapp/cipher/prerequisites","425"),exact:!0,sidebar:"developers"},{path:"/dapp/emerald/",component:d("/dapp/emerald/","340"),exact:!0,sidebar:"developers"},{path:"/dapp/emerald/writing-dapps-on-emerald",component:d("/dapp/emerald/writing-dapps-on-emerald","120"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/",component:d("/dapp/opl/","088"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/build",component:d("/dapp/opl/build","468"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/enclave",component:d("/dapp/opl/enclave","d03"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/frontend",component:d("/dapp/opl/frontend","804"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/host",component:d("/dapp/opl/host","7dd"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/introduction",component:d("/dapp/opl/introduction","36e"),exact:!0,sidebar:"developers"},{path:"/dapp/opl/setup",component:d("/dapp/opl/setup","a29"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/",component:d("/dapp/sapphire/","0aa"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/addresses",component:d("/dapp/sapphire/addresses","d31"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/authentication",component:d("/dapp/sapphire/authentication","f35"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/browser",component:d("/dapp/sapphire/browser","83a"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/deployment",component:d("/dapp/sapphire/deployment","5b6"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/gasless",component:d("/dapp/sapphire/gasless","8f0"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/guide",component:d("/dapp/sapphire/guide","480"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/quickstart",component:d("/dapp/sapphire/quickstart","8a0"),exact:!0,sidebar:"developers"},{path:"/dapp/sapphire/security",component:d("/dapp/sapphire/security","d3f"),exact:!0,sidebar:"developers"},{path:"/dapp/tools/",component:d("/dapp/tools/","f8c"),exact:!0,sidebar:"developers"},{path:"/dapp/tools/band",component:d("/dapp/tools/band","70e"),exact:!0,sidebar:"developers"},{path:"/general/",component:d("/general/","7eb"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/",component:d("/general/manage-tokens/","2c0"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/",component:d("/general/manage-tokens/cli/","5b3"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/account",component:d("/general/manage-tokens/cli/account","940"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/addressbook",component:d("/general/manage-tokens/cli/addressbook","c36"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/network",component:d("/general/manage-tokens/cli/network","aa9"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/paratime",component:d("/general/manage-tokens/cli/paratime","d4d"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/setup",component:d("/general/manage-tokens/cli/setup","c6c"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/transaction",component:d("/general/manage-tokens/cli/transaction","04a"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/cli/wallet",component:d("/general/manage-tokens/cli/wallet","29b"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/faq",component:d("/general/manage-tokens/faq","e31"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens",component:d("/general/manage-tokens/holding-rose-tokens","6c8"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens/custody-providers",component:d("/general/manage-tokens/holding-rose-tokens/custody-providers","b6d"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/holding-rose-tokens/ledger-wallet",component:d("/general/manage-tokens/holding-rose-tokens/ledger-wallet","374"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime",component:d("/general/manage-tokens/how-to-transfer-eth-erc20-to-emerald-paratime","628"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets",component:d("/general/manage-tokens/oasis-wallets","838"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets/browser-extension",component:d("/general/manage-tokens/oasis-wallets/browser-extension","5dc"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/oasis-wallets/web",component:d("/general/manage-tokens/oasis-wallets/web","f97"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/staking-and-delegating",component:d("/general/manage-tokens/staking-and-delegating","620"),exact:!0,sidebar:"general"},{path:"/general/manage-tokens/terminology",component:d("/general/manage-tokens/terminology","af8"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/",component:d("/general/oasis-network/","662"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/faq",component:d("/general/oasis-network/faq","6aa"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/token-metrics-and-distribution",component:d("/general/oasis-network/token-metrics-and-distribution","ea1"),exact:!0,sidebar:"general"},{path:"/general/oasis-network/why-oasis",component:d("/general/oasis-network/why-oasis","bb0"),exact:!0,sidebar:"general"},{path:"/get-involved/",component:d("/get-involved/","948"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/delegation-policy",component:d("/get-involved/delegation-policy","37e"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/network-governance",component:d("/get-involved/network-governance","258"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/oasis-core",component:d("/get-involved/oasis-core","b41"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node",component:d("/get-involved/run-node","af2"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node/paratime-node",component:d("/get-involved/run-node/paratime-node","537"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/run-node/validator-node",component:d("/get-involved/run-node/validator-node","cc8"),exact:!0,sidebar:"getInvolved"},{path:"/get-involved/token-delivery-and-kyc",component:d("/get-involved/token-delivery-and-kyc","c17"),exact:!0,sidebar:"getInvolved"},{path:"/node/",component:d("/node/","ad0"),exact:!0,sidebar:"operators"},{path:"/node/genesis-doc",component:d("/node/genesis-doc","9d5"),exact:!0,sidebar:"operators"},{path:"/node/grpc",component:d("/node/grpc","5b7"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/",component:d("/node/mainnet/","963"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/eden-upgrade",component:d("/node/mainnet/eden-upgrade","460"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades",component:d("/node/mainnet/previous-upgrades","e6b"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades/cobalt-upgrade",component:d("/node/mainnet/previous-upgrades/cobalt-upgrade","e11"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades/damask-upgrade",component:d("/node/mainnet/previous-upgrades/damask-upgrade","7a6"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/previous-upgrades/mainnet-upgrade",component:d("/node/mainnet/previous-upgrades/mainnet-upgrade","9a5"),exact:!0,sidebar:"operators"},{path:"/node/mainnet/upgrade-log",component:d("/node/mainnet/upgrade-log","326"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/",component:d("/node/run-your-node/","722"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced",component:d("/node/run-your-node/advanced","8f3"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/copy-state-from-one-node-to-the-other",component:d("/node/run-your-node/advanced/copy-state-from-one-node-to-the-other","96b"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/remote-signer",component:d("/node/run-your-node/advanced/remote-signer","6ad"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/advanced/sync-node-using-state-sync",component:d("/node/run-your-node/advanced/sync-node-using-state-sync","15c"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/archive-node",component:d("/node/run-your-node/archive-node","aaa"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/ias-proxy",component:d("/node/run-your-node/ias-proxy","3f1"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/",component:d("/node/run-your-node/keymanager-node/","938"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/key-manager-upgrade",component:d("/node/run-your-node/keymanager-node/key-manager-upgrade","fa5"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/keymanager-node/signing-key-manager-policy",component:d("/node/run-your-node/keymanager-node/signing-key-manager-policy","120"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance",component:d("/node/run-your-node/maintenance","beb"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/adding-or-removing-nodes",component:d("/node/run-your-node/maintenance/adding-or-removing-nodes","c87"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/handling-network-upgrades",component:d("/node/run-your-node/maintenance/handling-network-upgrades","430"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/refreshing-certificates",component:d("/node/run-your-node/maintenance/refreshing-certificates","d99"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/shutting-down-a-node",component:d("/node/run-your-node/maintenance/shutting-down-a-node","d17"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/maintenance/wiping-node-state",component:d("/node/run-your-node/maintenance/wiping-node-state","7e3"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/non-validator-node",component:d("/node/run-your-node/non-validator-node","489"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/paratime-client-node",component:d("/node/run-your-node/paratime-client-node","456"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/paratime-node",component:d("/node/run-your-node/paratime-node","84c"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites",component:d("/node/run-your-node/prerequisites","22d"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/hardware-recommendations",component:d("/node/run-your-node/prerequisites/hardware-recommendations","301"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/oasis-node",component:d("/node/run-your-node/prerequisites/oasis-node","7d2"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee",component:d("/node/run-your-node/prerequisites/set-up-trusted-execution-environment-tee","7ac"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/stake-requirements",component:d("/node/run-your-node/prerequisites/stake-requirements","ddc"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/prerequisites/system-configuration",component:d("/node/run-your-node/prerequisites/system-configuration","83f"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/seed-node",component:d("/node/run-your-node/seed-node","c29"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/sentry-node",component:d("/node/run-your-node/sentry-node","2f5"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/troubleshooting",component:d("/node/run-your-node/troubleshooting","4c7"),exact:!0,sidebar:"operators"},{path:"/node/run-your-node/validator-node",component:d("/node/run-your-node/validator-node","f1e"),exact:!0,sidebar:"operators"},{path:"/node/testnet/",component:d("/node/testnet/","6e5"),exact:!0,sidebar:"operators"},{path:"/node/testnet/upgrade-log",component:d("/node/testnet/upgrade-log","2b4"),exact:!0,sidebar:"operators"},{path:"/node/web3",component:d("/node/web3","7f3"),exact:!0,sidebar:"operators"},{path:"/paratime/",component:d("/paratime/","2f9"),exact:!0,sidebar:"paratime"},{path:"/paratime/minimal-runtime",component:d("/paratime/minimal-runtime","241"),exact:!0,sidebar:"paratime"},{path:"/paratime/modules",component:d("/paratime/modules","18a"),exact:!0,sidebar:"paratime"},{path:"/paratime/prerequisites",component:d("/paratime/prerequisites","f49"),exact:!0,sidebar:"paratime"},{path:"/paratime/reproducibility",component:d("/paratime/reproducibility","d45"),exact:!0,sidebar:"paratime"},{path:"/rofl/",component:d("/rofl/","bd6"),exact:!0,sidebar:"rofl"},{path:"/rofl/app",component:d("/rofl/app","351"),exact:!0,sidebar:"rofl"},{path:"/rofl/prerequisites",component:d("/rofl/prerequisites","742"),exact:!0,sidebar:"rofl"},{path:"/rofl/trust-root",component:d("/rofl/trust-root","8ae"),exact:!0,sidebar:"rofl"},{path:"/",component:d("/","d84"),exact:!0}]}]}]},{path:"*",component:d("*")}]},6125:(e,t,n)=>{"use strict";n.d(t,{o:()=>a,x:()=>i});var r=n(6540),o=n(4848);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8536:(e,t,n)=>{"use strict";var r=n(6540),o=n(5338),a=n(4625),i=n(545),s=n(8193);const l=[n(119),n(6134),n(6294),n(1043)];var c=n(8328),u=n(6347),d=n(2831),p=n(4848);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var m=n(5260),h=n(4586),g=n(6025),b=n(6342),y=n(1003),v=n(2131),k=n(4090),w=n(2967),x=n(440),_=n(1463);function S(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.A)(),r=(0,v.o)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,p.jsxs)(m.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.A)(),{pathname:r}=(0,u.zy)();return e+(0,x.applyTrailingSlash)((0,g.A)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,p.jsxs)(m.A,{children:[(0,p.jsx)("meta",{property:"og:url",content:o}),(0,p.jsx)("link",{rel:"canonical",href:o})]})}function C(){const{i18n:{currentLocale:e}}=(0,h.A)(),{metadata:t,image:n}=(0,b.p)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(m.A,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:k.w})]}),n&&(0,p.jsx)(y.be,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(S,{}),(0,p.jsx)(_.A,{tag:w.Cy,locale:e}),(0,p.jsx)(m.A,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const A=new Map;var T=n(6125),P=n(6988),L=n(205);function j(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()=>o.forEach((e=>e?.()))}const R=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,L.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)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:r}),j("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function N(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.u)(c.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class O extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.A.canUseDOM?j("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=j("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(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(0,p.jsx)(R,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.qh,{location:t,render:()=>e})})}}const I=O,F="__docusaurus-base-url-issue-banner-container",D="__docusaurus-base-url-issue-banner",M="__docusaurus-base-url-issue-banner-suggestion-container";function z(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${F}';\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(/{let{route:t}=e;return!0===t.exact})))return A.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return A.set(e.pathname,t),{...e,pathname:t}}((0,u.zy)());return(0,p.jsx)(I,{location:e,children:H})}function G(){return(0,p.jsx)(Q.A,{children:(0,p.jsx)(P.l,{children:(0,p.jsxs)(T.x,{children:[(0,p.jsxs)(f,{children:[(0,p.jsx)(U,{}),(0,p.jsx)(C,{}),(0,p.jsx)($,{}),(0,p.jsx)(W,{})]}),(0,p.jsx)(V,{})]})})})}var Y=n(4054);const Z=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 o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.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 K=n(6921);const X=new Set,J=new Set,ee=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,te={prefetch:e=>{if(!(e=>!ee()&&!J.has(e)&&!X.has(e))(e))return!1;X.add(e);const t=(0,d.u)(c.A,e).flatMap((e=>{return t=e.route.path,Object.entries(Y).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Z(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!ee()&&!J.has(e))(e)&&(J.add(e),N(e))},ne=Object.freeze(te),re=Boolean(!0);if(s.A.canUseDOM){window.docusaurus=ne;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.vd,{children:(0,p.jsx)(a.Kd,{children:(0,p.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(re)window.docusaurusRoot=o.hydrateRoot(e,t,{onRecoverableError:n});else{const r=o.createRoot(e,{onRecoverableError:n});r.render(t),window.docusaurusRoot=r}};N(window.location.pathname).then((()=>{(0,r.startTransition)(s)}))}},6988:(e,t,n)=>{"use strict";n.d(t,{o:()=>d,l:()=>p});var r=n(6540),o=n(4784);const a=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":"adrs/0024-off-chain-runtime-logic","path":"/adrs/0024-off-chain-runtime-logic","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/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/authentication","path":"/dapp/sapphire/authentication","sidebar":"developers"},{"id":"dapp/sapphire/browser","path":"/dapp/sapphire/browser","sidebar":"developers"},{"id":"dapp/sapphire/deployment","path":"/dapp/sapphire/deployment","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/quickstart","path":"/dapp/sapphire/quickstart","sidebar":"developers"},{"id":"dapp/sapphire/README","path":"/dapp/sapphire/","sidebar":"developers"},{"id":"dapp/sapphire/security","path":"/dapp/sapphire/security","sidebar":"developers"},{"id":"dapp/tools/band","path":"/dapp/tools/band","sidebar":"developers"},{"id":"dapp/tools/README","path":"/dapp/tools/","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/oasis-wallets/browser-extension","path":"/general/manage-tokens/oasis-wallets/browser-extension","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/grpc","path":"/node/grpc","sidebar":"operators"},{"id":"node/mainnet/eden-upgrade","path":"/node/mainnet/eden-upgrade","sidebar":"operators"},{"id":"node/mainnet/previous-upgrades/cobalt-upgrade","path":"/node/mainnet/previous-upgrades/cobalt-upgrade","sidebar":"operators"},{"id":"node/mainnet/previous-upgrades/damask-upgrade","path":"/node/mainnet/previous-upgrades/damask-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/remote-signer","path":"/node/run-your-node/advanced/remote-signer","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/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/README","path":"/node/run-your-node/","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":"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":"rofl/app","path":"/rofl/app","sidebar":"rofl"},{"id":"rofl/prerequisites","path":"/rofl/prerequisites","sidebar":"rofl"},{"id":"rofl/README","path":"/rofl/","sidebar":"rofl"},{"id":"rofl/trust-root","path":"/rofl/trust-root","sidebar":"rofl"},{"id":"/adrs","path":"/adrs","sidebar":"adrs"},{"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":"general/manage-tokens/oasis-wallets","path":"/general/manage-tokens/oasis-wallets","sidebar":"general"},{"id":"general/manage-tokens/holding-rose-tokens","path":"/general/manage-tokens/holding-rose-tokens","sidebar":"general"},{"id":"get-involved/run-node","path":"/get-involved/run-node","sidebar":"getInvolved"},{"id":"node/mainnet/previous-upgrades","path":"/node/mainnet/previous-upgrades","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"}],"draftIds":[],"sidebars":{"adrs":{"link":{"path":"/adrs","label":"Architectural Decision Records"}},"oasisCore":{"link":{"path":"/core/","label":"Overview"}},"developers":{"link":{"path":"/dapp/","label":"Overview"}},"general":{"link":{"path":"/general/","label":"Overview"}},"getInvolved":{"link":{"path":"/get-involved/","label":"get-involved/README"}},"operators":{"link":{"path":"/node/","label":"Overview"}},"paratime":{"link":{"path":"/paratime/","label":"Overview"}},"rofl":{"link":{"path":"/rofl/","label":"Overview"}}}}],"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(2654);const l=JSON.parse('{"docusaurusVersion":"3.3.2","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.3.2"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.3.2"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.3.2"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.3.2"},"webpack-configuration-plugin":{"type":"local"},"docusaurus-plugin-client-redirects":{"type":"package","name":"@docusaurus/plugin-client-redirects","version":"3.3.2"},"@easyops-cn/docusaurus-search-local":{"type":"package","name":"@easyops-cn/docusaurus-search-local","version":"0.40.1"}}}');var c=n(4848);const u={siteConfig:o.A,siteMetadata:l,globalData:a,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},7489:(e,t,n)=>{"use strict";n.d(t,{A:()=>h});var r=n(6540),o=n(8193),a=n(5260),i=n(440),s=n(5476),l=n(3102),c=n(4848);function u(e){let{error:t,tryAgain:n}=e;return(0,c.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,c.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,c.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,c.jsx)(d,{error:t})]})}function d(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,c.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function p(e){let{children:t}=e;return(0,c.jsx)(l.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function f(e){let{error:t,tryAgain:n}=e;return(0,c.jsx)(p,{children:(0,c.jsxs)(h,{fallback:()=>(0,c.jsx)(u,{error:t,tryAgain:n}),children:[(0,c.jsx)(a.A,{children:(0,c.jsx)("title",{children:"Page Error"})}),(0,c.jsx)(s.A,{children:(0,c.jsx)(u,{error:t,tryAgain:n})})]})})}const m=e=>(0,c.jsx)(f,{...e});class h extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.A.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??m)(e)}return e??null}}},8193:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5260:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(545),o=n(4848);function a(e){return(0,o.jsx)(r.mg,{...e})}},8774:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});var r=n(6540),o=n(4625),a=n(440),i=n(4586),s=n(6654),l=n(8193),c=n(3427),u=n(6025),d=n(4848);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":g,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:{trailingSlash:v,baseUrl:k}}=(0,i.A)(),{withBaseUrl:w}=(0,u.h)(),x=(0,c.A)(),_=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>_.current));const S=p||f;const E=(0,s.A)(S),C=S?.replace("pathname://","");let A=void 0!==C?(T=C,b&&(e=>e.startsWith("/"))(T)?w(T):T):void 0;var T;A&&E&&(A=(0,a.applyTrailingSlash)(A,{trailingSlash:v,baseUrl:k}));const P=(0,r.useRef)(!1),L=n?o.k2:o.N_,j=l.A.canUseIntersectionObserver,R=(0,r.useRef)(),N=()=>{P.current||null==A||(window.docusaurus.preload(A),P.current=!0)};(0,r.useEffect)((()=>(!j&&E&&null!=A&&window.docusaurus.prefetch(A),()=>{j&&R.current&&R.current.disconnect()})),[R,A,j,E]);const O=A?.startsWith("#")??!1,I=!y.target||"_self"===y.target,F=!A||!E||!I||O;return g||!O&&F||x.collectLink(A),y.id&&x.collectAnchor(y.id),F?(0,d.jsx)("a",{ref:_,href:A,...S&&!E&&{target:"_blank",rel:"noopener noreferrer"},...y}):(0,d.jsx)(L,{...y,onMouseEnter:N,onTouchStart:N,innerRef:e=>{_.current=e,j&&e&&E&&(R.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(R.current.unobserve(e),R.current.disconnect(),null!=A&&window.docusaurus.prefetch(A))}))})),R.current.observe(e))},to:A,...n&&{isActive:h,activeClassName:m}})}const f=r.forwardRef(p)},1312:(e,t,n)=>{"use strict";n.d(t,{A:()=>c,T:()=>l});var r=n(6540),o=n(4848);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 i=n(2654);function s(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 i[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return a(s({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},7065:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r="default"},6654:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{A:()=>o,z:()=>r})},6025:(e,t,n)=>{"use strict";n.d(t,{A:()=>s,h:()=>i});var r=n(6540),o=n(4586),a=n(6654);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,o.A)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a.z)(n))return n;if(o)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)}},3427:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(6540);n(4848);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},4586:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6988);function a(){return(0,r.useContext)(o.o)}},2303:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(6125);function a(){return(0,r.useContext)(o.o)}},205:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});var r=n(6540);const o=n(8193).A.canUseDOM?r.useLayoutEffect:r.useEffect},6921:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const s=o?`${o}.${a}`:a;r(i)?e(i,s):t[s]=i}))}(e),t}},3102:(e,t,n)=>{"use strict";n.d(t,{W:()=>i,o:()=>a});var r=n(6540),o=n(4848);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),s=(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:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:s,children:t})}},4070:(e,t,n)=>{"use strict";n.d(t,{zK:()=>h,vT:()=>p,Gy:()=>u,HW:()=>g,ht:()=>d,r7:()=>m,jh:()=>f});var r=n(6347),o=n(4586),a=n(7065);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.A)();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.B6)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),o=n?.docs.find((e=>!!(0,r.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const c={},u=()=>i("docusaurus-plugin-content-docs")??c,d=e=>{try{return function(e,t,n){void 0===t&&(t=a.W),void 0===n&&(n={});const r=i(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function p(e){void 0===e&&(e={});const t=u(),{pathname:n}=(0,r.zy)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.B6)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&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 a}(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.zy)();return l(t,n)}function g(e){const t=d(e),{pathname:n}=(0,r.zy)();return function(e,t){const n=s(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},6294:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(5947),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},6134:(e,t,n)=>{"use strict";n.r(t);var r=n(1765),o=n(4784);!function(e){const{themeConfig:{prism:t}}=o.A,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(9700),n(7006)(`./prism-${e}`)})),delete globalThis.Prism}(r.My)},1107:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(4164),o=n(1312),a=n(6342),i=n(8774),s=n(3427);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(4848);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.A)(),{navbar:{hideOnScroll:p}}=(0,a.p)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,c.jsxs)(t,{...u,className:(0,r.A)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.A,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},3186:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(4848);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("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"})})}},5476:(e,t,n)=>{"use strict";n.d(t,{A:()=>It});var r=n(6540),o=n(4164),a=n(7489),i=n(1003),s=n(6347),l=n(1312),c=n(5062),u=n(4848);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,s.W6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.$)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,l.T)({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:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(7559),b=n(4090);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(h,{className:y.skipToContent})}var k=n(6342),w=n(5041);function x(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const _={closeButton:"closeButton_CVFx"};function S(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.A)("clean-btn close",_.closeButton,e.className),children:(0,u.jsx)(x,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,k.p)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.A)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const A={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function T(){const{announcementBar:e}=(0,k.p)(),{isActive:t,close:n}=(0,w.Mj)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:A.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:A.announcementBarPlaceholder}),(0,u.jsx)(C,{className:A.announcementBarContent}),a&&(0,u.jsx)(S,{onClick:n,className:A.announcementBarClose})]})}var P=n(2069),L=n(3104);var j=n(9532),R=n(5600);const N=r.createContext(null);function O(e){let{children:t}=e;const n=function(){const e=(0,P.M)(),t=(0,R.YL)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,j.ZC)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(N.Provider,{value:n,children:t})}function I(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function F(){const e=(0,r.useContext)(N);if(!e)throw new j.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,R.YL)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:I(a)})),[o,a,t])}function D(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=F();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var M=n(5293),z=n(2303);function B(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("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 $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("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 Q(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,z.A)(),s=(0,l.T)({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"===r?(0,l.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.A)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.A)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(B,{className:(0,o.A)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,o.A)(U.toggleIcon,U.darkToggleIcon)})]})})}const q=r.memo(Q),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function H(e){let{className:t}=e;const n=(0,k.p)().navbar.style,r=(0,k.p)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,M.G)();return r?null:(0,u.jsx)(q,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var W=n(3465);function G(){return(0,u.jsx)(W.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,P.M)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.T)({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(),children:(0,u.jsx)(x,{color:"var(--ifm-color-emphasis-600)"})})}function Z(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(G,{}),(0,u.jsx)(H,{className:"margin-right--md"}),(0,u.jsx)(Y,{})]})}var K=n(8774),X=n(6025),J=n(6654);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(3186);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,X.A)(r),p=(0,X.A)(t),f=(0,X.A)(o,{forcePrependBaseUrl:!0}),m=a&&o&&!(0,J.A)(o),h=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,m&&(0,u.jsx)(te.A,{...s&&{width:12,height:12}})]})};return o?(0,u.jsx)(K.A,{href:l?f:o,...c,...h}):(0,u.jsx)(K.A,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},...c,...h})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.A)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(1422),se=n(9169),le=n(4586);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.ys)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...s}=e;const l=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.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)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,o.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,o.A)("navbar__link",a),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(We,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:a,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.A)(),{pathname:t}=(0,s.zy)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),(0,u.jsxs)("li",{className:(0,o.A)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.A)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(We,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var me=n(2131);function he(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("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 ge="iconLanguage_nlXk";var be=n(1088),ye=n(5391),ve=n(5597),ke=n(4070),we=n(5891),xe=n(2384),_e=n(4471),Se=n(7674),Ee=n(6841),Ce=n(3810);const Ae='',Te='',Pe='',Le='',je='',Re='',Ne='',Oe={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 Ie(e){let{document:t,type:n,page:r,metadata:o,tokens:a,isInterOfTree:i,isLastOfTree:s}=e;const l=0===n,c=1===n,u=[];i?u.push(Re):s&&u.push(Ne);const d=u.map((e=>`${e}`)),p=`${l?Ae:c?Te:Pe}`,f=[`${(0,Ce.C)(t.t,(0,Se.g)(o,"t"),a)}`];if(!i&&!s&&be.tb){const e=r?(r.b??[]).concat(r.t).concat(t.s&&t.s!==r.t?t.s:[]):t.b;f.push(`${(0,_e.$)(e??[])}`)}else l||f.push(`${(0,Ee.Z)(r.t||(t.u.startsWith("/docs/api-reference/")?"API Reference":""),a)}`);const m=`${Le}`;return[...d,p,``,...f,"",m].join("")}function Fe(){return`${je}${(0,l.T)({id:"theme.SearchBar.noResultsText",message:"No results"})}`}var De=n(2849),Me=n(3385);async function ze(){const e=await Promise.all([n.e(489),n.e(5741)]).then(n.t.bind(n,489,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 n=(0,z.A)(),{siteConfig:{baseUrl:o},i18n:{currentLocale:a}}=(0,le.A)(),i=(0,ke.vT)();let c=o;try{const{preferredVersion:e}=(0,ve.g1)(i?.pluginId??be.UB);e&&!e.isLast&&(c=e.path+"/")}catch(D){if(be.I$&&!(D instanceof j.dV))throw D}const d=(0,s.W6)(),p=(0,s.zy)(),f=(0,r.useRef)(null),m=(0,r.useRef)(new Map),h=(0,r.useRef)(!1),[g,b]=(0,r.useState)(!1),[y,v]=(0,r.useState)(!1),[k,w]=(0,r.useState)(""),x=(0,r.useRef)(null),_=(0,r.useRef)(""),[S,E]=(0,r.useState)("");(0,r.useEffect)((()=>{if(!Array.isArray(be.Hg))return;let e="";if(p.pathname.startsWith(c)){const t=p.pathname.substring(c.length);let n;for(const e of be.Hg){const r="string"==typeof e?e:e.path;if(t===r||t.startsWith(`${r}/`)){n=r;break}}n&&(e=n)}_.current!==e&&(m.current.delete(e),_.current=e),E(e)}),[p.pathname,c]);const C=!!be.O6&&Array.isArray(be.Hg)&&""===S,A=(0,r.useCallback)((async()=>{if(C||m.current.get(S))return;m.current.set(S,"loading"),x.current?.autocomplete.destroy(),b(!0);const[{wrappedIndexes:e,zhDictionary:t},n]=await Promise.all([(0,we.Z)(c,S),ze()]);if(x.current=n(f.current,{hint:!1,autoselect:!0,openOnFocus:!0,cssClasses:{root:(0,ye.A)(Oe.searchBar,{[Oe.searchBarLeft]:"left"===be.ZG}),noPrefix:!0,dropdownMenu:Oe.dropdownMenu,input:Oe.input,hint:Oe.hint,suggestions:Oe.suggestions,suggestion:Oe.suggestion,cursor:Oe.cursor,dataset:Oe.dataset,empty:Oe.empty}},[{source:(0,xe.m)(e,t,be.AT),templates:{suggestion:Ie,empty:Fe,footer:e=>{let{query:t,isEmpty:n}=e;if(n&&(!S||!be.dz))return;const r=(e=>{let{query:t,isEmpty:n}=e;const r=document.createElement("a"),i=new URLSearchParams;let s;if(i.set("q",t),S){const e=S&&Array.isArray(be.Hg)?be.Hg.find((e=>"string"==typeof e?e===S:e.path===S)):S,t=e?(0,Me.p)(e,a).label:S;s=be.dz&&n?(0,l.T)({id:"theme.SearchBar.seeAllOutsideContext",message:"See results outside {context}"},{context:t}):(0,l.T)({id:"theme.SearchBar.searchInContext",message:"See all results in {context}"},{context:t})}else s=(0,l.T)({id:"theme.SearchBar.seeAll",message:"See all results"});if(!S||!Array.isArray(be.Hg)||be.dz&&n||i.set("ctx",S),c!==o){if(!c.startsWith(o))throw new Error(`Version url '${c}' does not start with base url '${o}', this is a bug of \`@easyops-cn/docusaurus-search-local\`, please report it.`);i.set("version",c.substring(o.length))}const u=`${o}search?${i.toString()}`;return r.href=u,r.textContent=s,r.addEventListener("click",(e=>{e.ctrlKey||e.metaKey||(e.preventDefault(),x.current?.autocomplete.close(),d.push(u))})),r})({query:t,isEmpty:n}),i=document.createElement("div");return i.className=Oe.hitFooter,i.appendChild(r),i}}}]).on("autocomplete:selected",(function(e,t){let{document:{u:n,h:r},tokens:o}=t;f.current?.blur();let a=n;if(be.CU&&o.length>0){const e=new URLSearchParams;for(const t of o)e.append(Be,t);a+=`?${e.toString()}`}r&&(a+=r),d.push(a)})).on("autocomplete:closed",(()=>{f.current?.blur()})),m.current.set(S,"done"),b(!1),h.current){const e=f.current;e.value&&x.current?.autocomplete.open(),e.focus()}}),[C,S,c,o,d]);(0,r.useEffect)((()=>{if(!be.CU)return;const e=n?new URLSearchParams(p.search).getAll(Be):[];setTimeout((()=>{const t=document.querySelector("article");if(!t)return;const n=new be.CU(t);n.unmark(),0!==e.length&&n.mark(e),w(e.join(" ")),x.current?.autocomplete.setVal(e.join(" "))}))}),[n,p.search,p.pathname]);const[T,P]=(0,r.useState)(!1),L=(0,r.useCallback)((()=>{h.current=!0,A(),P(!0),t?.(!0)}),[t,A]),R=(0,r.useCallback)((()=>{P(!1),t?.(!1)}),[t]),N=(0,r.useCallback)((()=>{A()}),[A]),O=(0,r.useCallback)((e=>{w(e.target.value),e.target.value&&v(!0)}),[]),I=!!n&&/mac/i.test(navigator.userAgentData?.platform??navigator.platform);(0,r.useEffect)((()=>{if(!be.WW)return;const e=e=>{!(I?e.metaKey:e.ctrlKey)||"k"!==e.key&&"K"!==e.key||(e.preventDefault(),f.current?.focus(),L())};return document.addEventListener("keydown",e),()=>{document.removeEventListener("keydown",e)}}),[I,L]);const F=(0,r.useCallback)((()=>{const e=new URLSearchParams(p.search);e.delete(Be);const t=e.toString(),n=p.pathname+(""!=t?`?${t}`:"")+p.hash;n!=p.pathname+p.search+p.hash&&d.push(n),w(""),x.current?.autocomplete.setVal("")}),[p.pathname,p.search,p.hash,d]);return(0,u.jsxs)("div",{className:(0,ye.A)("navbar__search",Oe.searchBarContainer,{[Oe.searchIndexLoading]:g&&y,[Oe.focused]:T}),hidden:C,children:[(0,u.jsx)("input",{placeholder:(0,l.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),"aria-label":"Search",className:"navbar__search-input",onMouseEnter:N,onFocus:L,onBlur:R,onChange:O,ref:f,value:k}),(0,u.jsx)(De.A,{className:Oe.searchBarLoadingRing}),be.WW&&be.pk&&(""!==k?(0,u.jsx)("button",{className:Oe.searchClearButton,onClick:F,children:"\u2715"}):n&&(0,u.jsxs)("div",{className:Oe.searchHintContainer,children:[(0,u.jsx)("kbd",{className:Oe.searchHint,children:I?"\u2318":"ctrl"}),(0,u.jsx)("kbd",{className:Oe.searchHint,children:"K"})]}))]})},Ue={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Qe(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.A)(n,Ue.navbarSearchContainer),children:t})}var qe=n(4142);const Ve=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.A)(),p=(0,me.o)(),{search:f,hash:m}=(0,s.zy)(),h=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${o}`;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":""}})),...r],g=t?(0,l.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(he,{className:ge}),g]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Qe,{className:n,children:(0,u.jsx)($e,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.A)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,ke.zK)(r),i=(0,qe.QB)(t,r),s=a?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>s||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,ke.zK)(r),i=(0,qe.fW)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,qe.Vd)(r)[0],i=t??a.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:c,hash:d}=(0,s.zy)(),p=(0,ke.zK)(n),f=(0,ke.jh)(n),{savePreferredVersionName:m}=(0,ve.g1)(n),h=[...o,...f.map((e=>{const t=p.alternateDocVersions[e.name]??Ve(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...a],g=(0,qe.Vd)(n)[0],b=t&&h.length>1?(0,l.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,y=t&&h.length>1?void 0:Ve(g).path;return h.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:y,items:h,isActive:r?()=>!1:void 0})}};function We(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=He[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function Ge(){const e=(0,P.M)(),t=(0,k.p)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(We,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Ye(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.A,{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)",children:"\u2190 Back to main menu"})})}function Ze(){const e=0===(0,k.p)().navbar.items.length,t=F();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Ye,{onClick:()=>t.hide()}),t.content]})}function Ke(){const e=(0,P.M)();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?(0,u.jsx)(D,{header:(0,u.jsx)(Z,{}),primaryMenu:(0,u.jsx)(Ge,{}),secondaryMenu:(0,u.jsx)(Ze,{})}):null}const Xe={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Je(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.A)("navbar-sidebar__backdrop",e.className)})}function et(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,k.p)(),i=(0,P.M)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,L.Mq)(((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 o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.A)("navbar","navbar--fixed-top",n&&[Xe.navbarHideable,!d&&Xe.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Je,{onClick:i.toggle}),(0,u.jsx)(Ke,{})]})}var tt=n(440);const nt={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function rt(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(l.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function ot(e){let{error:t}=e;const n=(0,tt.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:nt.errorBoundaryError,children:n})}class at extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const it="right";function st(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function lt(){const{toggle:e,shown:t}=(0,P.M)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.T)({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",children:(0,u.jsx)(st,{})})}const ct={colorModeToggle:"colorModeToggle_DEke"};function ut(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(at,{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}),children:(0,u.jsx)(We,{...e})},t)))})}function dt(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function pt(){const e=(0,P.M)(),t=(0,k.p)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??it)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(dt,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(lt,{}),(0,u.jsx)(G,{}),(0,u.jsx)(ut,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ut,{items:r}),(0,u.jsx)(H,{className:ct.colorModeToggle}),!o&&(0,u.jsx)(Qe,{children:(0,u.jsx)($e,{})})]})})}function ft(){return(0,u.jsx)(et,{children:(0,u.jsx)(pt,{})})}function mt(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,s=(0,X.A)(n),l=(0,X.A)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(K.A,{className:"footer__link-item",...r?{href:a?l:r}:{to:s},...i,children:[o,r&&!(0,J.A)(r)&&(0,u.jsx)(te.A,{})]})}function ht(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(mt,{item:t})},t.href??t.to)}function gt(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(ht,{item:e},t)))})]})}function bt(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(gt,{column:e},t)))})}function yt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function vt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(mt,{item:t})}function kt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(vt,{item:e}),t.length!==n+1&&(0,u.jsx)(yt,{})]},n)))})})}function wt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(bt,{columns:t}):(0,u.jsx)(kt,{links:t})}var xt=n(1122);const _t={footerLogoLink:"footerLogoLink_BH7S"};function St(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.h)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(xt.A,{className:(0,o.A)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function Et(e){let{logo:t}=e;return t.href?(0,u.jsx)(K.A,{href:t.href,className:_t.footerLogoLink,target:t.target,children:(0,u.jsx)(St,{logo:t})}):(0,u.jsx)(St,{logo:t})}function Ct(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function At(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.A)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function Tt(){const{footer:e}=(0,k.p)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(At,{style:o,links:n&&n.length>0&&(0,u.jsx)(wt,{links:n}),logo:r&&(0,u.jsx)(Et,{logo:r}),copyright:t&&(0,u.jsx)(Ct,{copyright:t})})}const Pt=r.memo(Tt),Lt=(0,j.fM)([M.a,w.oq,L.Tv,ve.VQ,i.Jx,function(e){let{children:t}=e;return(0,u.jsx)(R.y_,{children:(0,u.jsx)(P.e,{children:(0,u.jsx)(O,{children:t})})})}]);function jt(e){let{children:t}=e;return(0,u.jsx)(Lt,{children:t})}var Rt=n(1107);function Nt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(Rt.A,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(rt,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(ot,{error:t})})]})})})}const Ot={mainWrapper:"mainWrapper_z2l0"};function It(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:l}=e;return(0,b.J)(),(0,u.jsxs)(jt,{children:[(0,u.jsx)(i.be,{title:s,description:l}),(0,u.jsx)(v,{}),(0,u.jsx)(T,{}),(0,u.jsx)(ft,{}),(0,u.jsx)("div",{id:d,className:(0,o.A)(g.G.wrapper.main,Ot.mainWrapper,r),children:(0,u.jsx)(a.A,{fallback:e=>(0,u.jsx)(Nt,{...e}),children:t})}),!n&&(0,u.jsx)(Pt,{})]})}},3465:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(8774),o=n(6025),a=n(4586),i=n(6342),s=n(1122),l=n(4848);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.A)(t.src),dark:(0,o.A)(t.srcDark||t.src)},i=(0,l.jsx)(s.A,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,l.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.A)(),{navbar:{title:n,logo:s}}=(0,i.p)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,o.A)(s?.href||"/"),m=n?"":t,h=s?.alt??m;return(0,l.jsxs)(r.A,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:h,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},1463:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(5260),o=n(4848);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.A,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1122:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});var r=n(6540),o=n(4164),a=n(2303),i=n(5293);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(4848);function c(e){let{className:t,children:n}=e;const c=(0,a.A)(),{colorMode:u}=(0,i.G)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.A)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,l.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},1422:(e,t,n)=>{"use strict";n.d(t,{N:()=>b,u:()=>c});var r=n(6540),o=n(8193),a=n(205),i=n(3109),s=n(4848);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??l}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function m(e){if(!o.A.canUseDOM)return e?u:d}function h(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,s.jsx)(t,{ref:u,style:c?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:o})}function g(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[l,c]=(0,r.useState)(t);return(0,a.A)((()=>{t||i(!0)}),[t]),(0,a.A)((()=>{o&&c(t)}),[o,t]),o?(0,s.jsx)(h,{...n,collapsed:l}):null}function b(e){let{lazy:t,...n}=e;const r=t?g:h;return(0,s.jsx)(r,{...n})}},5041:(e,t,n)=>{"use strict";n.d(t,{Mj:()=>h,oq:()=>m});var r=n(6540),o=n(2303),a=n(9466),i=n(9532),s=n(6342),l=n(4848);const c=(0,a.Wf)("docusaurus.announcement.dismiss"),u=(0,a.Wf)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.p)(),t=(0,o.A)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(){const e=(0,r.useContext)(f);if(!e)throw new i.dV("AnnouncementBarProvider");return e}},5293:(e,t,n)=>{"use strict";n.d(t,{G:()=>b,a:()=>g});var r=n(6540),o=n(8193),a=n(9532),i=n(9466),s=n(6342),l=n(4848);const c=r.createContext(void 0),u="theme",d=(0,i.Wf)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>o.A.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),h=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.p)(),[o,a]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&h(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(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:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(c);if(null==e)throw new a.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},5597:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>b,g1:()=>v});var r=n(6540),o=n(4070),a=n(7065),i=n(6342),s=n(4142),l=n(9532),c=n(9466),u=n(4848);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.Wf)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.Wf)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.Wf)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const m=r.createContext(null);function h(){const e=(0,o.Gy)(),t=(0,i.p)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=h();return(0,u.jsx)(m.Provider,{value:n,children:t})}function b(e){let{children:t}=e;return s.C5?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function y(){const e=(0,r.useContext)(m);if(!e)throw new l.dV("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=a.W);const t=(0,o.ht)(e),[n,i]=y(),{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])}}},6588:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,t:()=>c});var r=n(6540),o=n(9532),a=n(4848);const i=Symbol("EmptyContext"),s=r.createContext(i);function l(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(s);if(e===i)throw new o.dV("DocsSidebarProvider");return e}},2252:(e,t,n)=>{"use strict";n.d(t,{n:()=>s,r:()=>l});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(null===e)throw new o.dV("DocsVersionProvider");return e}},2069:(e,t,n)=>{"use strict";n.d(t,{M:()=>f,e:()=>p});var r=n(6540),o=n(5600),a=n(4581),i=n(7485),s=n(6342),l=n(9532),c=n(4848);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.YL)(),{items:t}=(0,s.p)().navbar;return 0===t.length&&!e.component}(),t=(0,a.l)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.$Z)((()=>{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 p(e){let{children:t}=e;const n=d();return(0,c.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new l.dV("NavbarMobileSidebarProvider");return e}},5600:(e,t,n)=>{"use strict";n.d(t,{GX:()=>c,YL:()=>l,y_:()=>s});var r=n(6540),o=n(9532),a=n(4848);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(!e)throw new o.dV("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.dV("NavbarSecondaryMenuContentProvider");const[,s]=a,l=(0,o.Be)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},4090:(e,t,n)=>{"use strict";n.d(t,{w:()=>o,J:()=>a});var r=n(6540);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},4581:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(6540),o=n(8193);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!o.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},7559:(e,t,n)=>{"use strict";n.d(t,{G:()=>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",unlistedBanner:"theme-unlisted-banner",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:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},3109:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>r})},4142:(e,t,n)=>{"use strict";n.d(t,{$S:()=>h,B5:()=>C,C5:()=>p,Nr:()=>m,OF:()=>x,QB:()=>E,Vd:()=>_,Y:()=>k,cC:()=>f,d1:()=>A,fW:()=>S,w8:()=>y});var r=n(6540),o=n(6347),a=n(2831),i=n(4070),s=n(5597),l=n(2252),c=n(6588),u=n(1682),d=n(9169);const p=!!i.Gy;function f(e){const t=(0,l.r)();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){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=m(t);if(e)return e}}(e):void 0:e.href}function h(){const{pathname:e}=(0,o.zy)(),t=(0,c.t)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=w({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.ys)(e,t),b=(e,t)=>e.some((e=>y(e,t)));function y(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||b(e.items,t))}function v(e,t){switch(e.type){case"category":return y(e,t)||e.items.some((e=>v(e,t)));case"link":return!e.unlisted||y(e,t);default:return!0}}function k(e,t){return(0,r.useMemo)((()=>e.filter((e=>v(e,t)))),[e,t])}function w(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.ys)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.ys)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function x(){const e=(0,c.t)(),{pathname:t}=(0,o.zy)(),n=(0,i.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?w({sidebarItems:e.items,pathname:t}):null}function _(e){const{activeVersion:t}=(0,i.zK)(e),{preferredVersion:n}=(0,s.g1)(e),o=(0,i.r7)(e);return(0,r.useMemo)((()=>(0,u.s)([t,n,o].filter(Boolean))),[t,n,o])}function S(e,t){const n=_(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 E(e,t){const n=_(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.s)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function C(e){let{route:t}=e;const n=(0,o.zy)(),r=(0,l.r)(),i=t.routes,s=i.find((e=>(0,o.B6)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.v)(i),sidebarName:c,sidebarItems:u}}function A(e){return e.filter((e=>!("category"===e.type||"link"===e.type)||!!m(e)))}},7485:(e,t,n)=>{"use strict";n.d(t,{$Z:()=>i,aZ:()=>l});var r=n(6540),o=n(6347),a=n(9532);function i(e){!function(e){const t=(0,o.W6)(),n=(0,a._q)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){const t=(0,o.W6)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}function l(e){return s((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}},1682:(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 o(e){return Array.from(new Set(e))}n.d(t,{X:()=>r,s:()=>o})},1003:(e,t,n)=>{"use strict";n.d(t,{e3:()=>f,be:()=>d,Jx:()=>m});var r=n(6540),o=n(4164),a=n(5260),i=n(3102);function s(){const e=r.useContext(i.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(6025),c=n(4586);var u=n(4848);function d(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const s=function(e){const{siteConfig:t}=(0,c.A)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,l.h)(),p=o?d(o,{absolute:!0}):void 0;return(0,u.jsxs)(a.A,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(p),s=(0,o.A)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(a.A,{children:(0,u.jsx)("html",{className:s})}),n]})}function m(e){let{children:t}=e;const n=s(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(f,{className:(0,o.A)(r,a),children:t})}},9532:(e,t,n)=>{"use strict";n.d(t,{Be:()=>c,ZC:()=>s,_q:()=>i,dV:()=>l,fM:()=>u});var r=n(6540),o=n(205),a=n(4848);function i(e){const t=(0,r.useRef)(e);return(0,o.A)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,o.A)((()=>{t.current=e})),t.current}class l 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 c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},9169:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>s,ys:()=>i});var r=n(6540),o=n(8328),a=n(4586);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,a.A)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.A,baseUrl:e})),[e])}},3104:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>f,Tv:()=>u,a_:()=>m,gk:()=>h});var r=n(6540),o=n(8193),a=n(2303),i=n(205),s=n(9532),l=n(4848);const c=r.createContext(void 0);function u(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(0,l.jsx)(c.Provider,{value:n,children:t})}function d(){const e=(0,r.useContext)(c);if(null==e)throw new s.dV("ScrollControllerProvider");return e}const p=()=>o.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function f(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),o=(0,r.useRef)(p()),a=(0,s._q)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=p();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function m(){const e=d(),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),o=(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,i.A)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:o}}function h(){const e=(0,r.useRef)(null),t=(0,a.A)()&&"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 o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},2967:(e,t,n)=>{"use strict";n.d(t,{Cy:()=>r,tU:()=>o});n(4586);const r="default";function o(e,t){return`docs-${e}-${t}`}},9466:(e,t,n)=>{"use strict";n.d(t,{Dv:()=>u,Wf:()=>c});var r=n(6540);const o="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(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,s||(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),s=!0),null}var t}let s=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(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=i(t?.persistence);return null===n?l:{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),a({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),a({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 u(e,t){const n=(0,r.useRef)((()=>null===e?l:c(e,t))).current(),o=(0,r.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,r.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},2131:(e,t,n)=>{"use strict";n.d(t,{o:()=>i});var r=n(4586),o=n(6347),a=n(440);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.A)(),{pathname:l}=(0,o.zy)(),c=(0,a.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5062:(e,t,n)=>{"use strict";n.d(t,{$:()=>i});var r=n(6540),o=n(6347),a=n(9532);function i(e){const t=(0,o.zy)(),n=(0,a.ZC)(t),i=(0,a._q)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6342:(e,t,n)=>{"use strict";n.d(t,{p:()=>o});var r=n(4586);function o(){return(0,r.A)().siteConfig.themeConfig}},2983:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=void 0;const r=n(2566);function o(e){return e.endsWith("/")?e:`${e}/`}function a(e){return(0,r.removeSuffix)(e,"/")}t.addTrailingSlash=o,t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[i]=e.split(/[#?]/),s="/"===i||i===r?i:(l=i,n?o(l):a(l));var l;return e.replace(i,s)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=a},253:(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]}},440: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.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(2983);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}}),Object.defineProperty(t,"addTrailingSlash",{enumerable:!0,get:function(){return o.addTrailingSlash}}),Object.defineProperty(t,"addLeadingSlash",{enumerable:!0,get:function(){return o.addLeadingSlash}}),Object.defineProperty(t,"removeTrailingSlash",{enumerable:!0,get:function(){return o.removeTrailingSlash}});var a=n(2566);Object.defineProperty(t,"addPrefix",{enumerable:!0,get:function(){return a.addPrefix}}),Object.defineProperty(t,"removeSuffix",{enumerable:!0,get:function(){return a.removeSuffix}}),Object.defineProperty(t,"addSuffix",{enumerable:!0,get:function(){return a.addSuffix}}),Object.defineProperty(t,"removePrefix",{enumerable:!0,get:function(){return a.removePrefix}});var i=n(253);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return i.getErrorCausalChain}})},2566:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=void 0,t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){return""===t?e:e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},2849:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});n(6540);var r=n(5391);const o={loadingRing:"loadingRing_RJI3","loading-ring":"loading-ring_FB5o"};var a=n(4848);function i(e){let{className:t}=e;return(0,a.jsxs)("div",{className:(0,r.A)(o.loadingRing,t),children:[(0,a.jsx)("div",{}),(0,a.jsx)("div",{}),(0,a.jsx)("div",{}),(0,a.jsx)("div",{})]})}},5891:(e,t,n)=>{"use strict";n.d(t,{Z:()=>s});var r=n(8291),o=n.n(r),a=n(1088);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}${a.IH.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:o().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}},2384:(e,t,n)=>{"use strict";n.d(t,{m:()=>l});var r=n(8291),o=n.n(r);var a=n(1088);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:o().Query.presence.REQUIRED,wildcard:(t?e.trailing||e.maybeTyping:e.trailing)?o().Query.wildcard.TRAILING:o().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 o()[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,a.BH);if(0===l.length)return void s([]);const c=function(e,t){const n=function(e,t){const n=[];return function e(r,o){if(0===r.length)return void n.push(o);const a=r[0];if(/\p{Unified_Ideograph}/u.test(a)){const n=function(e,t){const n=[];return function e(r,o){let a=0,i=!1;for(const s of t)if(r.substr(0,s.length)===s){const t={missed:o.missed,term:o.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>a;t-=1){const l=s.substr(0,t);if(r.substr(0,t)===l){a=t;const s={missed:o.missed,term:o.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:o.missed+1,term:o.term}):o.term.length>0&&n.push(o))}(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))}(a,t);for(const t of n){const n=o.concat(...t);e(r.slice(1),n)}}else{const t=o.concat({value:a});e(r.slice(1),t)}}(e,[]),n}(e,t);if(0===n.length)return[{tokens:e,term:e.map((e=>({value:e,presence:o().Query.presence.REQUIRED,wildcard:o().Query.wildcard.LEADING|o().Query.wildcard.TRAILING})))}];for(const o of n)o[o.length-1].maybeTyping=!0;const r=[];for(const i of a.BH)if("en"===i)a.sx||r.unshift(o().stopWordFilter);else{const e=o()[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 o of s)if(o.length>2)for(let e=o.length-1;e>=0;e-=1)l.push(o.slice(0,e).concat(o.slice(e+1)));return i(n).concat(i(l))}(l,t),u=[];e:for(const{term:t,tokens:o}of c)for(const{documents:r,index:a,type:i}of e)if(u.push(...a.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:o,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,o=n.type>0&&n.page?e.findIndex((e=>e.document===n.page)):n.index;return-1===r&&(r=t.index),-1===o&&(o=n.index),r===o?0===t.type?-1:0===n.type?1:t.index-n.index:r-o}))}(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,{$:()=>r})},3103:(e,t,n)=>{"use strict";function r(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}n.d(t,{Z:()=>r})},7674:(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,{g:()=>r})},6841:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(3103);function o(e,t,n){const a=[];for(const i of t){const n=e.toLowerCase().indexOf(i);if(n>=0){n>0&&a.push(o(e.substr(0,n),t)),a.push(`${(0,r.Z)(e.substr(n,i.length))}`);const s=n+i.length;s${(0,r.Z)(e)}`:(0,r.Z)(e):a.join("")}},3810:(e,t,n)=>{"use strict";n.d(t,{C:()=>l});var r=n(3103),o=n(6841);const a=/\w+|\p{Unified_Ideograph}/u;function i(e){const t=[];let n=0,r=e;for(;r.length>0;){const o=r.match(a);if(!o){t.push(r);break}o.index>0&&t.push(r.substring(0,o.index)),t.push(o[0]),n+=o.index+o[0].length,r=e.substring(n)}return t}var s=n(1088);function l(e,t,n,a){void 0===a&&(a=s.rG);const{chunkIndex:l,chunks:c}=function(e,t,n){const a=[];let s=0,l=0,c=-1;for(;sl){const t=i(e.substring(l,u)).map((e=>({html:(0,r.Z)(e),textLength:e.length})));for(const e of t)a.push(e)}-1===c&&(c=a.length),l=u+d,a.push({html:(0,o.Z)(e.substring(u,l),n,!0),textLength:d})}}if(l({html:(0,r.Z)(e),textLength:e.length})));for(const e of t)a.push(e)}return{chunkIndex:c,chunks:a}}(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,y=!1;for(;m0){const e=u.pop();m+e.textLength<=a?(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<=a?(p.push(e.html),g+=e.textLength,m+=e.textLength):(y=!0,f.length=0)}}return(b||u.length>0)&&p.unshift("\u2026"),(y||f.length>0)&&p.push("\u2026"),p.join("")}},3385:(e,t,n)=>{"use strict";function r(e,t){if("string"==typeof e)return{label:e,path:e};{const{label:n,path:r}=e;return"string"==typeof n?{label:n,path:r}:Object.prototype.hasOwnProperty.call(n,t)?{label:n[t],path:r}:{label:r,path:r}}}n.d(t,{p:()=>r})},1088:(e,t,n)=>{"use strict";n.d(t,{CU:()=>a,UB:()=>f,tb:()=>c,O6:()=>g,I$:()=>m,BH:()=>r,sx:()=>o,ZG:()=>p,WW:()=>u,pk:()=>d,Hg:()=>h,IH:()=>i,rG:()=>l,AT:()=>s,dz:()=>b});n(8291);const r=["en"],o=!1,a=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},1513:(e,t,n)=>{"use strict";n.d(t,{zR:()=>k,TM:()=>C,yJ:()=>f,sC:()=>T,AO:()=>p});var r=n(8168);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&o(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=n(1561);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,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.A)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!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,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,h(),k.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(k.entries[k.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=k.index+e;return t>=0&&t{"use strict";var r=n(4363),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={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]||o}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 o=f(n);o&&o!==m&&e(t,o,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,o,a,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,o,a,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},4634:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},8291:(e,t,n)=>{var r,o;!function(){var a,i,s,l,c,u,d,p,f,m,h,g,b,y,v,k,w,x,_,S,E,C,A,T,P,L,j,R,N,O,I=function(e){var t=new I.Builder;return t.pipeline.add(I.trimmer,I.stopWordFilter,I.stemmer),t.searchPipeline.add(I.stemmer),e.call(t,t),t.build()};I.version="2.3.9",I.utils={},I.utils.warn=(a=this,function(e){a.console&&console.warn&&console.warn(e)}),I.utils.asString=function(e){return null==e?"":e.toString()},I.utils.clone=function(e){if(null==e)return e;for(var t=Object.create(null),n=Object.keys(e),r=0;r0){var l=I.utils.clone(t)||{};l.position=[i,s],l.index=o.length,o.push(new I.Token(n.slice(i,a),l))}i=a+1}}return o},I.tokenizer.separator=/[\s\-]+/,I.Pipeline=function(){this._stack=[]},I.Pipeline.registeredFunctions=Object.create(null),I.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&I.utils.warn("Overwriting existing registered function: "+t),e.label=t,I.Pipeline.registeredFunctions[e.label]=e},I.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||I.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},I.Pipeline.load=function(e){var t=new I.Pipeline;return e.forEach((function(e){var n=I.Pipeline.registeredFunctions[e];if(!n)throw new Error("Cannot load unregistered function: "+e);t.add(n)})),t},I.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach((function(e){I.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},I.Pipeline.prototype.after=function(e,t){I.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)},I.Pipeline.prototype.before=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var n=this._stack.indexOf(e);if(-1==n)throw new Error("Cannot find existingFn");this._stack.splice(n,0,t)},I.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},I.Pipeline.prototype.run=function(e){for(var t=this._stack.length,n=0;n1&&(ae&&(n=o),a!=e);)r=n-t,o=t+Math.floor(r/2),a=this.elements[2*o];return a==e||a>e?2*o:as?c+=2:i==s&&(t+=n[l+1]*r[c+1],l+=2,c+=2);return t},I.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},I.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,n=0;t0){var a,i=o.str.charAt(0);i in o.node.edges?a=o.node.edges[i]:(a=new I.TokenSet,o.node.edges[i]=a),1==o.str.length&&(a.final=!0),r.push({node:a,editsRemaining:o.editsRemaining,str:o.str.slice(1)})}if(0!=o.editsRemaining){if("*"in o.node.edges)var s=o.node.edges["*"];else{s=new I.TokenSet;o.node.edges["*"]=s}if(0==o.str.length&&(s.final=!0),r.push({node:s,editsRemaining:o.editsRemaining-1,str:o.str}),o.str.length>1&&r.push({node:o.node,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)}),1==o.str.length&&(o.node.final=!0),o.str.length>=1){if("*"in o.node.edges)var l=o.node.edges["*"];else{l=new I.TokenSet;o.node.edges["*"]=l}1==o.str.length&&(l.final=!0),r.push({node:l,editsRemaining:o.editsRemaining-1,str:o.str.slice(1)})}if(o.str.length>1){var c,u=o.str.charAt(0),d=o.str.charAt(1);d in o.node.edges?c=o.node.edges[d]:(c=new I.TokenSet,o.node.edges[d]=c),1==o.str.length&&(c.final=!0),r.push({node:c,editsRemaining:o.editsRemaining-1,str:u+o.str.slice(2)})}}}return n},I.TokenSet.fromString=function(e){for(var t=new I.TokenSet,n=t,r=0,o=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()}},I.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},I.Index.prototype.search=function(e){return this.query((function(t){new I.QueryParser(e,t).parse()}))},I.Index.prototype.query=function(e){for(var t=new I.Query(this.fields),n=Object.create(null),r=Object.create(null),o=Object.create(null),a=Object.create(null),i=Object.create(null),s=0;s1?1:e},I.Builder.prototype.k1=function(e){this._k1=e},I.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 o=0;o=this.length)return I.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},I.QueryLexer.prototype.width=function(){return this.pos-this.start},I.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},I.QueryLexer.prototype.backup=function(){this.pos-=1},I.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=I.QueryLexer.EOS&&this.backup()},I.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(I.QueryLexer.TERM)),e.ignore(),e.more())return I.QueryLexer.lexText},I.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.EDIT_DISTANCE),I.QueryLexer.lexText},I.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.BOOST),I.QueryLexer.lexText},I.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(I.QueryLexer.TERM)},I.QueryLexer.termSeparator=I.tokenizer.separator,I.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==I.QueryLexer.EOS)return I.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return I.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if(t.match(I.QueryLexer.termSeparator))return I.QueryLexer.lexTerm}else e.escapeCharacter()}},I.QueryParser=function(e,t){this.lexer=new I.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},I.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=I.QueryParser.parseClause;e;)e=e(this);return this.query},I.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},I.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},I.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},I.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case I.QueryLexer.PRESENCE:return I.QueryParser.parsePresence;case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.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 I.QueryParseError(n,t.start,t.end)}},I.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=I.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=I.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+t.str+"'";throw new I.QueryParseError(n,t.start,t.end)}var r=e.peekLexeme();if(null==r){n="expecting term or field, found nothing";throw new I.QueryParseError(n,t.start,t.end)}switch(r.type){case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:n="expecting term or field, found '"+r.type+"'";throw new I.QueryParseError(n,r.start,r.end)}}},I.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 I.QueryParseError(r,t.start,t.end)}e.currentClause.fields=[t.str];var o=e.peekLexeme();if(null==o){r="expecting term, found nothing";throw new I.QueryParseError(r,t.start,t.end)}if(o.type===I.QueryLexer.TERM)return I.QueryParser.parseTerm;r="expecting term, found '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}},I.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 I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:var r="Unexpected lexeme type '"+n.type+"'";throw new I.QueryParseError(r,n.start,n.end)}else e.nextClause()}},I.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 I.QueryParseError(r,t.start,t.end)}e.currentClause.editDistance=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}else e.nextClause()}},I.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 I.QueryParseError(r,t.start,t.end)}e.currentClause.boost=n;var o=e.peekLexeme();if(null!=o)switch(o.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:r="Unexpected lexeme type '"+o.type+"'";throw new I.QueryParseError(r,o.start,o.end)}else e.nextClause()}},void 0===(o="function"==typeof(r=function(){return I})?r.call(t,n,t,e):r)||(e.exports=o)}()},119:(e,t,n)=>{"use strict";n.r(t)},1043:(e,t,n)=>{"use strict";n.r(t)},5947:function(e,t,n){var r,o;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 o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}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=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),c=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){l(a,{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)*o(Math.random()*t,.1,.95)),t=o(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 o,i=t.querySelector(r.barSelector),s=e?"-100":a(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),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,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[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===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},7839:()=>{!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],o=[];/^\w+$/.test(n)||o.push(/\w+/.exec(n)[0]),"diff"===n&&o.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:o,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})}(Prism)},824:()=>{Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}},9700:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,s=i.length;-1!==n.code.indexOf(o=t(r,s));)++s;return i[s]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=a.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++o;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),y=[];h&&y.push.apply(y,i([h])),y.push(g),b&&y.push.apply(y,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(y)):c.content=y}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},5342:()=>{!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)},3537:()=>{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},132:()=>{!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)},7006:(e,t,n)=>{var r={"./prism-diff":7839,"./prism-ini":824,"./prism-rust":5342,"./prism-solidity":3537,"./prism-toml":132};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=7006},2694:(e,t,n)=>{"use strict";var r=n(6925);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,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:a,resetWarningCache:o};return n.PropTypes=n,n}},5556:(e,t,n)=>{e.exports=n(2694)()},6925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:(e,t,n)=>{"use strict";var r=n(6540),o=n(9982);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n