diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1a3809cd35..8d735288b0 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -8,7 +8,7 @@ orbs:
parameters:
go_version:
type: string
- default: 1.23.8 # update CI Go version here
+ default: 1.25.1 # update CI Go version here
commands:
gcp-oidc-authenticate:
diff --git a/accounts/abi/bind/v2/base.go b/accounts/abi/bind/v2/base.go
index 744e4b6fd9..bac1e158b9 100644
--- a/accounts/abi/bind/v2/base.go
+++ b/accounts/abi/bind/v2/base.go
@@ -150,6 +150,11 @@ func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller
}
}
+// Address returns the deployment address of the contract.
+func (c *BoundContract) Address() common.Address {
+ return c.address
+}
+
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
diff --git a/accounts/abi/bind/v2/util_test.go b/accounts/abi/bind/v2/util_test.go
index b1b647a7b9..a9f5b4035c 100644
--- a/accounts/abi/bind/v2/util_test.go
+++ b/accounts/abi/bind/v2/util_test.go
@@ -100,22 +100,29 @@ func TestWaitDeployed(t *testing.T) {
}
func TestWaitDeployedCornerCases(t *testing.T) {
- backend := simulated.NewBackend(
- types.GenesisAlloc{
- crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
- },
+ var (
+ backend = simulated.NewBackend(
+ types.GenesisAlloc{
+ crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
+ },
+ )
+ head, _ = backend.Client().HeaderByNumber(t.Context(), nil) // Should be child's, good enough
+ gasPrice = new(big.Int).Add(head.BaseFee, big.NewInt(1))
+ signer = types.LatestSigner(params.AllDevChainProtocolChanges)
+ code = common.FromHex("6060604052600a8060106000396000f360606040526008565b00")
+ ctx, cancel = context.WithCancel(t.Context())
)
defer backend.Close()
- head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
- gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
-
- // Create a transaction to an account.
- code := "6060604052600a8060106000396000f360606040526008565b00"
- tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ // 1. WaitDeploy on a transaction that does not deploy a contract, verify it
+ // returns an error.
+ tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{
+ Nonce: 0,
+ To: &common.Address{0x01},
+ Gas: 300000,
+ GasPrice: gasPrice,
+ Data: code,
+ })
if err := backend.Client().SendTransaction(ctx, tx); err != nil {
t.Errorf("failed to send transaction: %q", err)
}
@@ -124,14 +131,23 @@ func TestWaitDeployedCornerCases(t *testing.T) {
t.Errorf("error mismatch: want %q, got %q, ", bind.ErrNoAddressInReceipt, err)
}
- // Create a transaction that is not mined.
- tx = types.NewContractCreation(1, big.NewInt(0), 3000000, gasPrice, common.FromHex(code))
- tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey)
-
+ // 2. Create a contract, but cancel the WaitDeploy before it is mined.
+ tx = types.MustSignNewTx(testKey, signer, &types.LegacyTx{
+ Nonce: 1,
+ Gas: 300000,
+ GasPrice: gasPrice,
+ Data: code,
+ })
+
+ // Wait in another thread so that we can quickly cancel it after submitting
+ // the transaction.
+ done := make(chan struct{})
go func() {
- contextCanceled := errors.New("context canceled")
- if _, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash()); err.Error() != contextCanceled.Error() {
- t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err)
+ defer close(done)
+ want := errors.New("context canceled")
+ _, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash())
+ if err == nil || errors.Is(want, err) {
+ t.Errorf("error mismatch: want %v, got %v", want, err)
}
}()
@@ -139,4 +155,11 @@ func TestWaitDeployedCornerCases(t *testing.T) {
t.Errorf("failed to send transaction: %q", err)
}
cancel()
+
+ // Wait for goroutine to exit or for a timeout.
+ select {
+ case <-done:
+ case <-time.After(time.Second * 2):
+ t.Fatalf("failed to cancel wait deploy")
+ }
}
diff --git a/accounts/keystore/keystore.go b/accounts/keystore/keystore.go
index fefba026ae..3e4266924f 100644
--- a/accounts/keystore/keystore.go
+++ b/accounts/keystore/keystore.go
@@ -99,9 +99,10 @@ func (ks *KeyStore) init(keydir string) {
// TODO: In order for this finalizer to work, there must be no references
// to ks. addressCache doesn't keep a reference but unlocked keys do,
// so the finalizer will not trigger until all timed unlocks have expired.
- runtime.SetFinalizer(ks, func(m *KeyStore) {
- m.cache.close()
- })
+ runtime.AddCleanup(ks, func(c *accountCache) {
+ c.close()
+ }, ks.cache)
+
// Create the initial list of wallets from the cache
accs := ks.cache.accounts()
ks.wallets = make([]accounts.Wallet, len(accs))
@@ -195,11 +196,14 @@ func (ks *KeyStore) Subscribe(sink chan<- accounts.WalletEvent) event.Subscripti
// forces a manual refresh (only triggers for systems where the filesystem notifier
// is not running).
func (ks *KeyStore) updater() {
+ ticker := time.NewTicker(walletRefreshCycle)
+ defer ticker.Stop()
+
for {
// Wait for an account update or a refresh timeout
select {
case <-ks.changes:
- case <-time.After(walletRefreshCycle):
+ case <-ticker.C:
}
// Run the wallet refresher
ks.refreshWallets()
diff --git a/accounts/usbwallet/hub.go b/accounts/usbwallet/hub.go
deleted file mode 100644
index 81457b7da2..0000000000
--- a/accounts/usbwallet/hub.go
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package usbwallet
-
-import (
- "errors"
- "runtime"
- "sync"
- "sync/atomic"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/log"
- "github.com/karalabe/hid"
-)
-
-// LedgerScheme is the protocol scheme prefixing account and wallet URLs.
-const LedgerScheme = "ledger"
-
-// TrezorScheme is the protocol scheme prefixing account and wallet URLs.
-const TrezorScheme = "trezor"
-
-// refreshCycle is the maximum time between wallet refreshes (if USB hotplug
-// notifications don't work).
-const refreshCycle = time.Second
-
-// refreshThrottling is the minimum time between wallet refreshes to avoid USB
-// trashing.
-const refreshThrottling = 500 * time.Millisecond
-
-// Hub is a accounts.Backend that can find and handle generic USB hardware wallets.
-type Hub struct {
- scheme string // Protocol scheme prefixing account and wallet URLs.
- vendorID uint16 // USB vendor identifier used for device discovery
- productIDs []uint16 // USB product identifiers used for device discovery
- usageID uint16 // USB usage page identifier used for macOS device discovery
- endpointID int // USB endpoint identifier used for non-macOS device discovery
- makeDriver func(log.Logger) driver // Factory method to construct a vendor specific driver
-
- refreshed time.Time // Time instance when the list of wallets was last refreshed
- wallets []accounts.Wallet // List of USB wallet devices currently tracking
- updateFeed event.Feed // Event feed to notify wallet additions/removals
- updateScope event.SubscriptionScope // Subscription scope tracking current live listeners
- updating bool // Whether the event notification loop is running
-
- quit chan chan error
-
- stateLock sync.RWMutex // Protects the internals of the hub from racey access
-
- // TODO(karalabe): remove if hotplug lands on Windows
- commsPend int // Number of operations blocking enumeration
- commsLock sync.Mutex // Lock protecting the pending counter and enumeration
- enumFails atomic.Uint32 // Number of times enumeration has failed
-}
-
-// NewLedgerHub creates a new hardware wallet manager for Ledger devices.
-func NewLedgerHub() (*Hub, error) {
- return newHub(LedgerScheme, 0x2c97, []uint16{
-
- // Device definitions taken from
- // https://github.com/LedgerHQ/ledger-live/blob/595cb73b7e6622dbbcfc11867082ddc886f1bf01/libs/ledgerjs/packages/devices/src/index.ts
-
- // Original product IDs
- 0x0000, /* Ledger Blue */
- 0x0001, /* Ledger Nano S */
- 0x0004, /* Ledger Nano X */
- 0x0005, /* Ledger Nano S Plus */
- 0x0006, /* Ledger Nano FTS */
- 0x0007, /* Ledger Flex */
-
- 0x0000, /* WebUSB Ledger Blue */
- 0x1000, /* WebUSB Ledger Nano S */
- 0x4000, /* WebUSB Ledger Nano X */
- 0x5000, /* WebUSB Ledger Nano S Plus */
- 0x6000, /* WebUSB Ledger Nano FTS */
- 0x7000, /* WebUSB Ledger Flex */
- }, 0xffa0, 0, newLedgerDriver)
-}
-
-// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices.
-func NewTrezorHubWithHID() (*Hub, error) {
- return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver)
-}
-
-// NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with
-// firmware version > 1.8.0
-func NewTrezorHubWithWebUSB() (*Hub, error) {
- return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver)
-}
-
-// newHub creates a new hardware wallet manager for generic USB devices.
-func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) {
- if !hid.Supported() {
- return nil, errors.New("unsupported platform")
- }
- hub := &Hub{
- scheme: scheme,
- vendorID: vendorID,
- productIDs: productIDs,
- usageID: usageID,
- endpointID: endpointID,
- makeDriver: makeDriver,
- quit: make(chan chan error),
- }
- hub.refreshWallets()
- return hub, nil
-}
-
-// Wallets implements accounts.Backend, returning all the currently tracked USB
-// devices that appear to be hardware wallets.
-func (hub *Hub) Wallets() []accounts.Wallet {
- // Make sure the list of wallets is up to date
- hub.refreshWallets()
-
- hub.stateLock.RLock()
- defer hub.stateLock.RUnlock()
-
- cpy := make([]accounts.Wallet, len(hub.wallets))
- copy(cpy, hub.wallets)
- return cpy
-}
-
-// refreshWallets scans the USB devices attached to the machine and updates the
-// list of wallets based on the found devices.
-func (hub *Hub) refreshWallets() {
- // Don't scan the USB like crazy it the user fetches wallets in a loop
- hub.stateLock.RLock()
- elapsed := time.Since(hub.refreshed)
- hub.stateLock.RUnlock()
-
- if elapsed < refreshThrottling {
- return
- }
- // If USB enumeration is continually failing, don't keep trying indefinitely
- if hub.enumFails.Load() > 2 {
- return
- }
- // Retrieve the current list of USB wallet devices
- var devices []hid.DeviceInfo
-
- if runtime.GOOS == "linux" {
- // hidapi on Linux opens the device during enumeration to retrieve some infos,
- // breaking the Ledger protocol if that is waiting for user confirmation. This
- // is a bug acknowledged at Ledger, but it won't be fixed on old devices so we
- // need to prevent concurrent comms ourselves. The more elegant solution would
- // be to ditch enumeration in favor of hotplug events, but that don't work yet
- // on Windows so if we need to hack it anyway, this is more elegant for now.
- hub.commsLock.Lock()
- if hub.commsPend > 0 { // A confirmation is pending, don't refresh
- hub.commsLock.Unlock()
- return
- }
- }
- infos, err := hid.Enumerate(hub.vendorID, 0)
- if err != nil {
- failcount := hub.enumFails.Add(1)
- if runtime.GOOS == "linux" {
- // See rationale before the enumeration why this is needed and only on Linux.
- hub.commsLock.Unlock()
- }
- log.Error("Failed to enumerate USB devices", "hub", hub.scheme,
- "vendor", hub.vendorID, "failcount", failcount, "err", err)
- return
- }
- hub.enumFails.Store(0)
-
- for _, info := range infos {
- for _, id := range hub.productIDs {
- // We check both the raw ProductID (legacy) and just the upper byte, as Ledger
- // uses `MMII`, encoding a model (MM) and an interface bitfield (II)
- mmOnly := info.ProductID & 0xff00
- // Windows and Macos use UsageID matching, Linux uses Interface matching
- if (info.ProductID == id || mmOnly == id) && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) {
- devices = append(devices, info)
- break
- }
- }
- }
- if runtime.GOOS == "linux" {
- // See rationale before the enumeration why this is needed and only on Linux.
- hub.commsLock.Unlock()
- }
- // Transform the current list of wallets into the new one
- hub.stateLock.Lock()
-
- var (
- wallets = make([]accounts.Wallet, 0, len(devices))
- events []accounts.WalletEvent
- )
-
- for _, device := range devices {
- url := accounts.URL{Scheme: hub.scheme, Path: device.Path}
-
- // Drop wallets in front of the next device or those that failed for some reason
- for len(hub.wallets) > 0 {
- // Abort if we're past the current device and found an operational one
- _, failure := hub.wallets[0].Status()
- if hub.wallets[0].URL().Cmp(url) >= 0 || failure == nil {
- break
- }
- // Drop the stale and failed devices
- events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped})
- hub.wallets = hub.wallets[1:]
- }
- // If there are no more wallets or the device is before the next, wrap new wallet
- if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 {
- logger := log.New("url", url)
- wallet := &wallet{hub: hub, driver: hub.makeDriver(logger), url: &url, info: device, log: logger}
-
- events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
- wallets = append(wallets, wallet)
- continue
- }
- // If the device is the same as the first wallet, keep it
- if hub.wallets[0].URL().Cmp(url) == 0 {
- wallets = append(wallets, hub.wallets[0])
- hub.wallets = hub.wallets[1:]
- continue
- }
- }
- // Drop any leftover wallets and set the new batch
- for _, wallet := range hub.wallets {
- events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
- }
- hub.refreshed = time.Now()
- hub.wallets = wallets
- hub.stateLock.Unlock()
-
- // Fire all wallet events and return
- for _, event := range events {
- hub.updateFeed.Send(event)
- }
-}
-
-// Subscribe implements accounts.Backend, creating an async subscription to
-// receive notifications on the addition or removal of USB wallets.
-func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
- // We need the mutex to reliably start/stop the update loop
- hub.stateLock.Lock()
- defer hub.stateLock.Unlock()
-
- // Subscribe the caller and track the subscriber count
- sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink))
-
- // Subscribers require an active notification loop, start it
- if !hub.updating {
- hub.updating = true
- go hub.updater()
- }
- return sub
-}
-
-// updater is responsible for maintaining an up-to-date list of wallets managed
-// by the USB hub, and for firing wallet addition/removal events.
-func (hub *Hub) updater() {
- for {
- // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout
- // <-hub.changes
- time.Sleep(refreshCycle)
-
- // Run the wallet refresher
- hub.refreshWallets()
-
- // If all our subscribers left, stop the updater
- hub.stateLock.Lock()
- if hub.updateScope.Count() == 0 {
- hub.updating = false
- hub.stateLock.Unlock()
- return
- }
- hub.stateLock.Unlock()
- }
-}
diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go
deleted file mode 100644
index 52595a1621..0000000000
--- a/accounts/usbwallet/ledger.go
+++ /dev/null
@@ -1,573 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// This file contains the implementation for interacting with the Ledger hardware
-// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo:
-// https://github.com/LedgerHQ/app-ethereum/blob/develop/doc/ethapp.adoc
-
-package usbwallet
-
-import (
- "encoding/binary"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "math/big"
-
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-// ledgerOpcode is an enumeration encoding the supported Ledger opcodes.
-type ledgerOpcode byte
-
-// ledgerParam1 is an enumeration encoding the supported Ledger parameters for
-// specific opcodes. The same parameter values may be reused between opcodes.
-type ledgerParam1 byte
-
-// ledgerParam2 is an enumeration encoding the supported Ledger parameters for
-// specific opcodes. The same parameter values may be reused between opcodes.
-type ledgerParam2 byte
-
-const (
- ledgerOpRetrieveAddress ledgerOpcode = 0x02 // Returns the public key and Ethereum address for a given BIP 32 path
- ledgerOpSignTransaction ledgerOpcode = 0x04 // Signs an Ethereum transaction after having the user validate the parameters
- ledgerOpGetConfiguration ledgerOpcode = 0x06 // Returns specific wallet application configuration
- ledgerOpSignTypedMessage ledgerOpcode = 0x0c // Signs an Ethereum message following the EIP 712 specification
-
- ledgerP1DirectlyFetchAddress ledgerParam1 = 0x00 // Return address directly from the wallet
- ledgerP1InitTypedMessageData ledgerParam1 = 0x00 // First chunk of Typed Message data
- ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing
- ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing
- ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address
-
- ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions
-)
-
-// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange
-// if the device replies with a mismatching header. This usually means the device
-// is in browser mode.
-var errLedgerReplyInvalidHeader = errors.New("ledger: invalid reply header")
-
-// errLedgerInvalidVersionReply is the error message returned by a Ledger version retrieval
-// when a response does arrive, but it does not contain the expected data.
-var errLedgerInvalidVersionReply = errors.New("ledger: invalid version reply")
-
-// ledgerDriver implements the communication with a Ledger hardware wallet.
-type ledgerDriver struct {
- device io.ReadWriter // USB device connection to communicate through
- version [3]byte // Current version of the Ledger firmware (zero if app is offline)
- browser bool // Flag whether the Ledger is in browser mode (reply channel mismatch)
- failure error // Any failure that would make the device unusable
- log log.Logger // Contextual logger to tag the ledger with its id
-}
-
-// newLedgerDriver creates a new instance of a Ledger USB protocol driver.
-func newLedgerDriver(logger log.Logger) driver {
- return &ledgerDriver{
- log: logger,
- }
-}
-
-// Status implements usbwallet.driver, returning various states the Ledger can
-// currently be in.
-func (w *ledgerDriver) Status() (string, error) {
- if w.failure != nil {
- return fmt.Sprintf("Failed: %v", w.failure), w.failure
- }
- if w.browser {
- return "Ethereum app in browser mode", w.failure
- }
- if w.offline() {
- return "Ethereum app offline", w.failure
- }
- return fmt.Sprintf("Ethereum app v%d.%d.%d online", w.version[0], w.version[1], w.version[2]), w.failure
-}
-
-// offline returns whether the wallet and the Ethereum app is offline or not.
-//
-// The method assumes that the state lock is held!
-func (w *ledgerDriver) offline() bool {
- return w.version == [3]byte{0, 0, 0}
-}
-
-// Open implements usbwallet.driver, attempting to initialize the connection to the
-// Ledger hardware wallet. The Ledger does not require a user passphrase, so that
-// parameter is silently discarded.
-func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error {
- w.device, w.failure = device, nil
-
- _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath)
- if err != nil {
- // Ethereum app is not running or in browser mode, nothing more to do, return
- if err == errLedgerReplyInvalidHeader {
- w.browser = true
- }
- return nil
- }
- // Try to resolve the Ethereum app's version, will fail prior to v1.0.2
- if w.version, err = w.ledgerVersion(); err != nil {
- w.version = [3]byte{1, 0, 0} // Assume worst case, can't verify if v1.0.0 or v1.0.1
- }
- return nil
-}
-
-// Close implements usbwallet.driver, cleaning up and metadata maintained within
-// the Ledger driver.
-func (w *ledgerDriver) Close() error {
- w.browser, w.version = false, [3]byte{}
- return nil
-}
-
-// Heartbeat implements usbwallet.driver, performing a sanity check against the
-// Ledger to see if it's still online.
-func (w *ledgerDriver) Heartbeat() error {
- if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply {
- w.failure = err
- return err
- }
- return nil
-}
-
-// Derive implements usbwallet.driver, sending a derivation request to the Ledger
-// and returning the Ethereum address located on that derivation path.
-func (w *ledgerDriver) Derive(path accounts.DerivationPath) (common.Address, error) {
- return w.ledgerDerive(path)
-}
-
-// SignTx implements usbwallet.driver, sending the transaction to the Ledger and
-// waiting for the user to confirm or deny the transaction.
-//
-// Note, if the version of the Ethereum application running on the Ledger wallet is
-// too old to sign EIP-155 transactions, but such is requested nonetheless, an error
-// will be returned opposed to silently signing in Homestead mode.
-func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
- // If the Ethereum app doesn't run, abort
- if w.offline() {
- return common.Address{}, nil, accounts.ErrWalletClosed
- }
- // Ensure the wallet is capable of signing the given transaction
- if chainID != nil && (w.version[0] < 1 || (w.version[0] == 1 && w.version[1] == 0 && w.version[2] < 3)) {
- //lint:ignore ST1005 brand name displayed on the console
- return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
- }
- // All infos gathered and metadata checks out, request signing
- return w.ledgerSign(path, tx, chainID)
-}
-
-// SignTypedMessage implements usbwallet.driver, sending the message to the Ledger and
-// waiting for the user to sign or deny the transaction.
-//
-// Note: this was introduced in the ledger 1.5.0 firmware
-func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) {
- // If the Ethereum app doesn't run, abort
- if w.offline() {
- return nil, accounts.ErrWalletClosed
- }
- // Ensure the wallet is capable of signing the given transaction
- if w.version[0] < 1 && w.version[1] < 5 {
- //lint:ignore ST1005 brand name displayed on the console
- return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
- }
- // All infos gathered and metadata checks out, request signing
- return w.ledgerSignTypedMessage(path, domainHash, messageHash)
-}
-
-// ledgerVersion retrieves the current version of the Ethereum wallet app running
-// on the Ledger wallet.
-//
-// The version retrieval protocol is defined as follows:
-//
-// CLA | INS | P1 | P2 | Lc | Le
-// ----+-----+----+----+----+---
-// E0 | 06 | 00 | 00 | 00 | 04
-//
-// With no input data, and the output data being:
-//
-// Description | Length
-// ---------------------------------------------------+--------
-// Flags 01: arbitrary data signature enabled by user | 1 byte
-// Application major version | 1 byte
-// Application minor version | 1 byte
-// Application patch version | 1 byte
-func (w *ledgerDriver) ledgerVersion() ([3]byte, error) {
- // Send the request and wait for the response
- reply, err := w.ledgerExchange(ledgerOpGetConfiguration, 0, 0, nil)
- if err != nil {
- return [3]byte{}, err
- }
- if len(reply) != 4 {
- return [3]byte{}, errLedgerInvalidVersionReply
- }
- // Cache the version for future reference
- var version [3]byte
- copy(version[:], reply[1:])
- return version, nil
-}
-
-// ledgerDerive retrieves the currently active Ethereum address from a Ledger
-// wallet at the specified derivation path.
-//
-// The address derivation protocol is defined as follows:
-//
-// CLA | INS | P1 | P2 | Lc | Le
-// ----+-----+----+----+-----+---
-// E0 | 02 | 00 return address
-// 01 display address and confirm before returning
-// | 00: do not return the chain code
-// | 01: return the chain code
-// | var | 00
-//
-// Where the input data is:
-//
-// Description | Length
-// -------------------------------------------------+--------
-// Number of BIP 32 derivations to perform (max 10) | 1 byte
-// First derivation index (big endian) | 4 bytes
-// ... | 4 bytes
-// Last derivation index (big endian) | 4 bytes
-//
-// And the output data is:
-//
-// Description | Length
-// ------------------------+-------------------
-// Public Key length | 1 byte
-// Uncompressed Public Key | arbitrary
-// Ethereum address length | 1 byte
-// Ethereum address | 40 bytes hex ascii
-// Chain code if requested | 32 bytes
-func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, error) {
- // Flatten the derivation path into the Ledger request
- path := make([]byte, 1+4*len(derivationPath))
- path[0] = byte(len(derivationPath))
- for i, component := range derivationPath {
- binary.BigEndian.PutUint32(path[1+4*i:], component)
- }
- // Send the request and wait for the response
- reply, err := w.ledgerExchange(ledgerOpRetrieveAddress, ledgerP1DirectlyFetchAddress, ledgerP2DiscardAddressChainCode, path)
- if err != nil {
- return common.Address{}, err
- }
- // Discard the public key, we don't need that for now
- if len(reply) < 1 || len(reply) < 1+int(reply[0]) {
- return common.Address{}, errors.New("reply lacks public key entry")
- }
- reply = reply[1+int(reply[0]):]
-
- // Extract the Ethereum hex address string
- if len(reply) < 1 || len(reply) < 1+int(reply[0]) {
- return common.Address{}, errors.New("reply lacks address entry")
- }
- hexstr := reply[1 : 1+int(reply[0])]
-
- // Decode the hex string into an Ethereum address and return
- var address common.Address
- if _, err = hex.Decode(address[:], hexstr); err != nil {
- return common.Address{}, err
- }
- return address, nil
-}
-
-// ledgerSign sends the transaction to the Ledger wallet, and waits for the user
-// to confirm or deny the transaction.
-//
-// The transaction signing protocol is defined as follows:
-//
-// CLA | INS | P1 | P2 | Lc | Le
-// ----+-----+----+----+-----+---
-// E0 | 04 | 00: first transaction data block
-// 80: subsequent transaction data block
-// | 00 | variable | variable
-//
-// Where the input for the first transaction block (first 255 bytes) is:
-//
-// Description | Length
-// -------------------------------------------------+----------
-// Number of BIP 32 derivations to perform (max 10) | 1 byte
-// First derivation index (big endian) | 4 bytes
-// ... | 4 bytes
-// Last derivation index (big endian) | 4 bytes
-// RLP transaction chunk | arbitrary
-//
-// And the input for subsequent transaction blocks (first 255 bytes) are:
-//
-// Description | Length
-// ----------------------+----------
-// RLP transaction chunk | arbitrary
-//
-// And the output data is:
-//
-// Description | Length
-// ------------+---------
-// signature V | 1 byte
-// signature R | 32 bytes
-// signature S | 32 bytes
-func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
- // Flatten the derivation path into the Ledger request
- path := make([]byte, 1+4*len(derivationPath))
- path[0] = byte(len(derivationPath))
- for i, component := range derivationPath {
- binary.BigEndian.PutUint32(path[1+4*i:], component)
- }
- // Create the transaction RLP based on whether legacy or EIP155 signing was requested
- var (
- txrlp []byte
- err error
- )
- if chainID == nil {
- if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil {
- return common.Address{}, nil, err
- }
- } else {
- if tx.Type() == types.DynamicFeeTxType {
- if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
- return common.Address{}, nil, err
- }
- // append type to transaction
- txrlp = append([]byte{tx.Type()}, txrlp...)
- } else if tx.Type() == types.AccessListTxType {
- if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
- return common.Address{}, nil, err
- }
- // append type to transaction
- txrlp = append([]byte{tx.Type()}, txrlp...)
- } else if tx.Type() == types.LegacyTxType {
- if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
- return common.Address{}, nil, err
- }
- }
- }
- payload := append(path, txrlp...)
-
- // Send the request and wait for the response
- var (
- op = ledgerP1InitTransactionData
- reply []byte
- )
-
- // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
- // https://github.com/LedgerHQ/app-ethereum/issues/409
- chunk := 255
- if tx.Type() == types.LegacyTxType {
- for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
- }
- }
-
- for len(payload) > 0 {
- // Calculate the size of the next data chunk
- if chunk > len(payload) {
- chunk = len(payload)
- }
- // Send the chunk over, ensuring it's processed correctly
- reply, err = w.ledgerExchange(ledgerOpSignTransaction, op, 0, payload[:chunk])
- if err != nil {
- return common.Address{}, nil, err
- }
- // Shift the payload and ensure subsequent chunks are marked as such
- payload = payload[chunk:]
- op = ledgerP1ContTransactionData
- }
- // Extract the Ethereum signature and do a sanity validation
- if len(reply) != crypto.SignatureLength {
- return common.Address{}, nil, errors.New("reply lacks signature")
- }
- signature := append(reply[1:], reply[0])
-
- // Create the correct signer and signature transform based on the chain ID
- var signer types.Signer
- if chainID == nil {
- signer = new(types.HomesteadSigner)
- } else {
- signer = types.LatestSignerForChainID(chainID)
- // For non-legacy transactions, V is 0 or 1, no need to subtract here.
- if tx.Type() == types.LegacyTxType {
- signature[64] -= byte(chainID.Uint64()*2 + 35)
- }
- }
- signed, err := tx.WithSignature(signer, signature)
- if err != nil {
- return common.Address{}, nil, err
- }
- sender, err := types.Sender(signer, signed)
- if err != nil {
- return common.Address{}, nil, err
- }
- return sender, signed, nil
-}
-
-// ledgerSignTypedMessage sends the transaction to the Ledger wallet, and waits for the user
-// to confirm or deny the transaction.
-//
-// The signing protocol is defined as follows:
-//
-// CLA | INS | P1 | P2 | Lc | Le
-// ----+-----+----+-----------------------------+-----+---
-// E0 | 0C | 00 | implementation version : 00 | variable | variable
-//
-// Where the input is:
-//
-// Description | Length
-// -------------------------------------------------+----------
-// Number of BIP 32 derivations to perform (max 10) | 1 byte
-// First derivation index (big endian) | 4 bytes
-// ... | 4 bytes
-// Last derivation index (big endian) | 4 bytes
-// domain hash | 32 bytes
-// message hash | 32 bytes
-//
-// And the output data is:
-//
-// Description | Length
-// ------------+---------
-// signature V | 1 byte
-// signature R | 32 bytes
-// signature S | 32 bytes
-func (w *ledgerDriver) ledgerSignTypedMessage(derivationPath []uint32, domainHash []byte, messageHash []byte) ([]byte, error) {
- // Flatten the derivation path into the Ledger request
- path := make([]byte, 1+4*len(derivationPath))
- path[0] = byte(len(derivationPath))
- for i, component := range derivationPath {
- binary.BigEndian.PutUint32(path[1+4*i:], component)
- }
- // Create the 712 message
- payload := append(path, domainHash...)
- payload = append(payload, messageHash...)
-
- // Send the request and wait for the response
- var (
- op = ledgerP1InitTypedMessageData
- reply []byte
- err error
- )
-
- // Send the message over, ensuring it's processed correctly
- reply, err = w.ledgerExchange(ledgerOpSignTypedMessage, op, 0, payload)
-
- if err != nil {
- return nil, err
- }
-
- // Extract the Ethereum signature and do a sanity validation
- if len(reply) != crypto.SignatureLength {
- return nil, errors.New("reply lacks signature")
- }
- signature := append(reply[1:], reply[0])
- return signature, nil
-}
-
-// ledgerExchange performs a data exchange with the Ledger wallet, sending it a
-// message and retrieving the response.
-//
-// The common transport header is defined as follows:
-//
-// Description | Length
-// --------------------------------------+----------
-// Communication channel ID (big endian) | 2 bytes
-// Command tag | 1 byte
-// Packet sequence index (big endian) | 2 bytes
-// Payload | arbitrary
-//
-// The Communication channel ID allows commands multiplexing over the same
-// physical link. It is not used for the time being, and should be set to 0101
-// to avoid compatibility issues with implementations ignoring a leading 00 byte.
-//
-// The Command tag describes the message content. Use TAG_APDU (0x05) for standard
-// APDU payloads, or TAG_PING (0x02) for a simple link test.
-//
-// The Packet sequence index describes the current sequence for fragmented payloads.
-// The first fragment index is 0x00.
-//
-// APDU Command payloads are encoded as follows:
-//
-// Description | Length
-// -----------------------------------
-// APDU length (big endian) | 2 bytes
-// APDU CLA | 1 byte
-// APDU INS | 1 byte
-// APDU P1 | 1 byte
-// APDU P2 | 1 byte
-// APDU length | 1 byte
-// Optional APDU data | arbitrary
-func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 ledgerParam2, data []byte) ([]byte, error) {
- // Construct the message payload, possibly split into multiple chunks
- apdu := make([]byte, 2, 7+len(data))
-
- binary.BigEndian.PutUint16(apdu, uint16(5+len(data)))
- apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...)
- apdu = append(apdu, data...)
-
- // Stream all the chunks to the device
- header := []byte{0x01, 0x01, 0x05, 0x00, 0x00} // Channel ID and command tag appended
- chunk := make([]byte, 64)
- space := len(chunk) - len(header)
-
- for i := 0; len(apdu) > 0; i++ {
- // Construct the new message to stream
- chunk = append(chunk[:0], header...)
- binary.BigEndian.PutUint16(chunk[3:], uint16(i))
-
- if len(apdu) > space {
- chunk = append(chunk, apdu[:space]...)
- apdu = apdu[space:]
- } else {
- chunk = append(chunk, apdu...)
- apdu = nil
- }
- // Send over to the device
- w.log.Trace("Data chunk sent to the Ledger", "chunk", hexutil.Bytes(chunk))
- if _, err := w.device.Write(chunk); err != nil {
- return nil, err
- }
- }
- // Stream the reply back from the wallet in 64 byte chunks
- var reply []byte
- chunk = chunk[:64] // Yeah, we surely have enough space
- for {
- // Read the next chunk from the Ledger wallet
- if _, err := io.ReadFull(w.device, chunk); err != nil {
- return nil, err
- }
- w.log.Trace("Data chunk received from the Ledger", "chunk", hexutil.Bytes(chunk))
-
- // Make sure the transport header matches
- if chunk[0] != 0x01 || chunk[1] != 0x01 || chunk[2] != 0x05 {
- return nil, errLedgerReplyInvalidHeader
- }
- // If it's the first chunk, retrieve the total message length
- var payload []byte
-
- if chunk[3] == 0x00 && chunk[4] == 0x00 {
- reply = make([]byte, 0, int(binary.BigEndian.Uint16(chunk[5:7])))
- payload = chunk[7:]
- } else {
- payload = chunk[5:]
- }
- // Append to the reply and stop when filled up
- if left := cap(reply) - len(reply); left > len(payload) {
- reply = append(reply, payload...)
- } else {
- reply = append(reply, payload[:left]...)
- break
- }
- }
- return reply[:len(reply)-2], nil
-}
diff --git a/accounts/usbwallet/messages-common.pb.go b/accounts/usbwallet/messages-common.pb.go
new file mode 100644
index 0000000000..73800802bb
--- /dev/null
+++ b/accounts/usbwallet/messages-common.pb.go
@@ -0,0 +1,1198 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.34.2
+// protoc v5.27.1
+// source: messages-common.proto
+
+package trezor
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Failure_FailureType int32
+
+const (
+ Failure_Failure_UnexpectedMessage Failure_FailureType = 1
+ Failure_Failure_ButtonExpected Failure_FailureType = 2
+ Failure_Failure_DataError Failure_FailureType = 3
+ Failure_Failure_ActionCancelled Failure_FailureType = 4
+ Failure_Failure_PinExpected Failure_FailureType = 5
+ Failure_Failure_PinCancelled Failure_FailureType = 6
+ Failure_Failure_PinInvalid Failure_FailureType = 7
+ Failure_Failure_InvalidSignature Failure_FailureType = 8
+ Failure_Failure_ProcessError Failure_FailureType = 9
+ Failure_Failure_NotEnoughFunds Failure_FailureType = 10
+ Failure_Failure_NotInitialized Failure_FailureType = 11
+ Failure_Failure_PinMismatch Failure_FailureType = 12
+ Failure_Failure_FirmwareError Failure_FailureType = 99
+)
+
+// Enum value maps for Failure_FailureType.
+var (
+ Failure_FailureType_name = map[int32]string{
+ 1: "Failure_UnexpectedMessage",
+ 2: "Failure_ButtonExpected",
+ 3: "Failure_DataError",
+ 4: "Failure_ActionCancelled",
+ 5: "Failure_PinExpected",
+ 6: "Failure_PinCancelled",
+ 7: "Failure_PinInvalid",
+ 8: "Failure_InvalidSignature",
+ 9: "Failure_ProcessError",
+ 10: "Failure_NotEnoughFunds",
+ 11: "Failure_NotInitialized",
+ 12: "Failure_PinMismatch",
+ 99: "Failure_FirmwareError",
+ }
+ Failure_FailureType_value = map[string]int32{
+ "Failure_UnexpectedMessage": 1,
+ "Failure_ButtonExpected": 2,
+ "Failure_DataError": 3,
+ "Failure_ActionCancelled": 4,
+ "Failure_PinExpected": 5,
+ "Failure_PinCancelled": 6,
+ "Failure_PinInvalid": 7,
+ "Failure_InvalidSignature": 8,
+ "Failure_ProcessError": 9,
+ "Failure_NotEnoughFunds": 10,
+ "Failure_NotInitialized": 11,
+ "Failure_PinMismatch": 12,
+ "Failure_FirmwareError": 99,
+ }
+)
+
+func (x Failure_FailureType) Enum() *Failure_FailureType {
+ p := new(Failure_FailureType)
+ *p = x
+ return p
+}
+
+func (x Failure_FailureType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Failure_FailureType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_common_proto_enumTypes[0].Descriptor()
+}
+
+func (Failure_FailureType) Type() protoreflect.EnumType {
+ return &file_messages_common_proto_enumTypes[0]
+}
+
+func (x Failure_FailureType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *Failure_FailureType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = Failure_FailureType(num)
+ return nil
+}
+
+// Deprecated: Use Failure_FailureType.Descriptor instead.
+func (Failure_FailureType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{1, 0}
+}
+
+// *
+// Type of button request
+type ButtonRequest_ButtonRequestType int32
+
+const (
+ ButtonRequest_ButtonRequest_Other ButtonRequest_ButtonRequestType = 1
+ ButtonRequest_ButtonRequest_FeeOverThreshold ButtonRequest_ButtonRequestType = 2
+ ButtonRequest_ButtonRequest_ConfirmOutput ButtonRequest_ButtonRequestType = 3
+ ButtonRequest_ButtonRequest_ResetDevice ButtonRequest_ButtonRequestType = 4
+ ButtonRequest_ButtonRequest_ConfirmWord ButtonRequest_ButtonRequestType = 5
+ ButtonRequest_ButtonRequest_WipeDevice ButtonRequest_ButtonRequestType = 6
+ ButtonRequest_ButtonRequest_ProtectCall ButtonRequest_ButtonRequestType = 7
+ ButtonRequest_ButtonRequest_SignTx ButtonRequest_ButtonRequestType = 8
+ ButtonRequest_ButtonRequest_FirmwareCheck ButtonRequest_ButtonRequestType = 9
+ ButtonRequest_ButtonRequest_Address ButtonRequest_ButtonRequestType = 10
+ ButtonRequest_ButtonRequest_PublicKey ButtonRequest_ButtonRequestType = 11
+ ButtonRequest_ButtonRequest_MnemonicWordCount ButtonRequest_ButtonRequestType = 12
+ ButtonRequest_ButtonRequest_MnemonicInput ButtonRequest_ButtonRequestType = 13
+ ButtonRequest_ButtonRequest_PassphraseType ButtonRequest_ButtonRequestType = 14
+ ButtonRequest_ButtonRequest_UnknownDerivationPath ButtonRequest_ButtonRequestType = 15
+)
+
+// Enum value maps for ButtonRequest_ButtonRequestType.
+var (
+ ButtonRequest_ButtonRequestType_name = map[int32]string{
+ 1: "ButtonRequest_Other",
+ 2: "ButtonRequest_FeeOverThreshold",
+ 3: "ButtonRequest_ConfirmOutput",
+ 4: "ButtonRequest_ResetDevice",
+ 5: "ButtonRequest_ConfirmWord",
+ 6: "ButtonRequest_WipeDevice",
+ 7: "ButtonRequest_ProtectCall",
+ 8: "ButtonRequest_SignTx",
+ 9: "ButtonRequest_FirmwareCheck",
+ 10: "ButtonRequest_Address",
+ 11: "ButtonRequest_PublicKey",
+ 12: "ButtonRequest_MnemonicWordCount",
+ 13: "ButtonRequest_MnemonicInput",
+ 14: "ButtonRequest_PassphraseType",
+ 15: "ButtonRequest_UnknownDerivationPath",
+ }
+ ButtonRequest_ButtonRequestType_value = map[string]int32{
+ "ButtonRequest_Other": 1,
+ "ButtonRequest_FeeOverThreshold": 2,
+ "ButtonRequest_ConfirmOutput": 3,
+ "ButtonRequest_ResetDevice": 4,
+ "ButtonRequest_ConfirmWord": 5,
+ "ButtonRequest_WipeDevice": 6,
+ "ButtonRequest_ProtectCall": 7,
+ "ButtonRequest_SignTx": 8,
+ "ButtonRequest_FirmwareCheck": 9,
+ "ButtonRequest_Address": 10,
+ "ButtonRequest_PublicKey": 11,
+ "ButtonRequest_MnemonicWordCount": 12,
+ "ButtonRequest_MnemonicInput": 13,
+ "ButtonRequest_PassphraseType": 14,
+ "ButtonRequest_UnknownDerivationPath": 15,
+ }
+)
+
+func (x ButtonRequest_ButtonRequestType) Enum() *ButtonRequest_ButtonRequestType {
+ p := new(ButtonRequest_ButtonRequestType)
+ *p = x
+ return p
+}
+
+func (x ButtonRequest_ButtonRequestType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ButtonRequest_ButtonRequestType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_common_proto_enumTypes[1].Descriptor()
+}
+
+func (ButtonRequest_ButtonRequestType) Type() protoreflect.EnumType {
+ return &file_messages_common_proto_enumTypes[1]
+}
+
+func (x ButtonRequest_ButtonRequestType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ButtonRequest_ButtonRequestType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ButtonRequest_ButtonRequestType(num)
+ return nil
+}
+
+// Deprecated: Use ButtonRequest_ButtonRequestType.Descriptor instead.
+func (ButtonRequest_ButtonRequestType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{2, 0}
+}
+
+// *
+// Type of PIN request
+type PinMatrixRequest_PinMatrixRequestType int32
+
+const (
+ PinMatrixRequest_PinMatrixRequestType_Current PinMatrixRequest_PinMatrixRequestType = 1
+ PinMatrixRequest_PinMatrixRequestType_NewFirst PinMatrixRequest_PinMatrixRequestType = 2
+ PinMatrixRequest_PinMatrixRequestType_NewSecond PinMatrixRequest_PinMatrixRequestType = 3
+)
+
+// Enum value maps for PinMatrixRequest_PinMatrixRequestType.
+var (
+ PinMatrixRequest_PinMatrixRequestType_name = map[int32]string{
+ 1: "PinMatrixRequestType_Current",
+ 2: "PinMatrixRequestType_NewFirst",
+ 3: "PinMatrixRequestType_NewSecond",
+ }
+ PinMatrixRequest_PinMatrixRequestType_value = map[string]int32{
+ "PinMatrixRequestType_Current": 1,
+ "PinMatrixRequestType_NewFirst": 2,
+ "PinMatrixRequestType_NewSecond": 3,
+ }
+)
+
+func (x PinMatrixRequest_PinMatrixRequestType) Enum() *PinMatrixRequest_PinMatrixRequestType {
+ p := new(PinMatrixRequest_PinMatrixRequestType)
+ *p = x
+ return p
+}
+
+func (x PinMatrixRequest_PinMatrixRequestType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (PinMatrixRequest_PinMatrixRequestType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_common_proto_enumTypes[2].Descriptor()
+}
+
+func (PinMatrixRequest_PinMatrixRequestType) Type() protoreflect.EnumType {
+ return &file_messages_common_proto_enumTypes[2]
+}
+
+func (x PinMatrixRequest_PinMatrixRequestType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *PinMatrixRequest_PinMatrixRequestType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = PinMatrixRequest_PinMatrixRequestType(num)
+ return nil
+}
+
+// Deprecated: Use PinMatrixRequest_PinMatrixRequestType.Descriptor instead.
+func (PinMatrixRequest_PinMatrixRequestType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{4, 0}
+}
+
+// *
+// Response: Success of the previous request
+// @end
+type Success struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` // human readable description of action or request-specific payload
+}
+
+func (x *Success) Reset() {
+ *x = Success{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Success) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Success) ProtoMessage() {}
+
+func (x *Success) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Success.ProtoReflect.Descriptor instead.
+func (*Success) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Success) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+// *
+// Response: Failure of the previous request
+// @end
+type Failure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code *Failure_FailureType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.Failure_FailureType" json:"code,omitempty"` // computer-readable definition of the error state
+ Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` // human-readable message of the error state
+}
+
+func (x *Failure) Reset() {
+ *x = Failure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Failure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Failure) ProtoMessage() {}
+
+func (x *Failure) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Failure.ProtoReflect.Descriptor instead.
+func (*Failure) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Failure) GetCode() Failure_FailureType {
+ if x != nil && x.Code != nil {
+ return *x.Code
+ }
+ return Failure_Failure_UnexpectedMessage
+}
+
+func (x *Failure) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+// *
+// Response: Device is waiting for HW button press.
+// @auxstart
+// @next ButtonAck
+type ButtonRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code *ButtonRequest_ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.ButtonRequest_ButtonRequestType" json:"code,omitempty"`
+ Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
+}
+
+func (x *ButtonRequest) Reset() {
+ *x = ButtonRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ButtonRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ButtonRequest) ProtoMessage() {}
+
+func (x *ButtonRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ButtonRequest.ProtoReflect.Descriptor instead.
+func (*ButtonRequest) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ButtonRequest) GetCode() ButtonRequest_ButtonRequestType {
+ if x != nil && x.Code != nil {
+ return *x.Code
+ }
+ return ButtonRequest_ButtonRequest_Other
+}
+
+func (x *ButtonRequest) GetData() string {
+ if x != nil && x.Data != nil {
+ return *x.Data
+ }
+ return ""
+}
+
+// *
+// Request: Computer agrees to wait for HW button press
+// @auxend
+type ButtonAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ButtonAck) Reset() {
+ *x = ButtonAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ButtonAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ButtonAck) ProtoMessage() {}
+
+func (x *ButtonAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ButtonAck.ProtoReflect.Descriptor instead.
+func (*ButtonAck) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{3}
+}
+
+// *
+// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
+// @auxstart
+// @next PinMatrixAck
+type PinMatrixRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type *PinMatrixRequest_PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType" json:"type,omitempty"`
+}
+
+func (x *PinMatrixRequest) Reset() {
+ *x = PinMatrixRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PinMatrixRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PinMatrixRequest) ProtoMessage() {}
+
+func (x *PinMatrixRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PinMatrixRequest.ProtoReflect.Descriptor instead.
+func (*PinMatrixRequest) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *PinMatrixRequest) GetType() PinMatrixRequest_PinMatrixRequestType {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return PinMatrixRequest_PinMatrixRequestType_Current
+}
+
+// *
+// Request: Computer responds with encoded PIN
+// @auxend
+type PinMatrixAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` // matrix encoded PIN entered by user
+}
+
+func (x *PinMatrixAck) Reset() {
+ *x = PinMatrixAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PinMatrixAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PinMatrixAck) ProtoMessage() {}
+
+func (x *PinMatrixAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PinMatrixAck.ProtoReflect.Descriptor instead.
+func (*PinMatrixAck) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *PinMatrixAck) GetPin() string {
+ if x != nil && x.Pin != nil {
+ return *x.Pin
+ }
+ return ""
+}
+
+// *
+// Response: Device awaits encryption passphrase
+// @auxstart
+// @next PassphraseAck
+type PassphraseRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ OnDevice *bool `protobuf:"varint,1,opt,name=on_device,json=onDevice" json:"on_device,omitempty"` // passphrase is being entered on the device
+}
+
+func (x *PassphraseRequest) Reset() {
+ *x = PassphraseRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PassphraseRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PassphraseRequest) ProtoMessage() {}
+
+func (x *PassphraseRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PassphraseRequest.ProtoReflect.Descriptor instead.
+func (*PassphraseRequest) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *PassphraseRequest) GetOnDevice() bool {
+ if x != nil && x.OnDevice != nil {
+ return *x.OnDevice
+ }
+ return false
+}
+
+// *
+// Request: Send passphrase back
+// @next PassphraseStateRequest
+type PassphraseAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Passphrase *string `protobuf:"bytes,1,opt,name=passphrase" json:"passphrase,omitempty"`
+ State []byte `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` // expected device state
+}
+
+func (x *PassphraseAck) Reset() {
+ *x = PassphraseAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PassphraseAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PassphraseAck) ProtoMessage() {}
+
+func (x *PassphraseAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PassphraseAck.ProtoReflect.Descriptor instead.
+func (*PassphraseAck) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *PassphraseAck) GetPassphrase() string {
+ if x != nil && x.Passphrase != nil {
+ return *x.Passphrase
+ }
+ return ""
+}
+
+func (x *PassphraseAck) GetState() []byte {
+ if x != nil {
+ return x.State
+ }
+ return nil
+}
+
+// *
+// Response: Device awaits passphrase state
+// @next PassphraseStateAck
+type PassphraseStateRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` // actual device state
+}
+
+func (x *PassphraseStateRequest) Reset() {
+ *x = PassphraseStateRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PassphraseStateRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PassphraseStateRequest) ProtoMessage() {}
+
+func (x *PassphraseStateRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PassphraseStateRequest.ProtoReflect.Descriptor instead.
+func (*PassphraseStateRequest) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *PassphraseStateRequest) GetState() []byte {
+ if x != nil {
+ return x.State
+ }
+ return nil
+}
+
+// *
+// Request: Send passphrase state back
+// @auxend
+type PassphraseStateAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *PassphraseStateAck) Reset() {
+ *x = PassphraseStateAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PassphraseStateAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PassphraseStateAck) ProtoMessage() {}
+
+func (x *PassphraseStateAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PassphraseStateAck.ProtoReflect.Descriptor instead.
+func (*PassphraseStateAck) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{9}
+}
+
+// *
+// Structure representing BIP32 (hierarchical deterministic) node
+// Used for imports of private key into the device and exporting public key out of device
+// @embed
+type HDNodeType struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"`
+ Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"`
+ ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"`
+ ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"`
+ PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"`
+ PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
+}
+
+func (x *HDNodeType) Reset() {
+ *x = HDNodeType{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_common_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HDNodeType) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HDNodeType) ProtoMessage() {}
+
+func (x *HDNodeType) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_common_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use HDNodeType.ProtoReflect.Descriptor instead.
+func (*HDNodeType) Descriptor() ([]byte, []int) {
+ return file_messages_common_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *HDNodeType) GetDepth() uint32 {
+ if x != nil && x.Depth != nil {
+ return *x.Depth
+ }
+ return 0
+}
+
+func (x *HDNodeType) GetFingerprint() uint32 {
+ if x != nil && x.Fingerprint != nil {
+ return *x.Fingerprint
+ }
+ return 0
+}
+
+func (x *HDNodeType) GetChildNum() uint32 {
+ if x != nil && x.ChildNum != nil {
+ return *x.ChildNum
+ }
+ return 0
+}
+
+func (x *HDNodeType) GetChainCode() []byte {
+ if x != nil {
+ return x.ChainCode
+ }
+ return nil
+}
+
+func (x *HDNodeType) GetPrivateKey() []byte {
+ if x != nil {
+ return x.PrivateKey
+ }
+ return nil
+}
+
+func (x *HDNodeType) GetPublicKey() []byte {
+ if x != nil {
+ return x.PublicKey
+ }
+ return nil
+}
+
+var File_messages_common_proto protoreflect.FileDescriptor
+
+var file_messages_common_proto_rawDesc = []byte{
+ 0x0a, 0x15, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
+ 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a,
+ 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x6f, 0x6e, 0x22, 0x23, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a,
+ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd5, 0x03, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c,
+ 0x75, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x2e, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x46, 0x61,
+ 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x22, 0xeb, 0x02, 0x0a, 0x0b, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x55, 0x6e, 0x65,
+ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x01,
+ 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x42, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11,
+ 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x44, 0x61, 0x74, 0x61, 0x45, 0x72, 0x72, 0x6f,
+ 0x72, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x41,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x10, 0x04,
+ 0x12, 0x17, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x45,
+ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x61, 0x69,
+ 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65,
+ 0x64, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50,
+ 0x69, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x46,
+ 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x69,
+ 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x61, 0x69,
+ 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x72, 0x72, 0x6f,
+ 0x72, 0x10, 0x09, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x4e,
+ 0x6f, 0x74, 0x45, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x10, 0x0a, 0x12,
+ 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x4e, 0x6f, 0x74, 0x49, 0x6e,
+ 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x10, 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x46,
+ 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74,
+ 0x63, 0x68, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f,
+ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x63, 0x22,
+ 0xe6, 0x04, 0x0a, 0x0d, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x12, 0x4e, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x3a, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64,
+ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf0, 0x03, 0x0a, 0x11, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x42,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4f, 0x74, 0x68,
+ 0x65, 0x72, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x46, 0x65, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x68, 0x72,
+ 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72,
+ 0x6d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74,
+ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x04, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72,
+ 0x6d, 0x57, 0x6f, 0x72, 0x64, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x42, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76,
+ 0x69, 0x63, 0x65, 0x10, 0x06, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x43, 0x61,
+ 0x6c, 0x6c, 0x10, 0x07, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x08, 0x12, 0x1f,
+ 0x0a, 0x1b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f,
+ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x10, 0x09, 0x12,
+ 0x19, 0x0a, 0x15, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x0a, 0x12, 0x1b, 0x0a, 0x17, 0x42, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50, 0x75, 0x62, 0x6c,
+ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f, 0x42, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69,
+ 0x63, 0x57, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x10, 0x0c, 0x12, 0x1f, 0x0a, 0x1b,
+ 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4d, 0x6e,
+ 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x10, 0x0d, 0x12, 0x20, 0x0a,
+ 0x1c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50,
+ 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0x0e, 0x12,
+ 0x27, 0x0a, 0x23, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x10, 0x0f, 0x22, 0x0b, 0x0a, 0x09, 0x42, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x22, 0xe9, 0x01, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74,
+ 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x40, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72,
+ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x7f, 0x0a, 0x14, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x69, 0x6e, 0x4d,
+ 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x69,
+ 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x4e, 0x65, 0x77, 0x46, 0x69, 0x72, 0x73, 0x74, 0x10, 0x02, 0x12, 0x22, 0x0a,
+ 0x1e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x10,
+ 0x03, 0x22, 0x20, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x41, 0x63,
+ 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x03,
+ 0x70, 0x69, 0x6e, 0x22, 0x30, 0x0a, 0x11, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
+ 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6e, 0x5f, 0x64,
+ 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x6e, 0x44,
+ 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x45, 0x0a, 0x0d, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72,
+ 0x61, 0x73, 0x65, 0x41, 0x63, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68,
+ 0x72, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73,
+ 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x2e, 0x0a, 0x16,
+ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x14, 0x0a, 0x12,
+ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41,
+ 0x63, 0x6b, 0x22, 0xc0, 0x01, 0x0a, 0x0a, 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0d,
+ 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65,
+ 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x69,
+ 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x08, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f,
+ 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69,
+ 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
+ 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
+ 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c,
+ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x6f, 0x2d,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72, 0x65, 0x7a,
+ 0x6f, 0x72,
+}
+
+var (
+ file_messages_common_proto_rawDescOnce sync.Once
+ file_messages_common_proto_rawDescData = file_messages_common_proto_rawDesc
+)
+
+func file_messages_common_proto_rawDescGZIP() []byte {
+ file_messages_common_proto_rawDescOnce.Do(func() {
+ file_messages_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_common_proto_rawDescData)
+ })
+ return file_messages_common_proto_rawDescData
+}
+
+var file_messages_common_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_messages_common_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
+var file_messages_common_proto_goTypes = []any{
+ (Failure_FailureType)(0), // 0: hw.trezor.messages.common.Failure.FailureType
+ (ButtonRequest_ButtonRequestType)(0), // 1: hw.trezor.messages.common.ButtonRequest.ButtonRequestType
+ (PinMatrixRequest_PinMatrixRequestType)(0), // 2: hw.trezor.messages.common.PinMatrixRequest.PinMatrixRequestType
+ (*Success)(nil), // 3: hw.trezor.messages.common.Success
+ (*Failure)(nil), // 4: hw.trezor.messages.common.Failure
+ (*ButtonRequest)(nil), // 5: hw.trezor.messages.common.ButtonRequest
+ (*ButtonAck)(nil), // 6: hw.trezor.messages.common.ButtonAck
+ (*PinMatrixRequest)(nil), // 7: hw.trezor.messages.common.PinMatrixRequest
+ (*PinMatrixAck)(nil), // 8: hw.trezor.messages.common.PinMatrixAck
+ (*PassphraseRequest)(nil), // 9: hw.trezor.messages.common.PassphraseRequest
+ (*PassphraseAck)(nil), // 10: hw.trezor.messages.common.PassphraseAck
+ (*PassphraseStateRequest)(nil), // 11: hw.trezor.messages.common.PassphraseStateRequest
+ (*PassphraseStateAck)(nil), // 12: hw.trezor.messages.common.PassphraseStateAck
+ (*HDNodeType)(nil), // 13: hw.trezor.messages.common.HDNodeType
+}
+var file_messages_common_proto_depIdxs = []int32{
+ 0, // 0: hw.trezor.messages.common.Failure.code:type_name -> hw.trezor.messages.common.Failure.FailureType
+ 1, // 1: hw.trezor.messages.common.ButtonRequest.code:type_name -> hw.trezor.messages.common.ButtonRequest.ButtonRequestType
+ 2, // 2: hw.trezor.messages.common.PinMatrixRequest.type:type_name -> hw.trezor.messages.common.PinMatrixRequest.PinMatrixRequestType
+ 3, // [3:3] is the sub-list for method output_type
+ 3, // [3:3] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
+}
+
+func init() { file_messages_common_proto_init() }
+func file_messages_common_proto_init() {
+ if File_messages_common_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_messages_common_proto_msgTypes[0].Exporter = func(v any, i int) any {
+ switch v := v.(*Success); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[1].Exporter = func(v any, i int) any {
+ switch v := v.(*Failure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[2].Exporter = func(v any, i int) any {
+ switch v := v.(*ButtonRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[3].Exporter = func(v any, i int) any {
+ switch v := v.(*ButtonAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[4].Exporter = func(v any, i int) any {
+ switch v := v.(*PinMatrixRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[5].Exporter = func(v any, i int) any {
+ switch v := v.(*PinMatrixAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[6].Exporter = func(v any, i int) any {
+ switch v := v.(*PassphraseRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[7].Exporter = func(v any, i int) any {
+ switch v := v.(*PassphraseAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[8].Exporter = func(v any, i int) any {
+ switch v := v.(*PassphraseStateRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[9].Exporter = func(v any, i int) any {
+ switch v := v.(*PassphraseStateAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_common_proto_msgTypes[10].Exporter = func(v any, i int) any {
+ switch v := v.(*HDNodeType); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_messages_common_proto_rawDesc,
+ NumEnums: 3,
+ NumMessages: 11,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_messages_common_proto_goTypes,
+ DependencyIndexes: file_messages_common_proto_depIdxs,
+ EnumInfos: file_messages_common_proto_enumTypes,
+ MessageInfos: file_messages_common_proto_msgTypes,
+ }.Build()
+ File_messages_common_proto = out.File
+ file_messages_common_proto_rawDesc = nil
+ file_messages_common_proto_goTypes = nil
+ file_messages_common_proto_depIdxs = nil
+}
diff --git a/accounts/usbwallet/messages-common.proto b/accounts/usbwallet/messages-common.proto
new file mode 100644
index 0000000000..1f524e25d7
--- /dev/null
+++ b/accounts/usbwallet/messages-common.proto
@@ -0,0 +1,149 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.common;
+
+option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
+
+/**
+ * Response: Success of the previous request
+ * @end
+ */
+message Success {
+ optional string message = 1; // human readable description of action or request-specific payload
+}
+
+/**
+ * Response: Failure of the previous request
+ * @end
+ */
+message Failure {
+ optional FailureType code = 1; // computer-readable definition of the error state
+ optional string message = 2; // human-readable message of the error state
+ enum FailureType {
+ Failure_UnexpectedMessage = 1;
+ Failure_ButtonExpected = 2;
+ Failure_DataError = 3;
+ Failure_ActionCancelled = 4;
+ Failure_PinExpected = 5;
+ Failure_PinCancelled = 6;
+ Failure_PinInvalid = 7;
+ Failure_InvalidSignature = 8;
+ Failure_ProcessError = 9;
+ Failure_NotEnoughFunds = 10;
+ Failure_NotInitialized = 11;
+ Failure_PinMismatch = 12;
+ Failure_FirmwareError = 99;
+ }
+}
+
+/**
+ * Response: Device is waiting for HW button press.
+ * @auxstart
+ * @next ButtonAck
+ */
+message ButtonRequest {
+ optional ButtonRequestType code = 1;
+ optional string data = 2;
+ /**
+ * Type of button request
+ */
+ enum ButtonRequestType {
+ ButtonRequest_Other = 1;
+ ButtonRequest_FeeOverThreshold = 2;
+ ButtonRequest_ConfirmOutput = 3;
+ ButtonRequest_ResetDevice = 4;
+ ButtonRequest_ConfirmWord = 5;
+ ButtonRequest_WipeDevice = 6;
+ ButtonRequest_ProtectCall = 7;
+ ButtonRequest_SignTx = 8;
+ ButtonRequest_FirmwareCheck = 9;
+ ButtonRequest_Address = 10;
+ ButtonRequest_PublicKey = 11;
+ ButtonRequest_MnemonicWordCount = 12;
+ ButtonRequest_MnemonicInput = 13;
+ ButtonRequest_PassphraseType = 14;
+ ButtonRequest_UnknownDerivationPath = 15;
+ }
+}
+
+/**
+ * Request: Computer agrees to wait for HW button press
+ * @auxend
+ */
+message ButtonAck {
+}
+
+/**
+ * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
+ * @auxstart
+ * @next PinMatrixAck
+ */
+message PinMatrixRequest {
+ optional PinMatrixRequestType type = 1;
+ /**
+ * Type of PIN request
+ */
+ enum PinMatrixRequestType {
+ PinMatrixRequestType_Current = 1;
+ PinMatrixRequestType_NewFirst = 2;
+ PinMatrixRequestType_NewSecond = 3;
+ }
+}
+
+/**
+ * Request: Computer responds with encoded PIN
+ * @auxend
+ */
+message PinMatrixAck {
+ required string pin = 1; // matrix encoded PIN entered by user
+}
+
+/**
+ * Response: Device awaits encryption passphrase
+ * @auxstart
+ * @next PassphraseAck
+ */
+message PassphraseRequest {
+ optional bool on_device = 1; // passphrase is being entered on the device
+}
+
+/**
+ * Request: Send passphrase back
+ * @next PassphraseStateRequest
+ */
+message PassphraseAck {
+ optional string passphrase = 1;
+ optional bytes state = 2; // expected device state
+}
+
+/**
+ * Response: Device awaits passphrase state
+ * @next PassphraseStateAck
+ */
+message PassphraseStateRequest {
+ optional bytes state = 1; // actual device state
+}
+
+/**
+ * Request: Send passphrase state back
+ * @auxend
+ */
+message PassphraseStateAck {
+}
+
+/**
+ * Structure representing BIP32 (hierarchical deterministic) node
+ * Used for imports of private key into the device and exporting public key out of device
+ * @embed
+ */
+message HDNodeType {
+ required uint32 depth = 1;
+ required uint32 fingerprint = 2;
+ required uint32 child_num = 3;
+ required bytes chain_code = 4;
+ optional bytes private_key = 5;
+ optional bytes public_key = 6;
+}
diff --git a/accounts/usbwallet/messages-ethereum.pb.go b/accounts/usbwallet/messages-ethereum.pb.go
new file mode 100644
index 0000000000..a92123efcd
--- /dev/null
+++ b/accounts/usbwallet/messages-ethereum.pb.go
@@ -0,0 +1,1002 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.34.2
+// protoc v5.27.1
+// source: messages-ethereum.proto
+
+package trezor
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// *
+// Request: Ask device for public key corresponding to address_n path
+// @start
+// @next EthereumPublicKey
+// @next Failure
+type EthereumGetPublicKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
+ ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` // optionally show on display before sending the result
+}
+
+func (x *EthereumGetPublicKey) Reset() {
+ *x = EthereumGetPublicKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumGetPublicKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumGetPublicKey) ProtoMessage() {}
+
+func (x *EthereumGetPublicKey) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumGetPublicKey.ProtoReflect.Descriptor instead.
+func (*EthereumGetPublicKey) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *EthereumGetPublicKey) GetAddressN() []uint32 {
+ if x != nil {
+ return x.AddressN
+ }
+ return nil
+}
+
+func (x *EthereumGetPublicKey) GetShowDisplay() bool {
+ if x != nil && x.ShowDisplay != nil {
+ return *x.ShowDisplay
+ }
+ return false
+}
+
+// *
+// Response: Contains public key derived from device private seed
+// @end
+type EthereumPublicKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Node *HDNodeType `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"` // BIP32 public node
+ Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` // serialized form of public node
+}
+
+func (x *EthereumPublicKey) Reset() {
+ *x = EthereumPublicKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumPublicKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumPublicKey) ProtoMessage() {}
+
+func (x *EthereumPublicKey) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumPublicKey.ProtoReflect.Descriptor instead.
+func (*EthereumPublicKey) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *EthereumPublicKey) GetNode() *HDNodeType {
+ if x != nil {
+ return x.Node
+ }
+ return nil
+}
+
+func (x *EthereumPublicKey) GetXpub() string {
+ if x != nil && x.Xpub != nil {
+ return *x.Xpub
+ }
+ return ""
+}
+
+// *
+// Request: Ask device for Ethereum address corresponding to address_n path
+// @start
+// @next EthereumAddress
+// @next Failure
+type EthereumGetAddress struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
+ ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` // optionally show on display before sending the result
+}
+
+func (x *EthereumGetAddress) Reset() {
+ *x = EthereumGetAddress{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumGetAddress) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumGetAddress) ProtoMessage() {}
+
+func (x *EthereumGetAddress) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumGetAddress.ProtoReflect.Descriptor instead.
+func (*EthereumGetAddress) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *EthereumGetAddress) GetAddressN() []uint32 {
+ if x != nil {
+ return x.AddressN
+ }
+ return nil
+}
+
+func (x *EthereumGetAddress) GetShowDisplay() bool {
+ if x != nil && x.ShowDisplay != nil {
+ return *x.ShowDisplay
+ }
+ return false
+}
+
+// *
+// Response: Contains an Ethereum address derived from device private seed
+// @end
+type EthereumAddress struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // Ethereum address as 20 bytes (legacy firmwares)
+ AddressHex *string `protobuf:"bytes,2,opt,name=addressHex" json:"addressHex,omitempty"` // Ethereum address as hex string (newer firmwares)
+}
+
+func (x *EthereumAddress) Reset() {
+ *x = EthereumAddress{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumAddress) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumAddress) ProtoMessage() {}
+
+func (x *EthereumAddress) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumAddress.ProtoReflect.Descriptor instead.
+func (*EthereumAddress) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *EthereumAddress) GetAddressBin() []byte {
+ if x != nil {
+ return x.AddressBin
+ }
+ return nil
+}
+
+func (x *EthereumAddress) GetAddressHex() string {
+ if x != nil && x.AddressHex != nil {
+ return *x.AddressHex
+ }
+ return ""
+}
+
+// *
+// Request: Ask device to sign transaction
+// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
+// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
+// @start
+// @next EthereumTxRequest
+// @next Failure
+type EthereumSignTx struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
+ Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` // <=256 bit unsigned big endian
+ GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` // <=256 bit unsigned big endian (in wei)
+ GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` // <=256 bit unsigned big endian
+ ToBin []byte `protobuf:"bytes,5,opt,name=toBin" json:"toBin,omitempty"` // recipient address (20 bytes, legacy firmware)
+ ToHex *string `protobuf:"bytes,11,opt,name=toHex" json:"toHex,omitempty"` // recipient address (hex string, newer firmware)
+ Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` // <=256 bit unsigned big endian (in wei)
+ DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` // The initial data chunk (<= 1024 bytes)
+ DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` // Length of transaction payload
+ ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` // Chain Id for EIP 155
+ TxType *uint32 `protobuf:"varint,10,opt,name=tx_type,json=txType" json:"tx_type,omitempty"` // (only for Wanchain)
+}
+
+func (x *EthereumSignTx) Reset() {
+ *x = EthereumSignTx{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumSignTx) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumSignTx) ProtoMessage() {}
+
+func (x *EthereumSignTx) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumSignTx.ProtoReflect.Descriptor instead.
+func (*EthereumSignTx) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *EthereumSignTx) GetAddressN() []uint32 {
+ if x != nil {
+ return x.AddressN
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetNonce() []byte {
+ if x != nil {
+ return x.Nonce
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetGasPrice() []byte {
+ if x != nil {
+ return x.GasPrice
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetGasLimit() []byte {
+ if x != nil {
+ return x.GasLimit
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetToBin() []byte {
+ if x != nil {
+ return x.ToBin
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetToHex() string {
+ if x != nil && x.ToHex != nil {
+ return *x.ToHex
+ }
+ return ""
+}
+
+func (x *EthereumSignTx) GetValue() []byte {
+ if x != nil {
+ return x.Value
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetDataInitialChunk() []byte {
+ if x != nil {
+ return x.DataInitialChunk
+ }
+ return nil
+}
+
+func (x *EthereumSignTx) GetDataLength() uint32 {
+ if x != nil && x.DataLength != nil {
+ return *x.DataLength
+ }
+ return 0
+}
+
+func (x *EthereumSignTx) GetChainId() uint32 {
+ if x != nil && x.ChainId != nil {
+ return *x.ChainId
+ }
+ return 0
+}
+
+func (x *EthereumSignTx) GetTxType() uint32 {
+ if x != nil && x.TxType != nil {
+ return *x.TxType
+ }
+ return 0
+}
+
+// *
+// Response: Device asks for more data from transaction payload, or returns the signature.
+// If data_length is set, device awaits that many more bytes of payload.
+// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
+// @end
+// @next EthereumTxAck
+type EthereumTxRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` // Number of bytes being requested (<= 1024)
+ SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` // Computed signature (recovery parameter, limited to 27 or 28)
+ SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` // Computed signature R component (256 bit)
+ SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` // Computed signature S component (256 bit)
+}
+
+func (x *EthereumTxRequest) Reset() {
+ *x = EthereumTxRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumTxRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumTxRequest) ProtoMessage() {}
+
+func (x *EthereumTxRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumTxRequest.ProtoReflect.Descriptor instead.
+func (*EthereumTxRequest) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *EthereumTxRequest) GetDataLength() uint32 {
+ if x != nil && x.DataLength != nil {
+ return *x.DataLength
+ }
+ return 0
+}
+
+func (x *EthereumTxRequest) GetSignatureV() uint32 {
+ if x != nil && x.SignatureV != nil {
+ return *x.SignatureV
+ }
+ return 0
+}
+
+func (x *EthereumTxRequest) GetSignatureR() []byte {
+ if x != nil {
+ return x.SignatureR
+ }
+ return nil
+}
+
+func (x *EthereumTxRequest) GetSignatureS() []byte {
+ if x != nil {
+ return x.SignatureS
+ }
+ return nil
+}
+
+// *
+// Request: Transaction payload data.
+// @next EthereumTxRequest
+type EthereumTxAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` // Bytes from transaction payload (<= 1024 bytes)
+}
+
+func (x *EthereumTxAck) Reset() {
+ *x = EthereumTxAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumTxAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumTxAck) ProtoMessage() {}
+
+func (x *EthereumTxAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumTxAck.ProtoReflect.Descriptor instead.
+func (*EthereumTxAck) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *EthereumTxAck) GetDataChunk() []byte {
+ if x != nil {
+ return x.DataChunk
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to sign message
+// @start
+// @next EthereumMessageSignature
+// @next Failure
+type EthereumSignMessage struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
+ Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` // message to be signed
+}
+
+func (x *EthereumSignMessage) Reset() {
+ *x = EthereumSignMessage{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumSignMessage) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumSignMessage) ProtoMessage() {}
+
+func (x *EthereumSignMessage) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumSignMessage.ProtoReflect.Descriptor instead.
+func (*EthereumSignMessage) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *EthereumSignMessage) GetAddressN() []uint32 {
+ if x != nil {
+ return x.AddressN
+ }
+ return nil
+}
+
+func (x *EthereumSignMessage) GetMessage() []byte {
+ if x != nil {
+ return x.Message
+ }
+ return nil
+}
+
+// *
+// Response: Signed message
+// @end
+type EthereumMessageSignature struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // address used to sign the message (20 bytes, legacy firmware)
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` // signature of the message
+ AddressHex *string `protobuf:"bytes,3,opt,name=addressHex" json:"addressHex,omitempty"` // address used to sign the message (hex string, newer firmware)
+}
+
+func (x *EthereumMessageSignature) Reset() {
+ *x = EthereumMessageSignature{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumMessageSignature) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumMessageSignature) ProtoMessage() {}
+
+func (x *EthereumMessageSignature) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumMessageSignature.ProtoReflect.Descriptor instead.
+func (*EthereumMessageSignature) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *EthereumMessageSignature) GetAddressBin() []byte {
+ if x != nil {
+ return x.AddressBin
+ }
+ return nil
+}
+
+func (x *EthereumMessageSignature) GetSignature() []byte {
+ if x != nil {
+ return x.Signature
+ }
+ return nil
+}
+
+func (x *EthereumMessageSignature) GetAddressHex() string {
+ if x != nil && x.AddressHex != nil {
+ return *x.AddressHex
+ }
+ return ""
+}
+
+// *
+// Request: Ask device to verify message
+// @start
+// @next Success
+// @next Failure
+type EthereumVerifyMessage struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // address to verify (20 bytes, legacy firmware)
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` // signature to verify
+ Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` // message to verify
+ AddressHex *string `protobuf:"bytes,4,opt,name=addressHex" json:"addressHex,omitempty"` // address to verify (hex string, newer firmware)
+}
+
+func (x *EthereumVerifyMessage) Reset() {
+ *x = EthereumVerifyMessage{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_ethereum_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EthereumVerifyMessage) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EthereumVerifyMessage) ProtoMessage() {}
+
+func (x *EthereumVerifyMessage) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_ethereum_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EthereumVerifyMessage.ProtoReflect.Descriptor instead.
+func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) {
+ return file_messages_ethereum_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *EthereumVerifyMessage) GetAddressBin() []byte {
+ if x != nil {
+ return x.AddressBin
+ }
+ return nil
+}
+
+func (x *EthereumVerifyMessage) GetSignature() []byte {
+ if x != nil {
+ return x.Signature
+ }
+ return nil
+}
+
+func (x *EthereumVerifyMessage) GetMessage() []byte {
+ if x != nil {
+ return x.Message
+ }
+ return nil
+}
+
+func (x *EthereumVerifyMessage) GetAddressHex() string {
+ if x != nil && x.AddressHex != nil {
+ return *x.AddressHex
+ }
+ return ""
+}
+
+var File_messages_ethereum_proto protoreflect.FileDescriptor
+
+var file_messages_ethereum_proto_rawDesc = []byte{
+ 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x75, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x68, 0x77, 0x2e, 0x74, 0x72,
+ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x1a, 0x15, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
+ 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a,
+ 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c,
+ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x4e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x77, 0x44, 0x69,
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x22, 0x62, 0x0a, 0x11, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
+ 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x6f,
+ 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72,
+ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
+ 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x70, 0x75, 0x62, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x78, 0x70, 0x75, 0x62, 0x22, 0x54, 0x0a, 0x12, 0x45, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
+ 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03,
+ 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4e, 0x12, 0x21, 0x0a, 0x0c,
+ 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x77, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x22,
+ 0x51, 0x0a, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42,
+ 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48,
+ 0x65, 0x78, 0x22, 0xc2, 0x02, 0x0a, 0x0e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53,
+ 0x69, 0x67, 0x6e, 0x54, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f,
+ 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x61, 0x73,
+ 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d,
+ 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d,
+ 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x42, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x05, 0x74, 0x6f, 0x42, 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x48, 0x65,
+ 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x48, 0x65, 0x78, 0x12, 0x14,
+ 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x69,
+ 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c,
+ 0x52, 0x10, 0x64, 0x61, 0x74, 0x61, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x68, 0x75,
+ 0x6e, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74,
+ 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x4c, 0x65, 0x6e,
+ 0x67, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18,
+ 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x17,
+ 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x06, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x11, 0x45, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x56, 0x12,
+ 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x53, 0x22, 0x2e, 0x0a, 0x0d, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x41,
+ 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e,
+ 0x6b, 0x22, 0x4c, 0x0a, 0x13, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53, 0x69, 0x67,
+ 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72,
+ 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64,
+ 0x72, 0x65, 0x73, 0x73, 0x4e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
+ 0x78, 0x0a, 0x18, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
+ 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73,
+ 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
+ 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64,
+ 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, 0x15, 0x45, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69,
+ 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x42, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x42, 0x77, 0x0a, 0x23, 0x63,
+ 0x6f, 0x6d, 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74,
+ 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x42, 0x15, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67,
+ 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72,
+ 0x65, 0x7a, 0x6f, 0x72,
+}
+
+var (
+ file_messages_ethereum_proto_rawDescOnce sync.Once
+ file_messages_ethereum_proto_rawDescData = file_messages_ethereum_proto_rawDesc
+)
+
+func file_messages_ethereum_proto_rawDescGZIP() []byte {
+ file_messages_ethereum_proto_rawDescOnce.Do(func() {
+ file_messages_ethereum_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_ethereum_proto_rawDescData)
+ })
+ return file_messages_ethereum_proto_rawDescData
+}
+
+var file_messages_ethereum_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_messages_ethereum_proto_goTypes = []any{
+ (*EthereumGetPublicKey)(nil), // 0: hw.trezor.messages.ethereum.EthereumGetPublicKey
+ (*EthereumPublicKey)(nil), // 1: hw.trezor.messages.ethereum.EthereumPublicKey
+ (*EthereumGetAddress)(nil), // 2: hw.trezor.messages.ethereum.EthereumGetAddress
+ (*EthereumAddress)(nil), // 3: hw.trezor.messages.ethereum.EthereumAddress
+ (*EthereumSignTx)(nil), // 4: hw.trezor.messages.ethereum.EthereumSignTx
+ (*EthereumTxRequest)(nil), // 5: hw.trezor.messages.ethereum.EthereumTxRequest
+ (*EthereumTxAck)(nil), // 6: hw.trezor.messages.ethereum.EthereumTxAck
+ (*EthereumSignMessage)(nil), // 7: hw.trezor.messages.ethereum.EthereumSignMessage
+ (*EthereumMessageSignature)(nil), // 8: hw.trezor.messages.ethereum.EthereumMessageSignature
+ (*EthereumVerifyMessage)(nil), // 9: hw.trezor.messages.ethereum.EthereumVerifyMessage
+ (*HDNodeType)(nil), // 10: hw.trezor.messages.common.HDNodeType
+}
+var file_messages_ethereum_proto_depIdxs = []int32{
+ 10, // 0: hw.trezor.messages.ethereum.EthereumPublicKey.node:type_name -> hw.trezor.messages.common.HDNodeType
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_messages_ethereum_proto_init() }
+func file_messages_ethereum_proto_init() {
+ if File_messages_ethereum_proto != nil {
+ return
+ }
+ file_messages_common_proto_init()
+ if !protoimpl.UnsafeEnabled {
+ file_messages_ethereum_proto_msgTypes[0].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumGetPublicKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[1].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumPublicKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[2].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumGetAddress); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[3].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumAddress); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[4].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumSignTx); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[5].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumTxRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[6].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumTxAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[7].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumSignMessage); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[8].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumMessageSignature); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_ethereum_proto_msgTypes[9].Exporter = func(v any, i int) any {
+ switch v := v.(*EthereumVerifyMessage); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_messages_ethereum_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 10,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_messages_ethereum_proto_goTypes,
+ DependencyIndexes: file_messages_ethereum_proto_depIdxs,
+ MessageInfos: file_messages_ethereum_proto_msgTypes,
+ }.Build()
+ File_messages_ethereum_proto = out.File
+ file_messages_ethereum_proto_rawDesc = nil
+ file_messages_ethereum_proto_goTypes = nil
+ file_messages_ethereum_proto_depIdxs = nil
+}
diff --git a/accounts/usbwallet/messages-ethereum.proto b/accounts/usbwallet/messages-ethereum.proto
new file mode 100644
index 0000000000..8e1150abb6
--- /dev/null
+++ b/accounts/usbwallet/messages-ethereum.proto
@@ -0,0 +1,133 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.ethereum;
+
+option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessageEthereum";
+
+import "messages-common.proto";
+
+
+/**
+ * Request: Ask device for public key corresponding to address_n path
+ * @start
+ * @next EthereumPublicKey
+ * @next Failure
+ */
+message EthereumGetPublicKey {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bool show_display = 2; // optionally show on display before sending the result
+}
+
+/**
+ * Response: Contains public key derived from device private seed
+ * @end
+ */
+message EthereumPublicKey {
+ optional hw.trezor.messages.common.HDNodeType node = 1; // BIP32 public node
+ optional string xpub = 2; // serialized form of public node
+}
+
+/**
+ * Request: Ask device for Ethereum address corresponding to address_n path
+ * @start
+ * @next EthereumAddress
+ * @next Failure
+ */
+message EthereumGetAddress {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bool show_display = 2; // optionally show on display before sending the result
+}
+
+/**
+ * Response: Contains an Ethereum address derived from device private seed
+ * @end
+ */
+message EthereumAddress {
+ optional bytes addressBin = 1; // Ethereum address as 20 bytes (legacy firmwares)
+ optional string addressHex = 2; // Ethereum address as hex string (newer firmwares)
+}
+
+/**
+ * Request: Ask device to sign transaction
+ * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
+ * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
+ * @start
+ * @next EthereumTxRequest
+ * @next Failure
+ */
+message EthereumSignTx {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bytes nonce = 2; // <=256 bit unsigned big endian
+ optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei)
+ optional bytes gas_limit = 4; // <=256 bit unsigned big endian
+ optional bytes toBin = 5; // recipient address (20 bytes, legacy firmware)
+ optional string toHex = 11; // recipient address (hex string, newer firmware)
+ optional bytes value = 6; // <=256 bit unsigned big endian (in wei)
+ optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes)
+ optional uint32 data_length = 8; // Length of transaction payload
+ optional uint32 chain_id = 9; // Chain Id for EIP 155
+ optional uint32 tx_type = 10; // (only for Wanchain)
+}
+
+/**
+ * Response: Device asks for more data from transaction payload, or returns the signature.
+ * If data_length is set, device awaits that many more bytes of payload.
+ * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
+ * @end
+ * @next EthereumTxAck
+ */
+message EthereumTxRequest {
+ optional uint32 data_length = 1; // Number of bytes being requested (<= 1024)
+ optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28)
+ optional bytes signature_r = 3; // Computed signature R component (256 bit)
+ optional bytes signature_s = 4; // Computed signature S component (256 bit)
+}
+
+/**
+ * Request: Transaction payload data.
+ * @next EthereumTxRequest
+ */
+message EthereumTxAck {
+ optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes)
+}
+
+/**
+ * Request: Ask device to sign message
+ * @start
+ * @next EthereumMessageSignature
+ * @next Failure
+ */
+message EthereumSignMessage {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bytes message = 2; // message to be signed
+}
+
+/**
+ * Response: Signed message
+ * @end
+ */
+message EthereumMessageSignature {
+ optional bytes addressBin = 1; // address used to sign the message (20 bytes, legacy firmware)
+ optional bytes signature = 2; // signature of the message
+ optional string addressHex = 3; // address used to sign the message (hex string, newer firmware)
+}
+
+/**
+ * Request: Ask device to verify message
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message EthereumVerifyMessage {
+ optional bytes addressBin = 1; // address to verify (20 bytes, legacy firmware)
+ optional bytes signature = 2; // signature to verify
+ optional bytes message = 3; // message to verify
+ optional string addressHex = 4; // address to verify (hex string, newer firmware)
+}
diff --git a/accounts/usbwallet/messages-management.pb.go b/accounts/usbwallet/messages-management.pb.go
new file mode 100644
index 0000000000..983e2d281d
--- /dev/null
+++ b/accounts/usbwallet/messages-management.pb.go
@@ -0,0 +1,2276 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.34.2
+// protoc v5.27.1
+// source: messages-management.proto
+
+package trezor
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// *
+// Structure representing passphrase source
+type ApplySettings_PassphraseSourceType int32
+
+const (
+ ApplySettings_ASK ApplySettings_PassphraseSourceType = 0
+ ApplySettings_DEVICE ApplySettings_PassphraseSourceType = 1
+ ApplySettings_HOST ApplySettings_PassphraseSourceType = 2
+)
+
+// Enum value maps for ApplySettings_PassphraseSourceType.
+var (
+ ApplySettings_PassphraseSourceType_name = map[int32]string{
+ 0: "ASK",
+ 1: "DEVICE",
+ 2: "HOST",
+ }
+ ApplySettings_PassphraseSourceType_value = map[string]int32{
+ "ASK": 0,
+ "DEVICE": 1,
+ "HOST": 2,
+ }
+)
+
+func (x ApplySettings_PassphraseSourceType) Enum() *ApplySettings_PassphraseSourceType {
+ p := new(ApplySettings_PassphraseSourceType)
+ *p = x
+ return p
+}
+
+func (x ApplySettings_PassphraseSourceType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (ApplySettings_PassphraseSourceType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_management_proto_enumTypes[0].Descriptor()
+}
+
+func (ApplySettings_PassphraseSourceType) Type() protoreflect.EnumType {
+ return &file_messages_management_proto_enumTypes[0]
+}
+
+func (x ApplySettings_PassphraseSourceType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *ApplySettings_PassphraseSourceType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = ApplySettings_PassphraseSourceType(num)
+ return nil
+}
+
+// Deprecated: Use ApplySettings_PassphraseSourceType.Descriptor instead.
+func (ApplySettings_PassphraseSourceType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{4, 0}
+}
+
+// *
+// Type of recovery procedure. These should be used as bitmask, e.g.,
+// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+// listing every method supported by the host computer.
+//
+// Note that ScrambledWords must be supported by every implementation
+// for backward compatibility; there is no way to not support it.
+type RecoveryDevice_RecoveryDeviceType int32
+
+const (
+ // use powers of two when extending this field
+ RecoveryDevice_RecoveryDeviceType_ScrambledWords RecoveryDevice_RecoveryDeviceType = 0 // words in scrambled order
+ RecoveryDevice_RecoveryDeviceType_Matrix RecoveryDevice_RecoveryDeviceType = 1 // matrix recovery type
+)
+
+// Enum value maps for RecoveryDevice_RecoveryDeviceType.
+var (
+ RecoveryDevice_RecoveryDeviceType_name = map[int32]string{
+ 0: "RecoveryDeviceType_ScrambledWords",
+ 1: "RecoveryDeviceType_Matrix",
+ }
+ RecoveryDevice_RecoveryDeviceType_value = map[string]int32{
+ "RecoveryDeviceType_ScrambledWords": 0,
+ "RecoveryDeviceType_Matrix": 1,
+ }
+)
+
+func (x RecoveryDevice_RecoveryDeviceType) Enum() *RecoveryDevice_RecoveryDeviceType {
+ p := new(RecoveryDevice_RecoveryDeviceType)
+ *p = x
+ return p
+}
+
+func (x RecoveryDevice_RecoveryDeviceType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (RecoveryDevice_RecoveryDeviceType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_management_proto_enumTypes[1].Descriptor()
+}
+
+func (RecoveryDevice_RecoveryDeviceType) Type() protoreflect.EnumType {
+ return &file_messages_management_proto_enumTypes[1]
+}
+
+func (x RecoveryDevice_RecoveryDeviceType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *RecoveryDevice_RecoveryDeviceType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = RecoveryDevice_RecoveryDeviceType(num)
+ return nil
+}
+
+// Deprecated: Use RecoveryDevice_RecoveryDeviceType.Descriptor instead.
+func (RecoveryDevice_RecoveryDeviceType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{17, 0}
+}
+
+// *
+// Type of Recovery Word request
+type WordRequest_WordRequestType int32
+
+const (
+ WordRequest_WordRequestType_Plain WordRequest_WordRequestType = 0
+ WordRequest_WordRequestType_Matrix9 WordRequest_WordRequestType = 1
+ WordRequest_WordRequestType_Matrix6 WordRequest_WordRequestType = 2
+)
+
+// Enum value maps for WordRequest_WordRequestType.
+var (
+ WordRequest_WordRequestType_name = map[int32]string{
+ 0: "WordRequestType_Plain",
+ 1: "WordRequestType_Matrix9",
+ 2: "WordRequestType_Matrix6",
+ }
+ WordRequest_WordRequestType_value = map[string]int32{
+ "WordRequestType_Plain": 0,
+ "WordRequestType_Matrix9": 1,
+ "WordRequestType_Matrix6": 2,
+ }
+)
+
+func (x WordRequest_WordRequestType) Enum() *WordRequest_WordRequestType {
+ p := new(WordRequest_WordRequestType)
+ *p = x
+ return p
+}
+
+func (x WordRequest_WordRequestType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (WordRequest_WordRequestType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_management_proto_enumTypes[2].Descriptor()
+}
+
+func (WordRequest_WordRequestType) Type() protoreflect.EnumType {
+ return &file_messages_management_proto_enumTypes[2]
+}
+
+func (x WordRequest_WordRequestType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *WordRequest_WordRequestType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = WordRequest_WordRequestType(num)
+ return nil
+}
+
+// Deprecated: Use WordRequest_WordRequestType.Descriptor instead.
+func (WordRequest_WordRequestType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{18, 0}
+}
+
+// *
+// Request: Reset device to default state and ask for device details
+// @start
+// @next Features
+type Initialize struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` // assumed device state, clear session if set and different
+ SkipPassphrase *bool `protobuf:"varint,2,opt,name=skip_passphrase,json=skipPassphrase" json:"skip_passphrase,omitempty"` // this session should always assume empty passphrase
+}
+
+func (x *Initialize) Reset() {
+ *x = Initialize{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Initialize) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Initialize) ProtoMessage() {}
+
+func (x *Initialize) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Initialize.ProtoReflect.Descriptor instead.
+func (*Initialize) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Initialize) GetState() []byte {
+ if x != nil {
+ return x.State
+ }
+ return nil
+}
+
+func (x *Initialize) GetSkipPassphrase() bool {
+ if x != nil && x.SkipPassphrase != nil {
+ return *x.SkipPassphrase
+ }
+ return false
+}
+
+// *
+// Request: Ask for device details (no device reset)
+// @start
+// @next Features
+type GetFeatures struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *GetFeatures) Reset() {
+ *x = GetFeatures{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetFeatures) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetFeatures) ProtoMessage() {}
+
+func (x *GetFeatures) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetFeatures.ProtoReflect.Descriptor instead.
+func (*GetFeatures) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{1}
+}
+
+// *
+// Response: Reports various information about the device
+// @end
+type Features struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` // name of the manufacturer, e.g. "trezor.io"
+ MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` // major version of the firmware/bootloader, e.g. 1
+ MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` // minor version of the firmware/bootloader, e.g. 0
+ PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` // patch version of the firmware/bootloader, e.g. 0
+ BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` // is device in bootloader mode?
+ DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` // device's unique identifier
+ PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // is device protected by PIN?
+ PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // is node/mnemonic encrypted using passphrase?
+ Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` // device language
+ Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` // device description label
+ Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` // does device contain seed?
+ Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` // SCM revision of firmware
+ BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` // hash of the bootloader
+ Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` // was storage imported from an external source?
+ PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` // is PIN already cached in session?
+ PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` // is passphrase already cached in session?
+ FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` // is valid firmware loaded?
+ NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` // does storage need backup? (equals to Storage.needs_backup)
+ Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` // device flags (equals to Storage.flags)
+ Model *string `protobuf:"bytes,21,opt,name=model" json:"model,omitempty"` // device hardware model
+ FwMajor *uint32 `protobuf:"varint,22,opt,name=fw_major,json=fwMajor" json:"fw_major,omitempty"` // reported firmware version if in bootloader mode
+ FwMinor *uint32 `protobuf:"varint,23,opt,name=fw_minor,json=fwMinor" json:"fw_minor,omitempty"` // reported firmware version if in bootloader mode
+ FwPatch *uint32 `protobuf:"varint,24,opt,name=fw_patch,json=fwPatch" json:"fw_patch,omitempty"` // reported firmware version if in bootloader mode
+ FwVendor *string `protobuf:"bytes,25,opt,name=fw_vendor,json=fwVendor" json:"fw_vendor,omitempty"` // reported firmware vendor if in bootloader mode
+ FwVendorKeys []byte `protobuf:"bytes,26,opt,name=fw_vendor_keys,json=fwVendorKeys" json:"fw_vendor_keys,omitempty"` // reported firmware vendor keys (their hash)
+ UnfinishedBackup *bool `protobuf:"varint,27,opt,name=unfinished_backup,json=unfinishedBackup" json:"unfinished_backup,omitempty"` // report unfinished backup (equals to Storage.unfinished_backup)
+ NoBackup *bool `protobuf:"varint,28,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` // report no backup (equals to Storage.no_backup)
+}
+
+func (x *Features) Reset() {
+ *x = Features{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Features) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Features) ProtoMessage() {}
+
+func (x *Features) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Features.ProtoReflect.Descriptor instead.
+func (*Features) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Features) GetVendor() string {
+ if x != nil && x.Vendor != nil {
+ return *x.Vendor
+ }
+ return ""
+}
+
+func (x *Features) GetMajorVersion() uint32 {
+ if x != nil && x.MajorVersion != nil {
+ return *x.MajorVersion
+ }
+ return 0
+}
+
+func (x *Features) GetMinorVersion() uint32 {
+ if x != nil && x.MinorVersion != nil {
+ return *x.MinorVersion
+ }
+ return 0
+}
+
+func (x *Features) GetPatchVersion() uint32 {
+ if x != nil && x.PatchVersion != nil {
+ return *x.PatchVersion
+ }
+ return 0
+}
+
+func (x *Features) GetBootloaderMode() bool {
+ if x != nil && x.BootloaderMode != nil {
+ return *x.BootloaderMode
+ }
+ return false
+}
+
+func (x *Features) GetDeviceId() string {
+ if x != nil && x.DeviceId != nil {
+ return *x.DeviceId
+ }
+ return ""
+}
+
+func (x *Features) GetPinProtection() bool {
+ if x != nil && x.PinProtection != nil {
+ return *x.PinProtection
+ }
+ return false
+}
+
+func (x *Features) GetPassphraseProtection() bool {
+ if x != nil && x.PassphraseProtection != nil {
+ return *x.PassphraseProtection
+ }
+ return false
+}
+
+func (x *Features) GetLanguage() string {
+ if x != nil && x.Language != nil {
+ return *x.Language
+ }
+ return ""
+}
+
+func (x *Features) GetLabel() string {
+ if x != nil && x.Label != nil {
+ return *x.Label
+ }
+ return ""
+}
+
+func (x *Features) GetInitialized() bool {
+ if x != nil && x.Initialized != nil {
+ return *x.Initialized
+ }
+ return false
+}
+
+func (x *Features) GetRevision() []byte {
+ if x != nil {
+ return x.Revision
+ }
+ return nil
+}
+
+func (x *Features) GetBootloaderHash() []byte {
+ if x != nil {
+ return x.BootloaderHash
+ }
+ return nil
+}
+
+func (x *Features) GetImported() bool {
+ if x != nil && x.Imported != nil {
+ return *x.Imported
+ }
+ return false
+}
+
+func (x *Features) GetPinCached() bool {
+ if x != nil && x.PinCached != nil {
+ return *x.PinCached
+ }
+ return false
+}
+
+func (x *Features) GetPassphraseCached() bool {
+ if x != nil && x.PassphraseCached != nil {
+ return *x.PassphraseCached
+ }
+ return false
+}
+
+func (x *Features) GetFirmwarePresent() bool {
+ if x != nil && x.FirmwarePresent != nil {
+ return *x.FirmwarePresent
+ }
+ return false
+}
+
+func (x *Features) GetNeedsBackup() bool {
+ if x != nil && x.NeedsBackup != nil {
+ return *x.NeedsBackup
+ }
+ return false
+}
+
+func (x *Features) GetFlags() uint32 {
+ if x != nil && x.Flags != nil {
+ return *x.Flags
+ }
+ return 0
+}
+
+func (x *Features) GetModel() string {
+ if x != nil && x.Model != nil {
+ return *x.Model
+ }
+ return ""
+}
+
+func (x *Features) GetFwMajor() uint32 {
+ if x != nil && x.FwMajor != nil {
+ return *x.FwMajor
+ }
+ return 0
+}
+
+func (x *Features) GetFwMinor() uint32 {
+ if x != nil && x.FwMinor != nil {
+ return *x.FwMinor
+ }
+ return 0
+}
+
+func (x *Features) GetFwPatch() uint32 {
+ if x != nil && x.FwPatch != nil {
+ return *x.FwPatch
+ }
+ return 0
+}
+
+func (x *Features) GetFwVendor() string {
+ if x != nil && x.FwVendor != nil {
+ return *x.FwVendor
+ }
+ return ""
+}
+
+func (x *Features) GetFwVendorKeys() []byte {
+ if x != nil {
+ return x.FwVendorKeys
+ }
+ return nil
+}
+
+func (x *Features) GetUnfinishedBackup() bool {
+ if x != nil && x.UnfinishedBackup != nil {
+ return *x.UnfinishedBackup
+ }
+ return false
+}
+
+func (x *Features) GetNoBackup() bool {
+ if x != nil && x.NoBackup != nil {
+ return *x.NoBackup
+ }
+ return false
+}
+
+// *
+// Request: clear session (removes cached PIN, passphrase, etc).
+// @start
+// @next Success
+type ClearSession struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *ClearSession) Reset() {
+ *x = ClearSession{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ClearSession) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ClearSession) ProtoMessage() {}
+
+func (x *ClearSession) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ClearSession.ProtoReflect.Descriptor instead.
+func (*ClearSession) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{3}
+}
+
+// *
+// Request: change language and/or label of the device
+// @start
+// @next Success
+// @next Failure
+type ApplySettings struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"`
+ UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"`
+ Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"`
+ PassphraseSource *ApplySettings_PassphraseSourceType `protobuf:"varint,5,opt,name=passphrase_source,json=passphraseSource,enum=hw.trezor.messages.management.ApplySettings_PassphraseSourceType" json:"passphrase_source,omitempty"`
+ AutoLockDelayMs *uint32 `protobuf:"varint,6,opt,name=auto_lock_delay_ms,json=autoLockDelayMs" json:"auto_lock_delay_ms,omitempty"`
+ DisplayRotation *uint32 `protobuf:"varint,7,opt,name=display_rotation,json=displayRotation" json:"display_rotation,omitempty"` // in degrees from North
+}
+
+func (x *ApplySettings) Reset() {
+ *x = ApplySettings{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ApplySettings) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ApplySettings) ProtoMessage() {}
+
+func (x *ApplySettings) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ApplySettings.ProtoReflect.Descriptor instead.
+func (*ApplySettings) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ApplySettings) GetLanguage() string {
+ if x != nil && x.Language != nil {
+ return *x.Language
+ }
+ return ""
+}
+
+func (x *ApplySettings) GetLabel() string {
+ if x != nil && x.Label != nil {
+ return *x.Label
+ }
+ return ""
+}
+
+func (x *ApplySettings) GetUsePassphrase() bool {
+ if x != nil && x.UsePassphrase != nil {
+ return *x.UsePassphrase
+ }
+ return false
+}
+
+func (x *ApplySettings) GetHomescreen() []byte {
+ if x != nil {
+ return x.Homescreen
+ }
+ return nil
+}
+
+func (x *ApplySettings) GetPassphraseSource() ApplySettings_PassphraseSourceType {
+ if x != nil && x.PassphraseSource != nil {
+ return *x.PassphraseSource
+ }
+ return ApplySettings_ASK
+}
+
+func (x *ApplySettings) GetAutoLockDelayMs() uint32 {
+ if x != nil && x.AutoLockDelayMs != nil {
+ return *x.AutoLockDelayMs
+ }
+ return 0
+}
+
+func (x *ApplySettings) GetDisplayRotation() uint32 {
+ if x != nil && x.DisplayRotation != nil {
+ return *x.DisplayRotation
+ }
+ return 0
+}
+
+// *
+// Request: set flags of the device
+// @start
+// @next Success
+// @next Failure
+type ApplyFlags struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` // bitmask, can only set bits, not unset
+}
+
+func (x *ApplyFlags) Reset() {
+ *x = ApplyFlags{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ApplyFlags) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ApplyFlags) ProtoMessage() {}
+
+func (x *ApplyFlags) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ApplyFlags.ProtoReflect.Descriptor instead.
+func (*ApplyFlags) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *ApplyFlags) GetFlags() uint32 {
+ if x != nil && x.Flags != nil {
+ return *x.Flags
+ }
+ return 0
+}
+
+// *
+// Request: Starts workflow for setting/changing/removing the PIN
+// @start
+// @next Success
+// @next Failure
+type ChangePin struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` // is PIN removal requested?
+}
+
+func (x *ChangePin) Reset() {
+ *x = ChangePin{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ChangePin) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ChangePin) ProtoMessage() {}
+
+func (x *ChangePin) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ChangePin.ProtoReflect.Descriptor instead.
+func (*ChangePin) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ChangePin) GetRemove() bool {
+ if x != nil && x.Remove != nil {
+ return *x.Remove
+ }
+ return false
+}
+
+// *
+// Request: Test if the device is alive, device sends back the message in Success response
+// @start
+// @next Success
+type Ping struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` // message to send back in Success message
+ ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` // ask for button press
+ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // ask for PIN if set in device
+ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // ask for passphrase if set in device
+}
+
+func (x *Ping) Reset() {
+ *x = Ping{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Ping) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Ping) ProtoMessage() {}
+
+func (x *Ping) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[7]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Ping.ProtoReflect.Descriptor instead.
+func (*Ping) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *Ping) GetMessage() string {
+ if x != nil && x.Message != nil {
+ return *x.Message
+ }
+ return ""
+}
+
+func (x *Ping) GetButtonProtection() bool {
+ if x != nil && x.ButtonProtection != nil {
+ return *x.ButtonProtection
+ }
+ return false
+}
+
+func (x *Ping) GetPinProtection() bool {
+ if x != nil && x.PinProtection != nil {
+ return *x.PinProtection
+ }
+ return false
+}
+
+func (x *Ping) GetPassphraseProtection() bool {
+ if x != nil && x.PassphraseProtection != nil {
+ return *x.PassphraseProtection
+ }
+ return false
+}
+
+// *
+// Request: Abort last operation that required user interaction
+// @start
+// @next Failure
+type Cancel struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *Cancel) Reset() {
+ *x = Cancel{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Cancel) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Cancel) ProtoMessage() {}
+
+func (x *Cancel) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[8]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Cancel.ProtoReflect.Descriptor instead.
+func (*Cancel) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{8}
+}
+
+// *
+// Request: Request a sample of random data generated by hardware RNG. May be used for testing.
+// @start
+// @next Entropy
+// @next Failure
+type GetEntropy struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` // size of requested entropy
+}
+
+func (x *GetEntropy) Reset() {
+ *x = GetEntropy{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetEntropy) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetEntropy) ProtoMessage() {}
+
+func (x *GetEntropy) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[9]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetEntropy.ProtoReflect.Descriptor instead.
+func (*GetEntropy) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *GetEntropy) GetSize() uint32 {
+ if x != nil && x.Size != nil {
+ return *x.Size
+ }
+ return 0
+}
+
+// *
+// Response: Reply with random data generated by internal RNG
+// @end
+type Entropy struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` // chunk of random generated bytes
+}
+
+func (x *Entropy) Reset() {
+ *x = Entropy{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Entropy) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Entropy) ProtoMessage() {}
+
+func (x *Entropy) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[10]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Entropy.ProtoReflect.Descriptor instead.
+func (*Entropy) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *Entropy) GetEntropy() []byte {
+ if x != nil {
+ return x.Entropy
+ }
+ return nil
+}
+
+// *
+// Request: Request device to wipe all sensitive data and settings
+// @start
+// @next Success
+// @next Failure
+type WipeDevice struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *WipeDevice) Reset() {
+ *x = WipeDevice{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *WipeDevice) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WipeDevice) ProtoMessage() {}
+
+func (x *WipeDevice) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WipeDevice.ProtoReflect.Descriptor instead.
+func (*WipeDevice) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{11}
+}
+
+// *
+// Request: Load seed and related internal settings from the computer
+// @start
+// @next Success
+// @next Failure
+type LoadDevice struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` // seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
+ Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` // BIP-32 node
+ Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` // set PIN protection
+ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
+ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` // device language
+ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` // device label
+ SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` // do not test mnemonic for valid BIP-39 checksum
+ U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
+}
+
+// Default values for LoadDevice fields.
+const (
+ Default_LoadDevice_Language = string("english")
+)
+
+func (x *LoadDevice) Reset() {
+ *x = LoadDevice{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *LoadDevice) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*LoadDevice) ProtoMessage() {}
+
+func (x *LoadDevice) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use LoadDevice.ProtoReflect.Descriptor instead.
+func (*LoadDevice) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *LoadDevice) GetMnemonic() string {
+ if x != nil && x.Mnemonic != nil {
+ return *x.Mnemonic
+ }
+ return ""
+}
+
+func (x *LoadDevice) GetNode() *HDNodeType {
+ if x != nil {
+ return x.Node
+ }
+ return nil
+}
+
+func (x *LoadDevice) GetPin() string {
+ if x != nil && x.Pin != nil {
+ return *x.Pin
+ }
+ return ""
+}
+
+func (x *LoadDevice) GetPassphraseProtection() bool {
+ if x != nil && x.PassphraseProtection != nil {
+ return *x.PassphraseProtection
+ }
+ return false
+}
+
+func (x *LoadDevice) GetLanguage() string {
+ if x != nil && x.Language != nil {
+ return *x.Language
+ }
+ return Default_LoadDevice_Language
+}
+
+func (x *LoadDevice) GetLabel() string {
+ if x != nil && x.Label != nil {
+ return *x.Label
+ }
+ return ""
+}
+
+func (x *LoadDevice) GetSkipChecksum() bool {
+ if x != nil && x.SkipChecksum != nil {
+ return *x.SkipChecksum
+ }
+ return false
+}
+
+func (x *LoadDevice) GetU2FCounter() uint32 {
+ if x != nil && x.U2FCounter != nil {
+ return *x.U2FCounter
+ }
+ return 0
+}
+
+// *
+// Request: Ask device to do initialization involving user interaction
+// @start
+// @next EntropyRequest
+// @next Failure
+type ResetDevice struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` // display entropy generated by the device before asking for additional entropy
+ Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` // strength of seed in bits
+ PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
+ PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // enable PIN protection
+ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` // device language
+ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` // device label
+ U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
+ SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` // postpone seed backup to BackupDevice workflow
+ NoBackup *bool `protobuf:"varint,9,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` // indicate that no backup is going to be made
+}
+
+// Default values for ResetDevice fields.
+const (
+ Default_ResetDevice_Strength = uint32(256)
+ Default_ResetDevice_Language = string("english")
+)
+
+func (x *ResetDevice) Reset() {
+ *x = ResetDevice{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ResetDevice) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ResetDevice) ProtoMessage() {}
+
+func (x *ResetDevice) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[13]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ResetDevice.ProtoReflect.Descriptor instead.
+func (*ResetDevice) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *ResetDevice) GetDisplayRandom() bool {
+ if x != nil && x.DisplayRandom != nil {
+ return *x.DisplayRandom
+ }
+ return false
+}
+
+func (x *ResetDevice) GetStrength() uint32 {
+ if x != nil && x.Strength != nil {
+ return *x.Strength
+ }
+ return Default_ResetDevice_Strength
+}
+
+func (x *ResetDevice) GetPassphraseProtection() bool {
+ if x != nil && x.PassphraseProtection != nil {
+ return *x.PassphraseProtection
+ }
+ return false
+}
+
+func (x *ResetDevice) GetPinProtection() bool {
+ if x != nil && x.PinProtection != nil {
+ return *x.PinProtection
+ }
+ return false
+}
+
+func (x *ResetDevice) GetLanguage() string {
+ if x != nil && x.Language != nil {
+ return *x.Language
+ }
+ return Default_ResetDevice_Language
+}
+
+func (x *ResetDevice) GetLabel() string {
+ if x != nil && x.Label != nil {
+ return *x.Label
+ }
+ return ""
+}
+
+func (x *ResetDevice) GetU2FCounter() uint32 {
+ if x != nil && x.U2FCounter != nil {
+ return *x.U2FCounter
+ }
+ return 0
+}
+
+func (x *ResetDevice) GetSkipBackup() bool {
+ if x != nil && x.SkipBackup != nil {
+ return *x.SkipBackup
+ }
+ return false
+}
+
+func (x *ResetDevice) GetNoBackup() bool {
+ if x != nil && x.NoBackup != nil {
+ return *x.NoBackup
+ }
+ return false
+}
+
+// *
+// Request: Perform backup of the device seed if not backed up using ResetDevice
+// @start
+// @next Success
+type BackupDevice struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *BackupDevice) Reset() {
+ *x = BackupDevice{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BackupDevice) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BackupDevice) ProtoMessage() {}
+
+func (x *BackupDevice) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[14]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BackupDevice.ProtoReflect.Descriptor instead.
+func (*BackupDevice) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{14}
+}
+
+// *
+// Response: Ask for additional entropy from host computer
+// @next EntropyAck
+type EntropyRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *EntropyRequest) Reset() {
+ *x = EntropyRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[15]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EntropyRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EntropyRequest) ProtoMessage() {}
+
+func (x *EntropyRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[15]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EntropyRequest.ProtoReflect.Descriptor instead.
+func (*EntropyRequest) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{15}
+}
+
+// *
+// Request: Provide additional entropy for seed generation function
+// @next Success
+type EntropyAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` // 256 bits (32 bytes) of random data
+}
+
+func (x *EntropyAck) Reset() {
+ *x = EntropyAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[16]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EntropyAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EntropyAck) ProtoMessage() {}
+
+func (x *EntropyAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[16]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EntropyAck.ProtoReflect.Descriptor instead.
+func (*EntropyAck) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *EntropyAck) GetEntropy() []byte {
+ if x != nil {
+ return x.Entropy
+ }
+ return nil
+}
+
+// *
+// Request: Start recovery workflow asking user for specific words of mnemonic
+// Used to recovery device safely even on untrusted computer.
+// @start
+// @next WordRequest
+type RecoveryDevice struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` // number of words in BIP-39 mnemonic
+ PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
+ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // enable PIN protection
+ Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` // device language
+ Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` // device label
+ EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` // enforce BIP-39 wordlist during the process
+ // 7 reserved for unused recovery method
+ Type *RecoveryDevice_RecoveryDeviceType `protobuf:"varint,8,opt,name=type,enum=hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType" json:"type,omitempty"` // supported recovery type
+ U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
+ DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` // perform dry-run recovery workflow (for safe mnemonic validation)
+}
+
+// Default values for RecoveryDevice fields.
+const (
+ Default_RecoveryDevice_Language = string("english")
+)
+
+func (x *RecoveryDevice) Reset() {
+ *x = RecoveryDevice{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[17]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *RecoveryDevice) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RecoveryDevice) ProtoMessage() {}
+
+func (x *RecoveryDevice) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[17]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use RecoveryDevice.ProtoReflect.Descriptor instead.
+func (*RecoveryDevice) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *RecoveryDevice) GetWordCount() uint32 {
+ if x != nil && x.WordCount != nil {
+ return *x.WordCount
+ }
+ return 0
+}
+
+func (x *RecoveryDevice) GetPassphraseProtection() bool {
+ if x != nil && x.PassphraseProtection != nil {
+ return *x.PassphraseProtection
+ }
+ return false
+}
+
+func (x *RecoveryDevice) GetPinProtection() bool {
+ if x != nil && x.PinProtection != nil {
+ return *x.PinProtection
+ }
+ return false
+}
+
+func (x *RecoveryDevice) GetLanguage() string {
+ if x != nil && x.Language != nil {
+ return *x.Language
+ }
+ return Default_RecoveryDevice_Language
+}
+
+func (x *RecoveryDevice) GetLabel() string {
+ if x != nil && x.Label != nil {
+ return *x.Label
+ }
+ return ""
+}
+
+func (x *RecoveryDevice) GetEnforceWordlist() bool {
+ if x != nil && x.EnforceWordlist != nil {
+ return *x.EnforceWordlist
+ }
+ return false
+}
+
+func (x *RecoveryDevice) GetType() RecoveryDevice_RecoveryDeviceType {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return RecoveryDevice_RecoveryDeviceType_ScrambledWords
+}
+
+func (x *RecoveryDevice) GetU2FCounter() uint32 {
+ if x != nil && x.U2FCounter != nil {
+ return *x.U2FCounter
+ }
+ return 0
+}
+
+func (x *RecoveryDevice) GetDryRun() bool {
+ if x != nil && x.DryRun != nil {
+ return *x.DryRun
+ }
+ return false
+}
+
+// *
+// Response: Device is waiting for user to enter word of the mnemonic
+// Its position is shown only on device's internal display.
+// @next WordAck
+type WordRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Type *WordRequest_WordRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.management.WordRequest_WordRequestType" json:"type,omitempty"`
+}
+
+func (x *WordRequest) Reset() {
+ *x = WordRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[18]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *WordRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WordRequest) ProtoMessage() {}
+
+func (x *WordRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[18]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WordRequest.ProtoReflect.Descriptor instead.
+func (*WordRequest) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *WordRequest) GetType() WordRequest_WordRequestType {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return WordRequest_WordRequestType_Plain
+}
+
+// *
+// Request: Computer replies with word from the mnemonic
+// @next WordRequest
+// @next Success
+// @next Failure
+type WordAck struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` // one word of mnemonic on asked position
+}
+
+func (x *WordAck) Reset() {
+ *x = WordAck{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *WordAck) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WordAck) ProtoMessage() {}
+
+func (x *WordAck) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WordAck.ProtoReflect.Descriptor instead.
+func (*WordAck) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *WordAck) GetWord() string {
+ if x != nil && x.Word != nil {
+ return *x.Word
+ }
+ return ""
+}
+
+// *
+// Request: Set U2F counter
+// @start
+// @next Success
+type SetU2FCounter struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // counter
+}
+
+func (x *SetU2FCounter) Reset() {
+ *x = SetU2FCounter{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_messages_management_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SetU2FCounter) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SetU2FCounter) ProtoMessage() {}
+
+func (x *SetU2FCounter) ProtoReflect() protoreflect.Message {
+ mi := &file_messages_management_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SetU2FCounter.ProtoReflect.Descriptor instead.
+func (*SetU2FCounter) Descriptor() ([]byte, []int) {
+ return file_messages_management_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *SetU2FCounter) GetU2FCounter() uint32 {
+ if x != nil && x.U2FCounter != nil {
+ return *x.U2FCounter
+ }
+ return 0
+}
+
+var File_messages_management_proto protoreflect.FileDescriptor
+
+var file_messages_management_proto_rawDesc = []byte{
+ 0x0a, 0x19, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x77, 0x2e,
+ 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e,
+ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x15, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x22, 0x4b, 0x0a, 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12,
+ 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x70, 0x61,
+ 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e,
+ 0x73, 0x6b, 0x69, 0x70, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x0d,
+ 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x8c, 0x07,
+ 0x0a, 0x08, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65,
+ 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, 0x6e, 0x64,
+ 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
+ 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
+ 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d,
+ 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f,
+ 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x62, 0x6f, 0x6f, 0x74,
+ 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65,
+ 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64,
+ 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70,
+ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33,
+ 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x70,
+ 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18,
+ 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12,
+ 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
+ 0x69, 0x7a, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74,
+ 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73,
+ 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65,
+ 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x62, 0x6f,
+ 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1a, 0x0a, 0x08,
+ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
+ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x6e, 0x5f,
+ 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x69,
+ 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x61, 0x73, 0x73, 0x70,
+ 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x11, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x10, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x43, 0x61,
+ 0x63, 0x68, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65,
+ 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
+ 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12,
+ 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18,
+ 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x61, 0x63, 0x6b,
+ 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x19,
+ 0x0a, 0x08, 0x66, 0x77, 0x5f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x07, 0x66, 0x77, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x5f,
+ 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x77, 0x4d,
+ 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68,
+ 0x18, 0x18, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x77, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12,
+ 0x1b, 0x0a, 0x09, 0x66, 0x77, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x19, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x66, 0x77, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x0e,
+ 0x66, 0x77, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x1a,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x66, 0x77, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4b, 0x65,
+ 0x79, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x75, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
+ 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75,
+ 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12,
+ 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x1c, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x0e, 0x0a, 0x0c,
+ 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x87, 0x03, 0x0a,
+ 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1a,
+ 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61,
+ 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c,
+ 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61,
+ 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x50, 0x61, 0x73,
+ 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x6f, 0x6d, 0x65, 0x73,
+ 0x63, 0x72, 0x65, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x6f, 0x6d,
+ 0x65, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x12, 0x6e, 0x0a, 0x11, 0x70, 0x61, 0x73, 0x73, 0x70,
+ 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x41, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
+ 0x2e, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x10, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
+ 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x6f, 0x5f,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c,
+ 0x61, 0x79, 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f,
+ 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
+ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
+ 0x35, 0x0a, 0x14, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x53, 0x4b, 0x10, 0x00,
+ 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04,
+ 0x48, 0x4f, 0x53, 0x54, 0x10, 0x02, 0x22, 0x22, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46,
+ 0x6c, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x23, 0x0a, 0x09, 0x43, 0x68,
+ 0x61, 0x6e, 0x67, 0x65, 0x50, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22,
+ 0xa9, 0x01, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+ 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68,
+ 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
+ 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x08, 0x0a, 0x06, 0x43,
+ 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x22, 0x20, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72,
+ 0x6f, 0x70, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x23, 0x0a, 0x07, 0x45, 0x6e, 0x74, 0x72, 0x6f,
+ 0x70, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x18, 0x01, 0x20,
+ 0x02, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x22, 0x0c, 0x0a, 0x0a,
+ 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0xab, 0x02, 0x0a, 0x0a, 0x4c,
+ 0x6f, 0x61, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6e, 0x65,
+ 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6e, 0x65,
+ 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
+ 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65,
+ 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70,
+ 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65,
+ 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75,
+ 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x07, 0x65, 0x6e, 0x67, 0x6c, 0x69,
+ 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05,
+ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62,
+ 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x73, 0x75, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x43,
+ 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x32,
+ 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0xcb, 0x02, 0x0a, 0x0b, 0x52, 0x65, 0x73,
+ 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x70,
+ 0x6c, 0x61, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x12,
+ 0x1f, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0d, 0x3a, 0x03, 0x32, 0x35, 0x36, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68,
+ 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70,
+ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70,
+ 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08,
+ 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x07,
+ 0x65, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
+ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x32,
+ 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70,
+ 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73,
+ 0x6b, 0x69, 0x70, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f,
+ 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f,
+ 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x0e, 0x0a, 0x0c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
+ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70,
+ 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x26, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x72,
+ 0x6f, 0x70, 0x79, 0x41, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79,
+ 0x22, 0xdd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76,
+ 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65,
+ 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70,
+ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23,
+ 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+ 0x3a, 0x07, 0x65, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75,
+ 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x66,
+ 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x57, 0x6f, 0x72, 0x64,
+ 0x6c, 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x40, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63,
+ 0x65, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32,
+ 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x0a, 0x75, 0x32, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x64,
+ 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72,
+ 0x79, 0x52, 0x75, 0x6e, 0x22, 0x5a, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
+ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x52, 0x65,
+ 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x53, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x64, 0x73, 0x10,
+ 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76,
+ 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x10, 0x01,
+ 0x22, 0xc5, 0x01, 0x0a, 0x0b, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x4e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a,
+ 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57,
+ 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x64, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
+ 0x22, 0x66, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x00, 0x12, 0x1b,
+ 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x39, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x57,
+ 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d,
+ 0x61, 0x74, 0x72, 0x69, 0x78, 0x36, 0x10, 0x02, 0x22, 0x1d, 0x0a, 0x07, 0x57, 0x6f, 0x72, 0x64,
+ 0x41, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28,
+ 0x09, 0x52, 0x04, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x30, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x55, 0x32,
+ 0x46, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75,
+ 0x32, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x42, 0x79, 0x0a, 0x23, 0x63, 0x6f, 0x6d,
+ 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74, 0x72, 0x65,
+ 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x42, 0x17, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75,
+ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67,
+ 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72,
+ 0x65, 0x7a, 0x6f, 0x72,
+}
+
+var (
+ file_messages_management_proto_rawDescOnce sync.Once
+ file_messages_management_proto_rawDescData = file_messages_management_proto_rawDesc
+)
+
+func file_messages_management_proto_rawDescGZIP() []byte {
+ file_messages_management_proto_rawDescOnce.Do(func() {
+ file_messages_management_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_management_proto_rawDescData)
+ })
+ return file_messages_management_proto_rawDescData
+}
+
+var file_messages_management_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_messages_management_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_messages_management_proto_goTypes = []any{
+ (ApplySettings_PassphraseSourceType)(0), // 0: hw.trezor.messages.management.ApplySettings.PassphraseSourceType
+ (RecoveryDevice_RecoveryDeviceType)(0), // 1: hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType
+ (WordRequest_WordRequestType)(0), // 2: hw.trezor.messages.management.WordRequest.WordRequestType
+ (*Initialize)(nil), // 3: hw.trezor.messages.management.Initialize
+ (*GetFeatures)(nil), // 4: hw.trezor.messages.management.GetFeatures
+ (*Features)(nil), // 5: hw.trezor.messages.management.Features
+ (*ClearSession)(nil), // 6: hw.trezor.messages.management.ClearSession
+ (*ApplySettings)(nil), // 7: hw.trezor.messages.management.ApplySettings
+ (*ApplyFlags)(nil), // 8: hw.trezor.messages.management.ApplyFlags
+ (*ChangePin)(nil), // 9: hw.trezor.messages.management.ChangePin
+ (*Ping)(nil), // 10: hw.trezor.messages.management.Ping
+ (*Cancel)(nil), // 11: hw.trezor.messages.management.Cancel
+ (*GetEntropy)(nil), // 12: hw.trezor.messages.management.GetEntropy
+ (*Entropy)(nil), // 13: hw.trezor.messages.management.Entropy
+ (*WipeDevice)(nil), // 14: hw.trezor.messages.management.WipeDevice
+ (*LoadDevice)(nil), // 15: hw.trezor.messages.management.LoadDevice
+ (*ResetDevice)(nil), // 16: hw.trezor.messages.management.ResetDevice
+ (*BackupDevice)(nil), // 17: hw.trezor.messages.management.BackupDevice
+ (*EntropyRequest)(nil), // 18: hw.trezor.messages.management.EntropyRequest
+ (*EntropyAck)(nil), // 19: hw.trezor.messages.management.EntropyAck
+ (*RecoveryDevice)(nil), // 20: hw.trezor.messages.management.RecoveryDevice
+ (*WordRequest)(nil), // 21: hw.trezor.messages.management.WordRequest
+ (*WordAck)(nil), // 22: hw.trezor.messages.management.WordAck
+ (*SetU2FCounter)(nil), // 23: hw.trezor.messages.management.SetU2FCounter
+ (*HDNodeType)(nil), // 24: hw.trezor.messages.common.HDNodeType
+}
+var file_messages_management_proto_depIdxs = []int32{
+ 0, // 0: hw.trezor.messages.management.ApplySettings.passphrase_source:type_name -> hw.trezor.messages.management.ApplySettings.PassphraseSourceType
+ 24, // 1: hw.trezor.messages.management.LoadDevice.node:type_name -> hw.trezor.messages.common.HDNodeType
+ 1, // 2: hw.trezor.messages.management.RecoveryDevice.type:type_name -> hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType
+ 2, // 3: hw.trezor.messages.management.WordRequest.type:type_name -> hw.trezor.messages.management.WordRequest.WordRequestType
+ 4, // [4:4] is the sub-list for method output_type
+ 4, // [4:4] is the sub-list for method input_type
+ 4, // [4:4] is the sub-list for extension type_name
+ 4, // [4:4] is the sub-list for extension extendee
+ 0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_messages_management_proto_init() }
+func file_messages_management_proto_init() {
+ if File_messages_management_proto != nil {
+ return
+ }
+ file_messages_common_proto_init()
+ if !protoimpl.UnsafeEnabled {
+ file_messages_management_proto_msgTypes[0].Exporter = func(v any, i int) any {
+ switch v := v.(*Initialize); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[1].Exporter = func(v any, i int) any {
+ switch v := v.(*GetFeatures); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[2].Exporter = func(v any, i int) any {
+ switch v := v.(*Features); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[3].Exporter = func(v any, i int) any {
+ switch v := v.(*ClearSession); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[4].Exporter = func(v any, i int) any {
+ switch v := v.(*ApplySettings); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[5].Exporter = func(v any, i int) any {
+ switch v := v.(*ApplyFlags); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[6].Exporter = func(v any, i int) any {
+ switch v := v.(*ChangePin); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[7].Exporter = func(v any, i int) any {
+ switch v := v.(*Ping); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[8].Exporter = func(v any, i int) any {
+ switch v := v.(*Cancel); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[9].Exporter = func(v any, i int) any {
+ switch v := v.(*GetEntropy); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[10].Exporter = func(v any, i int) any {
+ switch v := v.(*Entropy); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[11].Exporter = func(v any, i int) any {
+ switch v := v.(*WipeDevice); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[12].Exporter = func(v any, i int) any {
+ switch v := v.(*LoadDevice); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[13].Exporter = func(v any, i int) any {
+ switch v := v.(*ResetDevice); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[14].Exporter = func(v any, i int) any {
+ switch v := v.(*BackupDevice); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[15].Exporter = func(v any, i int) any {
+ switch v := v.(*EntropyRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[16].Exporter = func(v any, i int) any {
+ switch v := v.(*EntropyAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[17].Exporter = func(v any, i int) any {
+ switch v := v.(*RecoveryDevice); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[18].Exporter = func(v any, i int) any {
+ switch v := v.(*WordRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[19].Exporter = func(v any, i int) any {
+ switch v := v.(*WordAck); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_messages_management_proto_msgTypes[20].Exporter = func(v any, i int) any {
+ switch v := v.(*SetU2FCounter); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_messages_management_proto_rawDesc,
+ NumEnums: 3,
+ NumMessages: 21,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_messages_management_proto_goTypes,
+ DependencyIndexes: file_messages_management_proto_depIdxs,
+ EnumInfos: file_messages_management_proto_enumTypes,
+ MessageInfos: file_messages_management_proto_msgTypes,
+ }.Build()
+ File_messages_management_proto = out.File
+ file_messages_management_proto_rawDesc = nil
+ file_messages_management_proto_goTypes = nil
+ file_messages_management_proto_depIdxs = nil
+}
diff --git a/accounts/usbwallet/messages-management.proto b/accounts/usbwallet/messages-management.proto
new file mode 100644
index 0000000000..55eb58983e
--- /dev/null
+++ b/accounts/usbwallet/messages-management.proto
@@ -0,0 +1,291 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.management;
+
+option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessageManagement";
+
+import "messages-common.proto";
+
+/**
+ * Request: Reset device to default state and ask for device details
+ * @start
+ * @next Features
+ */
+message Initialize {
+ optional bytes state = 1; // assumed device state, clear session if set and different
+ optional bool skip_passphrase = 2; // this session should always assume empty passphrase
+}
+
+/**
+ * Request: Ask for device details (no device reset)
+ * @start
+ * @next Features
+ */
+message GetFeatures {
+}
+
+/**
+ * Response: Reports various information about the device
+ * @end
+ */
+message Features {
+ optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io"
+ optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1
+ optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0
+ optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0
+ optional bool bootloader_mode = 5; // is device in bootloader mode?
+ optional string device_id = 6; // device's unique identifier
+ optional bool pin_protection = 7; // is device protected by PIN?
+ optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase?
+ optional string language = 9; // device language
+ optional string label = 10; // device description label
+ optional bool initialized = 12; // does device contain seed?
+ optional bytes revision = 13; // SCM revision of firmware
+ optional bytes bootloader_hash = 14; // hash of the bootloader
+ optional bool imported = 15; // was storage imported from an external source?
+ optional bool pin_cached = 16; // is PIN already cached in session?
+ optional bool passphrase_cached = 17; // is passphrase already cached in session?
+ optional bool firmware_present = 18; // is valid firmware loaded?
+ optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup)
+ optional uint32 flags = 20; // device flags (equals to Storage.flags)
+ optional string model = 21; // device hardware model
+ optional uint32 fw_major = 22; // reported firmware version if in bootloader mode
+ optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode
+ optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode
+ optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode
+ optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash)
+ optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup)
+ optional bool no_backup = 28; // report no backup (equals to Storage.no_backup)
+}
+
+/**
+ * Request: clear session (removes cached PIN, passphrase, etc).
+ * @start
+ * @next Success
+ */
+message ClearSession {
+}
+
+/**
+ * Request: change language and/or label of the device
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ApplySettings {
+ optional string language = 1;
+ optional string label = 2;
+ optional bool use_passphrase = 3;
+ optional bytes homescreen = 4;
+ optional PassphraseSourceType passphrase_source = 5;
+ optional uint32 auto_lock_delay_ms = 6;
+ optional uint32 display_rotation = 7; // in degrees from North
+ /**
+ * Structure representing passphrase source
+ */
+ enum PassphraseSourceType {
+ ASK = 0;
+ DEVICE = 1;
+ HOST = 2;
+ }
+}
+
+/**
+ * Request: set flags of the device
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ApplyFlags {
+ optional uint32 flags = 1; // bitmask, can only set bits, not unset
+}
+
+/**
+ * Request: Starts workflow for setting/changing/removing the PIN
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ChangePin {
+ optional bool remove = 1; // is PIN removal requested?
+}
+
+/**
+ * Request: Test if the device is alive, device sends back the message in Success response
+ * @start
+ * @next Success
+ */
+message Ping {
+ optional string message = 1; // message to send back in Success message
+ optional bool button_protection = 2; // ask for button press
+ optional bool pin_protection = 3; // ask for PIN if set in device
+ optional bool passphrase_protection = 4; // ask for passphrase if set in device
+}
+
+/**
+ * Request: Abort last operation that required user interaction
+ * @start
+ * @next Failure
+ */
+message Cancel {
+}
+
+/**
+ * Request: Request a sample of random data generated by hardware RNG. May be used for testing.
+ * @start
+ * @next Entropy
+ * @next Failure
+ */
+message GetEntropy {
+ required uint32 size = 1; // size of requested entropy
+}
+
+/**
+ * Response: Reply with random data generated by internal RNG
+ * @end
+ */
+message Entropy {
+ required bytes entropy = 1; // chunk of random generated bytes
+}
+
+/**
+ * Request: Request device to wipe all sensitive data and settings
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message WipeDevice {
+}
+
+/**
+ * Request: Load seed and related internal settings from the computer
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message LoadDevice {
+ optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
+ optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node
+ optional string pin = 3; // set PIN protection
+ optional bool passphrase_protection = 4; // enable master node encryption using passphrase
+ optional string language = 5 [default='english']; // device language
+ optional string label = 6; // device label
+ optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum
+ optional uint32 u2f_counter = 8; // U2F counter
+}
+
+/**
+ * Request: Ask device to do initialization involving user interaction
+ * @start
+ * @next EntropyRequest
+ * @next Failure
+ */
+message ResetDevice {
+ optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy
+ optional uint32 strength = 2 [default=256]; // strength of seed in bits
+ optional bool passphrase_protection = 3; // enable master node encryption using passphrase
+ optional bool pin_protection = 4; // enable PIN protection
+ optional string language = 5 [default='english']; // device language
+ optional string label = 6; // device label
+ optional uint32 u2f_counter = 7; // U2F counter
+ optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow
+ optional bool no_backup = 9; // indicate that no backup is going to be made
+}
+
+/**
+ * Request: Perform backup of the device seed if not backed up using ResetDevice
+ * @start
+ * @next Success
+ */
+message BackupDevice {
+}
+
+/**
+ * Response: Ask for additional entropy from host computer
+ * @next EntropyAck
+ */
+message EntropyRequest {
+}
+
+/**
+ * Request: Provide additional entropy for seed generation function
+ * @next Success
+ */
+message EntropyAck {
+ optional bytes entropy = 1; // 256 bits (32 bytes) of random data
+}
+
+/**
+ * Request: Start recovery workflow asking user for specific words of mnemonic
+ * Used to recovery device safely even on untrusted computer.
+ * @start
+ * @next WordRequest
+ */
+message RecoveryDevice {
+ optional uint32 word_count = 1; // number of words in BIP-39 mnemonic
+ optional bool passphrase_protection = 2; // enable master node encryption using passphrase
+ optional bool pin_protection = 3; // enable PIN protection
+ optional string language = 4 [default='english']; // device language
+ optional string label = 5; // device label
+ optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process
+ // 7 reserved for unused recovery method
+ optional RecoveryDeviceType type = 8; // supported recovery type
+ optional uint32 u2f_counter = 9; // U2F counter
+ optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation)
+ /**
+ * Type of recovery procedure. These should be used as bitmask, e.g.,
+ * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+ * listing every method supported by the host computer.
+ *
+ * Note that ScrambledWords must be supported by every implementation
+ * for backward compatibility; there is no way to not support it.
+ */
+ enum RecoveryDeviceType {
+ // use powers of two when extending this field
+ RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order
+ RecoveryDeviceType_Matrix = 1; // matrix recovery type
+ }
+}
+
+/**
+ * Response: Device is waiting for user to enter word of the mnemonic
+ * Its position is shown only on device's internal display.
+ * @next WordAck
+ */
+message WordRequest {
+ optional WordRequestType type = 1;
+ /**
+ * Type of Recovery Word request
+ */
+ enum WordRequestType {
+ WordRequestType_Plain = 0;
+ WordRequestType_Matrix9 = 1;
+ WordRequestType_Matrix6 = 2;
+ }
+}
+
+/**
+ * Request: Computer replies with word from the mnemonic
+ * @next WordRequest
+ * @next Success
+ * @next Failure
+ */
+message WordAck {
+ required string word = 1; // one word of mnemonic on asked position
+}
+
+/**
+ * Request: Set U2F counter
+ * @start
+ * @next Success
+ */
+message SetU2FCounter {
+ optional uint32 u2f_counter = 1; // counter
+}
diff --git a/accounts/usbwallet/messages.pb.go b/accounts/usbwallet/messages.pb.go
new file mode 100644
index 0000000000..4518db679e
--- /dev/null
+++ b/accounts/usbwallet/messages.pb.go
@@ -0,0 +1,1366 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.34.2
+// protoc v5.27.1
+// source: messages.proto
+
+package trezor
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ descriptorpb "google.golang.org/protobuf/types/descriptorpb"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// *
+// Mapping between TREZOR wire identifier (uint) and a protobuf message
+type MessageType int32
+
+const (
+ // Management
+ MessageType_MessageType_Initialize MessageType = 0
+ MessageType_MessageType_Ping MessageType = 1
+ MessageType_MessageType_Success MessageType = 2
+ MessageType_MessageType_Failure MessageType = 3
+ MessageType_MessageType_ChangePin MessageType = 4
+ MessageType_MessageType_WipeDevice MessageType = 5
+ MessageType_MessageType_GetEntropy MessageType = 9
+ MessageType_MessageType_Entropy MessageType = 10
+ MessageType_MessageType_LoadDevice MessageType = 13
+ MessageType_MessageType_ResetDevice MessageType = 14
+ MessageType_MessageType_Features MessageType = 17
+ MessageType_MessageType_PinMatrixRequest MessageType = 18
+ MessageType_MessageType_PinMatrixAck MessageType = 19
+ MessageType_MessageType_Cancel MessageType = 20
+ MessageType_MessageType_ClearSession MessageType = 24
+ MessageType_MessageType_ApplySettings MessageType = 25
+ MessageType_MessageType_ButtonRequest MessageType = 26
+ MessageType_MessageType_ButtonAck MessageType = 27
+ MessageType_MessageType_ApplyFlags MessageType = 28
+ MessageType_MessageType_BackupDevice MessageType = 34
+ MessageType_MessageType_EntropyRequest MessageType = 35
+ MessageType_MessageType_EntropyAck MessageType = 36
+ MessageType_MessageType_PassphraseRequest MessageType = 41
+ MessageType_MessageType_PassphraseAck MessageType = 42
+ MessageType_MessageType_PassphraseStateRequest MessageType = 77
+ MessageType_MessageType_PassphraseStateAck MessageType = 78
+ MessageType_MessageType_RecoveryDevice MessageType = 45
+ MessageType_MessageType_WordRequest MessageType = 46
+ MessageType_MessageType_WordAck MessageType = 47
+ MessageType_MessageType_GetFeatures MessageType = 55
+ MessageType_MessageType_SetU2FCounter MessageType = 63
+ // Bootloader
+ MessageType_MessageType_FirmwareErase MessageType = 6
+ MessageType_MessageType_FirmwareUpload MessageType = 7
+ MessageType_MessageType_FirmwareRequest MessageType = 8
+ MessageType_MessageType_SelfTest MessageType = 32
+ // Bitcoin
+ MessageType_MessageType_GetPublicKey MessageType = 11
+ MessageType_MessageType_PublicKey MessageType = 12
+ MessageType_MessageType_SignTx MessageType = 15
+ MessageType_MessageType_TxRequest MessageType = 21
+ MessageType_MessageType_TxAck MessageType = 22
+ MessageType_MessageType_GetAddress MessageType = 29
+ MessageType_MessageType_Address MessageType = 30
+ MessageType_MessageType_SignMessage MessageType = 38
+ MessageType_MessageType_VerifyMessage MessageType = 39
+ MessageType_MessageType_MessageSignature MessageType = 40
+ // Crypto
+ MessageType_MessageType_CipherKeyValue MessageType = 23
+ MessageType_MessageType_CipheredKeyValue MessageType = 48
+ MessageType_MessageType_SignIdentity MessageType = 53
+ MessageType_MessageType_SignedIdentity MessageType = 54
+ MessageType_MessageType_GetECDHSessionKey MessageType = 61
+ MessageType_MessageType_ECDHSessionKey MessageType = 62
+ MessageType_MessageType_CosiCommit MessageType = 71
+ MessageType_MessageType_CosiCommitment MessageType = 72
+ MessageType_MessageType_CosiSign MessageType = 73
+ MessageType_MessageType_CosiSignature MessageType = 74
+ // Debug
+ MessageType_MessageType_DebugLinkDecision MessageType = 100
+ MessageType_MessageType_DebugLinkGetState MessageType = 101
+ MessageType_MessageType_DebugLinkState MessageType = 102
+ MessageType_MessageType_DebugLinkStop MessageType = 103
+ MessageType_MessageType_DebugLinkLog MessageType = 104
+ MessageType_MessageType_DebugLinkMemoryRead MessageType = 110
+ MessageType_MessageType_DebugLinkMemory MessageType = 111
+ MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112
+ MessageType_MessageType_DebugLinkFlashErase MessageType = 113
+ // Ethereum
+ MessageType_MessageType_EthereumGetPublicKey MessageType = 450
+ MessageType_MessageType_EthereumPublicKey MessageType = 451
+ MessageType_MessageType_EthereumGetAddress MessageType = 56
+ MessageType_MessageType_EthereumAddress MessageType = 57
+ MessageType_MessageType_EthereumSignTx MessageType = 58
+ MessageType_MessageType_EthereumTxRequest MessageType = 59
+ MessageType_MessageType_EthereumTxAck MessageType = 60
+ MessageType_MessageType_EthereumSignMessage MessageType = 64
+ MessageType_MessageType_EthereumVerifyMessage MessageType = 65
+ MessageType_MessageType_EthereumMessageSignature MessageType = 66
+ // NEM
+ MessageType_MessageType_NEMGetAddress MessageType = 67
+ MessageType_MessageType_NEMAddress MessageType = 68
+ MessageType_MessageType_NEMSignTx MessageType = 69
+ MessageType_MessageType_NEMSignedTx MessageType = 70
+ MessageType_MessageType_NEMDecryptMessage MessageType = 75
+ MessageType_MessageType_NEMDecryptedMessage MessageType = 76
+ // Lisk
+ MessageType_MessageType_LiskGetAddress MessageType = 114
+ MessageType_MessageType_LiskAddress MessageType = 115
+ MessageType_MessageType_LiskSignTx MessageType = 116
+ MessageType_MessageType_LiskSignedTx MessageType = 117
+ MessageType_MessageType_LiskSignMessage MessageType = 118
+ MessageType_MessageType_LiskMessageSignature MessageType = 119
+ MessageType_MessageType_LiskVerifyMessage MessageType = 120
+ MessageType_MessageType_LiskGetPublicKey MessageType = 121
+ MessageType_MessageType_LiskPublicKey MessageType = 122
+ // Tezos
+ MessageType_MessageType_TezosGetAddress MessageType = 150
+ MessageType_MessageType_TezosAddress MessageType = 151
+ MessageType_MessageType_TezosSignTx MessageType = 152
+ MessageType_MessageType_TezosSignedTx MessageType = 153
+ MessageType_MessageType_TezosGetPublicKey MessageType = 154
+ MessageType_MessageType_TezosPublicKey MessageType = 155
+ // Stellar
+ MessageType_MessageType_StellarSignTx MessageType = 202
+ MessageType_MessageType_StellarTxOpRequest MessageType = 203
+ MessageType_MessageType_StellarGetAddress MessageType = 207
+ MessageType_MessageType_StellarAddress MessageType = 208
+ MessageType_MessageType_StellarCreateAccountOp MessageType = 210
+ MessageType_MessageType_StellarPaymentOp MessageType = 211
+ MessageType_MessageType_StellarPathPaymentOp MessageType = 212
+ MessageType_MessageType_StellarManageOfferOp MessageType = 213
+ MessageType_MessageType_StellarCreatePassiveOfferOp MessageType = 214
+ MessageType_MessageType_StellarSetOptionsOp MessageType = 215
+ MessageType_MessageType_StellarChangeTrustOp MessageType = 216
+ MessageType_MessageType_StellarAllowTrustOp MessageType = 217
+ MessageType_MessageType_StellarAccountMergeOp MessageType = 218
+ // omitted: StellarInflationOp is not a supported operation, would be 219
+ MessageType_MessageType_StellarManageDataOp MessageType = 220
+ MessageType_MessageType_StellarBumpSequenceOp MessageType = 221
+ MessageType_MessageType_StellarSignedTx MessageType = 230
+ // TRON
+ MessageType_MessageType_TronGetAddress MessageType = 250
+ MessageType_MessageType_TronAddress MessageType = 251
+ MessageType_MessageType_TronSignTx MessageType = 252
+ MessageType_MessageType_TronSignedTx MessageType = 253
+ // Cardano
+ // dropped Sign/VerifyMessage ids 300-302
+ MessageType_MessageType_CardanoSignTx MessageType = 303
+ MessageType_MessageType_CardanoTxRequest MessageType = 304
+ MessageType_MessageType_CardanoGetPublicKey MessageType = 305
+ MessageType_MessageType_CardanoPublicKey MessageType = 306
+ MessageType_MessageType_CardanoGetAddress MessageType = 307
+ MessageType_MessageType_CardanoAddress MessageType = 308
+ MessageType_MessageType_CardanoTxAck MessageType = 309
+ MessageType_MessageType_CardanoSignedTx MessageType = 310
+ // Ontology
+ MessageType_MessageType_OntologyGetAddress MessageType = 350
+ MessageType_MessageType_OntologyAddress MessageType = 351
+ MessageType_MessageType_OntologyGetPublicKey MessageType = 352
+ MessageType_MessageType_OntologyPublicKey MessageType = 353
+ MessageType_MessageType_OntologySignTransfer MessageType = 354
+ MessageType_MessageType_OntologySignedTransfer MessageType = 355
+ MessageType_MessageType_OntologySignWithdrawOng MessageType = 356
+ MessageType_MessageType_OntologySignedWithdrawOng MessageType = 357
+ MessageType_MessageType_OntologySignOntIdRegister MessageType = 358
+ MessageType_MessageType_OntologySignedOntIdRegister MessageType = 359
+ MessageType_MessageType_OntologySignOntIdAddAttributes MessageType = 360
+ MessageType_MessageType_OntologySignedOntIdAddAttributes MessageType = 361
+ // Ripple
+ MessageType_MessageType_RippleGetAddress MessageType = 400
+ MessageType_MessageType_RippleAddress MessageType = 401
+ MessageType_MessageType_RippleSignTx MessageType = 402
+ MessageType_MessageType_RippleSignedTx MessageType = 403
+ // Monero
+ MessageType_MessageType_MoneroTransactionInitRequest MessageType = 501
+ MessageType_MessageType_MoneroTransactionInitAck MessageType = 502
+ MessageType_MessageType_MoneroTransactionSetInputRequest MessageType = 503
+ MessageType_MessageType_MoneroTransactionSetInputAck MessageType = 504
+ MessageType_MessageType_MoneroTransactionInputsPermutationRequest MessageType = 505
+ MessageType_MessageType_MoneroTransactionInputsPermutationAck MessageType = 506
+ MessageType_MessageType_MoneroTransactionInputViniRequest MessageType = 507
+ MessageType_MessageType_MoneroTransactionInputViniAck MessageType = 508
+ MessageType_MessageType_MoneroTransactionAllInputsSetRequest MessageType = 509
+ MessageType_MessageType_MoneroTransactionAllInputsSetAck MessageType = 510
+ MessageType_MessageType_MoneroTransactionSetOutputRequest MessageType = 511
+ MessageType_MessageType_MoneroTransactionSetOutputAck MessageType = 512
+ MessageType_MessageType_MoneroTransactionAllOutSetRequest MessageType = 513
+ MessageType_MessageType_MoneroTransactionAllOutSetAck MessageType = 514
+ MessageType_MessageType_MoneroTransactionSignInputRequest MessageType = 515
+ MessageType_MessageType_MoneroTransactionSignInputAck MessageType = 516
+ MessageType_MessageType_MoneroTransactionFinalRequest MessageType = 517
+ MessageType_MessageType_MoneroTransactionFinalAck MessageType = 518
+ MessageType_MessageType_MoneroKeyImageExportInitRequest MessageType = 530
+ MessageType_MessageType_MoneroKeyImageExportInitAck MessageType = 531
+ MessageType_MessageType_MoneroKeyImageSyncStepRequest MessageType = 532
+ MessageType_MessageType_MoneroKeyImageSyncStepAck MessageType = 533
+ MessageType_MessageType_MoneroKeyImageSyncFinalRequest MessageType = 534
+ MessageType_MessageType_MoneroKeyImageSyncFinalAck MessageType = 535
+ MessageType_MessageType_MoneroGetAddress MessageType = 540
+ MessageType_MessageType_MoneroAddress MessageType = 541
+ MessageType_MessageType_MoneroGetWatchKey MessageType = 542
+ MessageType_MessageType_MoneroWatchKey MessageType = 543
+ MessageType_MessageType_DebugMoneroDiagRequest MessageType = 546
+ MessageType_MessageType_DebugMoneroDiagAck MessageType = 547
+ MessageType_MessageType_MoneroGetTxKeyRequest MessageType = 550
+ MessageType_MessageType_MoneroGetTxKeyAck MessageType = 551
+ MessageType_MessageType_MoneroLiveRefreshStartRequest MessageType = 552
+ MessageType_MessageType_MoneroLiveRefreshStartAck MessageType = 553
+ MessageType_MessageType_MoneroLiveRefreshStepRequest MessageType = 554
+ MessageType_MessageType_MoneroLiveRefreshStepAck MessageType = 555
+ MessageType_MessageType_MoneroLiveRefreshFinalRequest MessageType = 556
+ MessageType_MessageType_MoneroLiveRefreshFinalAck MessageType = 557
+ // EOS
+ MessageType_MessageType_EosGetPublicKey MessageType = 600
+ MessageType_MessageType_EosPublicKey MessageType = 601
+ MessageType_MessageType_EosSignTx MessageType = 602
+ MessageType_MessageType_EosTxActionRequest MessageType = 603
+ MessageType_MessageType_EosTxActionAck MessageType = 604
+ MessageType_MessageType_EosSignedTx MessageType = 605
+ // Binance
+ MessageType_MessageType_BinanceGetAddress MessageType = 700
+ MessageType_MessageType_BinanceAddress MessageType = 701
+ MessageType_MessageType_BinanceGetPublicKey MessageType = 702
+ MessageType_MessageType_BinancePublicKey MessageType = 703
+ MessageType_MessageType_BinanceSignTx MessageType = 704
+ MessageType_MessageType_BinanceTxRequest MessageType = 705
+ MessageType_MessageType_BinanceTransferMsg MessageType = 706
+ MessageType_MessageType_BinanceOrderMsg MessageType = 707
+ MessageType_MessageType_BinanceCancelMsg MessageType = 708
+ MessageType_MessageType_BinanceSignedTx MessageType = 709
+)
+
+// Enum value maps for MessageType.
+var (
+ MessageType_name = map[int32]string{
+ 0: "MessageType_Initialize",
+ 1: "MessageType_Ping",
+ 2: "MessageType_Success",
+ 3: "MessageType_Failure",
+ 4: "MessageType_ChangePin",
+ 5: "MessageType_WipeDevice",
+ 9: "MessageType_GetEntropy",
+ 10: "MessageType_Entropy",
+ 13: "MessageType_LoadDevice",
+ 14: "MessageType_ResetDevice",
+ 17: "MessageType_Features",
+ 18: "MessageType_PinMatrixRequest",
+ 19: "MessageType_PinMatrixAck",
+ 20: "MessageType_Cancel",
+ 24: "MessageType_ClearSession",
+ 25: "MessageType_ApplySettings",
+ 26: "MessageType_ButtonRequest",
+ 27: "MessageType_ButtonAck",
+ 28: "MessageType_ApplyFlags",
+ 34: "MessageType_BackupDevice",
+ 35: "MessageType_EntropyRequest",
+ 36: "MessageType_EntropyAck",
+ 41: "MessageType_PassphraseRequest",
+ 42: "MessageType_PassphraseAck",
+ 77: "MessageType_PassphraseStateRequest",
+ 78: "MessageType_PassphraseStateAck",
+ 45: "MessageType_RecoveryDevice",
+ 46: "MessageType_WordRequest",
+ 47: "MessageType_WordAck",
+ 55: "MessageType_GetFeatures",
+ 63: "MessageType_SetU2FCounter",
+ 6: "MessageType_FirmwareErase",
+ 7: "MessageType_FirmwareUpload",
+ 8: "MessageType_FirmwareRequest",
+ 32: "MessageType_SelfTest",
+ 11: "MessageType_GetPublicKey",
+ 12: "MessageType_PublicKey",
+ 15: "MessageType_SignTx",
+ 21: "MessageType_TxRequest",
+ 22: "MessageType_TxAck",
+ 29: "MessageType_GetAddress",
+ 30: "MessageType_Address",
+ 38: "MessageType_SignMessage",
+ 39: "MessageType_VerifyMessage",
+ 40: "MessageType_MessageSignature",
+ 23: "MessageType_CipherKeyValue",
+ 48: "MessageType_CipheredKeyValue",
+ 53: "MessageType_SignIdentity",
+ 54: "MessageType_SignedIdentity",
+ 61: "MessageType_GetECDHSessionKey",
+ 62: "MessageType_ECDHSessionKey",
+ 71: "MessageType_CosiCommit",
+ 72: "MessageType_CosiCommitment",
+ 73: "MessageType_CosiSign",
+ 74: "MessageType_CosiSignature",
+ 100: "MessageType_DebugLinkDecision",
+ 101: "MessageType_DebugLinkGetState",
+ 102: "MessageType_DebugLinkState",
+ 103: "MessageType_DebugLinkStop",
+ 104: "MessageType_DebugLinkLog",
+ 110: "MessageType_DebugLinkMemoryRead",
+ 111: "MessageType_DebugLinkMemory",
+ 112: "MessageType_DebugLinkMemoryWrite",
+ 113: "MessageType_DebugLinkFlashErase",
+ 450: "MessageType_EthereumGetPublicKey",
+ 451: "MessageType_EthereumPublicKey",
+ 56: "MessageType_EthereumGetAddress",
+ 57: "MessageType_EthereumAddress",
+ 58: "MessageType_EthereumSignTx",
+ 59: "MessageType_EthereumTxRequest",
+ 60: "MessageType_EthereumTxAck",
+ 64: "MessageType_EthereumSignMessage",
+ 65: "MessageType_EthereumVerifyMessage",
+ 66: "MessageType_EthereumMessageSignature",
+ 67: "MessageType_NEMGetAddress",
+ 68: "MessageType_NEMAddress",
+ 69: "MessageType_NEMSignTx",
+ 70: "MessageType_NEMSignedTx",
+ 75: "MessageType_NEMDecryptMessage",
+ 76: "MessageType_NEMDecryptedMessage",
+ 114: "MessageType_LiskGetAddress",
+ 115: "MessageType_LiskAddress",
+ 116: "MessageType_LiskSignTx",
+ 117: "MessageType_LiskSignedTx",
+ 118: "MessageType_LiskSignMessage",
+ 119: "MessageType_LiskMessageSignature",
+ 120: "MessageType_LiskVerifyMessage",
+ 121: "MessageType_LiskGetPublicKey",
+ 122: "MessageType_LiskPublicKey",
+ 150: "MessageType_TezosGetAddress",
+ 151: "MessageType_TezosAddress",
+ 152: "MessageType_TezosSignTx",
+ 153: "MessageType_TezosSignedTx",
+ 154: "MessageType_TezosGetPublicKey",
+ 155: "MessageType_TezosPublicKey",
+ 202: "MessageType_StellarSignTx",
+ 203: "MessageType_StellarTxOpRequest",
+ 207: "MessageType_StellarGetAddress",
+ 208: "MessageType_StellarAddress",
+ 210: "MessageType_StellarCreateAccountOp",
+ 211: "MessageType_StellarPaymentOp",
+ 212: "MessageType_StellarPathPaymentOp",
+ 213: "MessageType_StellarManageOfferOp",
+ 214: "MessageType_StellarCreatePassiveOfferOp",
+ 215: "MessageType_StellarSetOptionsOp",
+ 216: "MessageType_StellarChangeTrustOp",
+ 217: "MessageType_StellarAllowTrustOp",
+ 218: "MessageType_StellarAccountMergeOp",
+ 220: "MessageType_StellarManageDataOp",
+ 221: "MessageType_StellarBumpSequenceOp",
+ 230: "MessageType_StellarSignedTx",
+ 250: "MessageType_TronGetAddress",
+ 251: "MessageType_TronAddress",
+ 252: "MessageType_TronSignTx",
+ 253: "MessageType_TronSignedTx",
+ 303: "MessageType_CardanoSignTx",
+ 304: "MessageType_CardanoTxRequest",
+ 305: "MessageType_CardanoGetPublicKey",
+ 306: "MessageType_CardanoPublicKey",
+ 307: "MessageType_CardanoGetAddress",
+ 308: "MessageType_CardanoAddress",
+ 309: "MessageType_CardanoTxAck",
+ 310: "MessageType_CardanoSignedTx",
+ 350: "MessageType_OntologyGetAddress",
+ 351: "MessageType_OntologyAddress",
+ 352: "MessageType_OntologyGetPublicKey",
+ 353: "MessageType_OntologyPublicKey",
+ 354: "MessageType_OntologySignTransfer",
+ 355: "MessageType_OntologySignedTransfer",
+ 356: "MessageType_OntologySignWithdrawOng",
+ 357: "MessageType_OntologySignedWithdrawOng",
+ 358: "MessageType_OntologySignOntIdRegister",
+ 359: "MessageType_OntologySignedOntIdRegister",
+ 360: "MessageType_OntologySignOntIdAddAttributes",
+ 361: "MessageType_OntologySignedOntIdAddAttributes",
+ 400: "MessageType_RippleGetAddress",
+ 401: "MessageType_RippleAddress",
+ 402: "MessageType_RippleSignTx",
+ 403: "MessageType_RippleSignedTx",
+ 501: "MessageType_MoneroTransactionInitRequest",
+ 502: "MessageType_MoneroTransactionInitAck",
+ 503: "MessageType_MoneroTransactionSetInputRequest",
+ 504: "MessageType_MoneroTransactionSetInputAck",
+ 505: "MessageType_MoneroTransactionInputsPermutationRequest",
+ 506: "MessageType_MoneroTransactionInputsPermutationAck",
+ 507: "MessageType_MoneroTransactionInputViniRequest",
+ 508: "MessageType_MoneroTransactionInputViniAck",
+ 509: "MessageType_MoneroTransactionAllInputsSetRequest",
+ 510: "MessageType_MoneroTransactionAllInputsSetAck",
+ 511: "MessageType_MoneroTransactionSetOutputRequest",
+ 512: "MessageType_MoneroTransactionSetOutputAck",
+ 513: "MessageType_MoneroTransactionAllOutSetRequest",
+ 514: "MessageType_MoneroTransactionAllOutSetAck",
+ 515: "MessageType_MoneroTransactionSignInputRequest",
+ 516: "MessageType_MoneroTransactionSignInputAck",
+ 517: "MessageType_MoneroTransactionFinalRequest",
+ 518: "MessageType_MoneroTransactionFinalAck",
+ 530: "MessageType_MoneroKeyImageExportInitRequest",
+ 531: "MessageType_MoneroKeyImageExportInitAck",
+ 532: "MessageType_MoneroKeyImageSyncStepRequest",
+ 533: "MessageType_MoneroKeyImageSyncStepAck",
+ 534: "MessageType_MoneroKeyImageSyncFinalRequest",
+ 535: "MessageType_MoneroKeyImageSyncFinalAck",
+ 540: "MessageType_MoneroGetAddress",
+ 541: "MessageType_MoneroAddress",
+ 542: "MessageType_MoneroGetWatchKey",
+ 543: "MessageType_MoneroWatchKey",
+ 546: "MessageType_DebugMoneroDiagRequest",
+ 547: "MessageType_DebugMoneroDiagAck",
+ 550: "MessageType_MoneroGetTxKeyRequest",
+ 551: "MessageType_MoneroGetTxKeyAck",
+ 552: "MessageType_MoneroLiveRefreshStartRequest",
+ 553: "MessageType_MoneroLiveRefreshStartAck",
+ 554: "MessageType_MoneroLiveRefreshStepRequest",
+ 555: "MessageType_MoneroLiveRefreshStepAck",
+ 556: "MessageType_MoneroLiveRefreshFinalRequest",
+ 557: "MessageType_MoneroLiveRefreshFinalAck",
+ 600: "MessageType_EosGetPublicKey",
+ 601: "MessageType_EosPublicKey",
+ 602: "MessageType_EosSignTx",
+ 603: "MessageType_EosTxActionRequest",
+ 604: "MessageType_EosTxActionAck",
+ 605: "MessageType_EosSignedTx",
+ 700: "MessageType_BinanceGetAddress",
+ 701: "MessageType_BinanceAddress",
+ 702: "MessageType_BinanceGetPublicKey",
+ 703: "MessageType_BinancePublicKey",
+ 704: "MessageType_BinanceSignTx",
+ 705: "MessageType_BinanceTxRequest",
+ 706: "MessageType_BinanceTransferMsg",
+ 707: "MessageType_BinanceOrderMsg",
+ 708: "MessageType_BinanceCancelMsg",
+ 709: "MessageType_BinanceSignedTx",
+ }
+ MessageType_value = map[string]int32{
+ "MessageType_Initialize": 0,
+ "MessageType_Ping": 1,
+ "MessageType_Success": 2,
+ "MessageType_Failure": 3,
+ "MessageType_ChangePin": 4,
+ "MessageType_WipeDevice": 5,
+ "MessageType_GetEntropy": 9,
+ "MessageType_Entropy": 10,
+ "MessageType_LoadDevice": 13,
+ "MessageType_ResetDevice": 14,
+ "MessageType_Features": 17,
+ "MessageType_PinMatrixRequest": 18,
+ "MessageType_PinMatrixAck": 19,
+ "MessageType_Cancel": 20,
+ "MessageType_ClearSession": 24,
+ "MessageType_ApplySettings": 25,
+ "MessageType_ButtonRequest": 26,
+ "MessageType_ButtonAck": 27,
+ "MessageType_ApplyFlags": 28,
+ "MessageType_BackupDevice": 34,
+ "MessageType_EntropyRequest": 35,
+ "MessageType_EntropyAck": 36,
+ "MessageType_PassphraseRequest": 41,
+ "MessageType_PassphraseAck": 42,
+ "MessageType_PassphraseStateRequest": 77,
+ "MessageType_PassphraseStateAck": 78,
+ "MessageType_RecoveryDevice": 45,
+ "MessageType_WordRequest": 46,
+ "MessageType_WordAck": 47,
+ "MessageType_GetFeatures": 55,
+ "MessageType_SetU2FCounter": 63,
+ "MessageType_FirmwareErase": 6,
+ "MessageType_FirmwareUpload": 7,
+ "MessageType_FirmwareRequest": 8,
+ "MessageType_SelfTest": 32,
+ "MessageType_GetPublicKey": 11,
+ "MessageType_PublicKey": 12,
+ "MessageType_SignTx": 15,
+ "MessageType_TxRequest": 21,
+ "MessageType_TxAck": 22,
+ "MessageType_GetAddress": 29,
+ "MessageType_Address": 30,
+ "MessageType_SignMessage": 38,
+ "MessageType_VerifyMessage": 39,
+ "MessageType_MessageSignature": 40,
+ "MessageType_CipherKeyValue": 23,
+ "MessageType_CipheredKeyValue": 48,
+ "MessageType_SignIdentity": 53,
+ "MessageType_SignedIdentity": 54,
+ "MessageType_GetECDHSessionKey": 61,
+ "MessageType_ECDHSessionKey": 62,
+ "MessageType_CosiCommit": 71,
+ "MessageType_CosiCommitment": 72,
+ "MessageType_CosiSign": 73,
+ "MessageType_CosiSignature": 74,
+ "MessageType_DebugLinkDecision": 100,
+ "MessageType_DebugLinkGetState": 101,
+ "MessageType_DebugLinkState": 102,
+ "MessageType_DebugLinkStop": 103,
+ "MessageType_DebugLinkLog": 104,
+ "MessageType_DebugLinkMemoryRead": 110,
+ "MessageType_DebugLinkMemory": 111,
+ "MessageType_DebugLinkMemoryWrite": 112,
+ "MessageType_DebugLinkFlashErase": 113,
+ "MessageType_EthereumGetPublicKey": 450,
+ "MessageType_EthereumPublicKey": 451,
+ "MessageType_EthereumGetAddress": 56,
+ "MessageType_EthereumAddress": 57,
+ "MessageType_EthereumSignTx": 58,
+ "MessageType_EthereumTxRequest": 59,
+ "MessageType_EthereumTxAck": 60,
+ "MessageType_EthereumSignMessage": 64,
+ "MessageType_EthereumVerifyMessage": 65,
+ "MessageType_EthereumMessageSignature": 66,
+ "MessageType_NEMGetAddress": 67,
+ "MessageType_NEMAddress": 68,
+ "MessageType_NEMSignTx": 69,
+ "MessageType_NEMSignedTx": 70,
+ "MessageType_NEMDecryptMessage": 75,
+ "MessageType_NEMDecryptedMessage": 76,
+ "MessageType_LiskGetAddress": 114,
+ "MessageType_LiskAddress": 115,
+ "MessageType_LiskSignTx": 116,
+ "MessageType_LiskSignedTx": 117,
+ "MessageType_LiskSignMessage": 118,
+ "MessageType_LiskMessageSignature": 119,
+ "MessageType_LiskVerifyMessage": 120,
+ "MessageType_LiskGetPublicKey": 121,
+ "MessageType_LiskPublicKey": 122,
+ "MessageType_TezosGetAddress": 150,
+ "MessageType_TezosAddress": 151,
+ "MessageType_TezosSignTx": 152,
+ "MessageType_TezosSignedTx": 153,
+ "MessageType_TezosGetPublicKey": 154,
+ "MessageType_TezosPublicKey": 155,
+ "MessageType_StellarSignTx": 202,
+ "MessageType_StellarTxOpRequest": 203,
+ "MessageType_StellarGetAddress": 207,
+ "MessageType_StellarAddress": 208,
+ "MessageType_StellarCreateAccountOp": 210,
+ "MessageType_StellarPaymentOp": 211,
+ "MessageType_StellarPathPaymentOp": 212,
+ "MessageType_StellarManageOfferOp": 213,
+ "MessageType_StellarCreatePassiveOfferOp": 214,
+ "MessageType_StellarSetOptionsOp": 215,
+ "MessageType_StellarChangeTrustOp": 216,
+ "MessageType_StellarAllowTrustOp": 217,
+ "MessageType_StellarAccountMergeOp": 218,
+ "MessageType_StellarManageDataOp": 220,
+ "MessageType_StellarBumpSequenceOp": 221,
+ "MessageType_StellarSignedTx": 230,
+ "MessageType_TronGetAddress": 250,
+ "MessageType_TronAddress": 251,
+ "MessageType_TronSignTx": 252,
+ "MessageType_TronSignedTx": 253,
+ "MessageType_CardanoSignTx": 303,
+ "MessageType_CardanoTxRequest": 304,
+ "MessageType_CardanoGetPublicKey": 305,
+ "MessageType_CardanoPublicKey": 306,
+ "MessageType_CardanoGetAddress": 307,
+ "MessageType_CardanoAddress": 308,
+ "MessageType_CardanoTxAck": 309,
+ "MessageType_CardanoSignedTx": 310,
+ "MessageType_OntologyGetAddress": 350,
+ "MessageType_OntologyAddress": 351,
+ "MessageType_OntologyGetPublicKey": 352,
+ "MessageType_OntologyPublicKey": 353,
+ "MessageType_OntologySignTransfer": 354,
+ "MessageType_OntologySignedTransfer": 355,
+ "MessageType_OntologySignWithdrawOng": 356,
+ "MessageType_OntologySignedWithdrawOng": 357,
+ "MessageType_OntologySignOntIdRegister": 358,
+ "MessageType_OntologySignedOntIdRegister": 359,
+ "MessageType_OntologySignOntIdAddAttributes": 360,
+ "MessageType_OntologySignedOntIdAddAttributes": 361,
+ "MessageType_RippleGetAddress": 400,
+ "MessageType_RippleAddress": 401,
+ "MessageType_RippleSignTx": 402,
+ "MessageType_RippleSignedTx": 403,
+ "MessageType_MoneroTransactionInitRequest": 501,
+ "MessageType_MoneroTransactionInitAck": 502,
+ "MessageType_MoneroTransactionSetInputRequest": 503,
+ "MessageType_MoneroTransactionSetInputAck": 504,
+ "MessageType_MoneroTransactionInputsPermutationRequest": 505,
+ "MessageType_MoneroTransactionInputsPermutationAck": 506,
+ "MessageType_MoneroTransactionInputViniRequest": 507,
+ "MessageType_MoneroTransactionInputViniAck": 508,
+ "MessageType_MoneroTransactionAllInputsSetRequest": 509,
+ "MessageType_MoneroTransactionAllInputsSetAck": 510,
+ "MessageType_MoneroTransactionSetOutputRequest": 511,
+ "MessageType_MoneroTransactionSetOutputAck": 512,
+ "MessageType_MoneroTransactionAllOutSetRequest": 513,
+ "MessageType_MoneroTransactionAllOutSetAck": 514,
+ "MessageType_MoneroTransactionSignInputRequest": 515,
+ "MessageType_MoneroTransactionSignInputAck": 516,
+ "MessageType_MoneroTransactionFinalRequest": 517,
+ "MessageType_MoneroTransactionFinalAck": 518,
+ "MessageType_MoneroKeyImageExportInitRequest": 530,
+ "MessageType_MoneroKeyImageExportInitAck": 531,
+ "MessageType_MoneroKeyImageSyncStepRequest": 532,
+ "MessageType_MoneroKeyImageSyncStepAck": 533,
+ "MessageType_MoneroKeyImageSyncFinalRequest": 534,
+ "MessageType_MoneroKeyImageSyncFinalAck": 535,
+ "MessageType_MoneroGetAddress": 540,
+ "MessageType_MoneroAddress": 541,
+ "MessageType_MoneroGetWatchKey": 542,
+ "MessageType_MoneroWatchKey": 543,
+ "MessageType_DebugMoneroDiagRequest": 546,
+ "MessageType_DebugMoneroDiagAck": 547,
+ "MessageType_MoneroGetTxKeyRequest": 550,
+ "MessageType_MoneroGetTxKeyAck": 551,
+ "MessageType_MoneroLiveRefreshStartRequest": 552,
+ "MessageType_MoneroLiveRefreshStartAck": 553,
+ "MessageType_MoneroLiveRefreshStepRequest": 554,
+ "MessageType_MoneroLiveRefreshStepAck": 555,
+ "MessageType_MoneroLiveRefreshFinalRequest": 556,
+ "MessageType_MoneroLiveRefreshFinalAck": 557,
+ "MessageType_EosGetPublicKey": 600,
+ "MessageType_EosPublicKey": 601,
+ "MessageType_EosSignTx": 602,
+ "MessageType_EosTxActionRequest": 603,
+ "MessageType_EosTxActionAck": 604,
+ "MessageType_EosSignedTx": 605,
+ "MessageType_BinanceGetAddress": 700,
+ "MessageType_BinanceAddress": 701,
+ "MessageType_BinanceGetPublicKey": 702,
+ "MessageType_BinancePublicKey": 703,
+ "MessageType_BinanceSignTx": 704,
+ "MessageType_BinanceTxRequest": 705,
+ "MessageType_BinanceTransferMsg": 706,
+ "MessageType_BinanceOrderMsg": 707,
+ "MessageType_BinanceCancelMsg": 708,
+ "MessageType_BinanceSignedTx": 709,
+ }
+)
+
+func (x MessageType) Enum() *MessageType {
+ p := new(MessageType)
+ *p = x
+ return p
+}
+
+func (x MessageType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (MessageType) Descriptor() protoreflect.EnumDescriptor {
+ return file_messages_proto_enumTypes[0].Descriptor()
+}
+
+func (MessageType) Type() protoreflect.EnumType {
+ return &file_messages_proto_enumTypes[0]
+}
+
+func (x MessageType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *MessageType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = MessageType(num)
+ return nil
+}
+
+// Deprecated: Use MessageType.Descriptor instead.
+func (MessageType) EnumDescriptor() ([]byte, []int) {
+ return file_messages_proto_rawDescGZIP(), []int{0}
+}
+
+var file_messages_proto_extTypes = []protoimpl.ExtensionInfo{
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50002,
+ Name: "hw.trezor.messages.wire_in",
+ Tag: "varint,50002,opt,name=wire_in",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50003,
+ Name: "hw.trezor.messages.wire_out",
+ Tag: "varint,50003,opt,name=wire_out",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50004,
+ Name: "hw.trezor.messages.wire_debug_in",
+ Tag: "varint,50004,opt,name=wire_debug_in",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50005,
+ Name: "hw.trezor.messages.wire_debug_out",
+ Tag: "varint,50005,opt,name=wire_debug_out",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50006,
+ Name: "hw.trezor.messages.wire_tiny",
+ Tag: "varint,50006,opt,name=wire_tiny",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50007,
+ Name: "hw.trezor.messages.wire_bootloader",
+ Tag: "varint,50007,opt,name=wire_bootloader",
+ Filename: "messages.proto",
+ },
+ {
+ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50008,
+ Name: "hw.trezor.messages.wire_no_fsm",
+ Tag: "varint,50008,opt,name=wire_no_fsm",
+ Filename: "messages.proto",
+ },
+}
+
+// Extension fields to descriptorpb.EnumValueOptions.
+var (
+ // optional bool wire_in = 50002;
+ E_WireIn = &file_messages_proto_extTypes[0] // message can be transmitted via wire from PC to TREZOR
+ // optional bool wire_out = 50003;
+ E_WireOut = &file_messages_proto_extTypes[1] // message can be transmitted via wire from TREZOR to PC
+ // optional bool wire_debug_in = 50004;
+ E_WireDebugIn = &file_messages_proto_extTypes[2] // message can be transmitted via debug wire from PC to TREZOR
+ // optional bool wire_debug_out = 50005;
+ E_WireDebugOut = &file_messages_proto_extTypes[3] // message can be transmitted via debug wire from TREZOR to PC
+ // optional bool wire_tiny = 50006;
+ E_WireTiny = &file_messages_proto_extTypes[4] // message is handled by TREZOR when the USB stack is in tiny mode
+ // optional bool wire_bootloader = 50007;
+ E_WireBootloader = &file_messages_proto_extTypes[5] // message is only handled by TREZOR Bootloader
+ // optional bool wire_no_fsm = 50008;
+ E_WireNoFsm = &file_messages_proto_extTypes[6] // message is not handled by TREZOR unless the USB stack is in tiny mode
+)
+
+var File_messages_proto protoreflect.FileDescriptor
+
+var file_messages_proto_rawDesc = []byte{
+ 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x12, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0xb9, 0x3f, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65,
+ 0x10, 0x00, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x1a, 0x0a, 0x10,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x67,
+ 0x10, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10,
+ 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x03,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x69, 0x6e, 0x10,
+ 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
+ 0x65, 0x10, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72,
+ 0x6f, 0x70, 0x79, 0x10, 0x09, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f,
+ 0x70, 0x79, 0x10, 0x0a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x6f, 0x61, 0x64, 0x44, 0x65,
+ 0x76, 0x69, 0x63, 0x65, 0x10, 0x0d, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x65,
+ 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x0e, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
+ 0x1e, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x10, 0x11, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12,
+ 0x26, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50,
+ 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10,
+ 0x12, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78,
+ 0x41, 0x63, 0x6b, 0x10, 0x13, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0,
+ 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x10, 0x14, 0x1a, 0x08, 0x90, 0xb5, 0x18,
+ 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x10, 0x18, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65,
+ 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x19, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23,
+ 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x1a, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0x1b, 0x1a, 0x0c,
+ 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x70, 0x70, 0x6c,
+ 0x79, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0x1c, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22,
+ 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x61,
+ 0x63, 0x6b, 0x75, 0x70, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x22, 0x1a, 0x04, 0x90, 0xb5,
+ 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x10, 0x23, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x41,
+ 0x63, 0x6b, 0x10, 0x24, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68,
+ 0x72, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x29, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x41, 0x63, 0x6b,
+ 0x10, 0x2a, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01,
+ 0x12, 0x2c, 0x0a, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x4d, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30,
+ 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x61,
+ 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x63, 0x6b,
+ 0x10, 0x4e, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01,
+ 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x2d,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x10, 0x2e, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x6f, 0x72, 0x64, 0x41, 0x63, 0x6b,
+ 0x10, 0x2f, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x73, 0x10, 0x37, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x74, 0x55, 0x32,
+ 0x46, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x3f, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01,
+ 0x12, 0x27, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x61, 0x73, 0x65, 0x10, 0x06, 0x1a,
+ 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1a, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72,
+ 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x10, 0x07, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8,
+ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x10, 0x08, 0x1a, 0x08, 0x98, 0xb5, 0x18, 0x01, 0xb8, 0xb5, 0x18, 0x01, 0x12, 0x22,
+ 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65,
+ 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x10, 0x20, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8, 0xb5,
+ 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x0b,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10,
+ 0x0c, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1c, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x0f, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x15,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1b, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x78, 0x41, 0x63, 0x6b, 0x10, 0x16, 0x1a, 0x04, 0x90,
+ 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x1d, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x1e, 0x1a, 0x04,
+ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10,
+ 0x26, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x10, 0x27, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x28, 0x1a, 0x04,
+ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x10, 0x17, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72,
+ 0x65, 0x64, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x10, 0x30, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x10, 0x35,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x49, 0x64, 0x65, 0x6e,
+ 0x74, 0x69, 0x74, 0x79, 0x10, 0x36, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x45,
+ 0x43, 0x44, 0x48, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x10, 0x3d, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x4b, 0x65, 0x79, 0x10, 0x3e, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x10, 0x47, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a,
+ 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73,
+ 0x69, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0x48, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x1e, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x10, 0x49, 0x1a, 0x04, 0x90,
+ 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x10, 0x4a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2f, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e,
+ 0x6b, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x64, 0x1a, 0x0c, 0xa0, 0xb5, 0x18,
+ 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x1d, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69,
+ 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0x65, 0x1a, 0x08, 0xa0, 0xb5,
+ 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x10, 0x66, 0x1a, 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75,
+ 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x10, 0x67, 0x1a, 0x04, 0xa0, 0xb5, 0x18,
+ 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4c, 0x6f, 0x67, 0x10, 0x68, 0x1a,
+ 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65,
+ 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x10, 0x6e, 0x1a, 0x04, 0xa0, 0xb5, 0x18, 0x01,
+ 0x12, 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10,
+ 0x6f, 0x1a, 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b,
+ 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x10, 0x70, 0x1a, 0x04, 0xa0,
+ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x46, 0x6c, 0x61, 0x73,
+ 0x68, 0x45, 0x72, 0x61, 0x73, 0x65, 0x10, 0x71, 0x1a, 0x04, 0xa0, 0xb5, 0x18, 0x01, 0x12, 0x2b,
+ 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
+ 0x65, 0x79, 0x10, 0xc2, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x75, 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xc3, 0x03, 0x1a,
+ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74,
+ 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x38, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
+ 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x39,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53, 0x69,
+ 0x67, 0x6e, 0x54, 0x78, 0x10, 0x3a, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x3b, 0x1a,
+ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x41,
+ 0x63, 0x6b, 0x10, 0x3c, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x75, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x40, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x56, 0x65, 0x72,
+ 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x41, 0x1a, 0x04, 0x90, 0xb5,
+ 0x18, 0x01, 0x12, 0x2e, 0x0a, 0x24, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x42, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10,
+ 0x43, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x10, 0x44, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x53, 0x69, 0x67, 0x6e,
+ 0x54, 0x78, 0x10, 0x45, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x53, 0x69, 0x67,
+ 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x46, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a,
+ 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d,
+ 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x4b,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
+ 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x4c, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10,
+ 0x72, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x10, 0x73, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x53, 0x69,
+ 0x67, 0x6e, 0x54, 0x78, 0x10, 0x74, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b,
+ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x75, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4c, 0x69, 0x73, 0x6b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10,
+ 0x76, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x77, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x10, 0x78, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b,
+ 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x79, 0x1a, 0x04,
+ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
+ 0x79, 0x10, 0x7a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x47, 0x65,
+ 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x96, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18,
+ 0x01, 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x97, 0x01,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x54,
+ 0x78, 0x10, 0x98, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x53,
+ 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x99, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
+ 0x79, 0x10, 0x9a, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x50,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x9b, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xca,
+ 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x54, 0x78,
+ 0x4f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xcb, 0x01, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72,
+ 0x65, 0x73, 0x73, 0x10, 0xcf, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c,
+ 0x6c, 0x61, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xd0, 0x01, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x70, 0x10, 0xd2, 0x01, 0x1a, 0x04, 0x90, 0xb5,
+ 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
+ 0x4f, 0x70, 0x10, 0xd3, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c,
+ 0x61, 0x72, 0x50, 0x61, 0x74, 0x68, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x10,
+ 0xd4, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x4d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x4f, 0x70, 0x10, 0xd5, 0x01, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a, 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x4f, 0x70,
+ 0x10, 0xd6, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72,
+ 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x70, 0x10, 0xd7, 0x01, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x4f, 0x70, 0x10, 0xd8, 0x01, 0x1a, 0x04, 0x90, 0xb5,
+ 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x72,
+ 0x75, 0x73, 0x74, 0x4f, 0x70, 0x10, 0xd9, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2c,
+ 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74,
+ 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x65, 0x72, 0x67,
+ 0x65, 0x4f, 0x70, 0x10, 0xda, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c,
+ 0x6c, 0x61, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4f, 0x70, 0x10,
+ 0xdc, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2c, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x42,
+ 0x75, 0x6d, 0x70, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4f, 0x70, 0x10, 0xdd, 0x01,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x53, 0x69, 0x67,
+ 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xe6, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x25,
+ 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72,
+ 0x6f, 0x6e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xfa, 0x01, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+ 0x10, 0xfb, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x16, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e, 0x53, 0x69, 0x67,
+ 0x6e, 0x54, 0x78, 0x10, 0xfc, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e,
+ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xfd, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xaf,
+ 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x54, 0x78,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xb0, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
+ 0x4b, 0x65, 0x79, 0x10, 0xb1, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64,
+ 0x61, 0x6e, 0x6f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xb2, 0x02, 0x1a,
+ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x47, 0x65, 0x74, 0x41,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xb3, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
+ 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43,
+ 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xb4, 0x02,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x54, 0x78, 0x41,
+ 0x63, 0x6b, 0x10, 0xb5, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61,
+ 0x6e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xb6, 0x02, 0x1a, 0x04, 0x98,
+ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x47, 0x65, 0x74, 0x41, 0x64,
+ 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xde, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26,
+ 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e,
+ 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xdf, 0x02,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x47, 0x65,
+ 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xe0, 0x02, 0x1a, 0x04, 0x90,
+ 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69,
+ 0x63, 0x4b, 0x65, 0x79, 0x10, 0xe1, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a,
+ 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74,
+ 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
+ 0x72, 0x10, 0xe2, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f,
+ 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72,
+ 0x10, 0xe3, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2e, 0x0a, 0x23, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67,
+ 0x79, 0x53, 0x69, 0x67, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x67,
+ 0x10, 0xe4, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67,
+ 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x4f,
+ 0x6e, 0x67, 0x10, 0xe5, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c,
+ 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x65, 0x67, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x10, 0xe6, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a,
+ 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74,
+ 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x74, 0x49, 0x64,
+ 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0xe7, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x35, 0x0a, 0x2a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x6e, 0x74,
+ 0x49, 0x64, 0x41, 0x64, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x10,
+ 0xe8, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x37, 0x0a, 0x2c, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
+ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x74, 0x49, 0x64, 0x41, 0x64, 0x64, 0x41, 0x74,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x10, 0xe9, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x10, 0x90, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65,
+ 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x91, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x92, 0x03, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x65,
+ 0x64, 0x54, 0x78, 0x10, 0x93, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
+ 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x69,
+ 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xf5, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x2f, 0x0a, 0x24, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x49, 0x6e, 0x69, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xf6, 0x03, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x37, 0x0a, 0x2c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x10, 0xf7, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
+ 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x49,
+ 0x6e, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xf8, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x40, 0x0a, 0x35, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xf9, 0x03, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x3c, 0x0a, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x75, 0x74, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0xfa, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x69, 0x6e, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x10, 0xfb, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f,
+ 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74,
+ 0x56, 0x69, 0x6e, 0x69, 0x41, 0x63, 0x6b, 0x10, 0xfc, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x3b, 0x0a, 0x30, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x41, 0x6c, 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x10, 0xfd, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x37, 0x0a,
+ 0x2c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e,
+ 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6c,
+ 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x53, 0x65, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xfe, 0x03,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xff, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x53, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x80, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x53, 0x65, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x81, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x41, 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x53, 0x65, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x82, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x83, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x84, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
+ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75,
+ 0x65, 0x73, 0x74, 0x10, 0x85, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
+ 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6e,
+ 0x61, 0x6c, 0x41, 0x63, 0x6b, 0x10, 0x86, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x36,
+ 0x0a, 0x2b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f,
+ 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x6f,
+ 0x72, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x92, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a, 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49,
+ 0x6d, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x41, 0x63,
+ 0x6b, 0x10, 0x93, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f,
+ 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x65, 0x70,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x94, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
+ 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79,
+ 0x6e, 0x63, 0x53, 0x74, 0x65, 0x70, 0x41, 0x63, 0x6b, 0x10, 0x95, 0x04, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x12, 0x35, 0x0a, 0x2a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65,
+ 0x53, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x10, 0x96, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x31, 0x0a, 0x26, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b,
+ 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x61, 0x6c,
+ 0x41, 0x63, 0x6b, 0x10, 0x97, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
+ 0x72, 0x6f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x9c, 0x04, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x10, 0x9d, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
+ 0x6f, 0x47, 0x65, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4b, 0x65, 0x79, 0x10, 0x9e, 0x04, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x57, 0x61, 0x74, 0x63, 0x68,
+ 0x4b, 0x65, 0x79, 0x10, 0x9f, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75,
+ 0x67, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x44, 0x69, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x10, 0xa2, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67,
+ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x44, 0x69, 0x61, 0x67, 0x41, 0x63, 0x6b, 0x10, 0xa3, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2c, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x47, 0x65, 0x74, 0x54,
+ 0x78, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xa6, 0x04, 0x1a, 0x04,
+ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x47, 0x65, 0x74, 0x54, 0x78, 0x4b,
+ 0x65, 0x79, 0x41, 0x63, 0x6b, 0x10, 0xa7, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34,
+ 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f,
+ 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53,
+ 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xa8, 0x04, 0x1a, 0x04,
+ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65,
+ 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xa9, 0x04,
+ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65,
+ 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x10, 0xaa, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2f, 0x0a, 0x24, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
+ 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x65, 0x70,
+ 0x41, 0x63, 0x6b, 0x10, 0xab, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
+ 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x46, 0x69, 0x6e,
+ 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xac, 0x04, 0x1a, 0x04, 0x90, 0xb5,
+ 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
+ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72,
+ 0x65, 0x73, 0x68, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x6b, 0x10, 0xad, 0x04, 0x1a, 0x04,
+ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
+ 0x4b, 0x65, 0x79, 0x10, 0xd8, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x50,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xd9, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18,
+ 0x01, 0x12, 0x20, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x45, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xda, 0x04, 0x1a, 0x04, 0x90,
+ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x54, 0x78, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xdb, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x25,
+ 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f,
+ 0x73, 0x54, 0x78, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0xdc, 0x04, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78,
+ 0x10, 0xdd, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65,
+ 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xbc, 0x05, 0x1a, 0x04, 0x90,
+ 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x10, 0xbd, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63,
+ 0x65, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xbe, 0x05,
+ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x75, 0x62,
+ 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xbf, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12,
+ 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42,
+ 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xc0, 0x05, 0x1a,
+ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x78, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xc1, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x29,
+ 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69,
+ 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x73, 0x67,
+ 0x10, 0xc2, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65,
+ 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x10, 0xc3, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18,
+ 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
+ 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x73,
+ 0x67, 0x10, 0xc4, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63,
+ 0x65, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xc5, 0x05, 0x1a, 0x04, 0x98, 0xb5,
+ 0x18, 0x01, 0x3a, 0x3c, 0x0a, 0x07, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x69, 0x6e, 0x12, 0x21, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x18, 0xd2, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x77, 0x69, 0x72, 0x65, 0x49, 0x6e,
+ 0x3a, 0x3e, 0x0a, 0x08, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x12, 0x21, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
+ 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+ 0xd3, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x77, 0x69, 0x72, 0x65, 0x4f, 0x75, 0x74,
+ 0x3a, 0x47, 0x0a, 0x0d, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69,
+ 0x6e, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd4, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x77, 0x69,
+ 0x72, 0x65, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x3a, 0x49, 0x0a, 0x0e, 0x77, 0x69, 0x72,
+ 0x65, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x12, 0x21, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
+ 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd5,
+ 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x77, 0x69, 0x72, 0x65, 0x44, 0x65, 0x62, 0x75,
+ 0x67, 0x4f, 0x75, 0x74, 0x3a, 0x40, 0x0a, 0x09, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6e,
+ 0x79, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd6, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69,
+ 0x72, 0x65, 0x54, 0x69, 0x6e, 0x79, 0x3a, 0x4c, 0x0a, 0x0f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x62,
+ 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd7, 0x86, 0x03,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x77, 0x69, 0x72, 0x65, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f,
+ 0x61, 0x64, 0x65, 0x72, 0x3a, 0x43, 0x0a, 0x0b, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x6e, 0x6f, 0x5f,
+ 0x66, 0x73, 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd8, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
+ 0x77, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x46, 0x73, 0x6d, 0x42, 0x6f, 0x0a, 0x23, 0x63, 0x6f, 0x6d,
+ 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74, 0x72, 0x65,
+ 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x42, 0x0d, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5a,
+ 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
+ 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c,
+ 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72,
+}
+
+var (
+ file_messages_proto_rawDescOnce sync.Once
+ file_messages_proto_rawDescData = file_messages_proto_rawDesc
+)
+
+func file_messages_proto_rawDescGZIP() []byte {
+ file_messages_proto_rawDescOnce.Do(func() {
+ file_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_proto_rawDescData)
+ })
+ return file_messages_proto_rawDescData
+}
+
+var file_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_messages_proto_goTypes = []any{
+ (MessageType)(0), // 0: hw.trezor.messages.MessageType
+ (*descriptorpb.EnumValueOptions)(nil), // 1: google.protobuf.EnumValueOptions
+}
+var file_messages_proto_depIdxs = []int32{
+ 1, // 0: hw.trezor.messages.wire_in:extendee -> google.protobuf.EnumValueOptions
+ 1, // 1: hw.trezor.messages.wire_out:extendee -> google.protobuf.EnumValueOptions
+ 1, // 2: hw.trezor.messages.wire_debug_in:extendee -> google.protobuf.EnumValueOptions
+ 1, // 3: hw.trezor.messages.wire_debug_out:extendee -> google.protobuf.EnumValueOptions
+ 1, // 4: hw.trezor.messages.wire_tiny:extendee -> google.protobuf.EnumValueOptions
+ 1, // 5: hw.trezor.messages.wire_bootloader:extendee -> google.protobuf.EnumValueOptions
+ 1, // 6: hw.trezor.messages.wire_no_fsm:extendee -> google.protobuf.EnumValueOptions
+ 7, // [7:7] is the sub-list for method output_type
+ 7, // [7:7] is the sub-list for method input_type
+ 7, // [7:7] is the sub-list for extension type_name
+ 0, // [0:7] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_messages_proto_init() }
+func file_messages_proto_init() {
+ if File_messages_proto != nil {
+ return
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_messages_proto_rawDesc,
+ NumEnums: 1,
+ NumMessages: 0,
+ NumExtensions: 7,
+ NumServices: 0,
+ },
+ GoTypes: file_messages_proto_goTypes,
+ DependencyIndexes: file_messages_proto_depIdxs,
+ EnumInfos: file_messages_proto_enumTypes,
+ ExtensionInfos: file_messages_proto_extTypes,
+ }.Build()
+ File_messages_proto = out.File
+ file_messages_proto_rawDesc = nil
+ file_messages_proto_goTypes = nil
+ file_messages_proto_depIdxs = nil
+}
diff --git a/accounts/usbwallet/messages.proto b/accounts/usbwallet/messages.proto
new file mode 100644
index 0000000000..c232bef60d
--- /dev/null
+++ b/accounts/usbwallet/messages.proto
@@ -0,0 +1,267 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages;
+
+/**
+ * Messages for TREZOR communication
+ */
+
+option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessage";
+
+
+import "google/protobuf/descriptor.proto";
+
+/**
+ * Options for specifying message direction and type of wire (normal/debug)
+ */
+extend google.protobuf.EnumValueOptions {
+ optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR
+ optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC
+ optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR
+ optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC
+ optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode
+ optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader
+ optional bool wire_no_fsm = 50008; // message is not handled by TREZOR unless the USB stack is in tiny mode
+}
+
+/**
+ * Mapping between TREZOR wire identifier (uint) and a protobuf message
+ */
+enum MessageType {
+
+ // Management
+ MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = true];
+ MessageType_Ping = 1 [(wire_in) = true];
+ MessageType_Success = 2 [(wire_out) = true];
+ MessageType_Failure = 3 [(wire_out) = true];
+ MessageType_ChangePin = 4 [(wire_in) = true];
+ MessageType_WipeDevice = 5 [(wire_in) = true];
+ MessageType_GetEntropy = 9 [(wire_in) = true];
+ MessageType_Entropy = 10 [(wire_out) = true];
+ MessageType_LoadDevice = 13 [(wire_in) = true];
+ MessageType_ResetDevice = 14 [(wire_in) = true];
+ MessageType_Features = 17 [(wire_out) = true];
+ MessageType_PinMatrixRequest = 18 [(wire_out) = true];
+ MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+ MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true];
+ MessageType_ClearSession = 24 [(wire_in) = true];
+ MessageType_ApplySettings = 25 [(wire_in) = true];
+ MessageType_ButtonRequest = 26 [(wire_out) = true];
+ MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+ MessageType_ApplyFlags = 28 [(wire_in) = true];
+ MessageType_BackupDevice = 34 [(wire_in) = true];
+ MessageType_EntropyRequest = 35 [(wire_out) = true];
+ MessageType_EntropyAck = 36 [(wire_in) = true];
+ MessageType_PassphraseRequest = 41 [(wire_out) = true];
+ MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+ MessageType_PassphraseStateRequest = 77 [(wire_out) = true];
+ MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+ MessageType_RecoveryDevice = 45 [(wire_in) = true];
+ MessageType_WordRequest = 46 [(wire_out) = true];
+ MessageType_WordAck = 47 [(wire_in) = true];
+ MessageType_GetFeatures = 55 [(wire_in) = true];
+ MessageType_SetU2FCounter = 63 [(wire_in) = true];
+
+ // Bootloader
+ MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true];
+ MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true];
+ MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true];
+ MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true];
+
+ // Bitcoin
+ MessageType_GetPublicKey = 11 [(wire_in) = true];
+ MessageType_PublicKey = 12 [(wire_out) = true];
+ MessageType_SignTx = 15 [(wire_in) = true];
+ MessageType_TxRequest = 21 [(wire_out) = true];
+ MessageType_TxAck = 22 [(wire_in) = true];
+ MessageType_GetAddress = 29 [(wire_in) = true];
+ MessageType_Address = 30 [(wire_out) = true];
+ MessageType_SignMessage = 38 [(wire_in) = true];
+ MessageType_VerifyMessage = 39 [(wire_in) = true];
+ MessageType_MessageSignature = 40 [(wire_out) = true];
+
+ // Crypto
+ MessageType_CipherKeyValue = 23 [(wire_in) = true];
+ MessageType_CipheredKeyValue = 48 [(wire_out) = true];
+ MessageType_SignIdentity = 53 [(wire_in) = true];
+ MessageType_SignedIdentity = 54 [(wire_out) = true];
+ MessageType_GetECDHSessionKey = 61 [(wire_in) = true];
+ MessageType_ECDHSessionKey = 62 [(wire_out) = true];
+ MessageType_CosiCommit = 71 [(wire_in) = true];
+ MessageType_CosiCommitment = 72 [(wire_out) = true];
+ MessageType_CosiSign = 73 [(wire_in) = true];
+ MessageType_CosiSignature = 74 [(wire_out) = true];
+
+ // Debug
+ MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+ MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = true];
+ MessageType_DebugLinkState = 102 [(wire_debug_out) = true];
+ MessageType_DebugLinkStop = 103 [(wire_debug_in) = true];
+ MessageType_DebugLinkLog = 104 [(wire_debug_out) = true];
+ MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true];
+ MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true];
+ MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true];
+ MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true];
+
+ // Ethereum
+ MessageType_EthereumGetPublicKey = 450 [(wire_in) = true];
+ MessageType_EthereumPublicKey = 451 [(wire_out) = true];
+ MessageType_EthereumGetAddress = 56 [(wire_in) = true];
+ MessageType_EthereumAddress = 57 [(wire_out) = true];
+ MessageType_EthereumSignTx = 58 [(wire_in) = true];
+ MessageType_EthereumTxRequest = 59 [(wire_out) = true];
+ MessageType_EthereumTxAck = 60 [(wire_in) = true];
+ MessageType_EthereumSignMessage = 64 [(wire_in) = true];
+ MessageType_EthereumVerifyMessage = 65 [(wire_in) = true];
+ MessageType_EthereumMessageSignature = 66 [(wire_out) = true];
+
+ // NEM
+ MessageType_NEMGetAddress = 67 [(wire_in) = true];
+ MessageType_NEMAddress = 68 [(wire_out) = true];
+ MessageType_NEMSignTx = 69 [(wire_in) = true];
+ MessageType_NEMSignedTx = 70 [(wire_out) = true];
+ MessageType_NEMDecryptMessage = 75 [(wire_in) = true];
+ MessageType_NEMDecryptedMessage = 76 [(wire_out) = true];
+
+ // Lisk
+ MessageType_LiskGetAddress = 114 [(wire_in) = true];
+ MessageType_LiskAddress = 115 [(wire_out) = true];
+ MessageType_LiskSignTx = 116 [(wire_in) = true];
+ MessageType_LiskSignedTx = 117 [(wire_out) = true];
+ MessageType_LiskSignMessage = 118 [(wire_in) = true];
+ MessageType_LiskMessageSignature = 119 [(wire_out) = true];
+ MessageType_LiskVerifyMessage = 120 [(wire_in) = true];
+ MessageType_LiskGetPublicKey = 121 [(wire_in) = true];
+ MessageType_LiskPublicKey = 122 [(wire_out) = true];
+
+ // Tezos
+ MessageType_TezosGetAddress = 150 [(wire_in) = true];
+ MessageType_TezosAddress = 151 [(wire_out) = true];
+ MessageType_TezosSignTx = 152 [(wire_in) = true];
+ MessageType_TezosSignedTx = 153 [(wire_out) = true];
+ MessageType_TezosGetPublicKey = 154 [(wire_in) = true];
+ MessageType_TezosPublicKey = 155 [(wire_out) = true];
+
+ // Stellar
+ MessageType_StellarSignTx = 202 [(wire_in) = true];
+ MessageType_StellarTxOpRequest = 203 [(wire_out) = true];
+ MessageType_StellarGetAddress = 207 [(wire_in) = true];
+ MessageType_StellarAddress = 208 [(wire_out) = true];
+ MessageType_StellarCreateAccountOp = 210 [(wire_in) = true];
+ MessageType_StellarPaymentOp = 211 [(wire_in) = true];
+ MessageType_StellarPathPaymentOp = 212 [(wire_in) = true];
+ MessageType_StellarManageOfferOp = 213 [(wire_in) = true];
+ MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true];
+ MessageType_StellarSetOptionsOp = 215 [(wire_in) = true];
+ MessageType_StellarChangeTrustOp = 216 [(wire_in) = true];
+ MessageType_StellarAllowTrustOp = 217 [(wire_in) = true];
+ MessageType_StellarAccountMergeOp = 218 [(wire_in) = true];
+ // omitted: StellarInflationOp is not a supported operation, would be 219
+ MessageType_StellarManageDataOp = 220 [(wire_in) = true];
+ MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true];
+ MessageType_StellarSignedTx = 230 [(wire_out) = true];
+
+ // TRON
+ MessageType_TronGetAddress = 250 [(wire_in) = true];
+ MessageType_TronAddress = 251 [(wire_out) = true];
+ MessageType_TronSignTx = 252 [(wire_in) = true];
+ MessageType_TronSignedTx = 253 [(wire_out) = true];
+
+ // Cardano
+ // dropped Sign/VerifyMessage ids 300-302
+ MessageType_CardanoSignTx = 303 [(wire_in) = true];
+ MessageType_CardanoTxRequest = 304 [(wire_out) = true];
+ MessageType_CardanoGetPublicKey = 305 [(wire_in) = true];
+ MessageType_CardanoPublicKey = 306 [(wire_out) = true];
+ MessageType_CardanoGetAddress = 307 [(wire_in) = true];
+ MessageType_CardanoAddress = 308 [(wire_out) = true];
+ MessageType_CardanoTxAck = 309 [(wire_in) = true];
+ MessageType_CardanoSignedTx = 310 [(wire_out) = true];
+
+ // Ontology
+ MessageType_OntologyGetAddress = 350 [(wire_in) = true];
+ MessageType_OntologyAddress = 351 [(wire_out) = true];
+ MessageType_OntologyGetPublicKey = 352 [(wire_in) = true];
+ MessageType_OntologyPublicKey = 353 [(wire_out) = true];
+ MessageType_OntologySignTransfer = 354 [(wire_in) = true];
+ MessageType_OntologySignedTransfer = 355 [(wire_out) = true];
+ MessageType_OntologySignWithdrawOng = 356 [(wire_in) = true];
+ MessageType_OntologySignedWithdrawOng = 357 [(wire_out) = true];
+ MessageType_OntologySignOntIdRegister = 358 [(wire_in) = true];
+ MessageType_OntologySignedOntIdRegister = 359 [(wire_out) = true];
+ MessageType_OntologySignOntIdAddAttributes = 360 [(wire_in) = true];
+ MessageType_OntologySignedOntIdAddAttributes = 361 [(wire_out) = true];
+
+ // Ripple
+ MessageType_RippleGetAddress = 400 [(wire_in) = true];
+ MessageType_RippleAddress = 401 [(wire_out) = true];
+ MessageType_RippleSignTx = 402 [(wire_in) = true];
+ MessageType_RippleSignedTx = 403 [(wire_in) = true];
+
+ // Monero
+ MessageType_MoneroTransactionInitRequest = 501 [(wire_out) = true];
+ MessageType_MoneroTransactionInitAck = 502 [(wire_out) = true];
+ MessageType_MoneroTransactionSetInputRequest = 503 [(wire_out) = true];
+ MessageType_MoneroTransactionSetInputAck = 504 [(wire_out) = true];
+ MessageType_MoneroTransactionInputsPermutationRequest = 505 [(wire_out) = true];
+ MessageType_MoneroTransactionInputsPermutationAck = 506 [(wire_out) = true];
+ MessageType_MoneroTransactionInputViniRequest = 507 [(wire_out) = true];
+ MessageType_MoneroTransactionInputViniAck = 508 [(wire_out) = true];
+ MessageType_MoneroTransactionAllInputsSetRequest = 509 [(wire_out) = true];
+ MessageType_MoneroTransactionAllInputsSetAck = 510 [(wire_out) = true];
+ MessageType_MoneroTransactionSetOutputRequest = 511 [(wire_out) = true];
+ MessageType_MoneroTransactionSetOutputAck = 512 [(wire_out) = true];
+ MessageType_MoneroTransactionAllOutSetRequest = 513 [(wire_out) = true];
+ MessageType_MoneroTransactionAllOutSetAck = 514 [(wire_out) = true];
+ MessageType_MoneroTransactionSignInputRequest = 515 [(wire_out) = true];
+ MessageType_MoneroTransactionSignInputAck = 516 [(wire_out) = true];
+ MessageType_MoneroTransactionFinalRequest = 517 [(wire_out) = true];
+ MessageType_MoneroTransactionFinalAck = 518 [(wire_out) = true];
+ MessageType_MoneroKeyImageExportInitRequest = 530 [(wire_out) = true];
+ MessageType_MoneroKeyImageExportInitAck = 531 [(wire_out) = true];
+ MessageType_MoneroKeyImageSyncStepRequest = 532 [(wire_out) = true];
+ MessageType_MoneroKeyImageSyncStepAck = 533 [(wire_out) = true];
+ MessageType_MoneroKeyImageSyncFinalRequest = 534 [(wire_out) = true];
+ MessageType_MoneroKeyImageSyncFinalAck = 535 [(wire_out) = true];
+ MessageType_MoneroGetAddress = 540 [(wire_in) = true];
+ MessageType_MoneroAddress = 541 [(wire_out) = true];
+ MessageType_MoneroGetWatchKey = 542 [(wire_in) = true];
+ MessageType_MoneroWatchKey = 543 [(wire_out) = true];
+ MessageType_DebugMoneroDiagRequest = 546 [(wire_in) = true];
+ MessageType_DebugMoneroDiagAck = 547 [(wire_out) = true];
+ MessageType_MoneroGetTxKeyRequest = 550 [(wire_in) = true];
+ MessageType_MoneroGetTxKeyAck = 551 [(wire_out) = true];
+ MessageType_MoneroLiveRefreshStartRequest = 552 [(wire_in) = true];
+ MessageType_MoneroLiveRefreshStartAck = 553 [(wire_out) = true];
+ MessageType_MoneroLiveRefreshStepRequest = 554 [(wire_in) = true];
+ MessageType_MoneroLiveRefreshStepAck = 555 [(wire_out) = true];
+ MessageType_MoneroLiveRefreshFinalRequest = 556 [(wire_in) = true];
+ MessageType_MoneroLiveRefreshFinalAck = 557 [(wire_out) = true];
+
+ // EOS
+ MessageType_EosGetPublicKey = 600 [(wire_in) = true];
+ MessageType_EosPublicKey = 601 [(wire_out) = true];
+ MessageType_EosSignTx = 602 [(wire_in) = true];
+ MessageType_EosTxActionRequest = 603 [(wire_out) = true];
+ MessageType_EosTxActionAck = 604 [(wire_in) = true];
+ MessageType_EosSignedTx = 605 [(wire_out) = true];
+
+ // Binance
+ MessageType_BinanceGetAddress = 700 [(wire_in) = true];
+ MessageType_BinanceAddress = 701 [(wire_out) = true];
+ MessageType_BinanceGetPublicKey = 702 [(wire_in) = true];
+ MessageType_BinancePublicKey = 703 [(wire_out) = true];
+ MessageType_BinanceSignTx = 704 [(wire_in) = true];
+ MessageType_BinanceTxRequest = 705 [(wire_out) = true];
+ MessageType_BinanceTransferMsg = 706 [(wire_in) = true];
+ MessageType_BinanceOrderMsg = 707 [(wire_in) = true];
+ MessageType_BinanceCancelMsg = 708 [(wire_in) = true];
+ MessageType_BinanceSignedTx = 709 [(wire_out) = true];
+}
diff --git a/accounts/usbwallet/trezor.go b/accounts/usbwallet/trezor.go
index d4862d161b..93aee3c289 100644
--- a/accounts/usbwallet/trezor.go
+++ b/accounts/usbwallet/trezor.go
@@ -16,365 +16,55 @@
// This file contains the implementation for interacting with the Trezor hardware
// wallets. The wire protocol spec can be found on the SatoshiLabs website:
-// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
+// https://docs.trezor.io/trezor-firmware/common/message-workflows.html
-package usbwallet
-
-import (
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "math"
- "math/big"
-
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
- "google.golang.org/protobuf/proto"
-)
-
-// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In
-// this case, the calling application should display a pinpad and send back the
-// encoded passphrase.
-var ErrTrezorPINNeeded = errors.New("trezor: pin needed")
-
-// ErrTrezorPassphraseNeeded is returned if opening the trezor requires a passphrase
-var ErrTrezorPassphraseNeeded = errors.New("trezor: passphrase needed")
-
-// errTrezorReplyInvalidHeader is the error message returned by a Trezor data exchange
-// if the device replies with a mismatching header. This usually means the device
-// is in browser mode.
-var errTrezorReplyInvalidHeader = errors.New("trezor: invalid reply header")
-
-// trezorDriver implements the communication with a Trezor hardware wallet.
-type trezorDriver struct {
- device io.ReadWriter // USB device connection to communicate through
- version [3]uint32 // Current version of the Trezor firmware
- label string // Current textual label of the Trezor device
- pinwait bool // Flags whether the device is waiting for PIN entry
- passphrasewait bool // Flags whether the device is waiting for passphrase entry
- failure error // Any failure that would make the device unusable
- log log.Logger // Contextual logger to tag the trezor with its id
-}
-
-// newTrezorDriver creates a new instance of a Trezor USB protocol driver.
-func newTrezorDriver(logger log.Logger) driver {
- return &trezorDriver{
- log: logger,
- }
-}
-
-// Status implements accounts.Wallet, always whether the Trezor is opened, closed
-// or whether the Ethereum app was not started on it.
-func (w *trezorDriver) Status() (string, error) {
- if w.failure != nil {
- return fmt.Sprintf("Failed: %v", w.failure), w.failure
- }
- if w.device == nil {
- return "Closed", w.failure
- }
- if w.pinwait {
- return fmt.Sprintf("Trezor v%d.%d.%d '%s' waiting for PIN", w.version[0], w.version[1], w.version[2], w.label), w.failure
- }
- return fmt.Sprintf("Trezor v%d.%d.%d '%s' online", w.version[0], w.version[1], w.version[2], w.label), w.failure
-}
-
-// Open implements usbwallet.driver, attempting to initialize the connection to
-// the Trezor hardware wallet. Initializing the Trezor is a two or three phase operation:
-// - The first phase is to initialize the connection and read the wallet's
-// features. This phase is invoked if the provided passphrase is empty. The
-// device will display the pinpad as a result and will return an appropriate
-// error to notify the user that a second open phase is needed.
-// - The second phase is to unlock access to the Trezor, which is done by the
-// user actually providing a passphrase mapping a keyboard keypad to the pin
-// number of the user (shuffled according to the pinpad displayed).
-// - If needed the device will ask for passphrase which will require calling
-// open again with the actual passphrase (3rd phase)
-func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error {
- w.device, w.failure = device, nil
-
- // If phase 1 is requested, init the connection and wait for user callback
- if passphrase == "" && !w.passphrasewait {
- // If we're already waiting for a PIN entry, insta-return
- if w.pinwait {
- return ErrTrezorPINNeeded
- }
- // Initialize a connection to the device
- features := new(trezor.Features)
- if _, err := w.trezorExchange(&trezor.Initialize{}, features); err != nil {
- return err
- }
- w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()}
- w.label = features.GetLabel()
-
- // Do a manual ping, forcing the device to ask for its PIN and Passphrase
- askPin := true
- askPassphrase := true
- res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin, PassphraseProtection: &askPassphrase}, new(trezor.PinMatrixRequest), new(trezor.PassphraseRequest), new(trezor.Success))
- if err != nil {
- return err
- }
- // Only return the PIN request if the device wasn't unlocked until now
- switch res {
- case 0:
- w.pinwait = true
- return ErrTrezorPINNeeded
- case 1:
- w.pinwait = false
- w.passphrasewait = true
- return ErrTrezorPassphraseNeeded
- case 2:
- return nil // responded with trezor.Success
- }
- }
- // Phase 2 requested with actual PIN entry
- if w.pinwait {
- w.pinwait = false
- res, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success), new(trezor.PassphraseRequest))
- if err != nil {
- w.failure = err
- return err
- }
- if res == 1 {
- w.passphrasewait = true
- return ErrTrezorPassphraseNeeded
- }
- } else if w.passphrasewait {
- w.passphrasewait = false
- if _, err := w.trezorExchange(&trezor.PassphraseAck{Passphrase: &passphrase}, new(trezor.Success)); err != nil {
- w.failure = err
- return err
- }
- }
-
- return nil
-}
-
-// Close implements usbwallet.driver, cleaning up and metadata maintained within
-// the Trezor driver.
-func (w *trezorDriver) Close() error {
- w.version, w.label, w.pinwait = [3]uint32{}, "", false
- return nil
-}
-
-// Heartbeat implements usbwallet.driver, performing a sanity check against the
-// Trezor to see if it's still online.
-func (w *trezorDriver) Heartbeat() error {
- if _, err := w.trezorExchange(&trezor.Ping{}, new(trezor.Success)); err != nil {
- w.failure = err
- return err
- }
- return nil
-}
-
-// Derive implements usbwallet.driver, sending a derivation request to the Trezor
-// and returning the Ethereum address located on that derivation path.
-func (w *trezorDriver) Derive(path accounts.DerivationPath) (common.Address, error) {
- return w.trezorDerive(path)
-}
-
-// SignTx implements usbwallet.driver, sending the transaction to the Trezor and
-// waiting for the user to confirm or deny the transaction.
-func (w *trezorDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
- if w.device == nil {
- return common.Address{}, nil, accounts.ErrWalletClosed
- }
- return w.trezorSign(path, tx, chainID)
-}
+// !!! STAHP !!!
+//
+// Before you touch the protocol files, you need to be aware of a breaking change
+// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10->
+// 2.1.0 (Model T). The Ethereum address representation was changed from the 20
+// byte binary blob to a 42 byte hex string. The upstream protocol buffer files
+// only support the new format, so blindly pulling in a new spec will break old
+// devices!
+//
+// The Trezor devs had the foresight to add the string version as a new message
+// code instead of replacing the binary one. This means that the proto file can
+// actually define both the old and the new versions as optional. Please ensure
+// that you add back the old addresses everywhere (to avoid name clash. use the
+// addressBin and addressHex names).
+//
+// If in doubt, reach out to @karalabe.
-func (w *trezorDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) {
- return nil, accounts.ErrNotSupported
-}
+// To regenerate the protocol files in this package:
+// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
+// - Build with the usual `./configure && make` and ensure it's on your $PATH
+// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
+// - Grab the latest Go plugin `go get -u google.golang.org/protobuf/cmd/protoc-gen-go`
+// - Vendor in the latest Go plugin `govendor fetch google.golang.org/protobuf/...`
-// trezorDerive sends a derivation request to the Trezor device and returns the
-// Ethereum address located on that path.
-func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, error) {
- address := new(trezor.EthereumAddress)
- if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil {
- return common.Address{}, err
- }
- if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary formats
- return common.BytesToAddress(addr), nil
- }
- if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal formats
- return common.HexToAddress(addr), nil
- }
- return common.Address{}, errors.New("missing derived address")
-}
+//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
-// trezorSign sends the transaction to the Trezor wallet, and waits for the user
-// to confirm or deny the transaction.
-func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
- // Create the transaction initiation message
- data := tx.Data()
- length := uint32(len(data))
+// Package trezor contains the wire protocol.
+package trezor
- request := &trezor.EthereumSignTx{
- AddressN: derivationPath,
- Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(),
- GasPrice: tx.GasPrice().Bytes(),
- GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(),
- Value: tx.Value().Bytes(),
- DataLength: &length,
- }
- if to := tx.To(); to != nil {
- // Non contract deploy, set recipient explicitly
- hex := to.Hex()
- request.ToHex = &hex // Newer firmwares (old will ignore)
- request.ToBin = (*to)[:] // Older firmwares (new will ignore)
- }
- if length > 1024 { // Send the data chunked if that was requested
- request.DataInitialChunk, data = data[:1024], data[1024:]
- } else {
- request.DataInitialChunk, data = data, nil
- }
- if chainID != nil { // EIP-155 transaction, set chain ID explicitly (only 32 bit is supported!?)
- id := uint32(chainID.Int64())
- request.ChainId = &id
- }
- // Send the initiation message and stream content until a signature is returned
- response := new(trezor.EthereumTxRequest)
- if _, err := w.trezorExchange(request, response); err != nil {
- return common.Address{}, nil, err
- }
- for response.DataLength != nil && int(*response.DataLength) <= len(data) {
- chunk := data[:*response.DataLength]
- data = data[*response.DataLength:]
-
- if _, err := w.trezorExchange(&trezor.EthereumTxAck{DataChunk: chunk}, response); err != nil {
- return common.Address{}, nil, err
- }
- }
- // Extract the Ethereum signature and do a sanity validation
- if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 {
- return common.Address{}, nil, errors.New("reply lacks signature")
- } else if response.GetSignatureV() == 0 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
- // for chainId >= (MaxUint32-36)/2, Trezor returns signature bit only
- // https://github.com/trezor/trezor-mcu/pull/399
- return common.Address{}, nil, errors.New("reply lacks signature")
- }
- signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV()))
+import (
+ "reflect"
- // Create the correct signer and signature transform based on the chain ID
- var signer types.Signer
- if chainID == nil {
- signer = new(types.HomesteadSigner)
- } else {
- // Trezor backend does not support typed transactions yet.
- signer = types.NewEIP155Signer(chainID)
- // if chainId is above (MaxUint32 - 36) / 2 then the final v values is returned
- // directly. Otherwise, the returned value is 35 + chainid * 2.
- if signature[64] > 1 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
- signature[64] -= byte(chainID.Uint64()*2 + 35)
- }
- }
+ "google.golang.org/protobuf/proto"
+)
- // Inject the final signature into the transaction and sanity check the sender
- signed, err := tx.WithSignature(signer, signature)
- if err != nil {
- return common.Address{}, nil, err
- }
- sender, err := types.Sender(signer, signed)
- if err != nil {
- return common.Address{}, nil, err
- }
- return sender, signed, nil
+// Type returns the protocol buffer type number of a specific message. If the
+// message is nil, this method panics!
+func Type(msg proto.Message) uint16 {
+ return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()])
}
-// trezorExchange performs a data exchange with the Trezor wallet, sending it a
-// message and retrieving the response. If multiple responses are possible, the
-// method will also return the index of the destination object used.
-func (w *trezorDriver) trezorExchange(req proto.Message, results ...proto.Message) (int, error) {
- // Construct the original message payload to chunk up
- data, err := proto.Marshal(req)
- if err != nil {
- return 0, err
- }
- payload := make([]byte, 8+len(data))
- copy(payload, []byte{0x23, 0x23})
- binary.BigEndian.PutUint16(payload[2:], trezor.Type(req))
- binary.BigEndian.PutUint32(payload[4:], uint32(len(data)))
- copy(payload[8:], data)
-
- // Stream all the chunks to the device
- chunk := make([]byte, 64)
- chunk[0] = 0x3f // Report ID magic number
-
- for len(payload) > 0 {
- // Construct the new message to stream, padding with zeroes if needed
- if len(payload) > 63 {
- copy(chunk[1:], payload[:63])
- payload = payload[63:]
- } else {
- copy(chunk[1:], payload)
- copy(chunk[1+len(payload):], make([]byte, 63-len(payload)))
- payload = nil
- }
- // Send over to the device
- w.log.Trace("Data chunk sent to the Trezor", "chunk", hexutil.Bytes(chunk))
- if _, err := w.device.Write(chunk); err != nil {
- return 0, err
- }
- }
- // Stream the reply back from the wallet in 64 byte chunks
- var (
- kind uint16
- reply []byte
- )
- for {
- // Read the next chunk from the Trezor wallet
- if _, err := io.ReadFull(w.device, chunk); err != nil {
- return 0, err
- }
- w.log.Trace("Data chunk received from the Trezor", "chunk", hexutil.Bytes(chunk))
-
- // Make sure the transport header matches
- if chunk[0] != 0x3f || (len(reply) == 0 && (chunk[1] != 0x23 || chunk[2] != 0x23)) {
- return 0, errTrezorReplyInvalidHeader
- }
- // If it's the first chunk, retrieve the reply message type and total message length
- var payload []byte
-
- if len(reply) == 0 {
- kind = binary.BigEndian.Uint16(chunk[3:5])
- reply = make([]byte, 0, int(binary.BigEndian.Uint32(chunk[5:9])))
- payload = chunk[9:]
- } else {
- payload = chunk[1:]
- }
- // Append to the reply and stop when filled up
- if left := cap(reply) - len(reply); left > len(payload) {
- reply = append(reply, payload...)
- } else {
- reply = append(reply, payload[:left]...)
- break
- }
- }
- // Try to parse the reply into the requested reply message
- if kind == uint16(trezor.MessageType_MessageType_Failure) {
- // Trezor returned a failure, extract and return the message
- failure := new(trezor.Failure)
- if err := proto.Unmarshal(reply, failure); err != nil {
- return 0, err
- }
- return 0, errors.New("trezor: " + failure.GetMessage())
- }
- if kind == uint16(trezor.MessageType_MessageType_ButtonRequest) {
- // Trezor is waiting for user confirmation, ack and wait for the next message
- return w.trezorExchange(&trezor.ButtonAck{}, results...)
- }
- for i, res := range results {
- if trezor.Type(res) == kind {
- return i, proto.Unmarshal(reply, res)
- }
- }
- expected := make([]string, len(results))
- for i, res := range results {
- expected[i] = trezor.Name(trezor.Type(res))
+// Name returns the friendly message type name of a specific protocol buffer
+// type number.
+func Name(kind uint16) string {
+ name := MessageType_name[int32(kind)]
+ if len(name) < 12 {
+ return name
}
- return 0, fmt.Errorf("trezor: expected reply types %s, got %s", expected, trezor.Name(kind))
+ return name[12:]
}
diff --git a/accounts/usbwallet/trezor/trezor.go b/accounts/usbwallet/trezor/trezor.go
deleted file mode 100644
index 93aee3c289..0000000000
--- a/accounts/usbwallet/trezor/trezor.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// This file contains the implementation for interacting with the Trezor hardware
-// wallets. The wire protocol spec can be found on the SatoshiLabs website:
-// https://docs.trezor.io/trezor-firmware/common/message-workflows.html
-
-// !!! STAHP !!!
-//
-// Before you touch the protocol files, you need to be aware of a breaking change
-// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10->
-// 2.1.0 (Model T). The Ethereum address representation was changed from the 20
-// byte binary blob to a 42 byte hex string. The upstream protocol buffer files
-// only support the new format, so blindly pulling in a new spec will break old
-// devices!
-//
-// The Trezor devs had the foresight to add the string version as a new message
-// code instead of replacing the binary one. This means that the proto file can
-// actually define both the old and the new versions as optional. Please ensure
-// that you add back the old addresses everywhere (to avoid name clash. use the
-// addressBin and addressHex names).
-//
-// If in doubt, reach out to @karalabe.
-
-// To regenerate the protocol files in this package:
-// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
-// - Build with the usual `./configure && make` and ensure it's on your $PATH
-// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
-// - Grab the latest Go plugin `go get -u google.golang.org/protobuf/cmd/protoc-gen-go`
-// - Vendor in the latest Go plugin `govendor fetch google.golang.org/protobuf/...`
-
-//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
-
-// Package trezor contains the wire protocol.
-package trezor
-
-import (
- "reflect"
-
- "google.golang.org/protobuf/proto"
-)
-
-// Type returns the protocol buffer type number of a specific message. If the
-// message is nil, this method panics!
-func Type(msg proto.Message) uint16 {
- return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()])
-}
-
-// Name returns the friendly message type name of a specific protocol buffer
-// type number.
-func Name(kind uint16) string {
- name := MessageType_name[int32(kind)]
- if len(name) < 12 {
- return name
- }
- return name[12:]
-}
diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go
deleted file mode 100644
index 0fd0415a9e..0000000000
--- a/accounts/usbwallet/wallet.go
+++ /dev/null
@@ -1,643 +0,0 @@
-// Copyright 2017 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// Package usbwallet implements support for USB hardware wallets.
-package usbwallet
-
-import (
- "context"
- "fmt"
- "io"
- "math/big"
- "sync"
- "time"
-
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/log"
- "github.com/karalabe/hid"
-)
-
-// Maximum time between wallet health checks to detect USB unplugs.
-const heartbeatCycle = time.Second
-
-// Minimum time to wait between self derivation attempts, even it the user is
-// requesting accounts like crazy.
-const selfDeriveThrottling = time.Second
-
-// driver defines the vendor specific functionality hardware wallets instances
-// must implement to allow using them with the wallet lifecycle management.
-type driver interface {
- // Status returns a textual status to aid the user in the current state of the
- // wallet. It also returns an error indicating any failure the wallet might have
- // encountered.
- Status() (string, error)
-
- // Open initializes access to a wallet instance. The passphrase parameter may
- // or may not be used by the implementation of a particular wallet instance.
- Open(device io.ReadWriter, passphrase string) error
-
- // Close releases any resources held by an open wallet instance.
- Close() error
-
- // Heartbeat performs a sanity check against the hardware wallet to see if it
- // is still online and healthy.
- Heartbeat() error
-
- // Derive sends a derivation request to the USB device and returns the Ethereum
- // address located on that path.
- Derive(path accounts.DerivationPath) (common.Address, error)
-
- // SignTx sends the transaction to the USB device and waits for the user to confirm
- // or deny the transaction.
- SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error)
-
- SignTypedMessage(path accounts.DerivationPath, messageHash []byte, domainHash []byte) ([]byte, error)
-}
-
-// wallet represents the common functionality shared by all USB hardware
-// wallets to prevent reimplementing the same complex maintenance mechanisms
-// for different vendors.
-type wallet struct {
- hub *Hub // USB hub scanning
- driver driver // Hardware implementation of the low level device operations
- url *accounts.URL // Textual URL uniquely identifying this wallet
-
- info hid.DeviceInfo // Known USB device infos about the wallet
- device hid.Device // USB device advertising itself as a hardware wallet
-
- accounts []accounts.Account // List of derive accounts pinned on the hardware wallet
- paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
-
- deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported)
- deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported)
- deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
- deriveReq chan chan struct{} // Channel to request a self-derivation on
- deriveQuit chan chan error // Channel to terminate the self-deriver with
-
- healthQuit chan chan error
-
- // Locking a hardware wallet is a bit special. Since hardware devices are lower
- // performing, any communication with them might take a non negligible amount of
- // time. Worse still, waiting for user confirmation can take arbitrarily long,
- // but exclusive communication must be upheld during. Locking the entire wallet
- // in the mean time however would stall any parts of the system that don't want
- // to communicate, just read some state (e.g. list the accounts).
- //
- // As such, a hardware wallet needs two locks to function correctly. A state
- // lock can be used to protect the wallet's software-side internal state, which
- // must not be held exclusively during hardware communication. A communication
- // lock can be used to achieve exclusive access to the device itself, this one
- // however should allow "skipping" waiting for operations that might want to
- // use the device, but can live without too (e.g. account self-derivation).
- //
- // Since we have two locks, it's important to know how to properly use them:
- // - Communication requires the `device` to not change, so obtaining the
- // commsLock should be done after having a stateLock.
- // - Communication must not disable read access to the wallet state, so it
- // must only ever hold a *read* lock to stateLock.
- commsLock chan struct{} // Mutex (buf=1) for the USB comms without keeping the state locked
- stateLock sync.RWMutex // Protects read and write access to the wallet struct fields
-
- log log.Logger // Contextual logger to tag the base with its id
-}
-
-// URL implements accounts.Wallet, returning the URL of the USB hardware device.
-func (w *wallet) URL() accounts.URL {
- return *w.url // Immutable, no need for a lock
-}
-
-// Status implements accounts.Wallet, returning a custom status message from the
-// underlying vendor-specific hardware wallet implementation.
-func (w *wallet) Status() (string, error) {
- w.stateLock.RLock() // No device communication, state lock is enough
- defer w.stateLock.RUnlock()
-
- status, failure := w.driver.Status()
- if w.device == nil {
- return "Closed", failure
- }
- return status, failure
-}
-
-// Open implements accounts.Wallet, attempting to open a USB connection to the
-// hardware wallet.
-func (w *wallet) Open(passphrase string) error {
- w.stateLock.Lock() // State lock is enough since there's no connection yet at this point
- defer w.stateLock.Unlock()
-
- // If the device was already opened once, refuse to try again
- if w.paths != nil {
- return accounts.ErrWalletAlreadyOpen
- }
- // Make sure the actual device connection is done only once
- if w.device == nil {
- device, err := w.info.Open()
- if err != nil {
- return err
- }
- w.device = device
- w.commsLock = make(chan struct{}, 1)
- w.commsLock <- struct{}{} // Enable lock
- }
- // Delegate device initialization to the underlying driver
- if err := w.driver.Open(w.device, passphrase); err != nil {
- return err
- }
- // Connection successful, start life-cycle management
- w.paths = make(map[common.Address]accounts.DerivationPath)
-
- w.deriveReq = make(chan chan struct{})
- w.deriveQuit = make(chan chan error)
- w.healthQuit = make(chan chan error)
-
- go w.heartbeat()
- go w.selfDerive()
-
- // Notify anyone listening for wallet events that a new device is accessible
- go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
-
- return nil
-}
-
-// heartbeat is a health check loop for the USB wallets to periodically verify
-// whether they are still present or if they malfunctioned.
-func (w *wallet) heartbeat() {
- w.log.Debug("USB wallet health-check started")
- defer w.log.Debug("USB wallet health-check stopped")
-
- // Execute heartbeat checks until termination or error
- var (
- errc chan error
- err error
- )
- for errc == nil && err == nil {
- // Wait until termination is requested or the heartbeat cycle arrives
- select {
- case errc = <-w.healthQuit:
- // Termination requested
- continue
- case <-time.After(heartbeatCycle):
- // Heartbeat time
- }
- // Execute a tiny data exchange to see responsiveness
- w.stateLock.RLock()
- if w.device == nil {
- // Terminated while waiting for the lock
- w.stateLock.RUnlock()
- continue
- }
- <-w.commsLock // Don't lock state while resolving version
- err = w.driver.Heartbeat()
- w.commsLock <- struct{}{}
- w.stateLock.RUnlock()
-
- if err != nil {
- w.stateLock.Lock() // Lock state to tear the wallet down
- w.close()
- w.stateLock.Unlock()
- }
- // Ignore non hardware related errors
- err = nil
- }
- // In case of error, wait for termination
- if err != nil {
- w.log.Debug("USB wallet health-check failed", "err", err)
- errc = <-w.healthQuit
- }
- errc <- err
-}
-
-// Close implements accounts.Wallet, closing the USB connection to the device.
-func (w *wallet) Close() error {
- // Ensure the wallet was opened
- w.stateLock.RLock()
- hQuit, dQuit := w.healthQuit, w.deriveQuit
- w.stateLock.RUnlock()
-
- // Terminate the health checks
- var herr error
- if hQuit != nil {
- errc := make(chan error)
- hQuit <- errc
- herr = <-errc // Save for later, we *must* close the USB
- }
- // Terminate the self-derivations
- var derr error
- if dQuit != nil {
- errc := make(chan error)
- dQuit <- errc
- derr = <-errc // Save for later, we *must* close the USB
- }
- // Terminate the device connection
- w.stateLock.Lock()
- defer w.stateLock.Unlock()
-
- w.healthQuit = nil
- w.deriveQuit = nil
- w.deriveReq = nil
-
- if err := w.close(); err != nil {
- return err
- }
- if herr != nil {
- return herr
- }
- return derr
-}
-
-// close is the internal wallet closer that terminates the USB connection and
-// resets all the fields to their defaults.
-//
-// Note, close assumes the state lock is held!
-func (w *wallet) close() error {
- // Allow duplicate closes, especially for health-check failures
- if w.device == nil {
- return nil
- }
- // Close the device, clear everything, then return
- w.device.Close()
- w.device = nil
-
- w.accounts, w.paths = nil, nil
- return w.driver.Close()
-}
-
-// Accounts implements accounts.Wallet, returning the list of accounts pinned to
-// the USB hardware wallet. If self-derivation was enabled, the account list is
-// periodically expanded based on current chain state.
-func (w *wallet) Accounts() []accounts.Account {
- // Attempt self-derivation if it's running
- reqc := make(chan struct{}, 1)
- select {
- case w.deriveReq <- reqc:
- // Self-derivation request accepted, wait for it
- <-reqc
- default:
- // Self-derivation offline, throttled or busy, skip
- }
- // Return whatever account list we ended up with
- w.stateLock.RLock()
- defer w.stateLock.RUnlock()
-
- cpy := make([]accounts.Account, len(w.accounts))
- copy(cpy, w.accounts)
- return cpy
-}
-
-// selfDerive is an account derivation loop that upon request attempts to find
-// new non-zero accounts.
-func (w *wallet) selfDerive() {
- w.log.Debug("USB wallet self-derivation started")
- defer w.log.Debug("USB wallet self-derivation stopped")
-
- // Execute self-derivations until termination or error
- var (
- reqc chan struct{}
- errc chan error
- err error
- )
- for errc == nil && err == nil {
- // Wait until either derivation or termination is requested
- select {
- case errc = <-w.deriveQuit:
- // Termination requested
- continue
- case reqc = <-w.deriveReq:
- // Account discovery requested
- }
- // Derivation needs a chain and device access, skip if either unavailable
- w.stateLock.RLock()
- if w.device == nil || w.deriveChain == nil {
- w.stateLock.RUnlock()
- reqc <- struct{}{}
- continue
- }
- select {
- case <-w.commsLock:
- default:
- w.stateLock.RUnlock()
- reqc <- struct{}{}
- continue
- }
- // Device lock obtained, derive the next batch of accounts
- var (
- accs []accounts.Account
- paths []accounts.DerivationPath
-
- nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...)
- nextAddrs = append([]common.Address{}, w.deriveNextAddrs...)
-
- context = context.Background()
- )
- for i := 0; i < len(nextAddrs); i++ {
- for empty := false; !empty; {
- // Retrieve the next derived Ethereum account
- if nextAddrs[i] == (common.Address{}) {
- if nextAddrs[i], err = w.driver.Derive(nextPaths[i]); err != nil {
- w.log.Warn("USB wallet account derivation failed", "err", err)
- break
- }
- }
- // Check the account's status against the current chain state
- var (
- balance *big.Int
- nonce uint64
- )
- balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil)
- if err != nil {
- w.log.Warn("USB wallet balance retrieval failed", "err", err)
- break
- }
- nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil)
- if err != nil {
- w.log.Warn("USB wallet nonce retrieval failed", "err", err)
- break
- }
- // We've just self-derived a new account, start tracking it locally
- // unless the account was empty.
- path := make(accounts.DerivationPath, len(nextPaths[i]))
- copy(path[:], nextPaths[i][:])
- if balance.Sign() == 0 && nonce == 0 {
- empty = true
- // If it indeed was empty, make a log output for it anyway. In the case
- // of legacy-ledger, the first account on the legacy-path will
- // be shown to the user, even if we don't actively track it
- if i < len(nextAddrs)-1 {
- w.log.Info("Skipping tracking first account on legacy path, use personal.deriveAccount(,, false) to track",
- "path", path, "address", nextAddrs[i])
- break
- }
- }
- paths = append(paths, path)
- account := accounts.Account{
- Address: nextAddrs[i],
- URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
- }
- accs = append(accs, account)
-
- // Display a log message to the user for new (or previously empty accounts)
- if _, known := w.paths[nextAddrs[i]]; !known || (!empty && nextAddrs[i] == w.deriveNextAddrs[i]) {
- w.log.Info("USB wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce)
- }
- // Fetch the next potential account
- if !empty {
- nextAddrs[i] = common.Address{}
- nextPaths[i][len(nextPaths[i])-1]++
- }
- }
- }
- // Self derivation complete, release device lock
- w.commsLock <- struct{}{}
- w.stateLock.RUnlock()
-
- // Insert any accounts successfully derived
- w.stateLock.Lock()
- for i := 0; i < len(accs); i++ {
- if _, ok := w.paths[accs[i].Address]; !ok {
- w.accounts = append(w.accounts, accs[i])
- w.paths[accs[i].Address] = paths[i]
- }
- }
- // Shift the self-derivation forward
- // TODO(karalabe): don't overwrite changes from wallet.SelfDerive
- w.deriveNextAddrs = nextAddrs
- w.deriveNextPaths = nextPaths
- w.stateLock.Unlock()
-
- // Notify the user of termination and loop after a bit of time (to avoid trashing)
- reqc <- struct{}{}
- if err == nil {
- select {
- case errc = <-w.deriveQuit:
- // Termination requested, abort
- case <-time.After(selfDeriveThrottling):
- // Waited enough, willing to self-derive again
- }
- }
- }
- // In case of error, wait for termination
- if err != nil {
- w.log.Debug("USB wallet self-derivation failed", "err", err)
- errc = <-w.deriveQuit
- }
- errc <- err
-}
-
-// Contains implements accounts.Wallet, returning whether a particular account is
-// or is not pinned into this wallet instance. Although we could attempt to resolve
-// unpinned accounts, that would be an non-negligible hardware operation.
-func (w *wallet) Contains(account accounts.Account) bool {
- w.stateLock.RLock()
- defer w.stateLock.RUnlock()
-
- _, exists := w.paths[account.Address]
- return exists
-}
-
-// Derive implements accounts.Wallet, deriving a new account at the specific
-// derivation path. If pin is set to true, the account will be added to the list
-// of tracked accounts.
-func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
- // Try to derive the actual account and update its URL if successful
- w.stateLock.RLock() // Avoid device disappearing during derivation
-
- if w.device == nil {
- w.stateLock.RUnlock()
- return accounts.Account{}, accounts.ErrWalletClosed
- }
- <-w.commsLock // Avoid concurrent hardware access
- address, err := w.driver.Derive(path)
- w.commsLock <- struct{}{}
-
- w.stateLock.RUnlock()
-
- // If an error occurred or no pinning was requested, return
- if err != nil {
- return accounts.Account{}, err
- }
- account := accounts.Account{
- Address: address,
- URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
- }
- if !pin {
- return account, nil
- }
- // Pinning needs to modify the state
- w.stateLock.Lock()
- defer w.stateLock.Unlock()
-
- if w.device == nil {
- return accounts.Account{}, accounts.ErrWalletClosed
- }
-
- if _, ok := w.paths[address]; !ok {
- w.accounts = append(w.accounts, account)
- w.paths[address] = make(accounts.DerivationPath, len(path))
- copy(w.paths[address], path)
- }
- return account, nil
-}
-
-// SelfDerive sets a base account derivation path from which the wallet attempts
-// to discover non zero accounts and automatically add them to list of tracked
-// accounts.
-//
-// Note, self derivation will increment the last component of the specified path
-// opposed to descending into a child path to allow discovering accounts starting
-// from non zero components.
-//
-// Some hardware wallets switched derivation paths through their evolution, so
-// this method supports providing multiple bases to discover old user accounts
-// too. Only the last base will be used to derive the next empty account.
-//
-// You can disable automatic account discovery by calling SelfDerive with a nil
-// chain state reader.
-func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
- w.stateLock.Lock()
- defer w.stateLock.Unlock()
-
- w.deriveNextPaths = make([]accounts.DerivationPath, len(bases))
- for i, base := range bases {
- w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base))
- copy(w.deriveNextPaths[i][:], base[:])
- }
- w.deriveNextAddrs = make([]common.Address, len(bases))
- w.deriveChain = chain
-}
-
-// signHash implements accounts.Wallet, however signing arbitrary data is not
-// supported for hardware wallets, so this method will always return an error.
-func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) {
- return nil, accounts.ErrNotSupported
-}
-
-// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
-func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
- // Unless we are doing 712 signing, simply dispatch to signHash
- if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) {
- return w.signHash(account, crypto.Keccak256(data))
- }
-
- // dispatch to 712 signing if the mimetype is TypedData and the format matches
- w.stateLock.RLock() // Comms have own mutex, this is for the state fields
- defer w.stateLock.RUnlock()
-
- // If the wallet is closed, abort
- if w.device == nil {
- return nil, accounts.ErrWalletClosed
- }
- // Make sure the requested account is contained within
- path, ok := w.paths[account.Address]
- if !ok {
- return nil, accounts.ErrUnknownAccount
- }
- // All infos gathered and metadata checks out, request signing
- <-w.commsLock
- defer func() { w.commsLock <- struct{}{} }()
-
- // Ensure the device isn't screwed with while user confirmation is pending
- // TODO(karalabe): remove if hotplug lands on Windows
- w.hub.commsLock.Lock()
- w.hub.commsPend++
- w.hub.commsLock.Unlock()
-
- defer func() {
- w.hub.commsLock.Lock()
- w.hub.commsPend--
- w.hub.commsLock.Unlock()
- }()
- // Sign the transaction
- signature, err := w.driver.SignTypedMessage(path, data[2:34], data[34:66])
- if err != nil {
- return nil, err
- }
- return signature, nil
-}
-
-// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given
-// data with the given account using passphrase as extra authentication.
-// Since USB wallets don't rely on passphrases, these are silently ignored.
-func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) {
- return w.SignData(account, mimeType, data)
-}
-
-func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) {
- return w.signHash(account, accounts.TextHash(text))
-}
-
-// SignTx implements accounts.Wallet. It sends the transaction over to the Ledger
-// wallet to request a confirmation from the user. It returns either the signed
-// transaction or a failure if the user denied the transaction.
-//
-// Note, if the version of the Ethereum application running on the Ledger wallet is
-// too old to sign EIP-155 transactions, but such is requested nonetheless, an error
-// will be returned opposed to silently signing in Homestead mode.
-func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
- w.stateLock.RLock() // Comms have own mutex, this is for the state fields
- defer w.stateLock.RUnlock()
-
- // If the wallet is closed, abort
- if w.device == nil {
- return nil, accounts.ErrWalletClosed
- }
- // Make sure the requested account is contained within
- path, ok := w.paths[account.Address]
- if !ok {
- return nil, accounts.ErrUnknownAccount
- }
- // All infos gathered and metadata checks out, request signing
- <-w.commsLock
- defer func() { w.commsLock <- struct{}{} }()
-
- // Ensure the device isn't screwed with while user confirmation is pending
- // TODO(karalabe): remove if hotplug lands on Windows
- w.hub.commsLock.Lock()
- w.hub.commsPend++
- w.hub.commsLock.Unlock()
-
- defer func() {
- w.hub.commsLock.Lock()
- w.hub.commsPend--
- w.hub.commsLock.Unlock()
- }()
- // Sign the transaction and verify the sender to avoid hardware fault surprises
- sender, signed, err := w.driver.SignTx(path, tx, chainID)
- if err != nil {
- return nil, err
- }
- if sender != account.Address {
- return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex())
- }
- return signed, nil
-}
-
-// SignTextWithPassphrase implements accounts.Wallet, however signing arbitrary
-// data is not supported for Ledger wallets, so this method will always return
-// an error.
-func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
- return w.SignText(account, accounts.TextHash(text))
-}
-
-// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given
-// transaction with the given account using passphrase as extra authentication.
-// Since USB wallets don't rely on passphrases, these are silently ignored.
-func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
- return w.SignTx(account, tx, chainID)
-}
diff --git a/beacon/blsync/block_sync_test.go b/beacon/blsync/block_sync_test.go
index e7c2c4d163..e471766738 100644
--- a/beacon/blsync/block_sync_test.go
+++ b/beacon/blsync/block_sync_test.go
@@ -32,7 +32,7 @@ var (
testServer2 = testServer("testServer2")
testBlock1 = types.NewBeaconBlock(&deneb.BeaconBlock{
- Slot: 123,
+ Slot: 127,
Body: deneb.BeaconBlockBody{
ExecutionPayload: deneb.ExecutionPayload{
BlockNumber: 456,
@@ -41,7 +41,7 @@ var (
},
})
testBlock2 = types.NewBeaconBlock(&deneb.BeaconBlock{
- Slot: 124,
+ Slot: 128,
Body: deneb.BeaconBlockBody{
ExecutionPayload: deneb.ExecutionPayload{
BlockNumber: 457,
@@ -49,6 +49,14 @@ var (
},
},
})
+ testFinal1 = types.NewExecutionHeader(&deneb.ExecutionPayloadHeader{
+ BlockNumber: 395,
+ BlockHash: zrntcommon.Hash32(common.HexToHash("abbe7625624bf8ddd84723709e2758956289465dd23475f02387e0854942666")),
+ })
+ testFinal2 = types.NewExecutionHeader(&deneb.ExecutionPayloadHeader{
+ BlockNumber: 420,
+ BlockHash: zrntcommon.Hash32(common.HexToHash("9182a6ef8723654de174283750932ccc092378549836bf4873657eeec474598")),
+ })
)
type testServer string
@@ -66,9 +74,10 @@ func TestBlockSync(t *testing.T) {
ts.AddServer(testServer1, 1)
ts.AddServer(testServer2, 1)
- expHeadBlock := func(expHead *types.BeaconBlock) {
+ expHeadEvent := func(expHead *types.BeaconBlock, expFinal *types.ExecutionHeader) {
t.Helper()
var expNumber, headNumber uint64
+ var expFinalHash, finalHash common.Hash
if expHead != nil {
p, err := expHead.ExecutionPayload()
if err != nil {
@@ -76,19 +85,26 @@ func TestBlockSync(t *testing.T) {
}
expNumber = p.NumberU64()
}
+ if expFinal != nil {
+ expFinalHash = expFinal.BlockHash()
+ }
select {
case event := <-headCh:
headNumber = event.Block.NumberU64()
+ finalHash = event.Finalized
default:
}
if headNumber != expNumber {
t.Errorf("Wrong head block, expected block number %d, got %d)", expNumber, headNumber)
}
+ if finalHash != expFinalHash {
+ t.Errorf("Wrong finalized block, expected block hash %064x, got %064x)", expFinalHash[:], finalHash[:])
+ }
}
// no block requests expected until head tracker knows about a head
ts.Run(1)
- expHeadBlock(nil)
+ expHeadEvent(nil, nil)
// set block 1 as prefetch head, announced by server 2
head1 := blockHeadInfo(testBlock1)
@@ -103,12 +119,13 @@ func TestBlockSync(t *testing.T) {
ts.AddAllowance(testServer2, 1)
ts.Run(3)
// head block still not expected as the fetched block is not the validated head yet
- expHeadBlock(nil)
+ expHeadEvent(nil, nil)
// set as validated head, expect no further requests but block 1 set as head block
ht.validated.Header = testBlock1.Header()
+ ht.finalized, ht.finalizedPayload = testBlock1.Header(), testFinal1
ts.Run(4)
- expHeadBlock(testBlock1)
+ expHeadEvent(testBlock1, testFinal1)
// set block 2 as prefetch head, announced by server 1
head2 := blockHeadInfo(testBlock2)
@@ -126,17 +143,26 @@ func TestBlockSync(t *testing.T) {
// expect req2 retry to server 2
ts.Run(7, testServer2, sync.ReqBeaconBlock(head2.BlockRoot))
// now head block should be unavailable again
- expHeadBlock(nil)
+ expHeadEvent(nil, nil)
// valid response, now head block should be block 2 immediately as it is already validated
+ // but head event is still not expected because an epoch boundary was crossed and the
+ // expected finality update has not arrived yet
ts.RequestEvent(request.EvResponse, ts.Request(7, 1), testBlock2)
ts.Run(8)
- expHeadBlock(testBlock2)
+ expHeadEvent(nil, nil)
+
+ // expected finality update arrived, now a head event is expected
+ ht.finalized, ht.finalizedPayload = testBlock2.Header(), testFinal2
+ ts.Run(9)
+ expHeadEvent(testBlock2, testFinal2)
}
type testHeadTracker struct {
- prefetch types.HeadInfo
- validated types.SignedHeader
+ prefetch types.HeadInfo
+ validated types.SignedHeader
+ finalized types.Header
+ finalizedPayload *types.ExecutionHeader
}
func (h *testHeadTracker) PrefetchHead() types.HeadInfo {
@@ -151,13 +177,14 @@ func (h *testHeadTracker) ValidatedOptimistic() (types.OptimisticUpdate, bool) {
}, h.validated.Header != (types.Header{})
}
-// TODO add test case for finality
func (h *testHeadTracker) ValidatedFinality() (types.FinalityUpdate, bool) {
- finalized := types.NewExecutionHeader(new(deneb.ExecutionPayloadHeader))
+ if h.validated.Header == (types.Header{}) || h.finalizedPayload == nil {
+ return types.FinalityUpdate{}, false
+ }
return types.FinalityUpdate{
- Attested: types.HeaderWithExecProof{Header: h.validated.Header},
- Finalized: types.HeaderWithExecProof{PayloadHeader: finalized},
+ Attested: types.HeaderWithExecProof{Header: h.finalized},
+ Finalized: types.HeaderWithExecProof{Header: h.finalized, PayloadHeader: h.finalizedPayload},
Signature: h.validated.Signature,
SignatureSlot: h.validated.SignatureSlot,
- }, h.validated.Header != (types.Header{})
+ }, true
}
diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go
index 93eba347ca..b98c718806 100644
--- a/beacon/engine/gen_epe.go
+++ b/beacon/engine/gen_epe.go
@@ -18,7 +18,7 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ BlobsBundle *BlobsBundle `json:"blobsBundle"`
Requests []hexutil.Bytes `json:"executionRequests"`
Override bool `json:"shouldOverrideBuilder"`
Witness *hexutil.Bytes `json:"witness,omitempty"`
@@ -45,7 +45,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ BlobsBundle *BlobsBundle `json:"blobsBundle"`
Requests []hexutil.Bytes `json:"executionRequests"`
Override *bool `json:"shouldOverrideBuilder"`
Witness *hexutil.Bytes `json:"witness,omitempty"`
diff --git a/beacon/engine/types.go b/beacon/engine/types.go
index b165686fcd..717769c66b 100644
--- a/beacon/engine/types.go
+++ b/beacon/engine/types.go
@@ -33,8 +33,22 @@ import (
type PayloadVersion byte
var (
+ // PayloadV1 is the identifier of ExecutionPayloadV1 introduced in paris fork.
+ // https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#executionpayloadv1
PayloadV1 PayloadVersion = 0x1
+
+ // PayloadV2 is the identifier of ExecutionPayloadV2 introduced in shanghai fork.
+ //
+ // https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#executionpayloadv2
+ // ExecutionPayloadV2 has the syntax of ExecutionPayloadV1 and appends a
+ // single field: withdrawals.
PayloadV2 PayloadVersion = 0x2
+
+ // PayloadV3 is the identifier of ExecutionPayloadV3 introduced in cancun fork.
+ //
+ // https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#executionpayloadv3
+ // ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new
+ // fields: blobGasUsed and excessBlobGas.
PayloadV3 PayloadVersion = 0x3
)
@@ -130,7 +144,7 @@ type StatelessPayloadStatusV1 struct {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+ BlobsBundle *BlobsBundle `json:"blobsBundle"`
Requests [][]byte `json:"executionRequests"`
Override bool `json:"shouldOverrideBuilder"`
Witness *hexutil.Bytes `json:"witness,omitempty"`
@@ -138,7 +152,12 @@ type ExecutionPayloadEnvelope struct {
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"`
}
-type BlobsBundleV1 struct {
+// BlobsBundle includes the marshalled sidecar data. Note this structure is
+// shared by BlobsBundleV1 and BlobsBundleV2 for the sake of simplicity.
+//
+// - BlobsBundleV1: proofs contain exactly len(blobs) kzg proofs.
+// - BlobsBundleV2: proofs contain exactly CELLS_PER_EXT_BLOB * len(blobs) cell proofs.
+type BlobsBundle struct {
Commitments []hexutil.Bytes `json:"commitments"`
Proofs []hexutil.Bytes `json:"proofs"`
Blobs []hexutil.Bytes `json:"blobs"`
@@ -151,7 +170,7 @@ type BlobAndProofV1 struct {
type BlobAndProofV2 struct {
Blob hexutil.Bytes `json:"blob"`
- CellProofs []hexutil.Bytes `json:"proofs"`
+ CellProofs []hexutil.Bytes `json:"proofs"` // proofs MUST contain exactly CELLS_PER_EXT_BLOB cell proofs.
}
// JSON type overrides for ExecutionPayloadEnvelope.
@@ -377,18 +396,27 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
}
// Add blobs.
- bundle := BlobsBundleV1{
+ bundle := BlobsBundle{
Commitments: make([]hexutil.Bytes, 0),
Blobs: make([]hexutil.Bytes, 0),
Proofs: make([]hexutil.Bytes, 0),
}
for _, sidecar := range sidecars {
for j := range sidecar.Blobs {
- bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
- bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:]))
+ bundle.Blobs = append(bundle.Blobs, sidecar.Blobs[j][:])
+ bundle.Commitments = append(bundle.Commitments, sidecar.Commitments[j][:])
}
+ // - Before the Osaka fork, only version-0 blob transactions should be packed,
+ // with the proof length equal to len(blobs).
+ //
+ // - After the Osaka fork, only version-1 blob transactions should be packed,
+ // with the proof length equal to CELLS_PER_EXT_BLOB * len(blobs).
+ //
+ // Ideally, length validation should be performed based on the bundle version.
+ // In practice, this is unnecessary because blob transaction filtering is
+ // already done during payload construction.
for _, proof := range sidecar.Proofs {
- bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(proof[:]))
+ bundle.Proofs = append(bundle.Proofs, proof[:])
}
}
diff --git a/beacon/params/config.go b/beacon/params/config.go
index 2f6ba082c5..492ee53308 100644
--- a/beacon/params/config.go
+++ b/beacon/params/config.go
@@ -20,6 +20,7 @@ import (
"crypto/sha256"
"fmt"
"math"
+ "math/big"
"os"
"slices"
"sort"
@@ -90,12 +91,8 @@ func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainC
// LoadForks parses the beacon chain configuration file (config.yaml) and extracts
// the list of forks.
-func (c *ChainConfig) LoadForks(path string) error {
- file, err := os.ReadFile(path)
- if err != nil {
- return fmt.Errorf("failed to read beacon chain config file: %v", err)
- }
- config := make(map[string]string)
+func (c *ChainConfig) LoadForks(file []byte) error {
+ config := make(map[string]any)
if err := yaml.Unmarshal(file, &config); err != nil {
return fmt.Errorf("failed to parse beacon chain config file: %v", err)
}
@@ -108,18 +105,36 @@ func (c *ChainConfig) LoadForks(path string) error {
for key, value := range config {
if strings.HasSuffix(key, "_FORK_VERSION") {
name := key[:len(key)-len("_FORK_VERSION")]
- if v, err := hexutil.Decode(value); err == nil {
+ switch version := value.(type) {
+ case int:
+ versions[name] = new(big.Int).SetUint64(uint64(version)).FillBytes(make([]byte, 4))
+ case uint64:
+ versions[name] = new(big.Int).SetUint64(version).FillBytes(make([]byte, 4))
+ case string:
+ v, err := hexutil.Decode(version)
+ if err != nil {
+ return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", version, err)
+ }
versions[name] = v
- } else {
- return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err)
+ default:
+ return fmt.Errorf("invalid fork version %q in beacon chain config file", version)
}
}
if strings.HasSuffix(key, "_FORK_EPOCH") {
name := key[:len(key)-len("_FORK_EPOCH")]
- if v, err := strconv.ParseUint(value, 10, 64); err == nil {
+ switch epoch := value.(type) {
+ case int:
+ epochs[name] = uint64(epoch)
+ case uint64:
+ epochs[name] = epoch
+ case string:
+ v, err := strconv.ParseUint(epoch, 10, 64)
+ if err != nil {
+ return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", epoch, err)
+ }
epochs[name] = v
- } else {
- return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err)
+ default:
+ return fmt.Errorf("invalid fork epoch %q in beacon chain config file", epoch)
}
}
}
diff --git a/beacon/params/config_test.go b/beacon/params/config_test.go
new file mode 100644
index 0000000000..41e120469b
--- /dev/null
+++ b/beacon/params/config_test.go
@@ -0,0 +1,34 @@
+package params
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestChainConfig_LoadForks(t *testing.T) {
+ const config = `
+GENESIS_FORK_VERSION: 0x00000000
+
+ALTAIR_FORK_VERSION: 0x00000001
+ALTAIR_FORK_EPOCH: 1
+
+EIP7928_FORK_VERSION: 0xb0000038
+EIP7928_FORK_EPOCH: 18446744073709551615
+
+BLOB_SCHEDULE: []
+`
+ c := &ChainConfig{}
+ err := c.LoadForks([]byte(config))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, fork := range c.Forks {
+ if fork.Name == "GENESIS" && (fork.Epoch != 0) {
+ t.Errorf("unexpected genesis fork epoch %d", fork.Epoch)
+ }
+ if fork.Name == "ALTAIR" && (fork.Epoch != 1 || !bytes.Equal(fork.Version, []byte{0, 0, 0, 1})) {
+ t.Errorf("unexpected altair fork epoch %d version %x", fork.Epoch, fork.Version)
+ }
+ }
+}
diff --git a/build/checksums.txt b/build/checksums.txt
index ab0f7547f6..98ee3a91ef 100644
--- a/build/checksums.txt
+++ b/build/checksums.txt
@@ -1,113 +1,85 @@
# This file contains sha256 checksums of optional build dependencies.
-# version:spec-tests fusaka-devnet-3%40v1.0.0
+# version:spec-tests v5.1.0
# https://github.com/ethereum/execution-spec-tests/releases
-# https://github.com/ethereum/execution-spec-tests/releases/download/fusaka-devnet-3%40v1.0.0
-576261e1280e5300c458aa9b05eccb2fec5ff80a0005940dc52fa03fdd907249 fixtures_fusaka-devnet-3.tar.gz
+# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
+a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
-# version:golang 1.25.0
+# version:golang 1.25.1
# https://go.dev/dl/
-4bd01e91297207bfa450ea40d4d5a93b1b531a5e438473b2a06e18e077227225 go1.25.0.src.tar.gz
-e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4 go1.25.0.aix-ppc64.tar.gz
-5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef go1.25.0.darwin-amd64.tar.gz
-95e836238bcf8f9a71bffea43344cbd35ee1f16db3aaced2f98dbac045d102db go1.25.0.darwin-amd64.pkg
-544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c go1.25.0.darwin-arm64.tar.gz
-202a0d8338c152cb4c9f04782429e9ba8bef31d9889272380837e4043c9d800a go1.25.0.darwin-arm64.pkg
-5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120 go1.25.0.dragonfly-amd64.tar.gz
-abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e go1.25.0.freebsd-386.tar.gz
-86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b go1.25.0.freebsd-amd64.tar.gz
-d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe go1.25.0.freebsd-arm.tar.gz
-451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e go1.25.0.freebsd-arm64.tar.gz
-7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe go1.25.0.freebsd-riscv64.tar.gz
-b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c go1.25.0.illumos-amd64.tar.gz
-8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a go1.25.0.linux-386.tar.gz
-2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613 go1.25.0.linux-amd64.tar.gz
-05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae go1.25.0.linux-arm64.tar.gz
-a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09 go1.25.0.linux-armv6l.tar.gz
-cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc go1.25.0.linux-loong64.tar.gz
-d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1 go1.25.0.linux-mips.tar.gz
-4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2 go1.25.0.linux-mips64.tar.gz
-70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc go1.25.0.linux-mips64le.tar.gz
-b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73 go1.25.0.linux-mipsle.tar.gz
-df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1 go1.25.0.linux-ppc64.tar.gz
-0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0 go1.25.0.linux-ppc64le.tar.gz
-c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67 go1.25.0.linux-riscv64.tar.gz
-34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408 go1.25.0.linux-s390x.tar.gz
-f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba go1.25.0.netbsd-386.tar.gz
-ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a go1.25.0.netbsd-amd64.tar.gz
-1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7 go1.25.0.netbsd-arm.tar.gz
-e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16 go1.25.0.netbsd-arm64.tar.gz
-4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8 go1.25.0.openbsd-386.tar.gz
-c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1 go1.25.0.openbsd-amd64.tar.gz
-a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d go1.25.0.openbsd-arm.tar.gz
-343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d go1.25.0.openbsd-arm64.tar.gz
-694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154 go1.25.0.openbsd-ppc64.tar.gz
-aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f go1.25.0.openbsd-riscv64.tar.gz
-46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986 go1.25.0.plan9-386.tar.gz
-29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b go1.25.0.plan9-amd64.tar.gz
-0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2 go1.25.0.plan9-arm.tar.gz
-9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611 go1.25.0.solaris-amd64.tar.gz
-df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7 go1.25.0.windows-386.zip
-afd9e0a8d2665ff122c8302bb4a3ce4a5331e4e630ddc388be1f9238adfa8fe3 go1.25.0.windows-386.msi
-89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b go1.25.0.windows-amd64.zip
-936bd87109da515f79d80211de5bc6cbda071f2cc577f7e6af1a9e754ea34819 go1.25.0.windows-amd64.msi
-27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c go1.25.0.windows-arm64.zip
-357d030b217ff68e700b6cfc56097bc21ad493bb45b79733a052d112f5031ed9 go1.25.0.windows-arm64.msi
+d010c109cee94d80efe681eab46bdea491ac906bf46583c32e9f0dbb0bd1a594 go1.25.1.src.tar.gz
+1d622468f767a1b9fe1e1e67bd6ce6744d04e0c68712adc689748bbeccb126bb go1.25.1.darwin-amd64.tar.gz
+68deebb214f39d542e518ebb0598a406ab1b5a22bba8ec9ade9f55fb4dd94a6c go1.25.1.darwin-arm64.tar.gz
+d03cdcbc9bd8baf5cf028de390478e9e2b3e4d0afe5a6582dedc19bfe6a263b2 go1.25.1.linux-386.tar.gz
+7716a0d940a0f6ae8e1f3b3f4f36299dc53e31b16840dbd171254312c41ca12e go1.25.1.linux-amd64.tar.gz
+65a3e34fb2126f55b34e1edfc709121660e1be2dee6bdf405fc399a63a95a87d go1.25.1.linux-arm64.tar.gz
+eb949be683e82a99e9861dafd7057e31ea40b161eae6c4cd18fdc0e8c4ae6225 go1.25.1.linux-armv6l.tar.gz
+be13d5479b8c75438f2efcaa8c191fba3af684b3228abc9c99c7aa8502f34424 go1.25.1.windows-386.zip
+4a974de310e7ee1d523d2fcedb114ba5fa75408c98eb3652023e55ccf3fa7cab go1.25.1.windows-amd64.zip
+45ab4290adbd6ee9e7f18f0d57eaa9008fdbef590882778ed93eac3c8cca06c5 go1.25.1.aix-ppc64.tar.gz
+2e3c1549bed3124763774d648f291ac42611232f48320ebbd23517c909c09b81 go1.25.1.dragonfly-amd64.tar.gz
+dc0198dd4ec520e13f26798def8750544edf6448d8e9c43fd2a814e4885932af go1.25.1.freebsd-386.tar.gz
+c4f1a7e7b258406e6f3b677ecdbd97bbb23ff9c0d44be4eb238a07d360f69ac8 go1.25.1.freebsd-amd64.tar.gz
+7772fc5ff71ed39297ec0c1599fc54e399642c9b848eac989601040923b0de9c go1.25.1.freebsd-arm.tar.gz
+5bb011d5d5b6218b12189f07aa0be618ab2002662fff1ca40afba7389735c207 go1.25.1.freebsd-arm64.tar.gz
+ccac716240cb049bebfafcb7eebc3758512178a4c51fc26da9cc032035d850c8 go1.25.1.freebsd-riscv64.tar.gz
+cc53910ffb9fcfdd988a9fa25b5423bae1cfa01b19616be646700e1f5453b466 go1.25.1.illumos-amd64.tar.gz
+efe809f923bcedab44bf7be2b3af8d182b512b1bf9c07d302e0c45d26c8f56f3 go1.25.1.linux-loong64.tar.gz
+c0de33679f6ed68991dc42dc4a602e74a666e3e166c1748ee1b5d1a7ea2ffbb2 go1.25.1.linux-mips.tar.gz
+c270f7b0c0bdfbcd54fef4481227c40d41bb518f9ae38ee930870f04a0a6a589 go1.25.1.linux-mips64.tar.gz
+80be871ba9c944f34d1868cdf5047e1cf2e1289fe08cdb90e2453d2f0d6965ae go1.25.1.linux-mips64le.tar.gz
+9f09defa9bb22ebf2cde76162f40958564e57ce5c2b3649bc063bebcbc9294c1 go1.25.1.linux-mipsle.tar.gz
+2c76b7d278c1d43ad19d478ad3f0f05e7b782b64b90870701b314fa48b5f43c6 go1.25.1.linux-ppc64.tar.gz
+8b0c8d3ee5b1b5c28b6bd63dc4438792012e01d03b4bf7a61d985c87edab7d1f go1.25.1.linux-ppc64le.tar.gz
+22fe934a9d0c9c57275716c55b92d46ebd887cec3177c9140705efa9f84ba1e2 go1.25.1.linux-riscv64.tar.gz
+9cfe517ba423f59f3738ca5c3d907c103253cffbbcc2987142f79c5de8c1bf93 go1.25.1.linux-s390x.tar.gz
+6af8a08353e76205d5b743dd7a3f0126684f96f62be0a31b75daf9837e512c46 go1.25.1.netbsd-386.tar.gz
+e5d534ff362edb1bd8c8e10892b6a027c4c1482454245d1529167676498684c7 go1.25.1.netbsd-amd64.tar.gz
+88bcf39254fdcea6a199c1c27d787831b652427ce60851ae9e41a3d7eb477f45 go1.25.1.netbsd-arm.tar.gz
+d7c2eabe1d04ee47bcaea2816fdd90dbd25d90d4dfa756faa9786c788e4f3a4e go1.25.1.netbsd-arm64.tar.gz
+14a2845977eb4dde11d929858c437a043467c427db87899935e90cee04a38d72 go1.25.1.openbsd-386.tar.gz
+d27ac54b38a13a09c81e67c82ac70d387037341c85c3399291c73e13e83fdd8c go1.25.1.openbsd-amd64.tar.gz
+0f4ab5f02500afa4befd51fed1e8b45e4d07ca050f641cc3acc76eaa4027b2c3 go1.25.1.openbsd-arm.tar.gz
+d46c3bd156843656f7f3cb0dec27ea51cd926ec3f7b80744bf8156e67c1c812f go1.25.1.openbsd-arm64.tar.gz
+c550514c67f22e409be10e40eace761e2e43069f4ef086ae6e60aac736c2b679 go1.25.1.openbsd-ppc64.tar.gz
+8a09a8714a2556eb13fc1f10b7ce2553fcea4971e3330fc3be0efd24aab45734 go1.25.1.openbsd-riscv64.tar.gz
+b0e1fefaf0c7abd71f139a54eee9767944aff5f0bc9d69c968234804884e552f go1.25.1.plan9-386.tar.gz
+e94732c94f149690aa0ab11c26090577211b4a988137cb2c03ec0b54e750402e go1.25.1.plan9-amd64.tar.gz
+7eb80e9de1e817d9089a54e8c7c5c8d8ed9e5fb4d4a012fc0f18fc422a484f0c go1.25.1.plan9-arm.tar.gz
+1261dfad7c4953c0ab90381bc1242dc54e394db7485c59349428d532b2273343 go1.25.1.solaris-amd64.tar.gz
+04bc3c078e9e904c4d58d6ac2532a5bdd402bd36a9ff0b5949b3c5e6006a05ee go1.25.1.windows-arm64.zip
-# version:golangci 2.0.2
+# version:golangci 2.4.0
# https://github.com/golangci/golangci-lint/releases/
-# https://github.com/golangci/golangci-lint/releases/download/v2.0.2/
-a88cbdc86b483fe44e90bf2dcc3fec2af8c754116e6edf0aa6592cac5baa7a0e golangci-lint-2.0.2-darwin-amd64.tar.gz
-664550e7954f5f4451aae99b4f7382c1a47039c66f39ca605f5d9af1a0d32b49 golangci-lint-2.0.2-darwin-arm64.tar.gz
-bda0f0f27d300502faceda8428834a76ca25986f6d9fc2bd41d201c3ed73f08e golangci-lint-2.0.2-freebsd-386.tar.gz
-1cbd0c7ade3fb027d61d38a646ec1b51be5846952b4b04a5330e7f4687f2270c golangci-lint-2.0.2-freebsd-amd64.tar.gz
-1e828a597726198b2e35acdbcc5f3aad85244d79846d2d2bdb05241c5a535f9e golangci-lint-2.0.2-freebsd-armv6.tar.gz
-848b49315dc5cddd0c9ce35e96ab33d584db0ea8fb57bcbf9784f1622bec0269 golangci-lint-2.0.2-freebsd-armv7.tar.gz
-cabf9a6beab574c7f98581eb237919e580024759e3cdc05c4d516b044dce6770 golangci-lint-2.0.2-illumos-amd64.tar.gz
-2fde80d15ed6527791f106d606120620e913c3a663c90a8596861d0a4461169e golangci-lint-2.0.2-linux-386.deb
-804bc6e350a8c613aaa0a33d8d45414a80157b0ba1b2c2335ac859f85ad98ebd golangci-lint-2.0.2-linux-386.rpm
-e64beb72fecf581e57d88ae3adb1c9d4bf022694b6bd92e3c8e460910bbdc37d golangci-lint-2.0.2-linux-386.tar.gz
-9c55aed174d7a52bb1d4006b36e7edee9023631f6b814a80cb39c9860d6f75c3 golangci-lint-2.0.2-linux-amd64.deb
-c55a2ef741a687b4c679696931f7fd4a467babd64c9457cf17bb9632fd1cecd1 golangci-lint-2.0.2-linux-amd64.rpm
-89cc8a7810dc63b9a37900da03e37c3601caf46d42265d774e0f1a5d883d53e2 golangci-lint-2.0.2-linux-amd64.tar.gz
-a3e78583c4e7ea1b63e82559f126bb3a5b12788676f158526752d53e67824b99 golangci-lint-2.0.2-linux-arm64.deb
-bd5dd52b5c9f18aa7a2904eda9a9f91c628e98623fe70b7afcbb847e2de84422 golangci-lint-2.0.2-linux-arm64.rpm
-789d5b91219ac68c2336f77d41cd7e33a910420594780f455893f8453d09595b golangci-lint-2.0.2-linux-arm64.tar.gz
-534cd4c464a66178714ed68152c1ed7aa73e5700bf409e4ed1a8363adf96afca golangci-lint-2.0.2-linux-armv6.deb
-cf7d02905a5fc80b96c9a64621693b4cc7337b1ce29986c19fd72608dafe66c5 golangci-lint-2.0.2-linux-armv6.rpm
-a0d81cb527d8fe878377f2356b5773e219b0b91832a6b59e7b9bcf9a90fe0b0e golangci-lint-2.0.2-linux-armv6.tar.gz
-dedd5be7fff8cba8fe15b658a59347ea90d7d02a9fff87f09c7687e6da05a8b6 golangci-lint-2.0.2-linux-armv7.deb
-85521b6f3ad2f5a2bc9bfe14b9b08623f764964048f75ed6dfcfaf8eb7d57cc1 golangci-lint-2.0.2-linux-armv7.rpm
-96471046c7780dda4ea680f65e92c2ef56ff58d40bcffaf6cfe9d6d48e3c27aa golangci-lint-2.0.2-linux-armv7.tar.gz
-815d914a7738e4362466b2d11004e8618b696b49e8ace13df2c2b25f28fb1e17 golangci-lint-2.0.2-linux-loong64.deb
-f16381e3d8a0f011b95e086d83d620248432b915d01f4beab4d29cfe4dc388b0 golangci-lint-2.0.2-linux-loong64.rpm
-1bd8d7714f9c92db6a0f23bae89f39c85ba047bec8eeb42b8748d30ae3228d18 golangci-lint-2.0.2-linux-loong64.tar.gz
-ea6e9d4aabb526aa298e47e8b026d8893d918c5eb919ba0ab403e315def74cc5 golangci-lint-2.0.2-linux-mips64.deb
-519d8d53af83fdc9c25cc3fba8b663331ac22ef68131d4b0084cb6f425b6f79a golangci-lint-2.0.2-linux-mips64.rpm
-80d655a0a1ac1b19dcef4b58fa2a7dadb646cc50ad08d460b5c53cdb421165e4 golangci-lint-2.0.2-linux-mips64.tar.gz
-aa0e75384bb482c865d4dfc95d23ceb25666bf20461b67a832f0eea6670312ec golangci-lint-2.0.2-linux-mips64le.deb
-f2a8b500fb69bdea1b01df6267aaa5218fa4a58aeb781c1a20d0d802fe465a52 golangci-lint-2.0.2-linux-mips64le.rpm
-e66a0c0c9a275f02d27a7caa9576112622306f001d73dfc082cf1ae446fc1242 golangci-lint-2.0.2-linux-mips64le.tar.gz
-e85ad51aac6428be2d8a37000d053697371a538a5bcbc1644caa7c5e77f6d0af golangci-lint-2.0.2-linux-ppc64le.deb
-906798365eac1944af2a9b9a303e6fd49ec9043307bc681b7a96277f7f8beea5 golangci-lint-2.0.2-linux-ppc64le.rpm
-f7f1a271b0af274d6c9ce000f5dc6e1fb194350c67bcc62494f96f791882ba92 golangci-lint-2.0.2-linux-ppc64le.tar.gz
-eea8bf643a42bf05de9780530db22923e5ab0d588f0e173594dc6518f2a25d2a golangci-lint-2.0.2-linux-riscv64.deb
-4ff40f9fe2954400836e2a011ba4744d00ffab5068a51368552dfce6aba3b81b golangci-lint-2.0.2-linux-riscv64.rpm
-531d8f225866674977d630afbf0533eb02f9bec607fb13895f7a2cd7b2e0a648 golangci-lint-2.0.2-linux-riscv64.tar.gz
-6f827647046c603f40d97ea5aadc6f48cd0bb5d19f7a3d56500c3b833d2a0342 golangci-lint-2.0.2-linux-s390x.deb
-387a090e9576d19ca86aac738172e58e07c19f2784a13bb387f4f0d75fb9c8d3 golangci-lint-2.0.2-linux-s390x.rpm
-57de1fb7722a9feb2d11ed0a007a93959d05b9db5929a392abc222e30012467e golangci-lint-2.0.2-linux-s390x.tar.gz
-ed95e0492ea86bf79eb661f0334474b2a4255093685ff587eccd797c5a54db7e golangci-lint-2.0.2-netbsd-386.tar.gz
-eab81d729778166415d349a80e568b2f2b3a781745a9be3212a92abb1e732daf golangci-lint-2.0.2-netbsd-amd64.tar.gz
-d20add73f7c2de2c3b01ed4fd7b63ffcf0a6597d5ea228d1699e92339a3cd047 golangci-lint-2.0.2-netbsd-arm64.tar.gz
-4e4f44e6057879cd62424ff1800a767d25a595c0e91d6d48809eea9186b4c739 golangci-lint-2.0.2-netbsd-armv6.tar.gz
-51ec17b16d8743ae4098a0171f04f0ed4d64561e3051b982778b0e6c306a1b03 golangci-lint-2.0.2-netbsd-armv7.tar.gz
-5482cf27b93fae1765c70ee2a95d4074d038e9dee61bdd61d017ce8893d3a4a8 golangci-lint-2.0.2-source.tar.gz
-a35d8fdf3e14079a10880dbbb7586b46faec89be96f086b244b3e565aac80313 golangci-lint-2.0.2-windows-386.zip
-fe4b946cc01366b989001215687003a9c4a7098589921f75e6228d6d8cffc15c golangci-lint-2.0.2-windows-amd64.zip
-646bd9250ef8c771d85cd22fe8e6f2397ae39599179755e3bbfa9ef97ad44090 golangci-lint-2.0.2-windows-arm64.zip
-ce1dc0bad6f8a61d64e6b3779eeb773479c175125d6f686b0e67ef9c8432d16e golangci-lint-2.0.2-windows-armv6.zip
-92684a48faabe792b11ac27ca8b25551eff940b0a1e84ad7244e98b4994962db golangci-lint-2.0.2-windows-armv7.zip
+# https://github.com/golangci/golangci-lint/releases/download/v2.4.0/
+7904ce63f79db44934939cf7a063086ea0ea98e9b19eba0a9d52ccdd0d21951c golangci-lint-2.4.0-darwin-amd64.tar.gz
+cd4dd53fa09b6646baff5fd22b8c64d91db02c21c7496df27992d75d34feec59 golangci-lint-2.4.0-darwin-arm64.tar.gz
+d58f426ebe14cc257e81562b4bf37a488ffb4ffbbb3ec73041eb3b38bb25c0e1 golangci-lint-2.4.0-freebsd-386.tar.gz
+6ec4a6177fc6c0dd541fbcb3a7612845266d020d35cc6fa92959220cdf64ca39 golangci-lint-2.4.0-freebsd-amd64.tar.gz
+4d473e3e71c01feaa915a0604fb35758b41284fb976cdeac3f842118d9ee7e17 golangci-lint-2.4.0-freebsd-armv6.tar.gz
+58727746c6530801a3f9a702a5945556a5eb7e88809222536dd9f9d54cafaeff golangci-lint-2.4.0-freebsd-armv7.tar.gz
+fbf28c662760e24c32f82f8d16dffdb4a82de7726a52ba1fad94f890c22997ea golangci-lint-2.4.0-illumos-amd64.tar.gz
+a15a000a8981ef665e971e0f67e2acda9066a9e37a59344393b7351d8fb49c81 golangci-lint-2.4.0-linux-386.tar.gz
+fae792524c04424c0ac369f5b8076f04b45cf29fc945a370e55d369a8dc11840 golangci-lint-2.4.0-linux-amd64.tar.gz
+70ac11f55b80ec78fd3a879249cc9255121b8dfd7f7ed4fc46ed137f4abf17e7 golangci-lint-2.4.0-linux-arm64.tar.gz
+4acdc40e5cebe99e4e7ced358a05b2e71789f409b41cb4f39bbb86ccfa14b1dc golangci-lint-2.4.0-linux-armv6.tar.gz
+2a68749568fa22b4a97cb88dbea655595563c795076536aa6c087f7968784bf3 golangci-lint-2.4.0-linux-armv7.tar.gz
+9e3369afb023711036dcb0b4f45c9fe2792af962fa1df050c9f6ac101a6c5d73 golangci-lint-2.4.0-linux-loong64.tar.gz
+bb9143d6329be2c4dbfffef9564078e7da7d88e7dde6c829b6263d98e072229e golangci-lint-2.4.0-linux-mips64.tar.gz
+5ad1765b40d56cd04d4afd805b3ba6f4bfd9b36181da93c31e9b17e483d8608d golangci-lint-2.4.0-linux-mips64le.tar.gz
+918936fb9c0d5ba96bef03cf4348b03938634cfcced49be1e9bb29cb5094fa73 golangci-lint-2.4.0-linux-ppc64le.tar.gz
+f7474c638e1fb67ebbdc654b55ca0125377ea0bc88e8fee8d964a4f24eacf828 golangci-lint-2.4.0-linux-riscv64.tar.gz
+b617a9543997c8bfceaffa88a75d4e595030c6add69fba800c1e4d8f5fe253dd golangci-lint-2.4.0-linux-s390x.tar.gz
+7db027b03a9ba328f795215b04f594036837bc7dd0dd7cd16776b02a6167981c golangci-lint-2.4.0-netbsd-386.tar.gz
+52d8f9393f4313df0a62b752c37775e3af0b818e43e8dd28954351542d7c60bc golangci-lint-2.4.0-netbsd-amd64.tar.gz
+5c0086027fb5a4af3829e530c8115db4b35d11afe1914322eef528eb8cd38c69 golangci-lint-2.4.0-netbsd-arm64.tar.gz
+6b779d6ed1aed87cefe195cc11759902b97a76551b593312c6833f2635a3488f golangci-lint-2.4.0-netbsd-armv6.tar.gz
+f00d1f4b7ec3468a0f9fffd0d9ea036248b029b7621cbc9a59c449ef94356d09 golangci-lint-2.4.0-netbsd-armv7.tar.gz
+3ce671b0b42b58e35066493aab75a7e2826c9e079988f1ba5d814a4029faaf87 golangci-lint-2.4.0-windows-386.zip
+003112f7a56746feaabf20b744054bf9acdf900c9e77176383623c4b1d76aaa9 golangci-lint-2.4.0-windows-amd64.zip
+dc0c2092af5d47fc2cd31a1dfe7b4c7e765fab22de98bd21ef2ffcc53ad9f54f golangci-lint-2.4.0-windows-arm64.zip
+0263d23e20a260cb1592d35e12a388f99efe2c51b3611fdc66fbd9db1fce664d golangci-lint-2.4.0-windows-armv6.zip
+9403c03bf648e6313036e0273149d44bad1b9ad53889b6d00e4ccb842ba3c058 golangci-lint-2.4.0-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
#
diff --git a/build/ci.go b/build/ci.go
index a91d511a32..b35412e657 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -64,6 +64,11 @@ import (
)
var (
+ goModules = []string{
+ ".",
+ "./cmd/keeper",
+ }
+
// Files that end up in the geth*.zip archive.
gethArchiveFiles = []string{
"COPYING",
@@ -216,7 +221,7 @@ func doInstall(cmdline []string) {
// Default: collect all 'main' packages in cmd/ and build those.
packages := flag.Args()
if len(packages) == 0 {
- packages = build.FindMainPackages("./cmd")
+ packages = build.FindMainPackages(&tc, "./cmd/...")
}
// Do the build!
@@ -298,6 +303,7 @@ func doTest(cmdline []string) {
if *dlgo {
tc.Root = build.DownloadGo(csdb)
}
+
gotest := tc.Go("test")
// CI needs a bit more time for the statetests (default 45m).
@@ -325,18 +331,26 @@ func doTest(cmdline []string) {
gotest.Args = append(gotest.Args, "-short")
}
- packages := []string{"./..."}
- if len(flag.CommandLine.Args()) > 0 {
- packages = flag.CommandLine.Args()
+ packages := flag.CommandLine.Args()
+ if len(packages) > 0 {
+ gotest.Args = append(gotest.Args, packages...)
+ build.MustRun(gotest)
+ return
+ }
+
+ // No packages specified, run all tests for all modules.
+ gotest.Args = append(gotest.Args, "./...")
+ for _, mod := range goModules {
+ test := *gotest
+ test.Dir = mod
+ build.MustRun(&test)
}
- gotest.Args = append(gotest.Args, packages...)
- build.MustRun(gotest)
}
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
ext := ".tar.gz"
- base := "fixtures_fusaka-devnet-3"
+ base := "fixtures_develop"
archivePath := filepath.Join(cachedir, base+ext)
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
log.Fatal(err)
@@ -354,40 +368,46 @@ func doCheckGenerate() {
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
tc = new(build.GoToolchain)
)
- // Compute the origin hashes of all the files
- var hashes map[string][32]byte
- var err error
- hashes, err = build.HashFolder(".", []string{"tests/testdata", "build/cache", ".git"})
- if err != nil {
- log.Fatal("Error computing hashes", "err", err)
- }
// Run any go generate steps we might be missing
var (
protocPath = downloadProtoc(*cachedir)
protocGenGoPath = downloadProtocGenGo(*cachedir)
)
- c := tc.Go("generate", "./...")
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
- c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
- build.MustRun(c)
- // Check if generate file hashes have changed
- generated, err := build.HashFolder(".", []string{"tests/testdata", "build/cache", ".git"})
- if err != nil {
- log.Fatalf("Error re-computing hashes: %v", err)
- }
- updates := build.DiffHashes(hashes, generated)
- for _, file := range updates {
- log.Printf("File changed: %s", file)
- }
- if len(updates) != 0 {
- log.Fatal("One or more generated files were updated by running 'go generate ./...'")
+ for _, mod := range goModules {
+ // Compute the origin hashes of all the files
+ hashes, err := build.HashFolder(mod, []string{"tests/testdata", "build/cache", ".git"})
+ if err != nil {
+ log.Fatal("Error computing hashes", "err", err)
+ }
+
+ c := tc.Go("generate", "./...")
+ c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
+ c.Dir = mod
+ build.MustRun(c)
+ // Check if generate file hashes have changed
+ generated, err := build.HashFolder(mod, []string{"tests/testdata", "build/cache", ".git"})
+ if err != nil {
+ log.Fatalf("Error re-computing hashes: %v", err)
+ }
+ updates := build.DiffHashes(hashes, generated)
+ for _, file := range updates {
+ log.Printf("File changed: %s", file)
+ }
+ if len(updates) != 0 {
+ log.Fatal("One or more generated files were updated by running 'go generate ./...'")
+ }
}
fmt.Println("No stale files detected.")
// Run go mod tidy check.
- build.MustRun(tc.Go("mod", "tidy", "-diff"))
+ for _, mod := range goModules {
+ tidy := tc.Go("mod", "tidy", "-diff")
+ tidy.Dir = mod
+ build.MustRun(tidy)
+ }
fmt.Println("No untidy module files detected.")
}
@@ -427,14 +447,30 @@ func doLint(cmdline []string) {
cachedir = flag.String("cachedir", "./build/cache", "directory for caching golangci-lint binary.")
)
flag.CommandLine.Parse(cmdline)
- packages := []string{"./..."}
- if len(flag.CommandLine.Args()) > 0 {
- packages = flag.CommandLine.Args()
- }
linter := downloadLinter(*cachedir)
- lflags := []string{"run", "--config", ".golangci.yml"}
- build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
+ linter, err := filepath.Abs(linter)
+ if err != nil {
+ log.Fatal(err)
+ }
+ config, err := filepath.Abs(".golangci.yml")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ lflags := []string{"run", "--config", config}
+ packages := flag.CommandLine.Args()
+ if len(packages) > 0 {
+ build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
+ } else {
+ // Run for all modules in workspace.
+ for _, mod := range goModules {
+ args := append(lflags, "./...")
+ lintcmd := exec.Command(linter, args...)
+ lintcmd.Dir = mod
+ build.MustRunWithOutput(lintcmd)
+ }
+ }
fmt.Println("You have achieved perfection.")
}
diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go
index 47d00761f3..47327b6844 100644
--- a/cmd/devp2p/internal/ethtest/suite.go
+++ b/cmd/devp2p/internal/ethtest/suite.go
@@ -1133,7 +1133,10 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
// transmit the same tx but with correct sidecar from the good peer.
var req *eth.GetPooledTransactionsPacket
- req, err = readUntil[eth.GetPooledTransactionsPacket](context.Background(), conn)
+ ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second)
+ defer cancel()
+
+ req, err = readUntil[eth.GetPooledTransactionsPacket](ctx, conn)
if err != nil {
errc <- fmt.Errorf("reading pooled tx request failed: %v", err)
return
diff --git a/cmd/era/main.go b/cmd/era/main.go
index 8163e65999..ab90cdd60e 100644
--- a/cmd/era/main.go
+++ b/cmd/era/main.go
@@ -279,10 +279,10 @@ func checkAccumulator(e *era.Era) error {
for it.Next() {
// 1) next() walks the block index, so we're able to implicitly verify it.
if it.Error() != nil {
- return fmt.Errorf("error reading block %d: %w", it.Number(), err)
+ return fmt.Errorf("error reading block %d: %w", it.Number(), it.Error())
}
block, receipts, err := it.BlockAndReceipts()
- if it.Error() != nil {
+ if err != nil {
return fmt.Errorf("error reading block %d: %w", it.Number(), err)
}
// 2) recompute tx root and verify against header.
@@ -299,6 +299,9 @@ func checkAccumulator(e *era.Era) error {
td.Add(td, block.Difficulty())
tds = append(tds, new(big.Int).Set(td))
}
+ if it.Error() != nil {
+ return fmt.Errorf("error reading block %d: %w", it.Number(), it.Error())
+ }
// 4+5) Verify accumulator and total difficulty.
got, err := era.ComputeAccumulator(hashes, tds)
if err != nil {
diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go
index 4c9df719fa..0026fd86e1 100644
--- a/cmd/evm/internal/t8ntool/execution.go
+++ b/cmd/evm/internal/t8ntool/execution.go
@@ -32,7 +32,6 @@ import (
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -152,7 +151,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
gasUsed = uint64(0)
blobGasUsed = uint64(0)
receipts = make(types.Receipts, 0)
- txIndex = 0
)
gaspool.AddGas(pre.Env.GasLimit)
vmContext := vm.BlockContext{
@@ -193,6 +191,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
Time: pre.Env.ParentTimestamp,
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
BlobGasUsed: pre.Env.ParentBlobGasUsed,
+ BaseFee: pre.Env.ParentBaseFee,
}
header := &types.Header{
Time: pre.Env.Timestamp,
@@ -250,24 +249,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
continue
}
}
- statedb.SetTxContext(tx.Hash(), txIndex)
+ statedb.SetTxContext(tx.Hash(), len(receipts))
var (
snapshot = statedb.Snapshot()
prevGas = gaspool.Gas()
)
- if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil {
- evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
- }
- // (ret []byte, usedGas uint64, failed bool, err error)
- msgResult, err := core.ApplyMessage(evm, msg, gaspool)
+ receipt, err := core.ApplyTransactionWithEVM(msg, gaspool, statedb, vmContext.BlockNumber, blockHash, pre.Env.Timestamp, tx, &gasUsed, evm)
if err != nil {
statedb.RevertToSnapshot(snapshot)
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
gaspool.SetGas(prevGas)
- if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxEnd != nil {
- evm.Config.Tracer.OnTxEnd(nil, err)
- }
continue
}
includedTxs = append(includedTxs, tx)
@@ -275,50 +267,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
}
blobGasUsed += txBlobGas
- gasUsed += msgResult.UsedGas
-
- // Receipt:
- {
- var root []byte
- if chainConfig.IsByzantium(vmContext.BlockNumber) {
- statedb.Finalise(true)
- } else {
- root = statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)).Bytes()
- }
-
- // Create a new receipt for the transaction, storing the intermediate root and
- // gas used by the tx.
- receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: gasUsed}
- if msgResult.Failed() {
- receipt.Status = types.ReceiptStatusFailed
- } else {
- receipt.Status = types.ReceiptStatusSuccessful
- }
- receipt.TxHash = tx.Hash()
- receipt.GasUsed = msgResult.UsedGas
-
- // If the transaction created a contract, store the creation address in the receipt.
- if msg.To == nil {
- receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
- }
-
- // Set the receipt logs and create the bloom filter.
- receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash, vmContext.Time)
- receipt.Bloom = types.CreateBloom(receipt)
-
- // These three are non-consensus fields:
- //receipt.BlockHash
- //receipt.BlockNumber
- receipt.TransactionIndex = uint(txIndex)
- receipts = append(receipts, receipt)
- if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxEnd != nil {
- evm.Config.Tracer.OnTxEnd(receipt, nil)
- }
- }
-
- txIndex++
+ receipts = append(receipts, receipt)
}
+
statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber))
+
// Add mining reward? (-1 means rewards are disabled)
if miningReward >= 0 {
// Add mining reward. The mining reward may be `0`, which only makes a difference in the cases
@@ -429,7 +382,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB
sdb := state.NewDatabase(tdb, nil)
statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts {
- statedb.SetCode(addr, a.Code)
+ statedb.SetCode(addr, a.Code, tracing.CodeChangeUnspecified)
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceIncreaseGenesisBalance)
for k, v := range a.Storage {
diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index b2cf28353b..ebb3e04461 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -322,7 +322,7 @@ func runCmd(ctx *cli.Context) error {
}
} else {
if len(code) > 0 {
- prestate.SetCode(receiver, code)
+ prestate.SetCode(receiver, code, tracing.CodeChangeUnspecified)
}
execFunc = func() ([]byte, uint64, error) {
// don't mutate the state!
diff --git a/cmd/evm/t8n_test.go b/cmd/evm/t8n_test.go
index 46146be787..3c6fd90b47 100644
--- a/cmd/evm/t8n_test.go
+++ b/cmd/evm/t8n_test.go
@@ -296,6 +296,14 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
+ { // Osaka test, EIP-7918 blob gas with parent base fee
+ base: "./testdata/34",
+ input: t8nInput{
+ "alloc.json", "txs.json", "env.json", "Osaka", "",
+ },
+ output: t8nOutput{alloc: true, result: true},
+ expOut: "exp.json",
+ },
} {
args := []string{"t8n"}
args = append(args, tc.output.get()...)
diff --git a/cmd/evm/testdata/1/exp.json b/cmd/evm/testdata/1/exp.json
index 50662f35ea..6537c9517d 100644
--- a/cmd/evm/testdata/1/exp.json
+++ b/cmd/evm/testdata/1/exp.json
@@ -29,7 +29,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/13/exp2.json b/cmd/evm/testdata/13/exp2.json
index 6415a4f1f4..f716289cf7 100644
--- a/cmd/evm/testdata/13/exp2.json
+++ b/cmd/evm/testdata/13/exp2.json
@@ -17,7 +17,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x84d0",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
},
{
@@ -31,7 +32,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x84d0",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x1"
}
],
diff --git a/cmd/evm/testdata/23/exp.json b/cmd/evm/testdata/23/exp.json
index 7f36165e35..2d9cd492db 100644
--- a/cmd/evm/testdata/23/exp.json
+++ b/cmd/evm/testdata/23/exp.json
@@ -16,7 +16,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x520b",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/24/exp.json b/cmd/evm/testdata/24/exp.json
index 8f380c662b..0dd552e112 100644
--- a/cmd/evm/testdata/24/exp.json
+++ b/cmd/evm/testdata/24/exp.json
@@ -32,7 +32,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0xa861",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
},
{
@@ -45,7 +46,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5aa5",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x1"
}
],
diff --git a/cmd/evm/testdata/25/exp.json b/cmd/evm/testdata/25/exp.json
index a674633762..3dac46aa60 100644
--- a/cmd/evm/testdata/25/exp.json
+++ b/cmd/evm/testdata/25/exp.json
@@ -28,7 +28,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/28/exp.json b/cmd/evm/testdata/28/exp.json
index b86c2d8def..15b29bc0ac 100644
--- a/cmd/evm/testdata/28/exp.json
+++ b/cmd/evm/testdata/28/exp.json
@@ -33,7 +33,10 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0xa865",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blobGasUsed": "0x20000",
+ "blobGasPrice": "0x1",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/29/exp.json b/cmd/evm/testdata/29/exp.json
index 7fbdc18283..69c8661aa8 100644
--- a/cmd/evm/testdata/29/exp.json
+++ b/cmd/evm/testdata/29/exp.json
@@ -31,7 +31,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/3/exp.json b/cmd/evm/testdata/3/exp.json
index 831c078591..807cdccfb4 100644
--- a/cmd/evm/testdata/3/exp.json
+++ b/cmd/evm/testdata/3/exp.json
@@ -29,7 +29,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x521f",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x5",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/30/exp.json b/cmd/evm/testdata/30/exp.json
index a206c3bbdf..9861f5a071 100644
--- a/cmd/evm/testdata/30/exp.json
+++ b/cmd/evm/testdata/30/exp.json
@@ -30,7 +30,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
},
{
@@ -44,7 +45,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x5208",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x1"
}
],
diff --git a/cmd/evm/testdata/33/exp.json b/cmd/evm/testdata/33/exp.json
index ae82ef3efa..b40ca9fee2 100644
--- a/cmd/evm/testdata/33/exp.json
+++ b/cmd/evm/testdata/33/exp.json
@@ -48,7 +48,8 @@
"contractAddress": "0x0000000000000000000000000000000000000000",
"gasUsed": "0x15fa9",
"effectiveGasPrice": null,
- "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0x1337000000000000000000000000000000000000000000000000000000000000",
+ "blockNumber": "0x1",
"transactionIndex": "0x0"
}
],
diff --git a/cmd/evm/testdata/34/README.md b/cmd/evm/testdata/34/README.md
new file mode 100644
index 0000000000..a18f85ca14
--- /dev/null
+++ b/cmd/evm/testdata/34/README.md
@@ -0,0 +1,6 @@
+This test verifies that Osaka fork blob gas calculation works correctly when
+parentBaseFee is provided. It tests the EIP-7918 reserve price calculation
+which requires parent.BaseFee to be properly set.
+
+Regression test for: nil pointer dereference when parent.BaseFee was not
+included in the parent header during Osaka fork blob gas calculations.
\ No newline at end of file
diff --git a/cmd/evm/testdata/34/alloc.json b/cmd/evm/testdata/34/alloc.json
new file mode 100644
index 0000000000..199de13285
--- /dev/null
+++ b/cmd/evm/testdata/34/alloc.json
@@ -0,0 +1,6 @@
+{
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0x1000000000000000000",
+ "nonce": "0x0"
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/34/env.json b/cmd/evm/testdata/34/env.json
new file mode 100644
index 0000000000..ae2bde5ef3
--- /dev/null
+++ b/cmd/evm/testdata/34/env.json
@@ -0,0 +1,18 @@
+{
+ "currentCoinbase": "0x0000000000000000000000000000000000000000",
+ "currentDifficulty": "0x0",
+ "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "currentGasLimit": "0x5f5e100",
+ "currentNumber": "0x1",
+ "currentTimestamp": "0x1000",
+ "parentTimestamp": "0x0",
+ "currentBaseFee": "0x10",
+ "parentBaseFee": "0x0a",
+ "parentGasUsed": "0x0",
+ "parentGasLimit": "0x5f5e100",
+ "currentExcessBlobGas": "0x0",
+ "parentExcessBlobGas": "0x0",
+ "parentBlobGasUsed": "0x20000",
+ "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "withdrawals": []
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/34/exp.json b/cmd/evm/testdata/34/exp.json
new file mode 100644
index 0000000000..56d24a532e
--- /dev/null
+++ b/cmd/evm/testdata/34/exp.json
@@ -0,0 +1,23 @@
+{
+ "alloc": {
+ "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
+ "balance": "0x1000000000000000000"
+ }
+ },
+ "result": {
+ "stateRoot": "0x01c28492482a1a1f66224726ef1059a7036fce69d1d2c991b65cd013725d5742",
+ "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "currentDifficulty": null,
+ "receipts": [],
+ "gasUsed": "0x0",
+ "currentBaseFee": "0x10",
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "currentExcessBlobGas": "0x0",
+ "blobGasUsed": "0x0",
+ "requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "requests": []
+ }
+}
\ No newline at end of file
diff --git a/cmd/evm/testdata/34/txs.json b/cmd/evm/testdata/34/txs.json
new file mode 100644
index 0000000000..0637a088a0
--- /dev/null
+++ b/cmd/evm/testdata/34/txs.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index d0f4d6f81d..c5145bbfb7 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -59,6 +59,8 @@ var (
Flags: slices.Concat([]cli.Flag{
utils.CachePreimagesFlag,
utils.OverrideOsaka,
+ utils.OverrideBPO1,
+ utils.OverrideBPO2,
utils.OverrideVerkle,
}, utils.DatabaseFlags),
Description: `
@@ -108,6 +110,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
utils.MetricsInfluxDBTokenFlag,
utils.MetricsInfluxDBBucketFlag,
utils.MetricsInfluxDBOrganizationFlag,
+ utils.StateSizeTrackingFlag,
utils.TxLookupLimitFlag,
utils.VMTraceFlag,
utils.VMTraceJsonConfigFlag,
@@ -273,6 +276,14 @@ func initGenesis(ctx *cli.Context) error {
v := ctx.Uint64(utils.OverrideOsaka.Name)
overrides.OverrideOsaka = &v
}
+ if ctx.IsSet(utils.OverrideBPO1.Name) {
+ v := ctx.Uint64(utils.OverrideBPO1.Name)
+ overrides.OverrideBPO1 = &v
+ }
+ if ctx.IsSet(utils.OverrideBPO2.Name) {
+ v := ctx.Uint64(utils.OverrideBPO2.Name)
+ overrides.OverrideBPO2 = &v
+ }
if ctx.IsSet(utils.OverrideVerkle.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
overrides.OverrideVerkle = &v
@@ -281,7 +292,7 @@ func initGenesis(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, false)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
+ triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
defer triedb.Close()
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
@@ -635,7 +646,7 @@ func dump(ctx *cli.Context) error {
if err != nil {
return err
}
- triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup
+ triedb := utils.MakeTrieDatabase(ctx, stack, db, true, true, false) // always enable preimage lookup
defer triedb.Close()
state, err := state.New(root, state.NewDatabase(triedb, nil))
diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index eebb932576..b43caf1491 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -209,7 +209,7 @@ func constructDevModeBanner(ctx *cli.Context, cfg gethConfig) string {
0x%x (10^49 ETH)
`, cfg.Eth.Miner.PendingFeeRecipient)
if cfg.Eth.Miner.PendingFeeRecipient == utils.DeveloperAddr {
- devModeBanner += fmt.Sprintf(`
+ devModeBanner += fmt.Sprintf(`
Private Key
------------------
0x%x
@@ -227,6 +227,18 @@ func makeFullNode(ctx *cli.Context) *node.Node {
v := ctx.Uint64(utils.OverrideOsaka.Name)
cfg.Eth.OverrideOsaka = &v
}
+ if ctx.IsSet(utils.OverrideBPO1.Name) {
+ v := ctx.Uint64(utils.OverrideBPO1.Name)
+ cfg.Eth.OverrideBPO1 = &v
+ }
+ if ctx.IsSet(utils.OverrideBPO2.Name) {
+ v := ctx.Uint64(utils.OverrideBPO2.Name)
+ cfg.Eth.OverrideBPO2 = &v
+ }
+ if ctx.IsSet(utils.OverrideVerkle.Name) {
+ v := ctx.Uint64(utils.OverrideVerkle.Name)
+ cfg.Eth.OverrideVerkle = &v
+ }
if ctx.IsSet(utils.OverrideOptimismCanyon.Name) {
v := ctx.Uint64(utils.OverrideOptimismCanyon.Name)
@@ -268,11 +280,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
cfg.Eth.OverrideOptimismInterop = &v
}
- if ctx.IsSet(utils.OverrideVerkle.Name) {
- v := ctx.Uint64(utils.OverrideVerkle.Name)
- cfg.Eth.OverrideVerkle = &v
- }
-
// Start metrics export if enabled
utils.SetupMetrics(&cfg.Metrics)
diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go
index 44a52521f0..c57add0656 100644
--- a/cmd/geth/dbcmd.go
+++ b/cmd/geth/dbcmd.go
@@ -524,7 +524,7 @@ func dbDumpTrie(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true)
defer db.Close()
- triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
defer triedb.Close()
var (
@@ -859,7 +859,7 @@ func inspectHistory(ctx *cli.Context) error {
db := utils.MakeChainDatabase(ctx, stack, true)
defer db.Close()
- triedb := utils.MakeTrieDatabase(ctx, db, false, false, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, db, false, false, false)
defer triedb.Close()
var (
diff --git a/cmd/geth/logging_test.go b/cmd/geth/logging_test.go
index 37fffecc30..d420c2d078 100644
--- a/cmd/geth/logging_test.go
+++ b/cmd/geth/logging_test.go
@@ -91,7 +91,7 @@ func testConsoleLogging(t *testing.T, format string, tStart, tEnd int) {
have = censor(have, tStart, tEnd)
want = censor(want, tStart, tEnd)
if have != want {
- t.Logf(nicediff([]byte(have), []byte(want)))
+ t.Log(nicediff([]byte(have), []byte(want)))
t.Fatalf("format %v, line %d\nhave %v\nwant %v", format, i, have, want)
}
}
@@ -142,7 +142,7 @@ func TestJsonLogging(t *testing.T) {
}
if !bytes.Equal(have, want) {
// show an intelligent diff
- t.Logf(nicediff(have, want))
+ t.Log(nicediff(have, want))
t.Errorf("file content wrong")
}
}
@@ -211,7 +211,7 @@ func TestFileOut(t *testing.T) {
}
if !bytes.Equal(have, want) {
// show an intelligent diff
- t.Logf(nicediff(have, want))
+ t.Log(nicediff(have, want))
t.Errorf("file content wrong")
}
}
@@ -231,7 +231,7 @@ func TestRotatingFileOut(t *testing.T) {
}
if !bytes.Equal(have, want) {
// show an intelligent diff
- t.Logf(nicediff(have, want))
+ t.Log(nicediff(have, want))
t.Errorf("file content wrong")
}
}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index feb92d8942..a3af05e85f 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -64,6 +64,8 @@ var (
utils.USBFlag,
utils.SmartCardDaemonPathFlag,
utils.OverrideOsaka,
+ utils.OverrideBPO1,
+ utils.OverrideBPO2,
utils.OverrideVerkle,
utils.OverrideOptimismCanyon,
utils.OverrideOptimismEcotone,
@@ -145,6 +147,8 @@ var (
utils.VMEnableDebugFlag,
utils.VMTraceFlag,
utils.VMTraceJsonConfigFlag,
+ utils.VMWitnessStatsFlag,
+ utils.VMStatelessSelfValidationFlag,
utils.NetworkIdFlag,
utils.EthStatsURLFlag,
utils.GpoBlocksFlag,
@@ -207,6 +211,7 @@ var (
utils.RPCGlobalGasCapFlag,
utils.RPCGlobalEVMTimeoutFlag,
utils.RPCGlobalTxFeeCapFlag,
+ utils.RPCGlobalLogQueryLimit,
utils.AllowUnprotectedTxs,
utils.BatchRequestLimit,
utils.BatchResponseMaxSize,
@@ -227,6 +232,7 @@ var (
utils.MetricsInfluxDBTokenFlag,
utils.MetricsInfluxDBBucketFlag,
utils.MetricsInfluxDBOrganizationFlag,
+ utils.StateSizeTrackingFlag,
}
)
diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go
index aa9ae7087f..7621dfa93c 100644
--- a/cmd/geth/snapshot.go
+++ b/cmd/geth/snapshot.go
@@ -217,7 +217,7 @@ func verifyState(ctx *cli.Context) error {
log.Error("Failed to load head block")
return errors.New("no head block")
}
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
defer triedb.Close()
var (
@@ -282,7 +282,7 @@ func traverseState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
@@ -391,7 +391,7 @@ func traverseRawState(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
defer triedb.Close()
headBlock := rawdb.ReadHeadBlock(chaindb)
@@ -558,20 +558,14 @@ func dumpState(ctx *cli.Context) error {
if err != nil {
return err
}
- triedb := utils.MakeTrieDatabase(ctx, db, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, db, false, true, false)
defer triedb.Close()
- snapConfig := snapshot.Config{
- CacheSize: 256,
- Recovery: false,
- NoBuild: true,
- AsyncBuild: false,
- }
- snaptree, err := snapshot.New(snapConfig, db, triedb, root)
+ stateIt, err := utils.NewStateIterator(triedb, db, root)
if err != nil {
return err
}
- accIt, err := snaptree.AccountIterator(root, common.BytesToHash(conf.Start))
+ accIt, err := stateIt.AccountIterator(root, common.BytesToHash(conf.Start))
if err != nil {
return err
}
@@ -605,7 +599,7 @@ func dumpState(ctx *cli.Context) error {
if !conf.SkipStorage {
da.Storage = make(map[common.Hash]string)
- stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{})
+ stIt, err := stateIt.StorageIterator(root, accIt.Hash(), common.Hash{})
if err != nil {
return err
}
@@ -640,7 +634,7 @@ func snapshotExportPreimages(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close()
- triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false)
+ triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, false, true, false)
defer triedb.Close()
var root common.Hash
@@ -658,17 +652,11 @@ func snapshotExportPreimages(ctx *cli.Context) error {
}
root = headBlock.Root()
}
- snapConfig := snapshot.Config{
- CacheSize: 256,
- Recovery: false,
- NoBuild: true,
- AsyncBuild: false,
- }
- snaptree, err := snapshot.New(snapConfig, chaindb, triedb, root)
+ stateIt, err := utils.NewStateIterator(triedb, chaindb, root)
if err != nil {
return err
}
- return utils.ExportSnapshotPreimages(chaindb, snaptree, ctx.Args().First(), root)
+ return utils.ExportSnapshotPreimages(chaindb, stateIt, ctx.Args().First(), root)
}
// checkAccount iterates the snap data layers, and looks up the given account
diff --git a/cmd/keeper/1192c3_block.rlp b/cmd/keeper/1192c3_block.rlp
new file mode 100644
index 0000000000..e788c2b8fd
Binary files /dev/null and b/cmd/keeper/1192c3_block.rlp differ
diff --git a/cmd/keeper/1192c3_witness.rlp b/cmd/keeper/1192c3_witness.rlp
new file mode 100644
index 0000000000..4990f2299f
Binary files /dev/null and b/cmd/keeper/1192c3_witness.rlp differ
diff --git a/cmd/keeper/README.md b/cmd/keeper/README.md
new file mode 100644
index 0000000000..4737a22674
--- /dev/null
+++ b/cmd/keeper/README.md
@@ -0,0 +1,69 @@
+# Keeper - geth as a zkvm guest
+
+Keeper command is a specialized tool for validating stateless execution of Ethereum blocks. It's designed to run as a zkvm guest.
+
+## Overview
+
+The keeper reads an RLP-encoded payload containing:
+- A block to execute
+- A witness with the necessary state data
+- A chainID
+
+It then executes the block statelessly and validates that the computed state root and receipt root match the values in the block header.
+
+## Building Keeper
+
+The keeper uses build tags to compile platform-specific input methods and chain configurations:
+
+### Example Implementation
+
+See `getpayload_example.go` for a complete example with embedded Hoodi block data:
+
+```bash
+# Build example with different chain configurations
+go build -tags "example" ./cmd/keeper
+```
+
+### Ziren zkVM Implementation
+
+Build for the Ziren zkVM platform, which is a MIPS ISA-based zkvm:
+
+```bash
+GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -tags "ziren" ./cmd/keeper
+```
+
+As an example runner, refer to https://gist.github.com/gballet/7b669a99eb3ab2b593324e3a76abd23d
+
+## Creating a Custom Platform Implementation
+
+To add support for a new platform (e.g., "myplatform"), create a new file with the appropriate build tag:
+
+### 1. Create `getinput_myplatform.go`
+
+```go
+//go:build myplatform
+
+package main
+
+import (
+ "github.com/ethereum/go-ethereum/params"
+ // ... other imports as needed
+)
+
+// getInput returns the RLP-encoded payload
+func getInput() []byte {
+ // Your platform-specific code to retrieve the RLP-encoded payload
+ // This might read from:
+ // - Memory-mapped I/O
+ // - Hardware registers
+ // - Serial port
+ // - Network interface
+ // - File system
+
+ // The payload must be RLP-encoded and contain:
+ // - Block with transactions
+ // - Witness with parent headers and state data
+
+ return encodedPayload
+}
+```
diff --git a/cmd/keeper/chainconfig.go b/cmd/keeper/chainconfig.go
new file mode 100644
index 0000000000..c9859d450f
--- /dev/null
+++ b/cmd/keeper/chainconfig.go
@@ -0,0 +1,38 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package main
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// getChainConfig returns the appropriate chain configuration based on the chainID.
+// Returns an error for unsupported chain IDs.
+func getChainConfig(chainID uint64) (*params.ChainConfig, error) {
+ switch chainID {
+ case 0, params.MainnetChainConfig.ChainID.Uint64():
+ return params.MainnetChainConfig, nil
+ case params.SepoliaChainConfig.ChainID.Uint64():
+ return params.SepoliaChainConfig, nil
+ case params.HoodiChainConfig.ChainID.Uint64():
+ return params.HoodiChainConfig, nil
+ default:
+ return nil, fmt.Errorf("unsupported chain ID: %d", chainID)
+ }
+}
diff --git a/cmd/keeper/getpayload_example.go b/cmd/keeper/getpayload_example.go
new file mode 100644
index 0000000000..683cc79248
--- /dev/null
+++ b/cmd/keeper/getpayload_example.go
@@ -0,0 +1,102 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+//go:build example
+
+package main
+
+import (
+ _ "embed"
+ "fmt"
+ "os"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/stateless"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// ExtWitness is a witness RLP encoding for transferring across clients.
+// This is taken from PR #32216 until it's merged.
+// It contains block headers, contract codes, state nodes, and storage keys
+// required for stateless execution verification.
+type ExtWitness struct {
+ Headers []*types.Header `json:"headers"`
+ Codes []hexutil.Bytes `json:"codes"`
+ State []hexutil.Bytes `json:"state"`
+ Keys []hexutil.Bytes `json:"keys"`
+}
+
+// This is taken from PR #32216 until it's merged
+// fromExtWitness converts the consensus witness format into our internal one.
+func fromExtWitness(ext *ExtWitness) (*stateless.Witness, error) {
+ w := &stateless.Witness{}
+ w.Headers = ext.Headers
+
+ w.Codes = make(map[string]struct{}, len(ext.Codes))
+ for _, code := range ext.Codes {
+ w.Codes[string(code)] = struct{}{}
+ }
+ w.State = make(map[string]struct{}, len(ext.State))
+ for _, node := range ext.State {
+ w.State[string(node)] = struct{}{}
+ }
+ return w, nil
+}
+
+//go:embed 1192c3_witness.rlp
+var witnessRlp []byte
+
+//go:embed 1192c3_block.rlp
+var blockRlp []byte
+
+// getInput is a platform-specific function that will recover the input payload
+// and returns it as a slice. It is expected to be an RLP-encoded Payload structure
+// that contains the witness and the block.
+// This is a demo version, that is intended to run on a regular computer, so what
+// it does is embed a small Hoodi block, encodes the Payload structure containing
+// the block and its witness as RLP, and returns the encoding.
+func getInput() []byte {
+ var block types.Block
+ err := rlp.DecodeBytes(blockRlp, &block)
+ if err != nil {
+ panic(err)
+ }
+
+ var extwitness ExtWitness
+ err = rlp.DecodeBytes(witnessRlp, &extwitness)
+ if err != nil {
+ panic(err)
+ }
+ witness, err := fromExtWitness(&extwitness)
+ if err != nil {
+ panic(err)
+ }
+
+ payload := Payload{
+ ChainID: params.HoodiChainConfig.ChainID.Uint64(),
+ Block: &block,
+ Witness: witness,
+ }
+
+ encoded, err := rlp.EncodeToBytes(payload)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to encode payload: %v\n", err)
+ os.Exit(20)
+ }
+ return encoded
+}
diff --git a/cmd/keeper/getpayload_ziren.go b/cmd/keeper/getpayload_ziren.go
new file mode 100644
index 0000000000..11c5845bcc
--- /dev/null
+++ b/cmd/keeper/getpayload_ziren.go
@@ -0,0 +1,31 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+//go:build ziren
+
+package main
+
+import (
+ zkruntime "github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime"
+)
+
+// getInput reads the input payload from the zkVM runtime environment.
+// The zkVM host provides the RLP-encoded Payload structure containing
+// the block and witness data through the runtime's input mechanism.
+func getInput() []byte {
+ input := zkruntime.Read[[]byte]()
+ return input
+}
diff --git a/cmd/keeper/go.mod b/cmd/keeper/go.mod
new file mode 100644
index 0000000000..8b8f66d9b7
--- /dev/null
+++ b/cmd/keeper/go.mod
@@ -0,0 +1,53 @@
+module github.com/ethereum/go-ethereum/cmd/keeper
+
+go 1.24.0
+
+require (
+ github.com/ethereum/go-ethereum v0.0.0-00010101000000-000000000000
+ github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
+)
+
+require (
+ github.com/BurntSushi/toml v1.4.0 // indirect
+ github.com/StackExchange/wmi v1.2.1 // indirect
+ github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
+ github.com/bits-and-blooms/bitset v1.20.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/consensys/gnark-crypto v0.18.0 // indirect
+ github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
+ github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
+ github.com/deckarep/golang-set/v2 v2.6.0 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
+ github.com/emicklei/dot v1.6.2 // indirect
+ github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect
+ github.com/ethereum/go-verkle v0.2.2 // indirect
+ github.com/ferranbt/fastssz v0.1.4 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/gofrs/flock v0.12.1 // indirect
+ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
+ github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
+ github.com/holiman/uint256 v1.3.2 // indirect
+ github.com/klauspost/compress v1.17.11 // indirect
+ github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
+ github.com/mitchellh/mapstructure v1.4.1 // indirect
+ github.com/naoina/go-stringutil v0.1.0 // indirect
+ github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
+ github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect
+ github.com/tklauser/go-sysconf v0.3.12 // indirect
+ github.com/tklauser/numcpus v0.6.1 // indirect
+ golang.org/x/crypto v0.36.0 // indirect
+ golang.org/x/sync v0.12.0 // indirect
+ golang.org/x/sys v0.36.0 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+)
+
+replace (
+ github.com/ethereum/go-ethereum => ../../
+ github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime => github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
+)
diff --git a/cmd/keeper/go.sum b/cmd/keeper/go.sum
new file mode 100644
index 0000000000..7b5d264617
--- /dev/null
+++ b/cmd/keeper/go.sum
@@ -0,0 +1,158 @@
+github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
+github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE=
+github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
+github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
+github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
+github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
+github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
+github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
+github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
+github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
+github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
+github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw=
+github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo=
+github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
+github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
+github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0=
+github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
+github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg=
+github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
+github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
+github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
+github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
+github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
+github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
+github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
+github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
+github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
+github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
+github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
+github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
+github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
+github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
+github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY=
+github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
+github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
+github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
+github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
+github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
+github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
+github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
+github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
+github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
+github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
+github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
+github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
+github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
+github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
+github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
+github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
+github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
+github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
+github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
+github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
+github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
+github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
+github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
+github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4=
+github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
+github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw=
+github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
+github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5 h1:MxKlbmI7Dta6O6Nsc9OAer/rOltjoL11CVLMqCiYnxU=
+github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5/go.mod h1:zk/SUgiiVz2U1ufZ+yM2MHPbD93W25KH5zK3qAxXbT4=
+golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
+golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
+golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/cmd/keeper/main.go b/cmd/keeper/main.go
new file mode 100644
index 0000000000..9b459f6f36
--- /dev/null
+++ b/cmd/keeper/main.go
@@ -0,0 +1,68 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime/debug"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/stateless"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Payload represents the input data for stateless execution containing
+// a block and its associated witness data for verification.
+type Payload struct {
+ ChainID uint64
+ Block *types.Block
+ Witness *stateless.Witness
+}
+
+func init() {
+ debug.SetGCPercent(-1) // Disable garbage collection
+}
+
+func main() {
+ input := getInput()
+ var payload Payload
+ rlp.DecodeBytes(input, &payload)
+
+ chainConfig, err := getChainConfig(payload.ChainID)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to get chain config: %v\n", err)
+ os.Exit(13)
+ }
+ vmConfig := vm.Config{}
+
+ crossStateRoot, crossReceiptRoot, err := core.ExecuteStateless(chainConfig, vmConfig, payload.Block, payload.Witness)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "stateless self-validation failed: %v\n", err)
+ os.Exit(10)
+ }
+ if crossStateRoot != payload.Block.Root() {
+ fmt.Fprintf(os.Stderr, "stateless self-validation root mismatch (cross: %x local: %x)\n", crossStateRoot, payload.Block.Root())
+ os.Exit(11)
+ }
+ if crossReceiptRoot != payload.Block.ReceiptHash() {
+ fmt.Fprintf(os.Stderr, "stateless self-validation receipt root mismatch (cross: %x local: %x)\n", crossReceiptRoot, payload.Block.ReceiptHash())
+ os.Exit(12)
+ }
+}
diff --git a/build/tools/tools.go b/cmd/keeper/stubs.go
similarity index 68%
rename from build/tools/tools.go
rename to cmd/keeper/stubs.go
index e9e2241d2f..04a3bc735b 100644
--- a/build/tools/tools.go
+++ b/cmd/keeper/stubs.go
@@ -1,4 +1,4 @@
-// Copyright 2019 The go-ethereum Authors
+// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
@@ -14,14 +14,13 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build tools
-// +build tools
+//go:build !example && !ziren
-package tools
+package main
-import (
- // Tool imports for go:generate.
- _ "github.com/fjl/gencodec"
- _ "golang.org/x/tools/cmd/stringer"
- _ "google.golang.org/protobuf/cmd/protoc-gen-go"
-)
+// getInput is a stub implementation for when no platform-specific build tags are set.
+// This allows golangci-lint to typecheck the code without errors.
+// The actual implementations are provided in platform-specific files.
+func getInput() []byte {
+ panic("stub")
+}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index b332a060de..db7bd691d8 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -48,6 +48,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/urfave/cli/v2"
)
@@ -567,9 +568,64 @@ func ExportPreimages(db ethdb.Database, fn string) error {
return nil
}
+// StateIterator is a temporary structure for traversing state in order. It serves
+// as an aggregator for both path scheme and hash scheme implementations and should
+// be removed once the hash scheme is fully deprecated.
+type StateIterator struct {
+ scheme string
+ root common.Hash
+ triedb *triedb.Database
+ snapshots *snapshot.Tree
+}
+
+// NewStateIterator constructs the state iterator with the specific root.
+func NewStateIterator(triedb *triedb.Database, db ethdb.Database, root common.Hash) (*StateIterator, error) {
+ if triedb.Scheme() == rawdb.PathScheme {
+ return &StateIterator{
+ scheme: rawdb.PathScheme,
+ root: root,
+ triedb: triedb,
+ }, nil
+ }
+ config := snapshot.Config{
+ CacheSize: 256,
+ Recovery: false,
+ NoBuild: true,
+ AsyncBuild: false,
+ }
+ snapshots, err := snapshot.New(config, db, triedb, root)
+ if err != nil {
+ return nil, err
+ }
+ return &StateIterator{
+ scheme: rawdb.HashScheme,
+ root: root,
+ triedb: triedb,
+ snapshots: snapshots,
+ }, nil
+}
+
+// AccountIterator creates a new account iterator for the specified root hash and
+// seeks to a starting account hash.
+func (it *StateIterator) AccountIterator(root common.Hash, start common.Hash) (snapshot.AccountIterator, error) {
+ if it.scheme == rawdb.PathScheme {
+ return it.triedb.AccountIterator(root, start)
+ }
+ return it.snapshots.AccountIterator(root, start)
+}
+
+// StorageIterator creates a new storage iterator for the specified root hash and
+// account. The iterator will be moved to the specific start position.
+func (it *StateIterator) StorageIterator(root common.Hash, accountHash common.Hash, start common.Hash) (snapshot.StorageIterator, error) {
+ if it.scheme == rawdb.PathScheme {
+ return it.triedb.StorageIterator(root, accountHash, start)
+ }
+ return it.snapshots.StorageIterator(root, accountHash, start)
+}
+
// ExportSnapshotPreimages exports the preimages corresponding to the enumeration of
// the snapshot for a given root.
-func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn string, root common.Hash) error {
+func ExportSnapshotPreimages(chaindb ethdb.Database, stateIt *StateIterator, fn string, root common.Hash) error {
log.Info("Exporting preimages", "file", fn)
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
@@ -602,7 +658,7 @@ func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn
)
go func() {
defer close(hashCh)
- accIt, err := snaptree.AccountIterator(root, common.Hash{})
+ accIt, err := stateIt.AccountIterator(root, common.Hash{})
if err != nil {
log.Error("Failed to create account iterator", "error", err)
return
@@ -619,7 +675,7 @@ func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn
hashCh <- hashAndPreimageSize{Hash: accIt.Hash(), Size: common.AddressLength}
if acc.Root != (common.Hash{}) && acc.Root != types.EmptyRootHash {
- stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{})
+ stIt, err := stateIt.StorageIterator(root, accIt.Hash(), common.Hash{})
if err != nil {
log.Error("Failed to create storage iterator", "error", err)
return
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 6cf39c2d4b..ca095389a3 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -24,7 +24,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "math"
"math/big"
"net"
"net/http"
@@ -259,6 +258,16 @@ var (
Usage: "Manually specify the Osaka fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
+ OverrideBPO1 = &cli.Uint64Flag{
+ Name: "override.bpo1",
+ Usage: "Manually specify the bpo1 fork timestamp, overriding the bundled setting",
+ Category: flags.EthCategory,
+ }
+ OverrideBPO2 = &cli.Uint64Flag{
+ Name: "override.bpo2",
+ Usage: "Manually specify the bpo2 fork timestamp, overriding the bundled setting",
+ Category: flags.EthCategory,
+ }
OverrideVerkle = &cli.Uint64Flag{
Name: "override.verkle",
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
@@ -321,6 +330,12 @@ var (
Usage: "Scheme to use for storing ethereum state ('hash' or 'path')",
Category: flags.StateCategory,
}
+ StateSizeTrackingFlag = &cli.BoolFlag{
+ Name: "state.size-tracking",
+ Usage: "Enable state size tracking, retrieve state size with debug_stateSize.",
+ Value: ethconfig.Defaults.EnableStateSizeTracking,
+ Category: flags.StateCategory,
+ }
StateHistoryFlag = &cli.Uint64Flag{
Name: "history.state",
Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)",
@@ -633,6 +648,16 @@ var (
Value: "{}",
Category: flags.VMCategory,
}
+ VMWitnessStatsFlag = &cli.BoolFlag{
+ Name: "vmwitnessstats",
+ Usage: "Enable collection of witness trie access statistics (automatically enables witness generation)",
+ Category: flags.VMCategory,
+ }
+ VMStatelessSelfValidationFlag = &cli.BoolFlag{
+ Name: "stateless-self-validation",
+ Usage: "Generate execution witnesses and self-check against them (testing purpose)",
+ Category: flags.VMCategory,
+ }
// API options.
RPCGlobalGasCapFlag = &cli.Uint64Flag{
Name: "rpc.gascap",
@@ -652,6 +677,12 @@ var (
Value: ethconfig.Defaults.RPCTxFeeCap,
Category: flags.APICategory,
}
+ RPCGlobalLogQueryLimit = &cli.IntFlag{
+ Name: "rpc.logquerylimit",
+ Usage: "Maximum number of alternative addresses or topics allowed per search position in eth_getLogs filter criteria (0 = no cap)",
+ Value: ethconfig.Defaults.LogQueryLimit,
+ Category: flags.APICategory,
+ }
// Authenticated RPC HTTP settings
AuthListenFlag = &cli.StringFlag{
Name: "authrpc.addr",
@@ -1782,7 +1813,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
// Ensure Go's GC ignores the database cache for trigger percentage
cache := ctx.Int(CacheFlag.Name)
- gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
+ gogc := max(20, min(100, 100/(float64(cache)/1024)))
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
godebug.SetGCPercent(int(gogc))
@@ -1877,6 +1908,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(CacheLogSizeFlag.Name) {
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
}
+ if ctx.IsSet(RPCGlobalLogQueryLimit.Name) {
+ cfg.LogQueryLimit = ctx.Int(RPCGlobalLogQueryLimit.Name)
+ }
if !ctx.Bool(SnapshotFlag.Name) || cfg.SnapshotCache == 0 {
// If snap-sync is requested, this flag is also required
if cfg.SyncMode == ethconfig.SnapSync {
@@ -1895,6 +1929,16 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(VMEnableDebugFlag.Name) {
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
}
+ if ctx.IsSet(VMWitnessStatsFlag.Name) {
+ cfg.EnableWitnessStats = ctx.Bool(VMWitnessStatsFlag.Name)
+ }
+ if ctx.IsSet(VMStatelessSelfValidationFlag.Name) {
+ cfg.StatelessSelfValidation = ctx.Bool(VMStatelessSelfValidationFlag.Name)
+ }
+ // Auto-enable StatelessSelfValidation when witness stats are enabled
+ if ctx.Bool(VMWitnessStatsFlag.Name) {
+ cfg.StatelessSelfValidation = true
+ }
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
@@ -1945,6 +1989,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.RollupSequencerTxConditionalEnabled = ctx.Bool(RollupSequencerTxConditionalEnabledFlag.Name)
cfg.RollupSequencerTxConditionalCostRateLimit = ctx.Int(RollupSequencerTxConditionalCostRateLimitFlag.Name)
+ if ctx.Bool(StateSizeTrackingFlag.Name) {
+ cfg.EnableStateSizeTracking = true
+ }
// Override any default configs for hard coded networks.
switch {
case ctx.Bool(MainnetFlag.Name):
@@ -2119,11 +2166,15 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig {
} else {
Fatalf("Could not parse --%s: %v", BeaconGenesisRootFlag.Name, err)
}
- configFile := ctx.String(BeaconConfigFlag.Name)
- if err := config.ChainConfig.LoadForks(configFile); err != nil {
- Fatalf("Could not load beacon chain config '%s': %v", configFile, err)
+ configPath := ctx.String(BeaconConfigFlag.Name)
+ file, err := os.ReadFile(configPath)
+ if err != nil {
+ Fatalf("failed to read beacon chain config file '%s': %v", configPath, err)
}
- log.Info("Using custom beacon chain config", "file", configFile)
+ if err := config.ChainConfig.LoadForks(file); err != nil {
+ Fatalf("Could not load beacon chain config '%s': %v", configPath, err)
+ }
+ log.Info("Using custom beacon chain config", "file", configPath)
} else {
if ctx.IsSet(BeaconGenesisRootFlag.Name) {
Fatalf("Genesis root is specified but custom beacon chain config is missing")
@@ -2214,7 +2265,8 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSyst
// RegisterFilterAPI adds the eth log filtering RPC API to the node.
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
filterSystem := filters.NewFilterSystem(backend, filters.Config{
- LogCacheSize: ethcfg.FilterLogCacheSize,
+ LogCacheSize: ethcfg.FilterLogCacheSize,
+ LogQueryLimit: ethcfg.LogQueryLimit,
})
stack.RegisterAPIs([]rpc.API{{
Namespace: "eth",
@@ -2444,6 +2496,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
// - DATADIR/triedb/merkle.journal
// - DATADIR/triedb/verkle.journal
TrieJournalDirectory: stack.ResolvePath("triedb"),
+
+ // Enable state size tracking if enabled
+ StateSizeTracking: ctx.Bool(StateSizeTrackingFlag.Name),
}
if options.ArchiveMode && !options.Preimages {
options.Preimages = true
@@ -2467,6 +2522,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
}
vmcfg := vm.Config{
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
+ EnableWitnessStats: ctx.Bool(VMWitnessStatsFlag.Name),
+ StatelessSelfValidation: ctx.Bool(VMStatelessSelfValidationFlag.Name) || ctx.Bool(VMWitnessStatsFlag.Name),
}
if ctx.IsSet(VMTraceFlag.Name) {
if name := ctx.String(VMTraceFlag.Name); name != "" {
@@ -2505,7 +2562,7 @@ func MakeConsolePreloads(ctx *cli.Context) []string {
}
// MakeTrieDatabase constructs a trie database based on the configured scheme.
-func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
+func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database {
config := &triedb.Config{
Preimages: preimage,
IsVerkle: isVerkle,
@@ -2521,10 +2578,13 @@ func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, read
config.HashDB = hashdb.Defaults
return triedb.NewDatabase(disk, config)
}
+ var pathConfig pathdb.Config
if readOnly {
- config.PathDB = pathdb.ReadOnly
+ pathConfig = *pathdb.ReadOnly
} else {
- config.PathDB = pathdb.Defaults
+ pathConfig = *pathdb.Defaults
}
+ pathConfig.JournalDirectory = stack.ResolvePath("triedb")
+ config.PathDB = &pathConfig
return triedb.NewDatabase(disk, config)
}
diff --git a/common/hexutil/json_test.go b/common/hexutil/json_test.go
index a014438458..3dc19680f9 100644
--- a/common/hexutil/json_test.go
+++ b/common/hexutil/json_test.go
@@ -408,7 +408,6 @@ func TestUnmarshalFixedUnprefixedText(t *testing.T) {
{input: "0x2", wantErr: ErrOddLength},
{input: "2", wantErr: ErrOddLength},
{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
- {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
// check that output is not modified for partially correct input
{input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
{input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
diff --git a/common/math/integer_test.go b/common/math/integer_test.go
index 4643a43f20..feb761c6dc 100644
--- a/common/math/integer_test.go
+++ b/common/math/integer_test.go
@@ -110,7 +110,7 @@ func TestMustParseUint64(t *testing.T) {
func TestMustParseUint64Panic(t *testing.T) {
defer func() {
if recover() == nil {
- t.Error("MustParseBig should've panicked")
+ t.Error("MustParseUint64 should've panicked")
}
}()
MustParseUint64("ggg")
diff --git a/conflicts.patch b/conflicts.patch
new file mode 100644
index 0000000000..bf8fa42003
--- /dev/null
+++ b/conflicts.patch
@@ -0,0 +1,10397 @@
+diff --git a/.circleci/config.yml b/.circleci/config.yml
+index 1a3809cd35..8d735288b0 100644
+--- a/.circleci/config.yml
++++ b/.circleci/config.yml
+@@ -8,7 +8,7 @@
+ parameters:
+ go_version:
+ type: string
+- default: 1.23.8 # update CI Go version here
++ default: 1.25.1 # update CI Go version here
+
+ commands:
+ gcp-oidc-authenticate:
+diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
+deleted file mode 100644
+index 0000000000..0000000000
+--- a/.github/workflows/go.yml
++++ /dev/null
+@@ -1,63 +0,0 @@
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+-%%%%%%% Changes from base to side #2
+- on:
+- push:
+- branches:
+- - master
+- pull_request:
+- branches:
+- - master
+- workflow_dispatch:
+-
+- jobs:
+- lint:
+- name: Lint
+- runs-on: self-hosted-ghr
+- steps:
+- - uses: actions/checkout@v4
+- with:
+- submodules: false
+-
+- # Cache build tools to avoid downloading them each time
+- - uses: actions/cache@v4
+- with:
+- path: build/cache
+- key: ${{ runner.os }}-build-tools-cache-${{ hashFiles('build/checksums.txt') }}
+-
+- - name: Set up Go
+- uses: actions/setup-go@v5
+- with:
+- go-version: 1.25
+- cache: false
+-
+- - name: Run linters
+- run: |
+- go run build/ci.go lint
+- go run build/ci.go check_generate
+- go run build/ci.go check_baddeps
+-
+- test:
+- name: Test
+- needs: lint
+- runs-on: self-hosted-ghr
+- strategy:
+- matrix:
+- go:
+- - '1.25'
+- - '1.24'
+- steps:
+- - uses: actions/checkout@v4
+- with:
+- submodules: true
+-
+- - name: Set up Go
+- uses: actions/setup-go@v5
+- with:
+- go-version: ${{ matrix.go }}
+- cache: false
+-
+- - name: Run tests
+-- run: go test ./...
+-+ run: go run build/ci.go test
+->>>>>>> Conflict 1 of 1 ends
+diff --git a/.github/workflows/validate_pr.yml b/.github/workflows/validate_pr.yml
+deleted file mode 100644
+index 0000000000..0000000000
+--- a/.github/workflows/validate_pr.yml
++++ /dev/null
+@@ -1,28 +0,0 @@
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+-%%%%%%% Changes from base to side #2
+- name: PR Format Validation
+-
+- on:
+- pull_request:
+- types: [opened, edited, synchronize]
+-
+- jobs:
+- validate-pr:
+- runs-on: ubuntu-latest
+- steps:
+- - name: Check PR Title Format
+- uses: actions/github-script@v7
+- with:
+- script: |
+- const prTitle = context.payload.pull_request.title;
+-- const titleRegex = /^(\.?[\w\s,{}/]+): .+/;
+-+ const titleRegex = /^([\w\s,{}/.]+): .+/;
+-
+- if (!titleRegex.test(prTitle)) {
+- core.setFailed(`PR title "${prTitle}" does not match required format: directory, ...: description`);
+- return;
+- }
+-
+- console.log('✅ PR title format is valid');
+->>>>>>> Conflict 1 of 1 ends
+diff --git a/accounts/usbwallet/hub.go b/accounts/usbwallet/hub.go
+deleted file mode 100644
+index 81457b7da2..0000000000
+--- a/accounts/usbwallet/hub.go
++++ /dev/null
+@@ -1,288 +0,0 @@
+-// Copyright 2017 The go-ethereum Authors
+-// This file is part of the go-ethereum library.
+-//
+-// The go-ethereum library is free software: you can redistribute it and/or modify
+-// it under the terms of the GNU Lesser General Public License as published by
+-// the Free Software Foundation, either version 3 of the License, or
+-// (at your option) any later version.
+-//
+-// The go-ethereum library is distributed in the hope that it will be useful,
+-// but WITHOUT ANY WARRANTY; without even the implied warranty of
+-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-// GNU Lesser General Public License for more details.
+-//
+-// You should have received a copy of the GNU Lesser General Public License
+-// along with the go-ethereum library. If not, see .
+-
+-package usbwallet
+-
+-import (
+- "errors"
+- "runtime"
+- "sync"
+- "sync/atomic"
+- "time"
+-
+- "github.com/ethereum/go-ethereum/accounts"
+- "github.com/ethereum/go-ethereum/event"
+- "github.com/ethereum/go-ethereum/log"
+- "github.com/karalabe/hid"
+-)
+-
+-// LedgerScheme is the protocol scheme prefixing account and wallet URLs.
+-const LedgerScheme = "ledger"
+-
+-// TrezorScheme is the protocol scheme prefixing account and wallet URLs.
+-const TrezorScheme = "trezor"
+-
+-// refreshCycle is the maximum time between wallet refreshes (if USB hotplug
+-// notifications don't work).
+-const refreshCycle = time.Second
+-
+-// refreshThrottling is the minimum time between wallet refreshes to avoid USB
+-// trashing.
+-const refreshThrottling = 500 * time.Millisecond
+-
+-// Hub is a accounts.Backend that can find and handle generic USB hardware wallets.
+-type Hub struct {
+- scheme string // Protocol scheme prefixing account and wallet URLs.
+- vendorID uint16 // USB vendor identifier used for device discovery
+- productIDs []uint16 // USB product identifiers used for device discovery
+- usageID uint16 // USB usage page identifier used for macOS device discovery
+- endpointID int // USB endpoint identifier used for non-macOS device discovery
+- makeDriver func(log.Logger) driver // Factory method to construct a vendor specific driver
+-
+- refreshed time.Time // Time instance when the list of wallets was last refreshed
+- wallets []accounts.Wallet // List of USB wallet devices currently tracking
+- updateFeed event.Feed // Event feed to notify wallet additions/removals
+- updateScope event.SubscriptionScope // Subscription scope tracking current live listeners
+- updating bool // Whether the event notification loop is running
+-
+- quit chan chan error
+-
+- stateLock sync.RWMutex // Protects the internals of the hub from racey access
+-
+- // TODO(karalabe): remove if hotplug lands on Windows
+- commsPend int // Number of operations blocking enumeration
+- commsLock sync.Mutex // Lock protecting the pending counter and enumeration
+- enumFails atomic.Uint32 // Number of times enumeration has failed
+-}
+-
+-// NewLedgerHub creates a new hardware wallet manager for Ledger devices.
+-func NewLedgerHub() (*Hub, error) {
+- return newHub(LedgerScheme, 0x2c97, []uint16{
+-
+- // Device definitions taken from
+- // https://github.com/LedgerHQ/ledger-live/blob/595cb73b7e6622dbbcfc11867082ddc886f1bf01/libs/ledgerjs/packages/devices/src/index.ts
+-
+- // Original product IDs
+- 0x0000, /* Ledger Blue */
+- 0x0001, /* Ledger Nano S */
+- 0x0004, /* Ledger Nano X */
+- 0x0005, /* Ledger Nano S Plus */
+- 0x0006, /* Ledger Nano FTS */
+- 0x0007, /* Ledger Flex */
+-
+- 0x0000, /* WebUSB Ledger Blue */
+- 0x1000, /* WebUSB Ledger Nano S */
+- 0x4000, /* WebUSB Ledger Nano X */
+- 0x5000, /* WebUSB Ledger Nano S Plus */
+- 0x6000, /* WebUSB Ledger Nano FTS */
+- 0x7000, /* WebUSB Ledger Flex */
+- }, 0xffa0, 0, newLedgerDriver)
+-}
+-
+-// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices.
+-func NewTrezorHubWithHID() (*Hub, error) {
+- return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver)
+-}
+-
+-// NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with
+-// firmware version > 1.8.0
+-func NewTrezorHubWithWebUSB() (*Hub, error) {
+- return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver)
+-}
+-
+-// newHub creates a new hardware wallet manager for generic USB devices.
+-func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) {
+- if !hid.Supported() {
+- return nil, errors.New("unsupported platform")
+- }
+- hub := &Hub{
+- scheme: scheme,
+- vendorID: vendorID,
+- productIDs: productIDs,
+- usageID: usageID,
+- endpointID: endpointID,
+- makeDriver: makeDriver,
+- quit: make(chan chan error),
+- }
+- hub.refreshWallets()
+- return hub, nil
+-}
+-
+-// Wallets implements accounts.Backend, returning all the currently tracked USB
+-// devices that appear to be hardware wallets.
+-func (hub *Hub) Wallets() []accounts.Wallet {
+- // Make sure the list of wallets is up to date
+- hub.refreshWallets()
+-
+- hub.stateLock.RLock()
+- defer hub.stateLock.RUnlock()
+-
+- cpy := make([]accounts.Wallet, len(hub.wallets))
+- copy(cpy, hub.wallets)
+- return cpy
+-}
+-
+-// refreshWallets scans the USB devices attached to the machine and updates the
+-// list of wallets based on the found devices.
+-func (hub *Hub) refreshWallets() {
+- // Don't scan the USB like crazy it the user fetches wallets in a loop
+- hub.stateLock.RLock()
+- elapsed := time.Since(hub.refreshed)
+- hub.stateLock.RUnlock()
+-
+- if elapsed < refreshThrottling {
+- return
+- }
+- // If USB enumeration is continually failing, don't keep trying indefinitely
+- if hub.enumFails.Load() > 2 {
+- return
+- }
+- // Retrieve the current list of USB wallet devices
+- var devices []hid.DeviceInfo
+-
+- if runtime.GOOS == "linux" {
+- // hidapi on Linux opens the device during enumeration to retrieve some infos,
+- // breaking the Ledger protocol if that is waiting for user confirmation. This
+- // is a bug acknowledged at Ledger, but it won't be fixed on old devices so we
+- // need to prevent concurrent comms ourselves. The more elegant solution would
+- // be to ditch enumeration in favor of hotplug events, but that don't work yet
+- // on Windows so if we need to hack it anyway, this is more elegant for now.
+- hub.commsLock.Lock()
+- if hub.commsPend > 0 { // A confirmation is pending, don't refresh
+- hub.commsLock.Unlock()
+- return
+- }
+- }
+- infos, err := hid.Enumerate(hub.vendorID, 0)
+- if err != nil {
+- failcount := hub.enumFails.Add(1)
+- if runtime.GOOS == "linux" {
+- // See rationale before the enumeration why this is needed and only on Linux.
+- hub.commsLock.Unlock()
+- }
+- log.Error("Failed to enumerate USB devices", "hub", hub.scheme,
+- "vendor", hub.vendorID, "failcount", failcount, "err", err)
+- return
+- }
+- hub.enumFails.Store(0)
+-
+- for _, info := range infos {
+- for _, id := range hub.productIDs {
+- // We check both the raw ProductID (legacy) and just the upper byte, as Ledger
+- // uses `MMII`, encoding a model (MM) and an interface bitfield (II)
+- mmOnly := info.ProductID & 0xff00
+- // Windows and Macos use UsageID matching, Linux uses Interface matching
+- if (info.ProductID == id || mmOnly == id) && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) {
+- devices = append(devices, info)
+- break
+- }
+- }
+- }
+- if runtime.GOOS == "linux" {
+- // See rationale before the enumeration why this is needed and only on Linux.
+- hub.commsLock.Unlock()
+- }
+- // Transform the current list of wallets into the new one
+- hub.stateLock.Lock()
+-
+- var (
+- wallets = make([]accounts.Wallet, 0, len(devices))
+- events []accounts.WalletEvent
+- )
+-
+- for _, device := range devices {
+- url := accounts.URL{Scheme: hub.scheme, Path: device.Path}
+-
+- // Drop wallets in front of the next device or those that failed for some reason
+- for len(hub.wallets) > 0 {
+- // Abort if we're past the current device and found an operational one
+- _, failure := hub.wallets[0].Status()
+- if hub.wallets[0].URL().Cmp(url) >= 0 || failure == nil {
+- break
+- }
+- // Drop the stale and failed devices
+- events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped})
+- hub.wallets = hub.wallets[1:]
+- }
+- // If there are no more wallets or the device is before the next, wrap new wallet
+- if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 {
+- logger := log.New("url", url)
+- wallet := &wallet{hub: hub, driver: hub.makeDriver(logger), url: &url, info: device, log: logger}
+-
+- events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
+- wallets = append(wallets, wallet)
+- continue
+- }
+- // If the device is the same as the first wallet, keep it
+- if hub.wallets[0].URL().Cmp(url) == 0 {
+- wallets = append(wallets, hub.wallets[0])
+- hub.wallets = hub.wallets[1:]
+- continue
+- }
+- }
+- // Drop any leftover wallets and set the new batch
+- for _, wallet := range hub.wallets {
+- events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
+- }
+- hub.refreshed = time.Now()
+- hub.wallets = wallets
+- hub.stateLock.Unlock()
+-
+- // Fire all wallet events and return
+- for _, event := range events {
+- hub.updateFeed.Send(event)
+- }
+-}
+-
+-// Subscribe implements accounts.Backend, creating an async subscription to
+-// receive notifications on the addition or removal of USB wallets.
+-func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
+- // We need the mutex to reliably start/stop the update loop
+- hub.stateLock.Lock()
+- defer hub.stateLock.Unlock()
+-
+- // Subscribe the caller and track the subscriber count
+- sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink))
+-
+- // Subscribers require an active notification loop, start it
+- if !hub.updating {
+- hub.updating = true
+- go hub.updater()
+- }
+- return sub
+-}
+-
+-// updater is responsible for maintaining an up-to-date list of wallets managed
+-// by the USB hub, and for firing wallet addition/removal events.
+-func (hub *Hub) updater() {
+- for {
+- // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout
+- // <-hub.changes
+- time.Sleep(refreshCycle)
+-
+- // Run the wallet refresher
+- hub.refreshWallets()
+-
+- // If all our subscribers left, stop the updater
+- hub.stateLock.Lock()
+- if hub.updateScope.Count() == 0 {
+- hub.updating = false
+- hub.stateLock.Unlock()
+- return
+- }
+- hub.stateLock.Unlock()
+- }
+-}
+diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go
+deleted file mode 100644
+index 52595a1621..0000000000
+--- a/accounts/usbwallet/ledger.go
++++ /dev/null
+@@ -1,573 +0,0 @@
+-// Copyright 2017 The go-ethereum Authors
+-// This file is part of the go-ethereum library.
+-//
+-// The go-ethereum library is free software: you can redistribute it and/or modify
+-// it under the terms of the GNU Lesser General Public License as published by
+-// the Free Software Foundation, either version 3 of the License, or
+-// (at your option) any later version.
+-//
+-// The go-ethereum library is distributed in the hope that it will be useful,
+-// but WITHOUT ANY WARRANTY; without even the implied warranty of
+-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-// GNU Lesser General Public License for more details.
+-//
+-// You should have received a copy of the GNU Lesser General Public License
+-// along with the go-ethereum library. If not, see .
+-
+-// This file contains the implementation for interacting with the Ledger hardware
+-// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo:
+-// https://github.com/LedgerHQ/app-ethereum/blob/develop/doc/ethapp.adoc
+-
+-package usbwallet
+-
+-import (
+- "encoding/binary"
+- "encoding/hex"
+- "errors"
+- "fmt"
+- "io"
+- "math/big"
+-
+- "github.com/ethereum/go-ethereum/accounts"
+- "github.com/ethereum/go-ethereum/common"
+- "github.com/ethereum/go-ethereum/common/hexutil"
+- "github.com/ethereum/go-ethereum/core/types"
+- "github.com/ethereum/go-ethereum/crypto"
+- "github.com/ethereum/go-ethereum/log"
+- "github.com/ethereum/go-ethereum/rlp"
+-)
+-
+-// ledgerOpcode is an enumeration encoding the supported Ledger opcodes.
+-type ledgerOpcode byte
+-
+-// ledgerParam1 is an enumeration encoding the supported Ledger parameters for
+-// specific opcodes. The same parameter values may be reused between opcodes.
+-type ledgerParam1 byte
+-
+-// ledgerParam2 is an enumeration encoding the supported Ledger parameters for
+-// specific opcodes. The same parameter values may be reused between opcodes.
+-type ledgerParam2 byte
+-
+-const (
+- ledgerOpRetrieveAddress ledgerOpcode = 0x02 // Returns the public key and Ethereum address for a given BIP 32 path
+- ledgerOpSignTransaction ledgerOpcode = 0x04 // Signs an Ethereum transaction after having the user validate the parameters
+- ledgerOpGetConfiguration ledgerOpcode = 0x06 // Returns specific wallet application configuration
+- ledgerOpSignTypedMessage ledgerOpcode = 0x0c // Signs an Ethereum message following the EIP 712 specification
+-
+- ledgerP1DirectlyFetchAddress ledgerParam1 = 0x00 // Return address directly from the wallet
+- ledgerP1InitTypedMessageData ledgerParam1 = 0x00 // First chunk of Typed Message data
+- ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing
+- ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing
+- ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address
+-
+- ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions
+-)
+-
+-// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange
+-// if the device replies with a mismatching header. This usually means the device
+-// is in browser mode.
+-var errLedgerReplyInvalidHeader = errors.New("ledger: invalid reply header")
+-
+-// errLedgerInvalidVersionReply is the error message returned by a Ledger version retrieval
+-// when a response does arrive, but it does not contain the expected data.
+-var errLedgerInvalidVersionReply = errors.New("ledger: invalid version reply")
+-
+-// ledgerDriver implements the communication with a Ledger hardware wallet.
+-type ledgerDriver struct {
+- device io.ReadWriter // USB device connection to communicate through
+- version [3]byte // Current version of the Ledger firmware (zero if app is offline)
+- browser bool // Flag whether the Ledger is in browser mode (reply channel mismatch)
+- failure error // Any failure that would make the device unusable
+- log log.Logger // Contextual logger to tag the ledger with its id
+-}
+-
+-// newLedgerDriver creates a new instance of a Ledger USB protocol driver.
+-func newLedgerDriver(logger log.Logger) driver {
+- return &ledgerDriver{
+- log: logger,
+- }
+-}
+-
+-// Status implements usbwallet.driver, returning various states the Ledger can
+-// currently be in.
+-func (w *ledgerDriver) Status() (string, error) {
+- if w.failure != nil {
+- return fmt.Sprintf("Failed: %v", w.failure), w.failure
+- }
+- if w.browser {
+- return "Ethereum app in browser mode", w.failure
+- }
+- if w.offline() {
+- return "Ethereum app offline", w.failure
+- }
+- return fmt.Sprintf("Ethereum app v%d.%d.%d online", w.version[0], w.version[1], w.version[2]), w.failure
+-}
+-
+-// offline returns whether the wallet and the Ethereum app is offline or not.
+-//
+-// The method assumes that the state lock is held!
+-func (w *ledgerDriver) offline() bool {
+- return w.version == [3]byte{0, 0, 0}
+-}
+-
+-// Open implements usbwallet.driver, attempting to initialize the connection to the
+-// Ledger hardware wallet. The Ledger does not require a user passphrase, so that
+-// parameter is silently discarded.
+-func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error {
+- w.device, w.failure = device, nil
+-
+- _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath)
+- if err != nil {
+- // Ethereum app is not running or in browser mode, nothing more to do, return
+- if err == errLedgerReplyInvalidHeader {
+- w.browser = true
+- }
+- return nil
+- }
+- // Try to resolve the Ethereum app's version, will fail prior to v1.0.2
+- if w.version, err = w.ledgerVersion(); err != nil {
+- w.version = [3]byte{1, 0, 0} // Assume worst case, can't verify if v1.0.0 or v1.0.1
+- }
+- return nil
+-}
+-
+-// Close implements usbwallet.driver, cleaning up and metadata maintained within
+-// the Ledger driver.
+-func (w *ledgerDriver) Close() error {
+- w.browser, w.version = false, [3]byte{}
+- return nil
+-}
+-
+-// Heartbeat implements usbwallet.driver, performing a sanity check against the
+-// Ledger to see if it's still online.
+-func (w *ledgerDriver) Heartbeat() error {
+- if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply {
+- w.failure = err
+- return err
+- }
+- return nil
+-}
+-
+-// Derive implements usbwallet.driver, sending a derivation request to the Ledger
+-// and returning the Ethereum address located on that derivation path.
+-func (w *ledgerDriver) Derive(path accounts.DerivationPath) (common.Address, error) {
+- return w.ledgerDerive(path)
+-}
+-
+-// SignTx implements usbwallet.driver, sending the transaction to the Ledger and
+-// waiting for the user to confirm or deny the transaction.
+-//
+-// Note, if the version of the Ethereum application running on the Ledger wallet is
+-// too old to sign EIP-155 transactions, but such is requested nonetheless, an error
+-// will be returned opposed to silently signing in Homestead mode.
+-func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
+- // If the Ethereum app doesn't run, abort
+- if w.offline() {
+- return common.Address{}, nil, accounts.ErrWalletClosed
+- }
+- // Ensure the wallet is capable of signing the given transaction
+- if chainID != nil && (w.version[0] < 1 || (w.version[0] == 1 && w.version[1] == 0 && w.version[2] < 3)) {
+- //lint:ignore ST1005 brand name displayed on the console
+- return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
+- }
+- // All infos gathered and metadata checks out, request signing
+- return w.ledgerSign(path, tx, chainID)
+-}
+-
+-// SignTypedMessage implements usbwallet.driver, sending the message to the Ledger and
+-// waiting for the user to sign or deny the transaction.
+-//
+-// Note: this was introduced in the ledger 1.5.0 firmware
+-func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) {
+- // If the Ethereum app doesn't run, abort
+- if w.offline() {
+- return nil, accounts.ErrWalletClosed
+- }
+- // Ensure the wallet is capable of signing the given transaction
+- if w.version[0] < 1 && w.version[1] < 5 {
+- //lint:ignore ST1005 brand name displayed on the console
+- return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
+- }
+- // All infos gathered and metadata checks out, request signing
+- return w.ledgerSignTypedMessage(path, domainHash, messageHash)
+-}
+-
+-// ledgerVersion retrieves the current version of the Ethereum wallet app running
+-// on the Ledger wallet.
+-//
+-// The version retrieval protocol is defined as follows:
+-//
+-// CLA | INS | P1 | P2 | Lc | Le
+-// ----+-----+----+----+----+---
+-// E0 | 06 | 00 | 00 | 00 | 04
+-//
+-// With no input data, and the output data being:
+-//
+-// Description | Length
+-// ---------------------------------------------------+--------
+-// Flags 01: arbitrary data signature enabled by user | 1 byte
+-// Application major version | 1 byte
+-// Application minor version | 1 byte
+-// Application patch version | 1 byte
+-func (w *ledgerDriver) ledgerVersion() ([3]byte, error) {
+- // Send the request and wait for the response
+- reply, err := w.ledgerExchange(ledgerOpGetConfiguration, 0, 0, nil)
+- if err != nil {
+- return [3]byte{}, err
+- }
+- if len(reply) != 4 {
+- return [3]byte{}, errLedgerInvalidVersionReply
+- }
+- // Cache the version for future reference
+- var version [3]byte
+- copy(version[:], reply[1:])
+- return version, nil
+-}
+-
+-// ledgerDerive retrieves the currently active Ethereum address from a Ledger
+-// wallet at the specified derivation path.
+-//
+-// The address derivation protocol is defined as follows:
+-//
+-// CLA | INS | P1 | P2 | Lc | Le
+-// ----+-----+----+----+-----+---
+-// E0 | 02 | 00 return address
+-// 01 display address and confirm before returning
+-// | 00: do not return the chain code
+-// | 01: return the chain code
+-// | var | 00
+-//
+-// Where the input data is:
+-//
+-// Description | Length
+-// -------------------------------------------------+--------
+-// Number of BIP 32 derivations to perform (max 10) | 1 byte
+-// First derivation index (big endian) | 4 bytes
+-// ... | 4 bytes
+-// Last derivation index (big endian) | 4 bytes
+-//
+-// And the output data is:
+-//
+-// Description | Length
+-// ------------------------+-------------------
+-// Public Key length | 1 byte
+-// Uncompressed Public Key | arbitrary
+-// Ethereum address length | 1 byte
+-// Ethereum address | 40 bytes hex ascii
+-// Chain code if requested | 32 bytes
+-func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, error) {
+- // Flatten the derivation path into the Ledger request
+- path := make([]byte, 1+4*len(derivationPath))
+- path[0] = byte(len(derivationPath))
+- for i, component := range derivationPath {
+- binary.BigEndian.PutUint32(path[1+4*i:], component)
+- }
+- // Send the request and wait for the response
+- reply, err := w.ledgerExchange(ledgerOpRetrieveAddress, ledgerP1DirectlyFetchAddress, ledgerP2DiscardAddressChainCode, path)
+- if err != nil {
+- return common.Address{}, err
+- }
+- // Discard the public key, we don't need that for now
+- if len(reply) < 1 || len(reply) < 1+int(reply[0]) {
+- return common.Address{}, errors.New("reply lacks public key entry")
+- }
+- reply = reply[1+int(reply[0]):]
+-
+- // Extract the Ethereum hex address string
+- if len(reply) < 1 || len(reply) < 1+int(reply[0]) {
+- return common.Address{}, errors.New("reply lacks address entry")
+- }
+- hexstr := reply[1 : 1+int(reply[0])]
+-
+- // Decode the hex string into an Ethereum address and return
+- var address common.Address
+- if _, err = hex.Decode(address[:], hexstr); err != nil {
+- return common.Address{}, err
+- }
+- return address, nil
+-}
+-
+-// ledgerSign sends the transaction to the Ledger wallet, and waits for the user
+-// to confirm or deny the transaction.
+-//
+-// The transaction signing protocol is defined as follows:
+-//
+-// CLA | INS | P1 | P2 | Lc | Le
+-// ----+-----+----+----+-----+---
+-// E0 | 04 | 00: first transaction data block
+-// 80: subsequent transaction data block
+-// | 00 | variable | variable
+-//
+-// Where the input for the first transaction block (first 255 bytes) is:
+-//
+-// Description | Length
+-// -------------------------------------------------+----------
+-// Number of BIP 32 derivations to perform (max 10) | 1 byte
+-// First derivation index (big endian) | 4 bytes
+-// ... | 4 bytes
+-// Last derivation index (big endian) | 4 bytes
+-// RLP transaction chunk | arbitrary
+-//
+-// And the input for subsequent transaction blocks (first 255 bytes) are:
+-//
+-// Description | Length
+-// ----------------------+----------
+-// RLP transaction chunk | arbitrary
+-//
+-// And the output data is:
+-//
+-// Description | Length
+-// ------------+---------
+-// signature V | 1 byte
+-// signature R | 32 bytes
+-// signature S | 32 bytes
+-func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
+- // Flatten the derivation path into the Ledger request
+- path := make([]byte, 1+4*len(derivationPath))
+- path[0] = byte(len(derivationPath))
+- for i, component := range derivationPath {
+- binary.BigEndian.PutUint32(path[1+4*i:], component)
+- }
+- // Create the transaction RLP based on whether legacy or EIP155 signing was requested
+- var (
+- txrlp []byte
+- err error
+- )
+- if chainID == nil {
+- if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil {
+- return common.Address{}, nil, err
+- }
+- } else {
+- if tx.Type() == types.DynamicFeeTxType {
+- if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
+- return common.Address{}, nil, err
+- }
+- // append type to transaction
+- txrlp = append([]byte{tx.Type()}, txrlp...)
+- } else if tx.Type() == types.AccessListTxType {
+- if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
+- return common.Address{}, nil, err
+- }
+- // append type to transaction
+- txrlp = append([]byte{tx.Type()}, txrlp...)
+- } else if tx.Type() == types.LegacyTxType {
+- if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
+- return common.Address{}, nil, err
+- }
+- }
+- }
+- payload := append(path, txrlp...)
+-
+- // Send the request and wait for the response
+- var (
+- op = ledgerP1InitTransactionData
+- reply []byte
+- )
+-
+- // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
+- // https://github.com/LedgerHQ/app-ethereum/issues/409
+- chunk := 255
+- if tx.Type() == types.LegacyTxType {
+- for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
+- }
+- }
+-
+- for len(payload) > 0 {
+- // Calculate the size of the next data chunk
+- if chunk > len(payload) {
+- chunk = len(payload)
+- }
+- // Send the chunk over, ensuring it's processed correctly
+- reply, err = w.ledgerExchange(ledgerOpSignTransaction, op, 0, payload[:chunk])
+- if err != nil {
+- return common.Address{}, nil, err
+- }
+- // Shift the payload and ensure subsequent chunks are marked as such
+- payload = payload[chunk:]
+- op = ledgerP1ContTransactionData
+- }
+- // Extract the Ethereum signature and do a sanity validation
+- if len(reply) != crypto.SignatureLength {
+- return common.Address{}, nil, errors.New("reply lacks signature")
+- }
+- signature := append(reply[1:], reply[0])
+-
+- // Create the correct signer and signature transform based on the chain ID
+- var signer types.Signer
+- if chainID == nil {
+- signer = new(types.HomesteadSigner)
+- } else {
+- signer = types.LatestSignerForChainID(chainID)
+- // For non-legacy transactions, V is 0 or 1, no need to subtract here.
+- if tx.Type() == types.LegacyTxType {
+- signature[64] -= byte(chainID.Uint64()*2 + 35)
+- }
+- }
+- signed, err := tx.WithSignature(signer, signature)
+- if err != nil {
+- return common.Address{}, nil, err
+- }
+- sender, err := types.Sender(signer, signed)
+- if err != nil {
+- return common.Address{}, nil, err
+- }
+- return sender, signed, nil
+-}
+-
+-// ledgerSignTypedMessage sends the transaction to the Ledger wallet, and waits for the user
+-// to confirm or deny the transaction.
+-//
+-// The signing protocol is defined as follows:
+-//
+-// CLA | INS | P1 | P2 | Lc | Le
+-// ----+-----+----+-----------------------------+-----+---
+-// E0 | 0C | 00 | implementation version : 00 | variable | variable
+-//
+-// Where the input is:
+-//
+-// Description | Length
+-// -------------------------------------------------+----------
+-// Number of BIP 32 derivations to perform (max 10) | 1 byte
+-// First derivation index (big endian) | 4 bytes
+-// ... | 4 bytes
+-// Last derivation index (big endian) | 4 bytes
+-// domain hash | 32 bytes
+-// message hash | 32 bytes
+-//
+-// And the output data is:
+-//
+-// Description | Length
+-// ------------+---------
+-// signature V | 1 byte
+-// signature R | 32 bytes
+-// signature S | 32 bytes
+-func (w *ledgerDriver) ledgerSignTypedMessage(derivationPath []uint32, domainHash []byte, messageHash []byte) ([]byte, error) {
+- // Flatten the derivation path into the Ledger request
+- path := make([]byte, 1+4*len(derivationPath))
+- path[0] = byte(len(derivationPath))
+- for i, component := range derivationPath {
+- binary.BigEndian.PutUint32(path[1+4*i:], component)
+- }
+- // Create the 712 message
+- payload := append(path, domainHash...)
+- payload = append(payload, messageHash...)
+-
+- // Send the request and wait for the response
+- var (
+- op = ledgerP1InitTypedMessageData
+- reply []byte
+- err error
+- )
+-
+- // Send the message over, ensuring it's processed correctly
+- reply, err = w.ledgerExchange(ledgerOpSignTypedMessage, op, 0, payload)
+-
+- if err != nil {
+- return nil, err
+- }
+-
+- // Extract the Ethereum signature and do a sanity validation
+- if len(reply) != crypto.SignatureLength {
+- return nil, errors.New("reply lacks signature")
+- }
+- signature := append(reply[1:], reply[0])
+- return signature, nil
+-}
+-
+-// ledgerExchange performs a data exchange with the Ledger wallet, sending it a
+-// message and retrieving the response.
+-//
+-// The common transport header is defined as follows:
+-//
+-// Description | Length
+-// --------------------------------------+----------
+-// Communication channel ID (big endian) | 2 bytes
+-// Command tag | 1 byte
+-// Packet sequence index (big endian) | 2 bytes
+-// Payload | arbitrary
+-//
+-// The Communication channel ID allows commands multiplexing over the same
+-// physical link. It is not used for the time being, and should be set to 0101
+-// to avoid compatibility issues with implementations ignoring a leading 00 byte.
+-//
+-// The Command tag describes the message content. Use TAG_APDU (0x05) for standard
+-// APDU payloads, or TAG_PING (0x02) for a simple link test.
+-//
+-// The Packet sequence index describes the current sequence for fragmented payloads.
+-// The first fragment index is 0x00.
+-//
+-// APDU Command payloads are encoded as follows:
+-//
+-// Description | Length
+-// -----------------------------------
+-// APDU length (big endian) | 2 bytes
+-// APDU CLA | 1 byte
+-// APDU INS | 1 byte
+-// APDU P1 | 1 byte
+-// APDU P2 | 1 byte
+-// APDU length | 1 byte
+-// Optional APDU data | arbitrary
+-func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 ledgerParam2, data []byte) ([]byte, error) {
+- // Construct the message payload, possibly split into multiple chunks
+- apdu := make([]byte, 2, 7+len(data))
+-
+- binary.BigEndian.PutUint16(apdu, uint16(5+len(data)))
+- apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...)
+- apdu = append(apdu, data...)
+-
+- // Stream all the chunks to the device
+- header := []byte{0x01, 0x01, 0x05, 0x00, 0x00} // Channel ID and command tag appended
+- chunk := make([]byte, 64)
+- space := len(chunk) - len(header)
+-
+- for i := 0; len(apdu) > 0; i++ {
+- // Construct the new message to stream
+- chunk = append(chunk[:0], header...)
+- binary.BigEndian.PutUint16(chunk[3:], uint16(i))
+-
+- if len(apdu) > space {
+- chunk = append(chunk, apdu[:space]...)
+- apdu = apdu[space:]
+- } else {
+- chunk = append(chunk, apdu...)
+- apdu = nil
+- }
+- // Send over to the device
+- w.log.Trace("Data chunk sent to the Ledger", "chunk", hexutil.Bytes(chunk))
+- if _, err := w.device.Write(chunk); err != nil {
+- return nil, err
+- }
+- }
+- // Stream the reply back from the wallet in 64 byte chunks
+- var reply []byte
+- chunk = chunk[:64] // Yeah, we surely have enough space
+- for {
+- // Read the next chunk from the Ledger wallet
+- if _, err := io.ReadFull(w.device, chunk); err != nil {
+- return nil, err
+- }
+- w.log.Trace("Data chunk received from the Ledger", "chunk", hexutil.Bytes(chunk))
+-
+- // Make sure the transport header matches
+- if chunk[0] != 0x01 || chunk[1] != 0x01 || chunk[2] != 0x05 {
+- return nil, errLedgerReplyInvalidHeader
+- }
+- // If it's the first chunk, retrieve the total message length
+- var payload []byte
+-
+- if chunk[3] == 0x00 && chunk[4] == 0x00 {
+- reply = make([]byte, 0, int(binary.BigEndian.Uint16(chunk[5:7])))
+- payload = chunk[7:]
+- } else {
+- payload = chunk[5:]
+- }
+- // Append to the reply and stop when filled up
+- if left := cap(reply) - len(reply); left > len(payload) {
+- reply = append(reply, payload...)
+- } else {
+- reply = append(reply, payload[:left]...)
+- break
+- }
+- }
+- return reply[:len(reply)-2], nil
+-}
+diff --git a/accounts/usbwallet/messages-common.pb.go b/accounts/usbwallet/messages-common.pb.go
+new file mode 100644
+index 0000000000..73800802bb
+--- /dev/null
++++ b/accounts/usbwallet/messages-common.pb.go
+@@ -0,0 +1,1198 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++// Code generated by protoc-gen-go. DO NOT EDIT.
++// versions:
++// protoc-gen-go v1.34.2
++// protoc v5.27.1
++// source: messages-common.proto
++
++package trezor
++
++import (
++ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
++ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
++ reflect "reflect"
++ sync "sync"
++)
++
++const (
++ // Verify that this generated code is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
++ // Verify that runtime/protoimpl is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
++)
++
++type Failure_FailureType int32
++
++const (
++ Failure_Failure_UnexpectedMessage Failure_FailureType = 1
++ Failure_Failure_ButtonExpected Failure_FailureType = 2
++ Failure_Failure_DataError Failure_FailureType = 3
++ Failure_Failure_ActionCancelled Failure_FailureType = 4
++ Failure_Failure_PinExpected Failure_FailureType = 5
++ Failure_Failure_PinCancelled Failure_FailureType = 6
++ Failure_Failure_PinInvalid Failure_FailureType = 7
++ Failure_Failure_InvalidSignature Failure_FailureType = 8
++ Failure_Failure_ProcessError Failure_FailureType = 9
++ Failure_Failure_NotEnoughFunds Failure_FailureType = 10
++ Failure_Failure_NotInitialized Failure_FailureType = 11
++ Failure_Failure_PinMismatch Failure_FailureType = 12
++ Failure_Failure_FirmwareError Failure_FailureType = 99
++)
++
++// Enum value maps for Failure_FailureType.
++var (
++ Failure_FailureType_name = map[int32]string{
++ 1: "Failure_UnexpectedMessage",
++ 2: "Failure_ButtonExpected",
++ 3: "Failure_DataError",
++ 4: "Failure_ActionCancelled",
++ 5: "Failure_PinExpected",
++ 6: "Failure_PinCancelled",
++ 7: "Failure_PinInvalid",
++ 8: "Failure_InvalidSignature",
++ 9: "Failure_ProcessError",
++ 10: "Failure_NotEnoughFunds",
++ 11: "Failure_NotInitialized",
++ 12: "Failure_PinMismatch",
++ 99: "Failure_FirmwareError",
++ }
++ Failure_FailureType_value = map[string]int32{
++ "Failure_UnexpectedMessage": 1,
++ "Failure_ButtonExpected": 2,
++ "Failure_DataError": 3,
++ "Failure_ActionCancelled": 4,
++ "Failure_PinExpected": 5,
++ "Failure_PinCancelled": 6,
++ "Failure_PinInvalid": 7,
++ "Failure_InvalidSignature": 8,
++ "Failure_ProcessError": 9,
++ "Failure_NotEnoughFunds": 10,
++ "Failure_NotInitialized": 11,
++ "Failure_PinMismatch": 12,
++ "Failure_FirmwareError": 99,
++ }
++)
++
++func (x Failure_FailureType) Enum() *Failure_FailureType {
++ p := new(Failure_FailureType)
++ *p = x
++ return p
++}
++
++func (x Failure_FailureType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (Failure_FailureType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_common_proto_enumTypes[0].Descriptor()
++}
++
++func (Failure_FailureType) Type() protoreflect.EnumType {
++ return &file_messages_common_proto_enumTypes[0]
++}
++
++func (x Failure_FailureType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *Failure_FailureType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = Failure_FailureType(num)
++ return nil
++}
++
++// Deprecated: Use Failure_FailureType.Descriptor instead.
++func (Failure_FailureType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{1, 0}
++}
++
++// *
++// Type of button request
++type ButtonRequest_ButtonRequestType int32
++
++const (
++ ButtonRequest_ButtonRequest_Other ButtonRequest_ButtonRequestType = 1
++ ButtonRequest_ButtonRequest_FeeOverThreshold ButtonRequest_ButtonRequestType = 2
++ ButtonRequest_ButtonRequest_ConfirmOutput ButtonRequest_ButtonRequestType = 3
++ ButtonRequest_ButtonRequest_ResetDevice ButtonRequest_ButtonRequestType = 4
++ ButtonRequest_ButtonRequest_ConfirmWord ButtonRequest_ButtonRequestType = 5
++ ButtonRequest_ButtonRequest_WipeDevice ButtonRequest_ButtonRequestType = 6
++ ButtonRequest_ButtonRequest_ProtectCall ButtonRequest_ButtonRequestType = 7
++ ButtonRequest_ButtonRequest_SignTx ButtonRequest_ButtonRequestType = 8
++ ButtonRequest_ButtonRequest_FirmwareCheck ButtonRequest_ButtonRequestType = 9
++ ButtonRequest_ButtonRequest_Address ButtonRequest_ButtonRequestType = 10
++ ButtonRequest_ButtonRequest_PublicKey ButtonRequest_ButtonRequestType = 11
++ ButtonRequest_ButtonRequest_MnemonicWordCount ButtonRequest_ButtonRequestType = 12
++ ButtonRequest_ButtonRequest_MnemonicInput ButtonRequest_ButtonRequestType = 13
++ ButtonRequest_ButtonRequest_PassphraseType ButtonRequest_ButtonRequestType = 14
++ ButtonRequest_ButtonRequest_UnknownDerivationPath ButtonRequest_ButtonRequestType = 15
++)
++
++// Enum value maps for ButtonRequest_ButtonRequestType.
++var (
++ ButtonRequest_ButtonRequestType_name = map[int32]string{
++ 1: "ButtonRequest_Other",
++ 2: "ButtonRequest_FeeOverThreshold",
++ 3: "ButtonRequest_ConfirmOutput",
++ 4: "ButtonRequest_ResetDevice",
++ 5: "ButtonRequest_ConfirmWord",
++ 6: "ButtonRequest_WipeDevice",
++ 7: "ButtonRequest_ProtectCall",
++ 8: "ButtonRequest_SignTx",
++ 9: "ButtonRequest_FirmwareCheck",
++ 10: "ButtonRequest_Address",
++ 11: "ButtonRequest_PublicKey",
++ 12: "ButtonRequest_MnemonicWordCount",
++ 13: "ButtonRequest_MnemonicInput",
++ 14: "ButtonRequest_PassphraseType",
++ 15: "ButtonRequest_UnknownDerivationPath",
++ }
++ ButtonRequest_ButtonRequestType_value = map[string]int32{
++ "ButtonRequest_Other": 1,
++ "ButtonRequest_FeeOverThreshold": 2,
++ "ButtonRequest_ConfirmOutput": 3,
++ "ButtonRequest_ResetDevice": 4,
++ "ButtonRequest_ConfirmWord": 5,
++ "ButtonRequest_WipeDevice": 6,
++ "ButtonRequest_ProtectCall": 7,
++ "ButtonRequest_SignTx": 8,
++ "ButtonRequest_FirmwareCheck": 9,
++ "ButtonRequest_Address": 10,
++ "ButtonRequest_PublicKey": 11,
++ "ButtonRequest_MnemonicWordCount": 12,
++ "ButtonRequest_MnemonicInput": 13,
++ "ButtonRequest_PassphraseType": 14,
++ "ButtonRequest_UnknownDerivationPath": 15,
++ }
++)
++
++func (x ButtonRequest_ButtonRequestType) Enum() *ButtonRequest_ButtonRequestType {
++ p := new(ButtonRequest_ButtonRequestType)
++ *p = x
++ return p
++}
++
++func (x ButtonRequest_ButtonRequestType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (ButtonRequest_ButtonRequestType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_common_proto_enumTypes[1].Descriptor()
++}
++
++func (ButtonRequest_ButtonRequestType) Type() protoreflect.EnumType {
++ return &file_messages_common_proto_enumTypes[1]
++}
++
++func (x ButtonRequest_ButtonRequestType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *ButtonRequest_ButtonRequestType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = ButtonRequest_ButtonRequestType(num)
++ return nil
++}
++
++// Deprecated: Use ButtonRequest_ButtonRequestType.Descriptor instead.
++func (ButtonRequest_ButtonRequestType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{2, 0}
++}
++
++// *
++// Type of PIN request
++type PinMatrixRequest_PinMatrixRequestType int32
++
++const (
++ PinMatrixRequest_PinMatrixRequestType_Current PinMatrixRequest_PinMatrixRequestType = 1
++ PinMatrixRequest_PinMatrixRequestType_NewFirst PinMatrixRequest_PinMatrixRequestType = 2
++ PinMatrixRequest_PinMatrixRequestType_NewSecond PinMatrixRequest_PinMatrixRequestType = 3
++)
++
++// Enum value maps for PinMatrixRequest_PinMatrixRequestType.
++var (
++ PinMatrixRequest_PinMatrixRequestType_name = map[int32]string{
++ 1: "PinMatrixRequestType_Current",
++ 2: "PinMatrixRequestType_NewFirst",
++ 3: "PinMatrixRequestType_NewSecond",
++ }
++ PinMatrixRequest_PinMatrixRequestType_value = map[string]int32{
++ "PinMatrixRequestType_Current": 1,
++ "PinMatrixRequestType_NewFirst": 2,
++ "PinMatrixRequestType_NewSecond": 3,
++ }
++)
++
++func (x PinMatrixRequest_PinMatrixRequestType) Enum() *PinMatrixRequest_PinMatrixRequestType {
++ p := new(PinMatrixRequest_PinMatrixRequestType)
++ *p = x
++ return p
++}
++
++func (x PinMatrixRequest_PinMatrixRequestType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (PinMatrixRequest_PinMatrixRequestType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_common_proto_enumTypes[2].Descriptor()
++}
++
++func (PinMatrixRequest_PinMatrixRequestType) Type() protoreflect.EnumType {
++ return &file_messages_common_proto_enumTypes[2]
++}
++
++func (x PinMatrixRequest_PinMatrixRequestType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *PinMatrixRequest_PinMatrixRequestType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = PinMatrixRequest_PinMatrixRequestType(num)
++ return nil
++}
++
++// Deprecated: Use PinMatrixRequest_PinMatrixRequestType.Descriptor instead.
++func (PinMatrixRequest_PinMatrixRequestType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{4, 0}
++}
++
++// *
++// Response: Success of the previous request
++// @end
++type Success struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` // human readable description of action or request-specific payload
++}
++
++func (x *Success) Reset() {
++ *x = Success{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[0]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Success) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Success) ProtoMessage() {}
++
++func (x *Success) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[0]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Success.ProtoReflect.Descriptor instead.
++func (*Success) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{0}
++}
++
++func (x *Success) GetMessage() string {
++ if x != nil && x.Message != nil {
++ return *x.Message
++ }
++ return ""
++}
++
++// *
++// Response: Failure of the previous request
++// @end
++type Failure struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Code *Failure_FailureType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.Failure_FailureType" json:"code,omitempty"` // computer-readable definition of the error state
++ Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` // human-readable message of the error state
++}
++
++func (x *Failure) Reset() {
++ *x = Failure{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[1]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Failure) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Failure) ProtoMessage() {}
++
++func (x *Failure) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[1]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Failure.ProtoReflect.Descriptor instead.
++func (*Failure) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{1}
++}
++
++func (x *Failure) GetCode() Failure_FailureType {
++ if x != nil && x.Code != nil {
++ return *x.Code
++ }
++ return Failure_Failure_UnexpectedMessage
++}
++
++func (x *Failure) GetMessage() string {
++ if x != nil && x.Message != nil {
++ return *x.Message
++ }
++ return ""
++}
++
++// *
++// Response: Device is waiting for HW button press.
++// @auxstart
++// @next ButtonAck
++type ButtonRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Code *ButtonRequest_ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.ButtonRequest_ButtonRequestType" json:"code,omitempty"`
++ Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
++}
++
++func (x *ButtonRequest) Reset() {
++ *x = ButtonRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[2]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ButtonRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ButtonRequest) ProtoMessage() {}
++
++func (x *ButtonRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[2]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ButtonRequest.ProtoReflect.Descriptor instead.
++func (*ButtonRequest) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{2}
++}
++
++func (x *ButtonRequest) GetCode() ButtonRequest_ButtonRequestType {
++ if x != nil && x.Code != nil {
++ return *x.Code
++ }
++ return ButtonRequest_ButtonRequest_Other
++}
++
++func (x *ButtonRequest) GetData() string {
++ if x != nil && x.Data != nil {
++ return *x.Data
++ }
++ return ""
++}
++
++// *
++// Request: Computer agrees to wait for HW button press
++// @auxend
++type ButtonAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *ButtonAck) Reset() {
++ *x = ButtonAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[3]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ButtonAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ButtonAck) ProtoMessage() {}
++
++func (x *ButtonAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[3]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ButtonAck.ProtoReflect.Descriptor instead.
++func (*ButtonAck) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{3}
++}
++
++// *
++// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
++// @auxstart
++// @next PinMatrixAck
++type PinMatrixRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Type *PinMatrixRequest_PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType" json:"type,omitempty"`
++}
++
++func (x *PinMatrixRequest) Reset() {
++ *x = PinMatrixRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[4]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PinMatrixRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PinMatrixRequest) ProtoMessage() {}
++
++func (x *PinMatrixRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[4]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PinMatrixRequest.ProtoReflect.Descriptor instead.
++func (*PinMatrixRequest) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{4}
++}
++
++func (x *PinMatrixRequest) GetType() PinMatrixRequest_PinMatrixRequestType {
++ if x != nil && x.Type != nil {
++ return *x.Type
++ }
++ return PinMatrixRequest_PinMatrixRequestType_Current
++}
++
++// *
++// Request: Computer responds with encoded PIN
++// @auxend
++type PinMatrixAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` // matrix encoded PIN entered by user
++}
++
++func (x *PinMatrixAck) Reset() {
++ *x = PinMatrixAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[5]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PinMatrixAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PinMatrixAck) ProtoMessage() {}
++
++func (x *PinMatrixAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[5]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PinMatrixAck.ProtoReflect.Descriptor instead.
++func (*PinMatrixAck) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{5}
++}
++
++func (x *PinMatrixAck) GetPin() string {
++ if x != nil && x.Pin != nil {
++ return *x.Pin
++ }
++ return ""
++}
++
++// *
++// Response: Device awaits encryption passphrase
++// @auxstart
++// @next PassphraseAck
++type PassphraseRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ OnDevice *bool `protobuf:"varint,1,opt,name=on_device,json=onDevice" json:"on_device,omitempty"` // passphrase is being entered on the device
++}
++
++func (x *PassphraseRequest) Reset() {
++ *x = PassphraseRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[6]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PassphraseRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PassphraseRequest) ProtoMessage() {}
++
++func (x *PassphraseRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[6]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PassphraseRequest.ProtoReflect.Descriptor instead.
++func (*PassphraseRequest) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{6}
++}
++
++func (x *PassphraseRequest) GetOnDevice() bool {
++ if x != nil && x.OnDevice != nil {
++ return *x.OnDevice
++ }
++ return false
++}
++
++// *
++// Request: Send passphrase back
++// @next PassphraseStateRequest
++type PassphraseAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Passphrase *string `protobuf:"bytes,1,opt,name=passphrase" json:"passphrase,omitempty"`
++ State []byte `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` // expected device state
++}
++
++func (x *PassphraseAck) Reset() {
++ *x = PassphraseAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[7]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PassphraseAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PassphraseAck) ProtoMessage() {}
++
++func (x *PassphraseAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[7]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PassphraseAck.ProtoReflect.Descriptor instead.
++func (*PassphraseAck) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{7}
++}
++
++func (x *PassphraseAck) GetPassphrase() string {
++ if x != nil && x.Passphrase != nil {
++ return *x.Passphrase
++ }
++ return ""
++}
++
++func (x *PassphraseAck) GetState() []byte {
++ if x != nil {
++ return x.State
++ }
++ return nil
++}
++
++// *
++// Response: Device awaits passphrase state
++// @next PassphraseStateAck
++type PassphraseStateRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` // actual device state
++}
++
++func (x *PassphraseStateRequest) Reset() {
++ *x = PassphraseStateRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[8]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PassphraseStateRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PassphraseStateRequest) ProtoMessage() {}
++
++func (x *PassphraseStateRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[8]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PassphraseStateRequest.ProtoReflect.Descriptor instead.
++func (*PassphraseStateRequest) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{8}
++}
++
++func (x *PassphraseStateRequest) GetState() []byte {
++ if x != nil {
++ return x.State
++ }
++ return nil
++}
++
++// *
++// Request: Send passphrase state back
++// @auxend
++type PassphraseStateAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *PassphraseStateAck) Reset() {
++ *x = PassphraseStateAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[9]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *PassphraseStateAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*PassphraseStateAck) ProtoMessage() {}
++
++func (x *PassphraseStateAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[9]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use PassphraseStateAck.ProtoReflect.Descriptor instead.
++func (*PassphraseStateAck) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{9}
++}
++
++// *
++// Structure representing BIP32 (hierarchical deterministic) node
++// Used for imports of private key into the device and exporting public key out of device
++// @embed
++type HDNodeType struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"`
++ Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"`
++ ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"`
++ ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"`
++ PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"`
++ PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
++}
++
++func (x *HDNodeType) Reset() {
++ *x = HDNodeType{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_common_proto_msgTypes[10]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *HDNodeType) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*HDNodeType) ProtoMessage() {}
++
++func (x *HDNodeType) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_common_proto_msgTypes[10]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use HDNodeType.ProtoReflect.Descriptor instead.
++func (*HDNodeType) Descriptor() ([]byte, []int) {
++ return file_messages_common_proto_rawDescGZIP(), []int{10}
++}
++
++func (x *HDNodeType) GetDepth() uint32 {
++ if x != nil && x.Depth != nil {
++ return *x.Depth
++ }
++ return 0
++}
++
++func (x *HDNodeType) GetFingerprint() uint32 {
++ if x != nil && x.Fingerprint != nil {
++ return *x.Fingerprint
++ }
++ return 0
++}
++
++func (x *HDNodeType) GetChildNum() uint32 {
++ if x != nil && x.ChildNum != nil {
++ return *x.ChildNum
++ }
++ return 0
++}
++
++func (x *HDNodeType) GetChainCode() []byte {
++ if x != nil {
++ return x.ChainCode
++ }
++ return nil
++}
++
++func (x *HDNodeType) GetPrivateKey() []byte {
++ if x != nil {
++ return x.PrivateKey
++ }
++ return nil
++}
++
++func (x *HDNodeType) GetPublicKey() []byte {
++ if x != nil {
++ return x.PublicKey
++ }
++ return nil
++}
++
++var File_messages_common_proto protoreflect.FileDescriptor
++
++var file_messages_common_proto_rawDesc = []byte{
++ 0x0a, 0x15, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
++ 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a,
++ 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
++ 0x6f, 0x6e, 0x22, 0x23, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a,
++ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
++ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd5, 0x03, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c,
++ 0x75, 0x72, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
++ 0x0e, 0x32, 0x2e, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x46, 0x61,
++ 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x22, 0xeb, 0x02, 0x0a, 0x0b, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x55, 0x6e, 0x65,
++ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x01,
++ 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x42, 0x75, 0x74, 0x74,
++ 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11,
++ 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x44, 0x61, 0x74, 0x61, 0x45, 0x72, 0x72, 0x6f,
++ 0x72, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x41,
++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x10, 0x04,
++ 0x12, 0x17, 0x0a, 0x13, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x45,
++ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x61, 0x69,
++ 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65,
++ 0x64, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50,
++ 0x69, 0x6e, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x46,
++ 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x53, 0x69,
++ 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x61, 0x69,
++ 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x45, 0x72, 0x72, 0x6f,
++ 0x72, 0x10, 0x09, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x4e,
++ 0x6f, 0x74, 0x45, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x10, 0x0a, 0x12,
++ 0x1a, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x4e, 0x6f, 0x74, 0x49, 0x6e,
++ 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x10, 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x46,
++ 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74,
++ 0x63, 0x68, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f,
++ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x10, 0x63, 0x22,
++ 0xe6, 0x04, 0x0a, 0x0d, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
++ 0x74, 0x12, 0x4e, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
++ 0x3a, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, 0x75, 0x74, 0x74,
++ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64,
++ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
++ 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf0, 0x03, 0x0a, 0x11, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x42,
++ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4f, 0x74, 0x68,
++ 0x65, 0x72, 0x10, 0x01, 0x12, 0x22, 0x0a, 0x1e, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65,
++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x46, 0x65, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x68, 0x72,
++ 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x75, 0x74, 0x74,
++ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72,
++ 0x6d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74,
++ 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74,
++ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x04, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74, 0x74,
++ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72,
++ 0x6d, 0x57, 0x6f, 0x72, 0x64, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, 0x42, 0x75, 0x74, 0x74, 0x6f,
++ 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76,
++ 0x69, 0x63, 0x65, 0x10, 0x06, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52,
++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x43, 0x61,
++ 0x6c, 0x6c, 0x10, 0x07, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65,
++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x08, 0x12, 0x1f,
++ 0x0a, 0x1b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f,
++ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x10, 0x09, 0x12,
++ 0x19, 0x0a, 0x15, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
++ 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x0a, 0x12, 0x1b, 0x0a, 0x17, 0x42, 0x75,
++ 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50, 0x75, 0x62, 0x6c,
++ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f, 0x42, 0x75, 0x74, 0x74, 0x6f,
++ 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4d, 0x6e, 0x65, 0x6d, 0x6f, 0x6e, 0x69,
++ 0x63, 0x57, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x10, 0x0c, 0x12, 0x1f, 0x0a, 0x1b,
++ 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x4d, 0x6e,
++ 0x65, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x10, 0x0d, 0x12, 0x20, 0x0a,
++ 0x1c, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x50,
++ 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x10, 0x0e, 0x12,
++ 0x27, 0x0a, 0x23, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
++ 0x5f, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69,
++ 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x10, 0x0f, 0x22, 0x0b, 0x0a, 0x09, 0x42, 0x75, 0x74, 0x74,
++ 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x22, 0xe9, 0x01, 0x0a, 0x10, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74,
++ 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x74, 0x79,
++ 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x40, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72,
++ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f,
++ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65,
++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52,
++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
++ 0x22, 0x7f, 0x0a, 0x14, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71,
++ 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x69, 0x6e, 0x4d,
++ 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x50, 0x69,
++ 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x4e, 0x65, 0x77, 0x46, 0x69, 0x72, 0x73, 0x74, 0x10, 0x02, 0x12, 0x22, 0x0a,
++ 0x1e, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
++ 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x10,
++ 0x03, 0x22, 0x20, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x41, 0x63,
++ 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x03,
++ 0x70, 0x69, 0x6e, 0x22, 0x30, 0x0a, 0x11, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
++ 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6e, 0x5f, 0x64,
++ 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x6e, 0x44,
++ 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x45, 0x0a, 0x0d, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72,
++ 0x61, 0x73, 0x65, 0x41, 0x63, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68,
++ 0x72, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73,
++ 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
++ 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x2e, 0x0a, 0x16,
++ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
++ 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x14, 0x0a, 0x12,
++ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41,
++ 0x63, 0x6b, 0x22, 0xc0, 0x01, 0x0a, 0x0a, 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0d,
++ 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65,
++ 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x69,
++ 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x69,
++ 0x6c, 0x64, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x02, 0x28, 0x0d, 0x52, 0x08, 0x63, 0x68,
++ 0x69, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f,
++ 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x02, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69,
++ 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
++ 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76,
++ 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
++ 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c,
++ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
++ 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x6f, 0x2d,
++ 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
++ 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72, 0x65, 0x7a,
++ 0x6f, 0x72,
++}
++
++var (
++ file_messages_common_proto_rawDescOnce sync.Once
++ file_messages_common_proto_rawDescData = file_messages_common_proto_rawDesc
++)
++
++func file_messages_common_proto_rawDescGZIP() []byte {
++ file_messages_common_proto_rawDescOnce.Do(func() {
++ file_messages_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_common_proto_rawDescData)
++ })
++ return file_messages_common_proto_rawDescData
++}
++
++var file_messages_common_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
++var file_messages_common_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
++var file_messages_common_proto_goTypes = []any{
++ (Failure_FailureType)(0), // 0: hw.trezor.messages.common.Failure.FailureType
++ (ButtonRequest_ButtonRequestType)(0), // 1: hw.trezor.messages.common.ButtonRequest.ButtonRequestType
++ (PinMatrixRequest_PinMatrixRequestType)(0), // 2: hw.trezor.messages.common.PinMatrixRequest.PinMatrixRequestType
++ (*Success)(nil), // 3: hw.trezor.messages.common.Success
++ (*Failure)(nil), // 4: hw.trezor.messages.common.Failure
++ (*ButtonRequest)(nil), // 5: hw.trezor.messages.common.ButtonRequest
++ (*ButtonAck)(nil), // 6: hw.trezor.messages.common.ButtonAck
++ (*PinMatrixRequest)(nil), // 7: hw.trezor.messages.common.PinMatrixRequest
++ (*PinMatrixAck)(nil), // 8: hw.trezor.messages.common.PinMatrixAck
++ (*PassphraseRequest)(nil), // 9: hw.trezor.messages.common.PassphraseRequest
++ (*PassphraseAck)(nil), // 10: hw.trezor.messages.common.PassphraseAck
++ (*PassphraseStateRequest)(nil), // 11: hw.trezor.messages.common.PassphraseStateRequest
++ (*PassphraseStateAck)(nil), // 12: hw.trezor.messages.common.PassphraseStateAck
++ (*HDNodeType)(nil), // 13: hw.trezor.messages.common.HDNodeType
++}
++var file_messages_common_proto_depIdxs = []int32{
++ 0, // 0: hw.trezor.messages.common.Failure.code:type_name -> hw.trezor.messages.common.Failure.FailureType
++ 1, // 1: hw.trezor.messages.common.ButtonRequest.code:type_name -> hw.trezor.messages.common.ButtonRequest.ButtonRequestType
++ 2, // 2: hw.trezor.messages.common.PinMatrixRequest.type:type_name -> hw.trezor.messages.common.PinMatrixRequest.PinMatrixRequestType
++ 3, // [3:3] is the sub-list for method output_type
++ 3, // [3:3] is the sub-list for method input_type
++ 3, // [3:3] is the sub-list for extension type_name
++ 3, // [3:3] is the sub-list for extension extendee
++ 0, // [0:3] is the sub-list for field type_name
++}
++
++func init() { file_messages_common_proto_init() }
++func file_messages_common_proto_init() {
++ if File_messages_common_proto != nil {
++ return
++ }
++ if !protoimpl.UnsafeEnabled {
++ file_messages_common_proto_msgTypes[0].Exporter = func(v any, i int) any {
++ switch v := v.(*Success); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[1].Exporter = func(v any, i int) any {
++ switch v := v.(*Failure); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[2].Exporter = func(v any, i int) any {
++ switch v := v.(*ButtonRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[3].Exporter = func(v any, i int) any {
++ switch v := v.(*ButtonAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[4].Exporter = func(v any, i int) any {
++ switch v := v.(*PinMatrixRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[5].Exporter = func(v any, i int) any {
++ switch v := v.(*PinMatrixAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[6].Exporter = func(v any, i int) any {
++ switch v := v.(*PassphraseRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[7].Exporter = func(v any, i int) any {
++ switch v := v.(*PassphraseAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[8].Exporter = func(v any, i int) any {
++ switch v := v.(*PassphraseStateRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[9].Exporter = func(v any, i int) any {
++ switch v := v.(*PassphraseStateAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_common_proto_msgTypes[10].Exporter = func(v any, i int) any {
++ switch v := v.(*HDNodeType); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ }
++ type x struct{}
++ out := protoimpl.TypeBuilder{
++ File: protoimpl.DescBuilder{
++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
++ RawDescriptor: file_messages_common_proto_rawDesc,
++ NumEnums: 3,
++ NumMessages: 11,
++ NumExtensions: 0,
++ NumServices: 0,
++ },
++ GoTypes: file_messages_common_proto_goTypes,
++ DependencyIndexes: file_messages_common_proto_depIdxs,
++ EnumInfos: file_messages_common_proto_enumTypes,
++ MessageInfos: file_messages_common_proto_msgTypes,
++ }.Build()
++ File_messages_common_proto = out.File
++ file_messages_common_proto_rawDesc = nil
++ file_messages_common_proto_goTypes = nil
++ file_messages_common_proto_depIdxs = nil
++}
+diff --git a/accounts/usbwallet/messages-common.proto b/accounts/usbwallet/messages-common.proto
+new file mode 100644
+index 0000000000..1f524e25d7
+--- /dev/null
++++ b/accounts/usbwallet/messages-common.proto
+@@ -0,0 +1,149 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++syntax = "proto2";
++package hw.trezor.messages.common;
++
++option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
++
++/**
++ * Response: Success of the previous request
++ * @end
++ */
++message Success {
++ optional string message = 1; // human readable description of action or request-specific payload
++}
++
++/**
++ * Response: Failure of the previous request
++ * @end
++ */
++message Failure {
++ optional FailureType code = 1; // computer-readable definition of the error state
++ optional string message = 2; // human-readable message of the error state
++ enum FailureType {
++ Failure_UnexpectedMessage = 1;
++ Failure_ButtonExpected = 2;
++ Failure_DataError = 3;
++ Failure_ActionCancelled = 4;
++ Failure_PinExpected = 5;
++ Failure_PinCancelled = 6;
++ Failure_PinInvalid = 7;
++ Failure_InvalidSignature = 8;
++ Failure_ProcessError = 9;
++ Failure_NotEnoughFunds = 10;
++ Failure_NotInitialized = 11;
++ Failure_PinMismatch = 12;
++ Failure_FirmwareError = 99;
++ }
++}
++
++/**
++ * Response: Device is waiting for HW button press.
++ * @auxstart
++ * @next ButtonAck
++ */
++message ButtonRequest {
++ optional ButtonRequestType code = 1;
++ optional string data = 2;
++ /**
++ * Type of button request
++ */
++ enum ButtonRequestType {
++ ButtonRequest_Other = 1;
++ ButtonRequest_FeeOverThreshold = 2;
++ ButtonRequest_ConfirmOutput = 3;
++ ButtonRequest_ResetDevice = 4;
++ ButtonRequest_ConfirmWord = 5;
++ ButtonRequest_WipeDevice = 6;
++ ButtonRequest_ProtectCall = 7;
++ ButtonRequest_SignTx = 8;
++ ButtonRequest_FirmwareCheck = 9;
++ ButtonRequest_Address = 10;
++ ButtonRequest_PublicKey = 11;
++ ButtonRequest_MnemonicWordCount = 12;
++ ButtonRequest_MnemonicInput = 13;
++ ButtonRequest_PassphraseType = 14;
++ ButtonRequest_UnknownDerivationPath = 15;
++ }
++}
++
++/**
++ * Request: Computer agrees to wait for HW button press
++ * @auxend
++ */
++message ButtonAck {
++}
++
++/**
++ * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
++ * @auxstart
++ * @next PinMatrixAck
++ */
++message PinMatrixRequest {
++ optional PinMatrixRequestType type = 1;
++ /**
++ * Type of PIN request
++ */
++ enum PinMatrixRequestType {
++ PinMatrixRequestType_Current = 1;
++ PinMatrixRequestType_NewFirst = 2;
++ PinMatrixRequestType_NewSecond = 3;
++ }
++}
++
++/**
++ * Request: Computer responds with encoded PIN
++ * @auxend
++ */
++message PinMatrixAck {
++ required string pin = 1; // matrix encoded PIN entered by user
++}
++
++/**
++ * Response: Device awaits encryption passphrase
++ * @auxstart
++ * @next PassphraseAck
++ */
++message PassphraseRequest {
++ optional bool on_device = 1; // passphrase is being entered on the device
++}
++
++/**
++ * Request: Send passphrase back
++ * @next PassphraseStateRequest
++ */
++message PassphraseAck {
++ optional string passphrase = 1;
++ optional bytes state = 2; // expected device state
++}
++
++/**
++ * Response: Device awaits passphrase state
++ * @next PassphraseStateAck
++ */
++message PassphraseStateRequest {
++ optional bytes state = 1; // actual device state
++}
++
++/**
++ * Request: Send passphrase state back
++ * @auxend
++ */
++message PassphraseStateAck {
++}
++
++/**
++ * Structure representing BIP32 (hierarchical deterministic) node
++ * Used for imports of private key into the device and exporting public key out of device
++ * @embed
++ */
++message HDNodeType {
++ required uint32 depth = 1;
++ required uint32 fingerprint = 2;
++ required uint32 child_num = 3;
++ required bytes chain_code = 4;
++ optional bytes private_key = 5;
++ optional bytes public_key = 6;
++}
+diff --git a/accounts/usbwallet/messages-ethereum.pb.go b/accounts/usbwallet/messages-ethereum.pb.go
+new file mode 100644
+index 0000000000..a92123efcd
+--- /dev/null
++++ b/accounts/usbwallet/messages-ethereum.pb.go
+@@ -0,0 +1,1002 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++// Code generated by protoc-gen-go. DO NOT EDIT.
++// versions:
++// protoc-gen-go v1.34.2
++// protoc v5.27.1
++// source: messages-ethereum.proto
++
++package trezor
++
++import (
++ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
++ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
++ reflect "reflect"
++ sync "sync"
++)
++
++const (
++ // Verify that this generated code is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
++ // Verify that runtime/protoimpl is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
++)
++
++// *
++// Request: Ask device for public key corresponding to address_n path
++// @start
++// @next EthereumPublicKey
++// @next Failure
++type EthereumGetPublicKey struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
++ ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` // optionally show on display before sending the result
++}
++
++func (x *EthereumGetPublicKey) Reset() {
++ *x = EthereumGetPublicKey{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[0]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumGetPublicKey) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumGetPublicKey) ProtoMessage() {}
++
++func (x *EthereumGetPublicKey) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[0]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumGetPublicKey.ProtoReflect.Descriptor instead.
++func (*EthereumGetPublicKey) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{0}
++}
++
++func (x *EthereumGetPublicKey) GetAddressN() []uint32 {
++ if x != nil {
++ return x.AddressN
++ }
++ return nil
++}
++
++func (x *EthereumGetPublicKey) GetShowDisplay() bool {
++ if x != nil && x.ShowDisplay != nil {
++ return *x.ShowDisplay
++ }
++ return false
++}
++
++// *
++// Response: Contains public key derived from device private seed
++// @end
++type EthereumPublicKey struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Node *HDNodeType `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"` // BIP32 public node
++ Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` // serialized form of public node
++}
++
++func (x *EthereumPublicKey) Reset() {
++ *x = EthereumPublicKey{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[1]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumPublicKey) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumPublicKey) ProtoMessage() {}
++
++func (x *EthereumPublicKey) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[1]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumPublicKey.ProtoReflect.Descriptor instead.
++func (*EthereumPublicKey) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{1}
++}
++
++func (x *EthereumPublicKey) GetNode() *HDNodeType {
++ if x != nil {
++ return x.Node
++ }
++ return nil
++}
++
++func (x *EthereumPublicKey) GetXpub() string {
++ if x != nil && x.Xpub != nil {
++ return *x.Xpub
++ }
++ return ""
++}
++
++// *
++// Request: Ask device for Ethereum address corresponding to address_n path
++// @start
++// @next EthereumAddress
++// @next Failure
++type EthereumGetAddress struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
++ ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` // optionally show on display before sending the result
++}
++
++func (x *EthereumGetAddress) Reset() {
++ *x = EthereumGetAddress{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[2]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumGetAddress) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumGetAddress) ProtoMessage() {}
++
++func (x *EthereumGetAddress) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[2]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumGetAddress.ProtoReflect.Descriptor instead.
++func (*EthereumGetAddress) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{2}
++}
++
++func (x *EthereumGetAddress) GetAddressN() []uint32 {
++ if x != nil {
++ return x.AddressN
++ }
++ return nil
++}
++
++func (x *EthereumGetAddress) GetShowDisplay() bool {
++ if x != nil && x.ShowDisplay != nil {
++ return *x.ShowDisplay
++ }
++ return false
++}
++
++// *
++// Response: Contains an Ethereum address derived from device private seed
++// @end
++type EthereumAddress struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // Ethereum address as 20 bytes (legacy firmwares)
++ AddressHex *string `protobuf:"bytes,2,opt,name=addressHex" json:"addressHex,omitempty"` // Ethereum address as hex string (newer firmwares)
++}
++
++func (x *EthereumAddress) Reset() {
++ *x = EthereumAddress{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[3]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumAddress) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumAddress) ProtoMessage() {}
++
++func (x *EthereumAddress) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[3]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumAddress.ProtoReflect.Descriptor instead.
++func (*EthereumAddress) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{3}
++}
++
++func (x *EthereumAddress) GetAddressBin() []byte {
++ if x != nil {
++ return x.AddressBin
++ }
++ return nil
++}
++
++func (x *EthereumAddress) GetAddressHex() string {
++ if x != nil && x.AddressHex != nil {
++ return *x.AddressHex
++ }
++ return ""
++}
++
++// *
++// Request: Ask device to sign transaction
++// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
++// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
++// @start
++// @next EthereumTxRequest
++// @next Failure
++type EthereumSignTx struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
++ Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` // <=256 bit unsigned big endian
++ GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` // <=256 bit unsigned big endian (in wei)
++ GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` // <=256 bit unsigned big endian
++ ToBin []byte `protobuf:"bytes,5,opt,name=toBin" json:"toBin,omitempty"` // recipient address (20 bytes, legacy firmware)
++ ToHex *string `protobuf:"bytes,11,opt,name=toHex" json:"toHex,omitempty"` // recipient address (hex string, newer firmware)
++ Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` // <=256 bit unsigned big endian (in wei)
++ DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` // The initial data chunk (<= 1024 bytes)
++ DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` // Length of transaction payload
++ ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` // Chain Id for EIP 155
++ TxType *uint32 `protobuf:"varint,10,opt,name=tx_type,json=txType" json:"tx_type,omitempty"` // (only for Wanchain)
++}
++
++func (x *EthereumSignTx) Reset() {
++ *x = EthereumSignTx{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[4]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumSignTx) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumSignTx) ProtoMessage() {}
++
++func (x *EthereumSignTx) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[4]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumSignTx.ProtoReflect.Descriptor instead.
++func (*EthereumSignTx) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{4}
++}
++
++func (x *EthereumSignTx) GetAddressN() []uint32 {
++ if x != nil {
++ return x.AddressN
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetNonce() []byte {
++ if x != nil {
++ return x.Nonce
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetGasPrice() []byte {
++ if x != nil {
++ return x.GasPrice
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetGasLimit() []byte {
++ if x != nil {
++ return x.GasLimit
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetToBin() []byte {
++ if x != nil {
++ return x.ToBin
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetToHex() string {
++ if x != nil && x.ToHex != nil {
++ return *x.ToHex
++ }
++ return ""
++}
++
++func (x *EthereumSignTx) GetValue() []byte {
++ if x != nil {
++ return x.Value
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetDataInitialChunk() []byte {
++ if x != nil {
++ return x.DataInitialChunk
++ }
++ return nil
++}
++
++func (x *EthereumSignTx) GetDataLength() uint32 {
++ if x != nil && x.DataLength != nil {
++ return *x.DataLength
++ }
++ return 0
++}
++
++func (x *EthereumSignTx) GetChainId() uint32 {
++ if x != nil && x.ChainId != nil {
++ return *x.ChainId
++ }
++ return 0
++}
++
++func (x *EthereumSignTx) GetTxType() uint32 {
++ if x != nil && x.TxType != nil {
++ return *x.TxType
++ }
++ return 0
++}
++
++// *
++// Response: Device asks for more data from transaction payload, or returns the signature.
++// If data_length is set, device awaits that many more bytes of payload.
++// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
++// @end
++// @next EthereumTxAck
++type EthereumTxRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` // Number of bytes being requested (<= 1024)
++ SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` // Computed signature (recovery parameter, limited to 27 or 28)
++ SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` // Computed signature R component (256 bit)
++ SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` // Computed signature S component (256 bit)
++}
++
++func (x *EthereumTxRequest) Reset() {
++ *x = EthereumTxRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[5]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumTxRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumTxRequest) ProtoMessage() {}
++
++func (x *EthereumTxRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[5]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumTxRequest.ProtoReflect.Descriptor instead.
++func (*EthereumTxRequest) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{5}
++}
++
++func (x *EthereumTxRequest) GetDataLength() uint32 {
++ if x != nil && x.DataLength != nil {
++ return *x.DataLength
++ }
++ return 0
++}
++
++func (x *EthereumTxRequest) GetSignatureV() uint32 {
++ if x != nil && x.SignatureV != nil {
++ return *x.SignatureV
++ }
++ return 0
++}
++
++func (x *EthereumTxRequest) GetSignatureR() []byte {
++ if x != nil {
++ return x.SignatureR
++ }
++ return nil
++}
++
++func (x *EthereumTxRequest) GetSignatureS() []byte {
++ if x != nil {
++ return x.SignatureS
++ }
++ return nil
++}
++
++// *
++// Request: Transaction payload data.
++// @next EthereumTxRequest
++type EthereumTxAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` // Bytes from transaction payload (<= 1024 bytes)
++}
++
++func (x *EthereumTxAck) Reset() {
++ *x = EthereumTxAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[6]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumTxAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumTxAck) ProtoMessage() {}
++
++func (x *EthereumTxAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[6]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumTxAck.ProtoReflect.Descriptor instead.
++func (*EthereumTxAck) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{6}
++}
++
++func (x *EthereumTxAck) GetDataChunk() []byte {
++ if x != nil {
++ return x.DataChunk
++ }
++ return nil
++}
++
++// *
++// Request: Ask device to sign message
++// @start
++// @next EthereumMessageSignature
++// @next Failure
++type EthereumSignMessage struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` // BIP-32 path to derive the key from master node
++ Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` // message to be signed
++}
++
++func (x *EthereumSignMessage) Reset() {
++ *x = EthereumSignMessage{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[7]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumSignMessage) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumSignMessage) ProtoMessage() {}
++
++func (x *EthereumSignMessage) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[7]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumSignMessage.ProtoReflect.Descriptor instead.
++func (*EthereumSignMessage) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{7}
++}
++
++func (x *EthereumSignMessage) GetAddressN() []uint32 {
++ if x != nil {
++ return x.AddressN
++ }
++ return nil
++}
++
++func (x *EthereumSignMessage) GetMessage() []byte {
++ if x != nil {
++ return x.Message
++ }
++ return nil
++}
++
++// *
++// Response: Signed message
++// @end
++type EthereumMessageSignature struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // address used to sign the message (20 bytes, legacy firmware)
++ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` // signature of the message
++ AddressHex *string `protobuf:"bytes,3,opt,name=addressHex" json:"addressHex,omitempty"` // address used to sign the message (hex string, newer firmware)
++}
++
++func (x *EthereumMessageSignature) Reset() {
++ *x = EthereumMessageSignature{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[8]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumMessageSignature) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumMessageSignature) ProtoMessage() {}
++
++func (x *EthereumMessageSignature) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[8]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumMessageSignature.ProtoReflect.Descriptor instead.
++func (*EthereumMessageSignature) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{8}
++}
++
++func (x *EthereumMessageSignature) GetAddressBin() []byte {
++ if x != nil {
++ return x.AddressBin
++ }
++ return nil
++}
++
++func (x *EthereumMessageSignature) GetSignature() []byte {
++ if x != nil {
++ return x.Signature
++ }
++ return nil
++}
++
++func (x *EthereumMessageSignature) GetAddressHex() string {
++ if x != nil && x.AddressHex != nil {
++ return *x.AddressHex
++ }
++ return ""
++}
++
++// *
++// Request: Ask device to verify message
++// @start
++// @next Success
++// @next Failure
++type EthereumVerifyMessage struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` // address to verify (20 bytes, legacy firmware)
++ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` // signature to verify
++ Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` // message to verify
++ AddressHex *string `protobuf:"bytes,4,opt,name=addressHex" json:"addressHex,omitempty"` // address to verify (hex string, newer firmware)
++}
++
++func (x *EthereumVerifyMessage) Reset() {
++ *x = EthereumVerifyMessage{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_ethereum_proto_msgTypes[9]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EthereumVerifyMessage) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EthereumVerifyMessage) ProtoMessage() {}
++
++func (x *EthereumVerifyMessage) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_ethereum_proto_msgTypes[9]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EthereumVerifyMessage.ProtoReflect.Descriptor instead.
++func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) {
++ return file_messages_ethereum_proto_rawDescGZIP(), []int{9}
++}
++
++func (x *EthereumVerifyMessage) GetAddressBin() []byte {
++ if x != nil {
++ return x.AddressBin
++ }
++ return nil
++}
++
++func (x *EthereumVerifyMessage) GetSignature() []byte {
++ if x != nil {
++ return x.Signature
++ }
++ return nil
++}
++
++func (x *EthereumVerifyMessage) GetMessage() []byte {
++ if x != nil {
++ return x.Message
++ }
++ return nil
++}
++
++func (x *EthereumVerifyMessage) GetAddressHex() string {
++ if x != nil && x.AddressHex != nil {
++ return *x.AddressHex
++ }
++ return ""
++}
++
++var File_messages_ethereum_proto protoreflect.FileDescriptor
++
++var file_messages_ethereum_proto_rawDesc = []byte{
++ 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72,
++ 0x65, 0x75, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x68, 0x77, 0x2e, 0x74, 0x72,
++ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x65, 0x74,
++ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x1a, 0x15, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
++ 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a,
++ 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c,
++ 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
++ 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
++ 0x73, 0x4e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c,
++ 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x77, 0x44, 0x69,
++ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x22, 0x62, 0x0a, 0x11, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
++ 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x6f,
++ 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72,
++ 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f,
++ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52,
++ 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x70, 0x75, 0x62, 0x18, 0x02, 0x20,
++ 0x01, 0x28, 0x09, 0x52, 0x04, 0x78, 0x70, 0x75, 0x62, 0x22, 0x54, 0x0a, 0x12, 0x45, 0x74, 0x68,
++ 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
++ 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03,
++ 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4e, 0x12, 0x21, 0x0a, 0x0c,
++ 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01,
++ 0x28, 0x08, 0x52, 0x0b, 0x73, 0x68, 0x6f, 0x77, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x22,
++ 0x51, 0x0a, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65,
++ 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e,
++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42,
++ 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78,
++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48,
++ 0x65, 0x78, 0x22, 0xc2, 0x02, 0x0a, 0x0e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53,
++ 0x69, 0x67, 0x6e, 0x54, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
++ 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
++ 0x73, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
++ 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f,
++ 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x61, 0x73,
++ 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d,
++ 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d,
++ 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x42, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
++ 0x0c, 0x52, 0x05, 0x74, 0x6f, 0x42, 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x48, 0x65,
++ 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x48, 0x65, 0x78, 0x12, 0x14,
++ 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76,
++ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x69,
++ 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c,
++ 0x52, 0x10, 0x64, 0x61, 0x74, 0x61, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x68, 0x75,
++ 0x6e, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74,
++ 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x4c, 0x65, 0x6e,
++ 0x67, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18,
++ 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x17,
++ 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52,
++ 0x06, 0x74, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x11, 0x45, 0x74, 0x68, 0x65,
++ 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a,
++ 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
++ 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1f,
++ 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x18, 0x02, 0x20,
++ 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x56, 0x12,
++ 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x18, 0x03,
++ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52,
++ 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x18,
++ 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
++ 0x53, 0x22, 0x2e, 0x0a, 0x0d, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x41,
++ 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b,
++ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e,
++ 0x6b, 0x22, 0x4c, 0x0a, 0x13, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53, 0x69, 0x67,
++ 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72,
++ 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x64, 0x64,
++ 0x72, 0x65, 0x73, 0x73, 0x4e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
++ 0x78, 0x0a, 0x18, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
++ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
++ 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73,
++ 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
++ 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64,
++ 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61,
++ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, 0x15, 0x45, 0x74,
++ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x69,
++ 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
++ 0x42, 0x69, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
++ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
++ 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01,
++ 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
++ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
++ 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x65, 0x78, 0x42, 0x77, 0x0a, 0x23, 0x63,
++ 0x6f, 0x6d, 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74,
++ 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
++ 0x75, 0x66, 0x42, 0x15, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75,
++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67,
++ 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
++ 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72,
++ 0x65, 0x7a, 0x6f, 0x72,
++}
++
++var (
++ file_messages_ethereum_proto_rawDescOnce sync.Once
++ file_messages_ethereum_proto_rawDescData = file_messages_ethereum_proto_rawDesc
++)
++
++func file_messages_ethereum_proto_rawDescGZIP() []byte {
++ file_messages_ethereum_proto_rawDescOnce.Do(func() {
++ file_messages_ethereum_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_ethereum_proto_rawDescData)
++ })
++ return file_messages_ethereum_proto_rawDescData
++}
++
++var file_messages_ethereum_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
++var file_messages_ethereum_proto_goTypes = []any{
++ (*EthereumGetPublicKey)(nil), // 0: hw.trezor.messages.ethereum.EthereumGetPublicKey
++ (*EthereumPublicKey)(nil), // 1: hw.trezor.messages.ethereum.EthereumPublicKey
++ (*EthereumGetAddress)(nil), // 2: hw.trezor.messages.ethereum.EthereumGetAddress
++ (*EthereumAddress)(nil), // 3: hw.trezor.messages.ethereum.EthereumAddress
++ (*EthereumSignTx)(nil), // 4: hw.trezor.messages.ethereum.EthereumSignTx
++ (*EthereumTxRequest)(nil), // 5: hw.trezor.messages.ethereum.EthereumTxRequest
++ (*EthereumTxAck)(nil), // 6: hw.trezor.messages.ethereum.EthereumTxAck
++ (*EthereumSignMessage)(nil), // 7: hw.trezor.messages.ethereum.EthereumSignMessage
++ (*EthereumMessageSignature)(nil), // 8: hw.trezor.messages.ethereum.EthereumMessageSignature
++ (*EthereumVerifyMessage)(nil), // 9: hw.trezor.messages.ethereum.EthereumVerifyMessage
++ (*HDNodeType)(nil), // 10: hw.trezor.messages.common.HDNodeType
++}
++var file_messages_ethereum_proto_depIdxs = []int32{
++ 10, // 0: hw.trezor.messages.ethereum.EthereumPublicKey.node:type_name -> hw.trezor.messages.common.HDNodeType
++ 1, // [1:1] is the sub-list for method output_type
++ 1, // [1:1] is the sub-list for method input_type
++ 1, // [1:1] is the sub-list for extension type_name
++ 1, // [1:1] is the sub-list for extension extendee
++ 0, // [0:1] is the sub-list for field type_name
++}
++
++func init() { file_messages_ethereum_proto_init() }
++func file_messages_ethereum_proto_init() {
++ if File_messages_ethereum_proto != nil {
++ return
++ }
++ file_messages_common_proto_init()
++ if !protoimpl.UnsafeEnabled {
++ file_messages_ethereum_proto_msgTypes[0].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumGetPublicKey); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[1].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumPublicKey); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[2].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumGetAddress); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[3].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumAddress); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[4].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumSignTx); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[5].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumTxRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[6].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumTxAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[7].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumSignMessage); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[8].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumMessageSignature); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_ethereum_proto_msgTypes[9].Exporter = func(v any, i int) any {
++ switch v := v.(*EthereumVerifyMessage); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ }
++ type x struct{}
++ out := protoimpl.TypeBuilder{
++ File: protoimpl.DescBuilder{
++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
++ RawDescriptor: file_messages_ethereum_proto_rawDesc,
++ NumEnums: 0,
++ NumMessages: 10,
++ NumExtensions: 0,
++ NumServices: 0,
++ },
++ GoTypes: file_messages_ethereum_proto_goTypes,
++ DependencyIndexes: file_messages_ethereum_proto_depIdxs,
++ MessageInfos: file_messages_ethereum_proto_msgTypes,
++ }.Build()
++ File_messages_ethereum_proto = out.File
++ file_messages_ethereum_proto_rawDesc = nil
++ file_messages_ethereum_proto_goTypes = nil
++ file_messages_ethereum_proto_depIdxs = nil
++}
+diff --git a/accounts/usbwallet/messages-ethereum.proto b/accounts/usbwallet/messages-ethereum.proto
+new file mode 100644
+index 0000000000..8e1150abb6
+--- /dev/null
++++ b/accounts/usbwallet/messages-ethereum.proto
+@@ -0,0 +1,133 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++syntax = "proto2";
++package hw.trezor.messages.ethereum;
++
++option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
++
++// Sugar for easier handling in Java
++option java_package = "com.satoshilabs.trezor.lib.protobuf";
++option java_outer_classname = "TrezorMessageEthereum";
++
++import "messages-common.proto";
++
++
++/**
++ * Request: Ask device for public key corresponding to address_n path
++ * @start
++ * @next EthereumPublicKey
++ * @next Failure
++ */
++message EthereumGetPublicKey {
++ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
++ optional bool show_display = 2; // optionally show on display before sending the result
++}
++
++/**
++ * Response: Contains public key derived from device private seed
++ * @end
++ */
++message EthereumPublicKey {
++ optional hw.trezor.messages.common.HDNodeType node = 1; // BIP32 public node
++ optional string xpub = 2; // serialized form of public node
++}
++
++/**
++ * Request: Ask device for Ethereum address corresponding to address_n path
++ * @start
++ * @next EthereumAddress
++ * @next Failure
++ */
++message EthereumGetAddress {
++ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
++ optional bool show_display = 2; // optionally show on display before sending the result
++}
++
++/**
++ * Response: Contains an Ethereum address derived from device private seed
++ * @end
++ */
++message EthereumAddress {
++ optional bytes addressBin = 1; // Ethereum address as 20 bytes (legacy firmwares)
++ optional string addressHex = 2; // Ethereum address as hex string (newer firmwares)
++}
++
++/**
++ * Request: Ask device to sign transaction
++ * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
++ * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
++ * @start
++ * @next EthereumTxRequest
++ * @next Failure
++ */
++message EthereumSignTx {
++ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
++ optional bytes nonce = 2; // <=256 bit unsigned big endian
++ optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei)
++ optional bytes gas_limit = 4; // <=256 bit unsigned big endian
++ optional bytes toBin = 5; // recipient address (20 bytes, legacy firmware)
++ optional string toHex = 11; // recipient address (hex string, newer firmware)
++ optional bytes value = 6; // <=256 bit unsigned big endian (in wei)
++ optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes)
++ optional uint32 data_length = 8; // Length of transaction payload
++ optional uint32 chain_id = 9; // Chain Id for EIP 155
++ optional uint32 tx_type = 10; // (only for Wanchain)
++}
++
++/**
++ * Response: Device asks for more data from transaction payload, or returns the signature.
++ * If data_length is set, device awaits that many more bytes of payload.
++ * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
++ * @end
++ * @next EthereumTxAck
++ */
++message EthereumTxRequest {
++ optional uint32 data_length = 1; // Number of bytes being requested (<= 1024)
++ optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28)
++ optional bytes signature_r = 3; // Computed signature R component (256 bit)
++ optional bytes signature_s = 4; // Computed signature S component (256 bit)
++}
++
++/**
++ * Request: Transaction payload data.
++ * @next EthereumTxRequest
++ */
++message EthereumTxAck {
++ optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes)
++}
++
++/**
++ * Request: Ask device to sign message
++ * @start
++ * @next EthereumMessageSignature
++ * @next Failure
++ */
++message EthereumSignMessage {
++ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
++ optional bytes message = 2; // message to be signed
++}
++
++/**
++ * Response: Signed message
++ * @end
++ */
++message EthereumMessageSignature {
++ optional bytes addressBin = 1; // address used to sign the message (20 bytes, legacy firmware)
++ optional bytes signature = 2; // signature of the message
++ optional string addressHex = 3; // address used to sign the message (hex string, newer firmware)
++}
++
++/**
++ * Request: Ask device to verify message
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message EthereumVerifyMessage {
++ optional bytes addressBin = 1; // address to verify (20 bytes, legacy firmware)
++ optional bytes signature = 2; // signature to verify
++ optional bytes message = 3; // message to verify
++ optional string addressHex = 4; // address to verify (hex string, newer firmware)
++}
+diff --git a/accounts/usbwallet/messages-management.pb.go b/accounts/usbwallet/messages-management.pb.go
+new file mode 100644
+index 0000000000..983e2d281d
+--- /dev/null
++++ b/accounts/usbwallet/messages-management.pb.go
+@@ -0,0 +1,2276 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++// Code generated by protoc-gen-go. DO NOT EDIT.
++// versions:
++// protoc-gen-go v1.34.2
++// protoc v5.27.1
++// source: messages-management.proto
++
++package trezor
++
++import (
++ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
++ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
++ reflect "reflect"
++ sync "sync"
++)
++
++const (
++ // Verify that this generated code is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
++ // Verify that runtime/protoimpl is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
++)
++
++// *
++// Structure representing passphrase source
++type ApplySettings_PassphraseSourceType int32
++
++const (
++ ApplySettings_ASK ApplySettings_PassphraseSourceType = 0
++ ApplySettings_DEVICE ApplySettings_PassphraseSourceType = 1
++ ApplySettings_HOST ApplySettings_PassphraseSourceType = 2
++)
++
++// Enum value maps for ApplySettings_PassphraseSourceType.
++var (
++ ApplySettings_PassphraseSourceType_name = map[int32]string{
++ 0: "ASK",
++ 1: "DEVICE",
++ 2: "HOST",
++ }
++ ApplySettings_PassphraseSourceType_value = map[string]int32{
++ "ASK": 0,
++ "DEVICE": 1,
++ "HOST": 2,
++ }
++)
++
++func (x ApplySettings_PassphraseSourceType) Enum() *ApplySettings_PassphraseSourceType {
++ p := new(ApplySettings_PassphraseSourceType)
++ *p = x
++ return p
++}
++
++func (x ApplySettings_PassphraseSourceType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (ApplySettings_PassphraseSourceType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_management_proto_enumTypes[0].Descriptor()
++}
++
++func (ApplySettings_PassphraseSourceType) Type() protoreflect.EnumType {
++ return &file_messages_management_proto_enumTypes[0]
++}
++
++func (x ApplySettings_PassphraseSourceType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *ApplySettings_PassphraseSourceType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = ApplySettings_PassphraseSourceType(num)
++ return nil
++}
++
++// Deprecated: Use ApplySettings_PassphraseSourceType.Descriptor instead.
++func (ApplySettings_PassphraseSourceType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{4, 0}
++}
++
++// *
++// Type of recovery procedure. These should be used as bitmask, e.g.,
++// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
++// listing every method supported by the host computer.
++//
++// Note that ScrambledWords must be supported by every implementation
++// for backward compatibility; there is no way to not support it.
++type RecoveryDevice_RecoveryDeviceType int32
++
++const (
++ // use powers of two when extending this field
++ RecoveryDevice_RecoveryDeviceType_ScrambledWords RecoveryDevice_RecoveryDeviceType = 0 // words in scrambled order
++ RecoveryDevice_RecoveryDeviceType_Matrix RecoveryDevice_RecoveryDeviceType = 1 // matrix recovery type
++)
++
++// Enum value maps for RecoveryDevice_RecoveryDeviceType.
++var (
++ RecoveryDevice_RecoveryDeviceType_name = map[int32]string{
++ 0: "RecoveryDeviceType_ScrambledWords",
++ 1: "RecoveryDeviceType_Matrix",
++ }
++ RecoveryDevice_RecoveryDeviceType_value = map[string]int32{
++ "RecoveryDeviceType_ScrambledWords": 0,
++ "RecoveryDeviceType_Matrix": 1,
++ }
++)
++
++func (x RecoveryDevice_RecoveryDeviceType) Enum() *RecoveryDevice_RecoveryDeviceType {
++ p := new(RecoveryDevice_RecoveryDeviceType)
++ *p = x
++ return p
++}
++
++func (x RecoveryDevice_RecoveryDeviceType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (RecoveryDevice_RecoveryDeviceType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_management_proto_enumTypes[1].Descriptor()
++}
++
++func (RecoveryDevice_RecoveryDeviceType) Type() protoreflect.EnumType {
++ return &file_messages_management_proto_enumTypes[1]
++}
++
++func (x RecoveryDevice_RecoveryDeviceType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *RecoveryDevice_RecoveryDeviceType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = RecoveryDevice_RecoveryDeviceType(num)
++ return nil
++}
++
++// Deprecated: Use RecoveryDevice_RecoveryDeviceType.Descriptor instead.
++func (RecoveryDevice_RecoveryDeviceType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{17, 0}
++}
++
++// *
++// Type of Recovery Word request
++type WordRequest_WordRequestType int32
++
++const (
++ WordRequest_WordRequestType_Plain WordRequest_WordRequestType = 0
++ WordRequest_WordRequestType_Matrix9 WordRequest_WordRequestType = 1
++ WordRequest_WordRequestType_Matrix6 WordRequest_WordRequestType = 2
++)
++
++// Enum value maps for WordRequest_WordRequestType.
++var (
++ WordRequest_WordRequestType_name = map[int32]string{
++ 0: "WordRequestType_Plain",
++ 1: "WordRequestType_Matrix9",
++ 2: "WordRequestType_Matrix6",
++ }
++ WordRequest_WordRequestType_value = map[string]int32{
++ "WordRequestType_Plain": 0,
++ "WordRequestType_Matrix9": 1,
++ "WordRequestType_Matrix6": 2,
++ }
++)
++
++func (x WordRequest_WordRequestType) Enum() *WordRequest_WordRequestType {
++ p := new(WordRequest_WordRequestType)
++ *p = x
++ return p
++}
++
++func (x WordRequest_WordRequestType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (WordRequest_WordRequestType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_management_proto_enumTypes[2].Descriptor()
++}
++
++func (WordRequest_WordRequestType) Type() protoreflect.EnumType {
++ return &file_messages_management_proto_enumTypes[2]
++}
++
++func (x WordRequest_WordRequestType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *WordRequest_WordRequestType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = WordRequest_WordRequestType(num)
++ return nil
++}
++
++// Deprecated: Use WordRequest_WordRequestType.Descriptor instead.
++func (WordRequest_WordRequestType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{18, 0}
++}
++
++// *
++// Request: Reset device to default state and ask for device details
++// @start
++// @next Features
++type Initialize struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` // assumed device state, clear session if set and different
++ SkipPassphrase *bool `protobuf:"varint,2,opt,name=skip_passphrase,json=skipPassphrase" json:"skip_passphrase,omitempty"` // this session should always assume empty passphrase
++}
++
++func (x *Initialize) Reset() {
++ *x = Initialize{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[0]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Initialize) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Initialize) ProtoMessage() {}
++
++func (x *Initialize) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[0]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Initialize.ProtoReflect.Descriptor instead.
++func (*Initialize) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{0}
++}
++
++func (x *Initialize) GetState() []byte {
++ if x != nil {
++ return x.State
++ }
++ return nil
++}
++
++func (x *Initialize) GetSkipPassphrase() bool {
++ if x != nil && x.SkipPassphrase != nil {
++ return *x.SkipPassphrase
++ }
++ return false
++}
++
++// *
++// Request: Ask for device details (no device reset)
++// @start
++// @next Features
++type GetFeatures struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *GetFeatures) Reset() {
++ *x = GetFeatures{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[1]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *GetFeatures) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*GetFeatures) ProtoMessage() {}
++
++func (x *GetFeatures) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[1]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use GetFeatures.ProtoReflect.Descriptor instead.
++func (*GetFeatures) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{1}
++}
++
++// *
++// Response: Reports various information about the device
++// @end
++type Features struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` // name of the manufacturer, e.g. "trezor.io"
++ MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` // major version of the firmware/bootloader, e.g. 1
++ MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` // minor version of the firmware/bootloader, e.g. 0
++ PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` // patch version of the firmware/bootloader, e.g. 0
++ BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` // is device in bootloader mode?
++ DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` // device's unique identifier
++ PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // is device protected by PIN?
++ PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // is node/mnemonic encrypted using passphrase?
++ Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` // device language
++ Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` // device description label
++ Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` // does device contain seed?
++ Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` // SCM revision of firmware
++ BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` // hash of the bootloader
++ Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` // was storage imported from an external source?
++ PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` // is PIN already cached in session?
++ PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` // is passphrase already cached in session?
++ FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` // is valid firmware loaded?
++ NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` // does storage need backup? (equals to Storage.needs_backup)
++ Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` // device flags (equals to Storage.flags)
++ Model *string `protobuf:"bytes,21,opt,name=model" json:"model,omitempty"` // device hardware model
++ FwMajor *uint32 `protobuf:"varint,22,opt,name=fw_major,json=fwMajor" json:"fw_major,omitempty"` // reported firmware version if in bootloader mode
++ FwMinor *uint32 `protobuf:"varint,23,opt,name=fw_minor,json=fwMinor" json:"fw_minor,omitempty"` // reported firmware version if in bootloader mode
++ FwPatch *uint32 `protobuf:"varint,24,opt,name=fw_patch,json=fwPatch" json:"fw_patch,omitempty"` // reported firmware version if in bootloader mode
++ FwVendor *string `protobuf:"bytes,25,opt,name=fw_vendor,json=fwVendor" json:"fw_vendor,omitempty"` // reported firmware vendor if in bootloader mode
++ FwVendorKeys []byte `protobuf:"bytes,26,opt,name=fw_vendor_keys,json=fwVendorKeys" json:"fw_vendor_keys,omitempty"` // reported firmware vendor keys (their hash)
++ UnfinishedBackup *bool `protobuf:"varint,27,opt,name=unfinished_backup,json=unfinishedBackup" json:"unfinished_backup,omitempty"` // report unfinished backup (equals to Storage.unfinished_backup)
++ NoBackup *bool `protobuf:"varint,28,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` // report no backup (equals to Storage.no_backup)
++}
++
++func (x *Features) Reset() {
++ *x = Features{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[2]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Features) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Features) ProtoMessage() {}
++
++func (x *Features) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[2]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Features.ProtoReflect.Descriptor instead.
++func (*Features) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{2}
++}
++
++func (x *Features) GetVendor() string {
++ if x != nil && x.Vendor != nil {
++ return *x.Vendor
++ }
++ return ""
++}
++
++func (x *Features) GetMajorVersion() uint32 {
++ if x != nil && x.MajorVersion != nil {
++ return *x.MajorVersion
++ }
++ return 0
++}
++
++func (x *Features) GetMinorVersion() uint32 {
++ if x != nil && x.MinorVersion != nil {
++ return *x.MinorVersion
++ }
++ return 0
++}
++
++func (x *Features) GetPatchVersion() uint32 {
++ if x != nil && x.PatchVersion != nil {
++ return *x.PatchVersion
++ }
++ return 0
++}
++
++func (x *Features) GetBootloaderMode() bool {
++ if x != nil && x.BootloaderMode != nil {
++ return *x.BootloaderMode
++ }
++ return false
++}
++
++func (x *Features) GetDeviceId() string {
++ if x != nil && x.DeviceId != nil {
++ return *x.DeviceId
++ }
++ return ""
++}
++
++func (x *Features) GetPinProtection() bool {
++ if x != nil && x.PinProtection != nil {
++ return *x.PinProtection
++ }
++ return false
++}
++
++func (x *Features) GetPassphraseProtection() bool {
++ if x != nil && x.PassphraseProtection != nil {
++ return *x.PassphraseProtection
++ }
++ return false
++}
++
++func (x *Features) GetLanguage() string {
++ if x != nil && x.Language != nil {
++ return *x.Language
++ }
++ return ""
++}
++
++func (x *Features) GetLabel() string {
++ if x != nil && x.Label != nil {
++ return *x.Label
++ }
++ return ""
++}
++
++func (x *Features) GetInitialized() bool {
++ if x != nil && x.Initialized != nil {
++ return *x.Initialized
++ }
++ return false
++}
++
++func (x *Features) GetRevision() []byte {
++ if x != nil {
++ return x.Revision
++ }
++ return nil
++}
++
++func (x *Features) GetBootloaderHash() []byte {
++ if x != nil {
++ return x.BootloaderHash
++ }
++ return nil
++}
++
++func (x *Features) GetImported() bool {
++ if x != nil && x.Imported != nil {
++ return *x.Imported
++ }
++ return false
++}
++
++func (x *Features) GetPinCached() bool {
++ if x != nil && x.PinCached != nil {
++ return *x.PinCached
++ }
++ return false
++}
++
++func (x *Features) GetPassphraseCached() bool {
++ if x != nil && x.PassphraseCached != nil {
++ return *x.PassphraseCached
++ }
++ return false
++}
++
++func (x *Features) GetFirmwarePresent() bool {
++ if x != nil && x.FirmwarePresent != nil {
++ return *x.FirmwarePresent
++ }
++ return false
++}
++
++func (x *Features) GetNeedsBackup() bool {
++ if x != nil && x.NeedsBackup != nil {
++ return *x.NeedsBackup
++ }
++ return false
++}
++
++func (x *Features) GetFlags() uint32 {
++ if x != nil && x.Flags != nil {
++ return *x.Flags
++ }
++ return 0
++}
++
++func (x *Features) GetModel() string {
++ if x != nil && x.Model != nil {
++ return *x.Model
++ }
++ return ""
++}
++
++func (x *Features) GetFwMajor() uint32 {
++ if x != nil && x.FwMajor != nil {
++ return *x.FwMajor
++ }
++ return 0
++}
++
++func (x *Features) GetFwMinor() uint32 {
++ if x != nil && x.FwMinor != nil {
++ return *x.FwMinor
++ }
++ return 0
++}
++
++func (x *Features) GetFwPatch() uint32 {
++ if x != nil && x.FwPatch != nil {
++ return *x.FwPatch
++ }
++ return 0
++}
++
++func (x *Features) GetFwVendor() string {
++ if x != nil && x.FwVendor != nil {
++ return *x.FwVendor
++ }
++ return ""
++}
++
++func (x *Features) GetFwVendorKeys() []byte {
++ if x != nil {
++ return x.FwVendorKeys
++ }
++ return nil
++}
++
++func (x *Features) GetUnfinishedBackup() bool {
++ if x != nil && x.UnfinishedBackup != nil {
++ return *x.UnfinishedBackup
++ }
++ return false
++}
++
++func (x *Features) GetNoBackup() bool {
++ if x != nil && x.NoBackup != nil {
++ return *x.NoBackup
++ }
++ return false
++}
++
++// *
++// Request: clear session (removes cached PIN, passphrase, etc).
++// @start
++// @next Success
++type ClearSession struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *ClearSession) Reset() {
++ *x = ClearSession{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[3]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ClearSession) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ClearSession) ProtoMessage() {}
++
++func (x *ClearSession) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[3]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ClearSession.ProtoReflect.Descriptor instead.
++func (*ClearSession) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{3}
++}
++
++// *
++// Request: change language and/or label of the device
++// @start
++// @next Success
++// @next Failure
++type ApplySettings struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"`
++ Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"`
++ UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"`
++ Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"`
++ PassphraseSource *ApplySettings_PassphraseSourceType `protobuf:"varint,5,opt,name=passphrase_source,json=passphraseSource,enum=hw.trezor.messages.management.ApplySettings_PassphraseSourceType" json:"passphrase_source,omitempty"`
++ AutoLockDelayMs *uint32 `protobuf:"varint,6,opt,name=auto_lock_delay_ms,json=autoLockDelayMs" json:"auto_lock_delay_ms,omitempty"`
++ DisplayRotation *uint32 `protobuf:"varint,7,opt,name=display_rotation,json=displayRotation" json:"display_rotation,omitempty"` // in degrees from North
++}
++
++func (x *ApplySettings) Reset() {
++ *x = ApplySettings{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[4]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ApplySettings) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ApplySettings) ProtoMessage() {}
++
++func (x *ApplySettings) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[4]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ApplySettings.ProtoReflect.Descriptor instead.
++func (*ApplySettings) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{4}
++}
++
++func (x *ApplySettings) GetLanguage() string {
++ if x != nil && x.Language != nil {
++ return *x.Language
++ }
++ return ""
++}
++
++func (x *ApplySettings) GetLabel() string {
++ if x != nil && x.Label != nil {
++ return *x.Label
++ }
++ return ""
++}
++
++func (x *ApplySettings) GetUsePassphrase() bool {
++ if x != nil && x.UsePassphrase != nil {
++ return *x.UsePassphrase
++ }
++ return false
++}
++
++func (x *ApplySettings) GetHomescreen() []byte {
++ if x != nil {
++ return x.Homescreen
++ }
++ return nil
++}
++
++func (x *ApplySettings) GetPassphraseSource() ApplySettings_PassphraseSourceType {
++ if x != nil && x.PassphraseSource != nil {
++ return *x.PassphraseSource
++ }
++ return ApplySettings_ASK
++}
++
++func (x *ApplySettings) GetAutoLockDelayMs() uint32 {
++ if x != nil && x.AutoLockDelayMs != nil {
++ return *x.AutoLockDelayMs
++ }
++ return 0
++}
++
++func (x *ApplySettings) GetDisplayRotation() uint32 {
++ if x != nil && x.DisplayRotation != nil {
++ return *x.DisplayRotation
++ }
++ return 0
++}
++
++// *
++// Request: set flags of the device
++// @start
++// @next Success
++// @next Failure
++type ApplyFlags struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` // bitmask, can only set bits, not unset
++}
++
++func (x *ApplyFlags) Reset() {
++ *x = ApplyFlags{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[5]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ApplyFlags) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ApplyFlags) ProtoMessage() {}
++
++func (x *ApplyFlags) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[5]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ApplyFlags.ProtoReflect.Descriptor instead.
++func (*ApplyFlags) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{5}
++}
++
++func (x *ApplyFlags) GetFlags() uint32 {
++ if x != nil && x.Flags != nil {
++ return *x.Flags
++ }
++ return 0
++}
++
++// *
++// Request: Starts workflow for setting/changing/removing the PIN
++// @start
++// @next Success
++// @next Failure
++type ChangePin struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` // is PIN removal requested?
++}
++
++func (x *ChangePin) Reset() {
++ *x = ChangePin{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[6]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ChangePin) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ChangePin) ProtoMessage() {}
++
++func (x *ChangePin) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[6]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ChangePin.ProtoReflect.Descriptor instead.
++func (*ChangePin) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{6}
++}
++
++func (x *ChangePin) GetRemove() bool {
++ if x != nil && x.Remove != nil {
++ return *x.Remove
++ }
++ return false
++}
++
++// *
++// Request: Test if the device is alive, device sends back the message in Success response
++// @start
++// @next Success
++type Ping struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` // message to send back in Success message
++ ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` // ask for button press
++ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // ask for PIN if set in device
++ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // ask for passphrase if set in device
++}
++
++func (x *Ping) Reset() {
++ *x = Ping{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[7]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Ping) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Ping) ProtoMessage() {}
++
++func (x *Ping) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[7]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Ping.ProtoReflect.Descriptor instead.
++func (*Ping) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{7}
++}
++
++func (x *Ping) GetMessage() string {
++ if x != nil && x.Message != nil {
++ return *x.Message
++ }
++ return ""
++}
++
++func (x *Ping) GetButtonProtection() bool {
++ if x != nil && x.ButtonProtection != nil {
++ return *x.ButtonProtection
++ }
++ return false
++}
++
++func (x *Ping) GetPinProtection() bool {
++ if x != nil && x.PinProtection != nil {
++ return *x.PinProtection
++ }
++ return false
++}
++
++func (x *Ping) GetPassphraseProtection() bool {
++ if x != nil && x.PassphraseProtection != nil {
++ return *x.PassphraseProtection
++ }
++ return false
++}
++
++// *
++// Request: Abort last operation that required user interaction
++// @start
++// @next Failure
++type Cancel struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *Cancel) Reset() {
++ *x = Cancel{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[8]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Cancel) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Cancel) ProtoMessage() {}
++
++func (x *Cancel) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[8]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Cancel.ProtoReflect.Descriptor instead.
++func (*Cancel) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{8}
++}
++
++// *
++// Request: Request a sample of random data generated by hardware RNG. May be used for testing.
++// @start
++// @next Entropy
++// @next Failure
++type GetEntropy struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` // size of requested entropy
++}
++
++func (x *GetEntropy) Reset() {
++ *x = GetEntropy{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[9]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *GetEntropy) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*GetEntropy) ProtoMessage() {}
++
++func (x *GetEntropy) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[9]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use GetEntropy.ProtoReflect.Descriptor instead.
++func (*GetEntropy) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{9}
++}
++
++func (x *GetEntropy) GetSize() uint32 {
++ if x != nil && x.Size != nil {
++ return *x.Size
++ }
++ return 0
++}
++
++// *
++// Response: Reply with random data generated by internal RNG
++// @end
++type Entropy struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` // chunk of random generated bytes
++}
++
++func (x *Entropy) Reset() {
++ *x = Entropy{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[10]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *Entropy) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*Entropy) ProtoMessage() {}
++
++func (x *Entropy) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[10]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use Entropy.ProtoReflect.Descriptor instead.
++func (*Entropy) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{10}
++}
++
++func (x *Entropy) GetEntropy() []byte {
++ if x != nil {
++ return x.Entropy
++ }
++ return nil
++}
++
++// *
++// Request: Request device to wipe all sensitive data and settings
++// @start
++// @next Success
++// @next Failure
++type WipeDevice struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *WipeDevice) Reset() {
++ *x = WipeDevice{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[11]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *WipeDevice) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*WipeDevice) ProtoMessage() {}
++
++func (x *WipeDevice) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[11]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use WipeDevice.ProtoReflect.Descriptor instead.
++func (*WipeDevice) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{11}
++}
++
++// *
++// Request: Load seed and related internal settings from the computer
++// @start
++// @next Success
++// @next Failure
++type LoadDevice struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` // seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
++ Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` // BIP-32 node
++ Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` // set PIN protection
++ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
++ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` // device language
++ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` // device label
++ SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` // do not test mnemonic for valid BIP-39 checksum
++ U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
++}
++
++// Default values for LoadDevice fields.
++const (
++ Default_LoadDevice_Language = string("english")
++)
++
++func (x *LoadDevice) Reset() {
++ *x = LoadDevice{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[12]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *LoadDevice) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*LoadDevice) ProtoMessage() {}
++
++func (x *LoadDevice) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[12]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use LoadDevice.ProtoReflect.Descriptor instead.
++func (*LoadDevice) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{12}
++}
++
++func (x *LoadDevice) GetMnemonic() string {
++ if x != nil && x.Mnemonic != nil {
++ return *x.Mnemonic
++ }
++ return ""
++}
++
++func (x *LoadDevice) GetNode() *HDNodeType {
++ if x != nil {
++ return x.Node
++ }
++ return nil
++}
++
++func (x *LoadDevice) GetPin() string {
++ if x != nil && x.Pin != nil {
++ return *x.Pin
++ }
++ return ""
++}
++
++func (x *LoadDevice) GetPassphraseProtection() bool {
++ if x != nil && x.PassphraseProtection != nil {
++ return *x.PassphraseProtection
++ }
++ return false
++}
++
++func (x *LoadDevice) GetLanguage() string {
++ if x != nil && x.Language != nil {
++ return *x.Language
++ }
++ return Default_LoadDevice_Language
++}
++
++func (x *LoadDevice) GetLabel() string {
++ if x != nil && x.Label != nil {
++ return *x.Label
++ }
++ return ""
++}
++
++func (x *LoadDevice) GetSkipChecksum() bool {
++ if x != nil && x.SkipChecksum != nil {
++ return *x.SkipChecksum
++ }
++ return false
++}
++
++func (x *LoadDevice) GetU2FCounter() uint32 {
++ if x != nil && x.U2FCounter != nil {
++ return *x.U2FCounter
++ }
++ return 0
++}
++
++// *
++// Request: Ask device to do initialization involving user interaction
++// @start
++// @next EntropyRequest
++// @next Failure
++type ResetDevice struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` // display entropy generated by the device before asking for additional entropy
++ Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` // strength of seed in bits
++ PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
++ PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // enable PIN protection
++ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` // device language
++ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` // device label
++ U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
++ SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` // postpone seed backup to BackupDevice workflow
++ NoBackup *bool `protobuf:"varint,9,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` // indicate that no backup is going to be made
++}
++
++// Default values for ResetDevice fields.
++const (
++ Default_ResetDevice_Strength = uint32(256)
++ Default_ResetDevice_Language = string("english")
++)
++
++func (x *ResetDevice) Reset() {
++ *x = ResetDevice{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[13]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *ResetDevice) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*ResetDevice) ProtoMessage() {}
++
++func (x *ResetDevice) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[13]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use ResetDevice.ProtoReflect.Descriptor instead.
++func (*ResetDevice) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{13}
++}
++
++func (x *ResetDevice) GetDisplayRandom() bool {
++ if x != nil && x.DisplayRandom != nil {
++ return *x.DisplayRandom
++ }
++ return false
++}
++
++func (x *ResetDevice) GetStrength() uint32 {
++ if x != nil && x.Strength != nil {
++ return *x.Strength
++ }
++ return Default_ResetDevice_Strength
++}
++
++func (x *ResetDevice) GetPassphraseProtection() bool {
++ if x != nil && x.PassphraseProtection != nil {
++ return *x.PassphraseProtection
++ }
++ return false
++}
++
++func (x *ResetDevice) GetPinProtection() bool {
++ if x != nil && x.PinProtection != nil {
++ return *x.PinProtection
++ }
++ return false
++}
++
++func (x *ResetDevice) GetLanguage() string {
++ if x != nil && x.Language != nil {
++ return *x.Language
++ }
++ return Default_ResetDevice_Language
++}
++
++func (x *ResetDevice) GetLabel() string {
++ if x != nil && x.Label != nil {
++ return *x.Label
++ }
++ return ""
++}
++
++func (x *ResetDevice) GetU2FCounter() uint32 {
++ if x != nil && x.U2FCounter != nil {
++ return *x.U2FCounter
++ }
++ return 0
++}
++
++func (x *ResetDevice) GetSkipBackup() bool {
++ if x != nil && x.SkipBackup != nil {
++ return *x.SkipBackup
++ }
++ return false
++}
++
++func (x *ResetDevice) GetNoBackup() bool {
++ if x != nil && x.NoBackup != nil {
++ return *x.NoBackup
++ }
++ return false
++}
++
++// *
++// Request: Perform backup of the device seed if not backed up using ResetDevice
++// @start
++// @next Success
++type BackupDevice struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *BackupDevice) Reset() {
++ *x = BackupDevice{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[14]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *BackupDevice) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*BackupDevice) ProtoMessage() {}
++
++func (x *BackupDevice) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[14]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use BackupDevice.ProtoReflect.Descriptor instead.
++func (*BackupDevice) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{14}
++}
++
++// *
++// Response: Ask for additional entropy from host computer
++// @next EntropyAck
++type EntropyRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++}
++
++func (x *EntropyRequest) Reset() {
++ *x = EntropyRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[15]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EntropyRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EntropyRequest) ProtoMessage() {}
++
++func (x *EntropyRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[15]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EntropyRequest.ProtoReflect.Descriptor instead.
++func (*EntropyRequest) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{15}
++}
++
++// *
++// Request: Provide additional entropy for seed generation function
++// @next Success
++type EntropyAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` // 256 bits (32 bytes) of random data
++}
++
++func (x *EntropyAck) Reset() {
++ *x = EntropyAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[16]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *EntropyAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*EntropyAck) ProtoMessage() {}
++
++func (x *EntropyAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[16]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use EntropyAck.ProtoReflect.Descriptor instead.
++func (*EntropyAck) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{16}
++}
++
++func (x *EntropyAck) GetEntropy() []byte {
++ if x != nil {
++ return x.Entropy
++ }
++ return nil
++}
++
++// *
++// Request: Start recovery workflow asking user for specific words of mnemonic
++// Used to recovery device safely even on untrusted computer.
++// @start
++// @next WordRequest
++type RecoveryDevice struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` // number of words in BIP-39 mnemonic
++ PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` // enable master node encryption using passphrase
++ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` // enable PIN protection
++ Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` // device language
++ Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` // device label
++ EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` // enforce BIP-39 wordlist during the process
++ // 7 reserved for unused recovery method
++ Type *RecoveryDevice_RecoveryDeviceType `protobuf:"varint,8,opt,name=type,enum=hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType" json:"type,omitempty"` // supported recovery type
++ U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // U2F counter
++ DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` // perform dry-run recovery workflow (for safe mnemonic validation)
++}
++
++// Default values for RecoveryDevice fields.
++const (
++ Default_RecoveryDevice_Language = string("english")
++)
++
++func (x *RecoveryDevice) Reset() {
++ *x = RecoveryDevice{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[17]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *RecoveryDevice) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*RecoveryDevice) ProtoMessage() {}
++
++func (x *RecoveryDevice) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[17]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use RecoveryDevice.ProtoReflect.Descriptor instead.
++func (*RecoveryDevice) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{17}
++}
++
++func (x *RecoveryDevice) GetWordCount() uint32 {
++ if x != nil && x.WordCount != nil {
++ return *x.WordCount
++ }
++ return 0
++}
++
++func (x *RecoveryDevice) GetPassphraseProtection() bool {
++ if x != nil && x.PassphraseProtection != nil {
++ return *x.PassphraseProtection
++ }
++ return false
++}
++
++func (x *RecoveryDevice) GetPinProtection() bool {
++ if x != nil && x.PinProtection != nil {
++ return *x.PinProtection
++ }
++ return false
++}
++
++func (x *RecoveryDevice) GetLanguage() string {
++ if x != nil && x.Language != nil {
++ return *x.Language
++ }
++ return Default_RecoveryDevice_Language
++}
++
++func (x *RecoveryDevice) GetLabel() string {
++ if x != nil && x.Label != nil {
++ return *x.Label
++ }
++ return ""
++}
++
++func (x *RecoveryDevice) GetEnforceWordlist() bool {
++ if x != nil && x.EnforceWordlist != nil {
++ return *x.EnforceWordlist
++ }
++ return false
++}
++
++func (x *RecoveryDevice) GetType() RecoveryDevice_RecoveryDeviceType {
++ if x != nil && x.Type != nil {
++ return *x.Type
++ }
++ return RecoveryDevice_RecoveryDeviceType_ScrambledWords
++}
++
++func (x *RecoveryDevice) GetU2FCounter() uint32 {
++ if x != nil && x.U2FCounter != nil {
++ return *x.U2FCounter
++ }
++ return 0
++}
++
++func (x *RecoveryDevice) GetDryRun() bool {
++ if x != nil && x.DryRun != nil {
++ return *x.DryRun
++ }
++ return false
++}
++
++// *
++// Response: Device is waiting for user to enter word of the mnemonic
++// Its position is shown only on device's internal display.
++// @next WordAck
++type WordRequest struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Type *WordRequest_WordRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.management.WordRequest_WordRequestType" json:"type,omitempty"`
++}
++
++func (x *WordRequest) Reset() {
++ *x = WordRequest{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[18]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *WordRequest) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*WordRequest) ProtoMessage() {}
++
++func (x *WordRequest) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[18]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use WordRequest.ProtoReflect.Descriptor instead.
++func (*WordRequest) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{18}
++}
++
++func (x *WordRequest) GetType() WordRequest_WordRequestType {
++ if x != nil && x.Type != nil {
++ return *x.Type
++ }
++ return WordRequest_WordRequestType_Plain
++}
++
++// *
++// Request: Computer replies with word from the mnemonic
++// @next WordRequest
++// @next Success
++// @next Failure
++type WordAck struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` // one word of mnemonic on asked position
++}
++
++func (x *WordAck) Reset() {
++ *x = WordAck{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[19]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *WordAck) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*WordAck) ProtoMessage() {}
++
++func (x *WordAck) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[19]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use WordAck.ProtoReflect.Descriptor instead.
++func (*WordAck) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{19}
++}
++
++func (x *WordAck) GetWord() string {
++ if x != nil && x.Word != nil {
++ return *x.Word
++ }
++ return ""
++}
++
++// *
++// Request: Set U2F counter
++// @start
++// @next Success
++type SetU2FCounter struct {
++ state protoimpl.MessageState
++ sizeCache protoimpl.SizeCache
++ unknownFields protoimpl.UnknownFields
++
++ U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` // counter
++}
++
++func (x *SetU2FCounter) Reset() {
++ *x = SetU2FCounter{}
++ if protoimpl.UnsafeEnabled {
++ mi := &file_messages_management_proto_msgTypes[20]
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ ms.StoreMessageInfo(mi)
++ }
++}
++
++func (x *SetU2FCounter) String() string {
++ return protoimpl.X.MessageStringOf(x)
++}
++
++func (*SetU2FCounter) ProtoMessage() {}
++
++func (x *SetU2FCounter) ProtoReflect() protoreflect.Message {
++ mi := &file_messages_management_proto_msgTypes[20]
++ if protoimpl.UnsafeEnabled && x != nil {
++ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
++ if ms.LoadMessageInfo() == nil {
++ ms.StoreMessageInfo(mi)
++ }
++ return ms
++ }
++ return mi.MessageOf(x)
++}
++
++// Deprecated: Use SetU2FCounter.ProtoReflect.Descriptor instead.
++func (*SetU2FCounter) Descriptor() ([]byte, []int) {
++ return file_messages_management_proto_rawDescGZIP(), []int{20}
++}
++
++func (x *SetU2FCounter) GetU2FCounter() uint32 {
++ if x != nil && x.U2FCounter != nil {
++ return *x.U2FCounter
++ }
++ return 0
++}
++
++var File_messages_management_proto protoreflect.FileDescriptor
++
++var file_messages_management_proto_rawDesc = []byte{
++ 0x0a, 0x19, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67,
++ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x68, 0x77, 0x2e,
++ 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e,
++ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x15, 0x6d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
++ 0x6f, 0x22, 0x4b, 0x0a, 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12,
++ 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
++ 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x70, 0x61,
++ 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e,
++ 0x73, 0x6b, 0x69, 0x70, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x0d,
++ 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x8c, 0x07,
++ 0x0a, 0x08, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65,
++ 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x65, 0x6e, 0x64,
++ 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73,
++ 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
++ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
++ 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
++ 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d,
++ 0x70, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20,
++ 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
++ 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x5f,
++ 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x62, 0x6f, 0x6f, 0x74,
++ 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65,
++ 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64,
++ 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70,
++ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
++ 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33,
++ 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f,
++ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x70,
++ 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74,
++ 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18,
++ 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12,
++ 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
++ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
++ 0x69, 0x7a, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74,
++ 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73,
++ 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73,
++ 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65,
++ 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x62, 0x6f,
++ 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1a, 0x0a, 0x08,
++ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
++ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x6e, 0x5f,
++ 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x69,
++ 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x61, 0x73, 0x73, 0x70,
++ 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x11, 0x20, 0x01,
++ 0x28, 0x08, 0x52, 0x10, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x43, 0x61,
++ 0x63, 0x68, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65,
++ 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
++ 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12,
++ 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18,
++ 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x61, 0x63, 0x6b,
++ 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28,
++ 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65,
++ 0x6c, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x19,
++ 0x0a, 0x08, 0x66, 0x77, 0x5f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0d,
++ 0x52, 0x07, 0x66, 0x77, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x5f,
++ 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x77, 0x4d,
++ 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x77, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68,
++ 0x18, 0x18, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x77, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12,
++ 0x1b, 0x0a, 0x09, 0x66, 0x77, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x18, 0x19, 0x20, 0x01,
++ 0x28, 0x09, 0x52, 0x08, 0x66, 0x77, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x0e,
++ 0x66, 0x77, 0x5f, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x1a,
++ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x66, 0x77, 0x56, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4b, 0x65,
++ 0x79, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x75, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
++ 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75,
++ 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12,
++ 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x1c, 0x20, 0x01,
++ 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x0e, 0x0a, 0x0c,
++ 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x87, 0x03, 0x0a,
++ 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1a,
++ 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
++ 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61,
++ 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c,
++ 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61,
++ 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x50, 0x61, 0x73,
++ 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x6f, 0x6d, 0x65, 0x73,
++ 0x63, 0x72, 0x65, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x6f, 0x6d,
++ 0x65, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x12, 0x6e, 0x0a, 0x11, 0x70, 0x61, 0x73, 0x73, 0x70,
++ 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01,
++ 0x28, 0x0e, 0x32, 0x41, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
++ 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
++ 0x2e, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x10, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
++ 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x6f, 0x5f,
++ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20,
++ 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c,
++ 0x61, 0x79, 0x4d, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f,
++ 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
++ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
++ 0x35, 0x0a, 0x14, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x6f, 0x75,
++ 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x53, 0x4b, 0x10, 0x00,
++ 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04,
++ 0x48, 0x4f, 0x53, 0x54, 0x10, 0x02, 0x22, 0x22, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x46,
++ 0x6c, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20,
++ 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x23, 0x0a, 0x09, 0x43, 0x68,
++ 0x61, 0x6e, 0x67, 0x65, 0x50, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76,
++ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x22,
++ 0xa9, 0x01, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f,
++ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x62,
++ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
++ 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74,
++ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68,
++ 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
++ 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73,
++ 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x08, 0x0a, 0x06, 0x43,
++ 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x22, 0x20, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72,
++ 0x6f, 0x70, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28,
++ 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x23, 0x0a, 0x07, 0x45, 0x6e, 0x74, 0x72, 0x6f,
++ 0x70, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x18, 0x01, 0x20,
++ 0x02, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x22, 0x0c, 0x0a, 0x0a,
++ 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0xab, 0x02, 0x0a, 0x0a, 0x4c,
++ 0x6f, 0x61, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6e, 0x65,
++ 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x6e, 0x65,
++ 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x12, 0x39, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
++ 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e,
++ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
++ 0x48, 0x44, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65,
++ 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70,
++ 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65,
++ 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
++ 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f,
++ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75,
++ 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x07, 0x65, 0x6e, 0x67, 0x6c, 0x69,
++ 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05,
++ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62,
++ 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b,
++ 0x73, 0x75, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x43,
++ 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f, 0x63,
++ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x32,
++ 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0xcb, 0x02, 0x0a, 0x0b, 0x52, 0x65, 0x73,
++ 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x70,
++ 0x6c, 0x61, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
++ 0x52, 0x0d, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x12,
++ 0x1f, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
++ 0x0d, 0x3a, 0x03, 0x32, 0x35, 0x36, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68,
++ 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x70,
++ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
++ 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65,
++ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f,
++ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70,
++ 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08,
++ 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x3a, 0x07,
++ 0x65, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
++ 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
++ 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f, 0x63,
++ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75, 0x32,
++ 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x69, 0x70,
++ 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73,
++ 0x6b, 0x69, 0x70, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x5f,
++ 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f,
++ 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x0e, 0x0a, 0x0c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70,
++ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70,
++ 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x26, 0x0a, 0x0a, 0x45, 0x6e, 0x74, 0x72,
++ 0x6f, 0x70, 0x79, 0x41, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70,
++ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79,
++ 0x22, 0xdd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76,
++ 0x69, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
++ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75,
++ 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x15, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65,
++ 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
++ 0x08, 0x52, 0x14, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x50, 0x72, 0x6f,
++ 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x69, 0x6e, 0x5f, 0x70,
++ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
++ 0x0d, 0x70, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23,
++ 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
++ 0x3a, 0x07, 0x65, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75,
++ 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01,
++ 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x66,
++ 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20,
++ 0x01, 0x28, 0x08, 0x52, 0x0f, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x57, 0x6f, 0x72, 0x64,
++ 0x6c, 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01,
++ 0x28, 0x0e, 0x32, 0x40, 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
++ 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63,
++ 0x65, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32,
++ 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52,
++ 0x0a, 0x75, 0x32, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x64,
++ 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72,
++ 0x79, 0x52, 0x75, 0x6e, 0x22, 0x5a, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
++ 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x52, 0x65,
++ 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x53, 0x63, 0x72, 0x61, 0x6d, 0x62, 0x6c, 0x65, 0x64, 0x57, 0x6f, 0x72, 0x64, 0x73, 0x10,
++ 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76,
++ 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x10, 0x01,
++ 0x22, 0xc5, 0x01, 0x0a, 0x0b, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
++ 0x12, 0x4e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a,
++ 0x2e, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57,
++ 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x57, 0x6f, 0x72, 0x64, 0x52,
++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
++ 0x22, 0x66, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54,
++ 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
++ 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x00, 0x12, 0x1b,
++ 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x39, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x57,
++ 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d,
++ 0x61, 0x74, 0x72, 0x69, 0x78, 0x36, 0x10, 0x02, 0x22, 0x1d, 0x0a, 0x07, 0x57, 0x6f, 0x72, 0x64,
++ 0x41, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28,
++ 0x09, 0x52, 0x04, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x30, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x55, 0x32,
++ 0x46, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x32, 0x66, 0x5f,
++ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x75,
++ 0x32, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x42, 0x79, 0x0a, 0x23, 0x63, 0x6f, 0x6d,
++ 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74, 0x72, 0x65,
++ 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
++ 0x42, 0x17, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4d,
++ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75,
++ 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67,
++ 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
++ 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72,
++ 0x65, 0x7a, 0x6f, 0x72,
++}
++
++var (
++ file_messages_management_proto_rawDescOnce sync.Once
++ file_messages_management_proto_rawDescData = file_messages_management_proto_rawDesc
++)
++
++func file_messages_management_proto_rawDescGZIP() []byte {
++ file_messages_management_proto_rawDescOnce.Do(func() {
++ file_messages_management_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_management_proto_rawDescData)
++ })
++ return file_messages_management_proto_rawDescData
++}
++
++var file_messages_management_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
++var file_messages_management_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
++var file_messages_management_proto_goTypes = []any{
++ (ApplySettings_PassphraseSourceType)(0), // 0: hw.trezor.messages.management.ApplySettings.PassphraseSourceType
++ (RecoveryDevice_RecoveryDeviceType)(0), // 1: hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType
++ (WordRequest_WordRequestType)(0), // 2: hw.trezor.messages.management.WordRequest.WordRequestType
++ (*Initialize)(nil), // 3: hw.trezor.messages.management.Initialize
++ (*GetFeatures)(nil), // 4: hw.trezor.messages.management.GetFeatures
++ (*Features)(nil), // 5: hw.trezor.messages.management.Features
++ (*ClearSession)(nil), // 6: hw.trezor.messages.management.ClearSession
++ (*ApplySettings)(nil), // 7: hw.trezor.messages.management.ApplySettings
++ (*ApplyFlags)(nil), // 8: hw.trezor.messages.management.ApplyFlags
++ (*ChangePin)(nil), // 9: hw.trezor.messages.management.ChangePin
++ (*Ping)(nil), // 10: hw.trezor.messages.management.Ping
++ (*Cancel)(nil), // 11: hw.trezor.messages.management.Cancel
++ (*GetEntropy)(nil), // 12: hw.trezor.messages.management.GetEntropy
++ (*Entropy)(nil), // 13: hw.trezor.messages.management.Entropy
++ (*WipeDevice)(nil), // 14: hw.trezor.messages.management.WipeDevice
++ (*LoadDevice)(nil), // 15: hw.trezor.messages.management.LoadDevice
++ (*ResetDevice)(nil), // 16: hw.trezor.messages.management.ResetDevice
++ (*BackupDevice)(nil), // 17: hw.trezor.messages.management.BackupDevice
++ (*EntropyRequest)(nil), // 18: hw.trezor.messages.management.EntropyRequest
++ (*EntropyAck)(nil), // 19: hw.trezor.messages.management.EntropyAck
++ (*RecoveryDevice)(nil), // 20: hw.trezor.messages.management.RecoveryDevice
++ (*WordRequest)(nil), // 21: hw.trezor.messages.management.WordRequest
++ (*WordAck)(nil), // 22: hw.trezor.messages.management.WordAck
++ (*SetU2FCounter)(nil), // 23: hw.trezor.messages.management.SetU2FCounter
++ (*HDNodeType)(nil), // 24: hw.trezor.messages.common.HDNodeType
++}
++var file_messages_management_proto_depIdxs = []int32{
++ 0, // 0: hw.trezor.messages.management.ApplySettings.passphrase_source:type_name -> hw.trezor.messages.management.ApplySettings.PassphraseSourceType
++ 24, // 1: hw.trezor.messages.management.LoadDevice.node:type_name -> hw.trezor.messages.common.HDNodeType
++ 1, // 2: hw.trezor.messages.management.RecoveryDevice.type:type_name -> hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType
++ 2, // 3: hw.trezor.messages.management.WordRequest.type:type_name -> hw.trezor.messages.management.WordRequest.WordRequestType
++ 4, // [4:4] is the sub-list for method output_type
++ 4, // [4:4] is the sub-list for method input_type
++ 4, // [4:4] is the sub-list for extension type_name
++ 4, // [4:4] is the sub-list for extension extendee
++ 0, // [0:4] is the sub-list for field type_name
++}
++
++func init() { file_messages_management_proto_init() }
++func file_messages_management_proto_init() {
++ if File_messages_management_proto != nil {
++ return
++ }
++ file_messages_common_proto_init()
++ if !protoimpl.UnsafeEnabled {
++ file_messages_management_proto_msgTypes[0].Exporter = func(v any, i int) any {
++ switch v := v.(*Initialize); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[1].Exporter = func(v any, i int) any {
++ switch v := v.(*GetFeatures); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[2].Exporter = func(v any, i int) any {
++ switch v := v.(*Features); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[3].Exporter = func(v any, i int) any {
++ switch v := v.(*ClearSession); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[4].Exporter = func(v any, i int) any {
++ switch v := v.(*ApplySettings); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[5].Exporter = func(v any, i int) any {
++ switch v := v.(*ApplyFlags); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[6].Exporter = func(v any, i int) any {
++ switch v := v.(*ChangePin); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[7].Exporter = func(v any, i int) any {
++ switch v := v.(*Ping); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[8].Exporter = func(v any, i int) any {
++ switch v := v.(*Cancel); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[9].Exporter = func(v any, i int) any {
++ switch v := v.(*GetEntropy); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[10].Exporter = func(v any, i int) any {
++ switch v := v.(*Entropy); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[11].Exporter = func(v any, i int) any {
++ switch v := v.(*WipeDevice); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[12].Exporter = func(v any, i int) any {
++ switch v := v.(*LoadDevice); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[13].Exporter = func(v any, i int) any {
++ switch v := v.(*ResetDevice); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[14].Exporter = func(v any, i int) any {
++ switch v := v.(*BackupDevice); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[15].Exporter = func(v any, i int) any {
++ switch v := v.(*EntropyRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[16].Exporter = func(v any, i int) any {
++ switch v := v.(*EntropyAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[17].Exporter = func(v any, i int) any {
++ switch v := v.(*RecoveryDevice); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[18].Exporter = func(v any, i int) any {
++ switch v := v.(*WordRequest); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[19].Exporter = func(v any, i int) any {
++ switch v := v.(*WordAck); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ file_messages_management_proto_msgTypes[20].Exporter = func(v any, i int) any {
++ switch v := v.(*SetU2FCounter); i {
++ case 0:
++ return &v.state
++ case 1:
++ return &v.sizeCache
++ case 2:
++ return &v.unknownFields
++ default:
++ return nil
++ }
++ }
++ }
++ type x struct{}
++ out := protoimpl.TypeBuilder{
++ File: protoimpl.DescBuilder{
++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
++ RawDescriptor: file_messages_management_proto_rawDesc,
++ NumEnums: 3,
++ NumMessages: 21,
++ NumExtensions: 0,
++ NumServices: 0,
++ },
++ GoTypes: file_messages_management_proto_goTypes,
++ DependencyIndexes: file_messages_management_proto_depIdxs,
++ EnumInfos: file_messages_management_proto_enumTypes,
++ MessageInfos: file_messages_management_proto_msgTypes,
++ }.Build()
++ File_messages_management_proto = out.File
++ file_messages_management_proto_rawDesc = nil
++ file_messages_management_proto_goTypes = nil
++ file_messages_management_proto_depIdxs = nil
++}
+diff --git a/accounts/usbwallet/messages-management.proto b/accounts/usbwallet/messages-management.proto
+new file mode 100644
+index 0000000000..55eb58983e
+--- /dev/null
++++ b/accounts/usbwallet/messages-management.proto
+@@ -0,0 +1,291 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++syntax = "proto2";
++package hw.trezor.messages.management;
++
++option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
++
++// Sugar for easier handling in Java
++option java_package = "com.satoshilabs.trezor.lib.protobuf";
++option java_outer_classname = "TrezorMessageManagement";
++
++import "messages-common.proto";
++
++/**
++ * Request: Reset device to default state and ask for device details
++ * @start
++ * @next Features
++ */
++message Initialize {
++ optional bytes state = 1; // assumed device state, clear session if set and different
++ optional bool skip_passphrase = 2; // this session should always assume empty passphrase
++}
++
++/**
++ * Request: Ask for device details (no device reset)
++ * @start
++ * @next Features
++ */
++message GetFeatures {
++}
++
++/**
++ * Response: Reports various information about the device
++ * @end
++ */
++message Features {
++ optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io"
++ optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1
++ optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0
++ optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0
++ optional bool bootloader_mode = 5; // is device in bootloader mode?
++ optional string device_id = 6; // device's unique identifier
++ optional bool pin_protection = 7; // is device protected by PIN?
++ optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase?
++ optional string language = 9; // device language
++ optional string label = 10; // device description label
++ optional bool initialized = 12; // does device contain seed?
++ optional bytes revision = 13; // SCM revision of firmware
++ optional bytes bootloader_hash = 14; // hash of the bootloader
++ optional bool imported = 15; // was storage imported from an external source?
++ optional bool pin_cached = 16; // is PIN already cached in session?
++ optional bool passphrase_cached = 17; // is passphrase already cached in session?
++ optional bool firmware_present = 18; // is valid firmware loaded?
++ optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup)
++ optional uint32 flags = 20; // device flags (equals to Storage.flags)
++ optional string model = 21; // device hardware model
++ optional uint32 fw_major = 22; // reported firmware version if in bootloader mode
++ optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode
++ optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode
++ optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode
++ optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash)
++ optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup)
++ optional bool no_backup = 28; // report no backup (equals to Storage.no_backup)
++}
++
++/**
++ * Request: clear session (removes cached PIN, passphrase, etc).
++ * @start
++ * @next Success
++ */
++message ClearSession {
++}
++
++/**
++ * Request: change language and/or label of the device
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message ApplySettings {
++ optional string language = 1;
++ optional string label = 2;
++ optional bool use_passphrase = 3;
++ optional bytes homescreen = 4;
++ optional PassphraseSourceType passphrase_source = 5;
++ optional uint32 auto_lock_delay_ms = 6;
++ optional uint32 display_rotation = 7; // in degrees from North
++ /**
++ * Structure representing passphrase source
++ */
++ enum PassphraseSourceType {
++ ASK = 0;
++ DEVICE = 1;
++ HOST = 2;
++ }
++}
++
++/**
++ * Request: set flags of the device
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message ApplyFlags {
++ optional uint32 flags = 1; // bitmask, can only set bits, not unset
++}
++
++/**
++ * Request: Starts workflow for setting/changing/removing the PIN
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message ChangePin {
++ optional bool remove = 1; // is PIN removal requested?
++}
++
++/**
++ * Request: Test if the device is alive, device sends back the message in Success response
++ * @start
++ * @next Success
++ */
++message Ping {
++ optional string message = 1; // message to send back in Success message
++ optional bool button_protection = 2; // ask for button press
++ optional bool pin_protection = 3; // ask for PIN if set in device
++ optional bool passphrase_protection = 4; // ask for passphrase if set in device
++}
++
++/**
++ * Request: Abort last operation that required user interaction
++ * @start
++ * @next Failure
++ */
++message Cancel {
++}
++
++/**
++ * Request: Request a sample of random data generated by hardware RNG. May be used for testing.
++ * @start
++ * @next Entropy
++ * @next Failure
++ */
++message GetEntropy {
++ required uint32 size = 1; // size of requested entropy
++}
++
++/**
++ * Response: Reply with random data generated by internal RNG
++ * @end
++ */
++message Entropy {
++ required bytes entropy = 1; // chunk of random generated bytes
++}
++
++/**
++ * Request: Request device to wipe all sensitive data and settings
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message WipeDevice {
++}
++
++/**
++ * Request: Load seed and related internal settings from the computer
++ * @start
++ * @next Success
++ * @next Failure
++ */
++message LoadDevice {
++ optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
++ optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node
++ optional string pin = 3; // set PIN protection
++ optional bool passphrase_protection = 4; // enable master node encryption using passphrase
++ optional string language = 5 [default='english']; // device language
++ optional string label = 6; // device label
++ optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum
++ optional uint32 u2f_counter = 8; // U2F counter
++}
++
++/**
++ * Request: Ask device to do initialization involving user interaction
++ * @start
++ * @next EntropyRequest
++ * @next Failure
++ */
++message ResetDevice {
++ optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy
++ optional uint32 strength = 2 [default=256]; // strength of seed in bits
++ optional bool passphrase_protection = 3; // enable master node encryption using passphrase
++ optional bool pin_protection = 4; // enable PIN protection
++ optional string language = 5 [default='english']; // device language
++ optional string label = 6; // device label
++ optional uint32 u2f_counter = 7; // U2F counter
++ optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow
++ optional bool no_backup = 9; // indicate that no backup is going to be made
++}
++
++/**
++ * Request: Perform backup of the device seed if not backed up using ResetDevice
++ * @start
++ * @next Success
++ */
++message BackupDevice {
++}
++
++/**
++ * Response: Ask for additional entropy from host computer
++ * @next EntropyAck
++ */
++message EntropyRequest {
++}
++
++/**
++ * Request: Provide additional entropy for seed generation function
++ * @next Success
++ */
++message EntropyAck {
++ optional bytes entropy = 1; // 256 bits (32 bytes) of random data
++}
++
++/**
++ * Request: Start recovery workflow asking user for specific words of mnemonic
++ * Used to recovery device safely even on untrusted computer.
++ * @start
++ * @next WordRequest
++ */
++message RecoveryDevice {
++ optional uint32 word_count = 1; // number of words in BIP-39 mnemonic
++ optional bool passphrase_protection = 2; // enable master node encryption using passphrase
++ optional bool pin_protection = 3; // enable PIN protection
++ optional string language = 4 [default='english']; // device language
++ optional string label = 5; // device label
++ optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process
++ // 7 reserved for unused recovery method
++ optional RecoveryDeviceType type = 8; // supported recovery type
++ optional uint32 u2f_counter = 9; // U2F counter
++ optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation)
++ /**
++ * Type of recovery procedure. These should be used as bitmask, e.g.,
++ * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
++ * listing every method supported by the host computer.
++ *
++ * Note that ScrambledWords must be supported by every implementation
++ * for backward compatibility; there is no way to not support it.
++ */
++ enum RecoveryDeviceType {
++ // use powers of two when extending this field
++ RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order
++ RecoveryDeviceType_Matrix = 1; // matrix recovery type
++ }
++}
++
++/**
++ * Response: Device is waiting for user to enter word of the mnemonic
++ * Its position is shown only on device's internal display.
++ * @next WordAck
++ */
++message WordRequest {
++ optional WordRequestType type = 1;
++ /**
++ * Type of Recovery Word request
++ */
++ enum WordRequestType {
++ WordRequestType_Plain = 0;
++ WordRequestType_Matrix9 = 1;
++ WordRequestType_Matrix6 = 2;
++ }
++}
++
++/**
++ * Request: Computer replies with word from the mnemonic
++ * @next WordRequest
++ * @next Success
++ * @next Failure
++ */
++message WordAck {
++ required string word = 1; // one word of mnemonic on asked position
++}
++
++/**
++ * Request: Set U2F counter
++ * @start
++ * @next Success
++ */
++message SetU2FCounter {
++ optional uint32 u2f_counter = 1; // counter
++}
+diff --git a/accounts/usbwallet/messages.pb.go b/accounts/usbwallet/messages.pb.go
+new file mode 100644
+index 0000000000..4518db679e
+--- /dev/null
++++ b/accounts/usbwallet/messages.pb.go
+@@ -0,0 +1,1366 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++// Code generated by protoc-gen-go. DO NOT EDIT.
++// versions:
++// protoc-gen-go v1.34.2
++// protoc v5.27.1
++// source: messages.proto
++
++package trezor
++
++import (
++ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
++ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
++ descriptorpb "google.golang.org/protobuf/types/descriptorpb"
++ reflect "reflect"
++ sync "sync"
++)
++
++const (
++ // Verify that this generated code is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
++ // Verify that runtime/protoimpl is sufficiently up-to-date.
++ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
++)
++
++// *
++// Mapping between TREZOR wire identifier (uint) and a protobuf message
++type MessageType int32
++
++const (
++ // Management
++ MessageType_MessageType_Initialize MessageType = 0
++ MessageType_MessageType_Ping MessageType = 1
++ MessageType_MessageType_Success MessageType = 2
++ MessageType_MessageType_Failure MessageType = 3
++ MessageType_MessageType_ChangePin MessageType = 4
++ MessageType_MessageType_WipeDevice MessageType = 5
++ MessageType_MessageType_GetEntropy MessageType = 9
++ MessageType_MessageType_Entropy MessageType = 10
++ MessageType_MessageType_LoadDevice MessageType = 13
++ MessageType_MessageType_ResetDevice MessageType = 14
++ MessageType_MessageType_Features MessageType = 17
++ MessageType_MessageType_PinMatrixRequest MessageType = 18
++ MessageType_MessageType_PinMatrixAck MessageType = 19
++ MessageType_MessageType_Cancel MessageType = 20
++ MessageType_MessageType_ClearSession MessageType = 24
++ MessageType_MessageType_ApplySettings MessageType = 25
++ MessageType_MessageType_ButtonRequest MessageType = 26
++ MessageType_MessageType_ButtonAck MessageType = 27
++ MessageType_MessageType_ApplyFlags MessageType = 28
++ MessageType_MessageType_BackupDevice MessageType = 34
++ MessageType_MessageType_EntropyRequest MessageType = 35
++ MessageType_MessageType_EntropyAck MessageType = 36
++ MessageType_MessageType_PassphraseRequest MessageType = 41
++ MessageType_MessageType_PassphraseAck MessageType = 42
++ MessageType_MessageType_PassphraseStateRequest MessageType = 77
++ MessageType_MessageType_PassphraseStateAck MessageType = 78
++ MessageType_MessageType_RecoveryDevice MessageType = 45
++ MessageType_MessageType_WordRequest MessageType = 46
++ MessageType_MessageType_WordAck MessageType = 47
++ MessageType_MessageType_GetFeatures MessageType = 55
++ MessageType_MessageType_SetU2FCounter MessageType = 63
++ // Bootloader
++ MessageType_MessageType_FirmwareErase MessageType = 6
++ MessageType_MessageType_FirmwareUpload MessageType = 7
++ MessageType_MessageType_FirmwareRequest MessageType = 8
++ MessageType_MessageType_SelfTest MessageType = 32
++ // Bitcoin
++ MessageType_MessageType_GetPublicKey MessageType = 11
++ MessageType_MessageType_PublicKey MessageType = 12
++ MessageType_MessageType_SignTx MessageType = 15
++ MessageType_MessageType_TxRequest MessageType = 21
++ MessageType_MessageType_TxAck MessageType = 22
++ MessageType_MessageType_GetAddress MessageType = 29
++ MessageType_MessageType_Address MessageType = 30
++ MessageType_MessageType_SignMessage MessageType = 38
++ MessageType_MessageType_VerifyMessage MessageType = 39
++ MessageType_MessageType_MessageSignature MessageType = 40
++ // Crypto
++ MessageType_MessageType_CipherKeyValue MessageType = 23
++ MessageType_MessageType_CipheredKeyValue MessageType = 48
++ MessageType_MessageType_SignIdentity MessageType = 53
++ MessageType_MessageType_SignedIdentity MessageType = 54
++ MessageType_MessageType_GetECDHSessionKey MessageType = 61
++ MessageType_MessageType_ECDHSessionKey MessageType = 62
++ MessageType_MessageType_CosiCommit MessageType = 71
++ MessageType_MessageType_CosiCommitment MessageType = 72
++ MessageType_MessageType_CosiSign MessageType = 73
++ MessageType_MessageType_CosiSignature MessageType = 74
++ // Debug
++ MessageType_MessageType_DebugLinkDecision MessageType = 100
++ MessageType_MessageType_DebugLinkGetState MessageType = 101
++ MessageType_MessageType_DebugLinkState MessageType = 102
++ MessageType_MessageType_DebugLinkStop MessageType = 103
++ MessageType_MessageType_DebugLinkLog MessageType = 104
++ MessageType_MessageType_DebugLinkMemoryRead MessageType = 110
++ MessageType_MessageType_DebugLinkMemory MessageType = 111
++ MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112
++ MessageType_MessageType_DebugLinkFlashErase MessageType = 113
++ // Ethereum
++ MessageType_MessageType_EthereumGetPublicKey MessageType = 450
++ MessageType_MessageType_EthereumPublicKey MessageType = 451
++ MessageType_MessageType_EthereumGetAddress MessageType = 56
++ MessageType_MessageType_EthereumAddress MessageType = 57
++ MessageType_MessageType_EthereumSignTx MessageType = 58
++ MessageType_MessageType_EthereumTxRequest MessageType = 59
++ MessageType_MessageType_EthereumTxAck MessageType = 60
++ MessageType_MessageType_EthereumSignMessage MessageType = 64
++ MessageType_MessageType_EthereumVerifyMessage MessageType = 65
++ MessageType_MessageType_EthereumMessageSignature MessageType = 66
++ // NEM
++ MessageType_MessageType_NEMGetAddress MessageType = 67
++ MessageType_MessageType_NEMAddress MessageType = 68
++ MessageType_MessageType_NEMSignTx MessageType = 69
++ MessageType_MessageType_NEMSignedTx MessageType = 70
++ MessageType_MessageType_NEMDecryptMessage MessageType = 75
++ MessageType_MessageType_NEMDecryptedMessage MessageType = 76
++ // Lisk
++ MessageType_MessageType_LiskGetAddress MessageType = 114
++ MessageType_MessageType_LiskAddress MessageType = 115
++ MessageType_MessageType_LiskSignTx MessageType = 116
++ MessageType_MessageType_LiskSignedTx MessageType = 117
++ MessageType_MessageType_LiskSignMessage MessageType = 118
++ MessageType_MessageType_LiskMessageSignature MessageType = 119
++ MessageType_MessageType_LiskVerifyMessage MessageType = 120
++ MessageType_MessageType_LiskGetPublicKey MessageType = 121
++ MessageType_MessageType_LiskPublicKey MessageType = 122
++ // Tezos
++ MessageType_MessageType_TezosGetAddress MessageType = 150
++ MessageType_MessageType_TezosAddress MessageType = 151
++ MessageType_MessageType_TezosSignTx MessageType = 152
++ MessageType_MessageType_TezosSignedTx MessageType = 153
++ MessageType_MessageType_TezosGetPublicKey MessageType = 154
++ MessageType_MessageType_TezosPublicKey MessageType = 155
++ // Stellar
++ MessageType_MessageType_StellarSignTx MessageType = 202
++ MessageType_MessageType_StellarTxOpRequest MessageType = 203
++ MessageType_MessageType_StellarGetAddress MessageType = 207
++ MessageType_MessageType_StellarAddress MessageType = 208
++ MessageType_MessageType_StellarCreateAccountOp MessageType = 210
++ MessageType_MessageType_StellarPaymentOp MessageType = 211
++ MessageType_MessageType_StellarPathPaymentOp MessageType = 212
++ MessageType_MessageType_StellarManageOfferOp MessageType = 213
++ MessageType_MessageType_StellarCreatePassiveOfferOp MessageType = 214
++ MessageType_MessageType_StellarSetOptionsOp MessageType = 215
++ MessageType_MessageType_StellarChangeTrustOp MessageType = 216
++ MessageType_MessageType_StellarAllowTrustOp MessageType = 217
++ MessageType_MessageType_StellarAccountMergeOp MessageType = 218
++ // omitted: StellarInflationOp is not a supported operation, would be 219
++ MessageType_MessageType_StellarManageDataOp MessageType = 220
++ MessageType_MessageType_StellarBumpSequenceOp MessageType = 221
++ MessageType_MessageType_StellarSignedTx MessageType = 230
++ // TRON
++ MessageType_MessageType_TronGetAddress MessageType = 250
++ MessageType_MessageType_TronAddress MessageType = 251
++ MessageType_MessageType_TronSignTx MessageType = 252
++ MessageType_MessageType_TronSignedTx MessageType = 253
++ // Cardano
++ // dropped Sign/VerifyMessage ids 300-302
++ MessageType_MessageType_CardanoSignTx MessageType = 303
++ MessageType_MessageType_CardanoTxRequest MessageType = 304
++ MessageType_MessageType_CardanoGetPublicKey MessageType = 305
++ MessageType_MessageType_CardanoPublicKey MessageType = 306
++ MessageType_MessageType_CardanoGetAddress MessageType = 307
++ MessageType_MessageType_CardanoAddress MessageType = 308
++ MessageType_MessageType_CardanoTxAck MessageType = 309
++ MessageType_MessageType_CardanoSignedTx MessageType = 310
++ // Ontology
++ MessageType_MessageType_OntologyGetAddress MessageType = 350
++ MessageType_MessageType_OntologyAddress MessageType = 351
++ MessageType_MessageType_OntologyGetPublicKey MessageType = 352
++ MessageType_MessageType_OntologyPublicKey MessageType = 353
++ MessageType_MessageType_OntologySignTransfer MessageType = 354
++ MessageType_MessageType_OntologySignedTransfer MessageType = 355
++ MessageType_MessageType_OntologySignWithdrawOng MessageType = 356
++ MessageType_MessageType_OntologySignedWithdrawOng MessageType = 357
++ MessageType_MessageType_OntologySignOntIdRegister MessageType = 358
++ MessageType_MessageType_OntologySignedOntIdRegister MessageType = 359
++ MessageType_MessageType_OntologySignOntIdAddAttributes MessageType = 360
++ MessageType_MessageType_OntologySignedOntIdAddAttributes MessageType = 361
++ // Ripple
++ MessageType_MessageType_RippleGetAddress MessageType = 400
++ MessageType_MessageType_RippleAddress MessageType = 401
++ MessageType_MessageType_RippleSignTx MessageType = 402
++ MessageType_MessageType_RippleSignedTx MessageType = 403
++ // Monero
++ MessageType_MessageType_MoneroTransactionInitRequest MessageType = 501
++ MessageType_MessageType_MoneroTransactionInitAck MessageType = 502
++ MessageType_MessageType_MoneroTransactionSetInputRequest MessageType = 503
++ MessageType_MessageType_MoneroTransactionSetInputAck MessageType = 504
++ MessageType_MessageType_MoneroTransactionInputsPermutationRequest MessageType = 505
++ MessageType_MessageType_MoneroTransactionInputsPermutationAck MessageType = 506
++ MessageType_MessageType_MoneroTransactionInputViniRequest MessageType = 507
++ MessageType_MessageType_MoneroTransactionInputViniAck MessageType = 508
++ MessageType_MessageType_MoneroTransactionAllInputsSetRequest MessageType = 509
++ MessageType_MessageType_MoneroTransactionAllInputsSetAck MessageType = 510
++ MessageType_MessageType_MoneroTransactionSetOutputRequest MessageType = 511
++ MessageType_MessageType_MoneroTransactionSetOutputAck MessageType = 512
++ MessageType_MessageType_MoneroTransactionAllOutSetRequest MessageType = 513
++ MessageType_MessageType_MoneroTransactionAllOutSetAck MessageType = 514
++ MessageType_MessageType_MoneroTransactionSignInputRequest MessageType = 515
++ MessageType_MessageType_MoneroTransactionSignInputAck MessageType = 516
++ MessageType_MessageType_MoneroTransactionFinalRequest MessageType = 517
++ MessageType_MessageType_MoneroTransactionFinalAck MessageType = 518
++ MessageType_MessageType_MoneroKeyImageExportInitRequest MessageType = 530
++ MessageType_MessageType_MoneroKeyImageExportInitAck MessageType = 531
++ MessageType_MessageType_MoneroKeyImageSyncStepRequest MessageType = 532
++ MessageType_MessageType_MoneroKeyImageSyncStepAck MessageType = 533
++ MessageType_MessageType_MoneroKeyImageSyncFinalRequest MessageType = 534
++ MessageType_MessageType_MoneroKeyImageSyncFinalAck MessageType = 535
++ MessageType_MessageType_MoneroGetAddress MessageType = 540
++ MessageType_MessageType_MoneroAddress MessageType = 541
++ MessageType_MessageType_MoneroGetWatchKey MessageType = 542
++ MessageType_MessageType_MoneroWatchKey MessageType = 543
++ MessageType_MessageType_DebugMoneroDiagRequest MessageType = 546
++ MessageType_MessageType_DebugMoneroDiagAck MessageType = 547
++ MessageType_MessageType_MoneroGetTxKeyRequest MessageType = 550
++ MessageType_MessageType_MoneroGetTxKeyAck MessageType = 551
++ MessageType_MessageType_MoneroLiveRefreshStartRequest MessageType = 552
++ MessageType_MessageType_MoneroLiveRefreshStartAck MessageType = 553
++ MessageType_MessageType_MoneroLiveRefreshStepRequest MessageType = 554
++ MessageType_MessageType_MoneroLiveRefreshStepAck MessageType = 555
++ MessageType_MessageType_MoneroLiveRefreshFinalRequest MessageType = 556
++ MessageType_MessageType_MoneroLiveRefreshFinalAck MessageType = 557
++ // EOS
++ MessageType_MessageType_EosGetPublicKey MessageType = 600
++ MessageType_MessageType_EosPublicKey MessageType = 601
++ MessageType_MessageType_EosSignTx MessageType = 602
++ MessageType_MessageType_EosTxActionRequest MessageType = 603
++ MessageType_MessageType_EosTxActionAck MessageType = 604
++ MessageType_MessageType_EosSignedTx MessageType = 605
++ // Binance
++ MessageType_MessageType_BinanceGetAddress MessageType = 700
++ MessageType_MessageType_BinanceAddress MessageType = 701
++ MessageType_MessageType_BinanceGetPublicKey MessageType = 702
++ MessageType_MessageType_BinancePublicKey MessageType = 703
++ MessageType_MessageType_BinanceSignTx MessageType = 704
++ MessageType_MessageType_BinanceTxRequest MessageType = 705
++ MessageType_MessageType_BinanceTransferMsg MessageType = 706
++ MessageType_MessageType_BinanceOrderMsg MessageType = 707
++ MessageType_MessageType_BinanceCancelMsg MessageType = 708
++ MessageType_MessageType_BinanceSignedTx MessageType = 709
++)
++
++// Enum value maps for MessageType.
++var (
++ MessageType_name = map[int32]string{
++ 0: "MessageType_Initialize",
++ 1: "MessageType_Ping",
++ 2: "MessageType_Success",
++ 3: "MessageType_Failure",
++ 4: "MessageType_ChangePin",
++ 5: "MessageType_WipeDevice",
++ 9: "MessageType_GetEntropy",
++ 10: "MessageType_Entropy",
++ 13: "MessageType_LoadDevice",
++ 14: "MessageType_ResetDevice",
++ 17: "MessageType_Features",
++ 18: "MessageType_PinMatrixRequest",
++ 19: "MessageType_PinMatrixAck",
++ 20: "MessageType_Cancel",
++ 24: "MessageType_ClearSession",
++ 25: "MessageType_ApplySettings",
++ 26: "MessageType_ButtonRequest",
++ 27: "MessageType_ButtonAck",
++ 28: "MessageType_ApplyFlags",
++ 34: "MessageType_BackupDevice",
++ 35: "MessageType_EntropyRequest",
++ 36: "MessageType_EntropyAck",
++ 41: "MessageType_PassphraseRequest",
++ 42: "MessageType_PassphraseAck",
++ 77: "MessageType_PassphraseStateRequest",
++ 78: "MessageType_PassphraseStateAck",
++ 45: "MessageType_RecoveryDevice",
++ 46: "MessageType_WordRequest",
++ 47: "MessageType_WordAck",
++ 55: "MessageType_GetFeatures",
++ 63: "MessageType_SetU2FCounter",
++ 6: "MessageType_FirmwareErase",
++ 7: "MessageType_FirmwareUpload",
++ 8: "MessageType_FirmwareRequest",
++ 32: "MessageType_SelfTest",
++ 11: "MessageType_GetPublicKey",
++ 12: "MessageType_PublicKey",
++ 15: "MessageType_SignTx",
++ 21: "MessageType_TxRequest",
++ 22: "MessageType_TxAck",
++ 29: "MessageType_GetAddress",
++ 30: "MessageType_Address",
++ 38: "MessageType_SignMessage",
++ 39: "MessageType_VerifyMessage",
++ 40: "MessageType_MessageSignature",
++ 23: "MessageType_CipherKeyValue",
++ 48: "MessageType_CipheredKeyValue",
++ 53: "MessageType_SignIdentity",
++ 54: "MessageType_SignedIdentity",
++ 61: "MessageType_GetECDHSessionKey",
++ 62: "MessageType_ECDHSessionKey",
++ 71: "MessageType_CosiCommit",
++ 72: "MessageType_CosiCommitment",
++ 73: "MessageType_CosiSign",
++ 74: "MessageType_CosiSignature",
++ 100: "MessageType_DebugLinkDecision",
++ 101: "MessageType_DebugLinkGetState",
++ 102: "MessageType_DebugLinkState",
++ 103: "MessageType_DebugLinkStop",
++ 104: "MessageType_DebugLinkLog",
++ 110: "MessageType_DebugLinkMemoryRead",
++ 111: "MessageType_DebugLinkMemory",
++ 112: "MessageType_DebugLinkMemoryWrite",
++ 113: "MessageType_DebugLinkFlashErase",
++ 450: "MessageType_EthereumGetPublicKey",
++ 451: "MessageType_EthereumPublicKey",
++ 56: "MessageType_EthereumGetAddress",
++ 57: "MessageType_EthereumAddress",
++ 58: "MessageType_EthereumSignTx",
++ 59: "MessageType_EthereumTxRequest",
++ 60: "MessageType_EthereumTxAck",
++ 64: "MessageType_EthereumSignMessage",
++ 65: "MessageType_EthereumVerifyMessage",
++ 66: "MessageType_EthereumMessageSignature",
++ 67: "MessageType_NEMGetAddress",
++ 68: "MessageType_NEMAddress",
++ 69: "MessageType_NEMSignTx",
++ 70: "MessageType_NEMSignedTx",
++ 75: "MessageType_NEMDecryptMessage",
++ 76: "MessageType_NEMDecryptedMessage",
++ 114: "MessageType_LiskGetAddress",
++ 115: "MessageType_LiskAddress",
++ 116: "MessageType_LiskSignTx",
++ 117: "MessageType_LiskSignedTx",
++ 118: "MessageType_LiskSignMessage",
++ 119: "MessageType_LiskMessageSignature",
++ 120: "MessageType_LiskVerifyMessage",
++ 121: "MessageType_LiskGetPublicKey",
++ 122: "MessageType_LiskPublicKey",
++ 150: "MessageType_TezosGetAddress",
++ 151: "MessageType_TezosAddress",
++ 152: "MessageType_TezosSignTx",
++ 153: "MessageType_TezosSignedTx",
++ 154: "MessageType_TezosGetPublicKey",
++ 155: "MessageType_TezosPublicKey",
++ 202: "MessageType_StellarSignTx",
++ 203: "MessageType_StellarTxOpRequest",
++ 207: "MessageType_StellarGetAddress",
++ 208: "MessageType_StellarAddress",
++ 210: "MessageType_StellarCreateAccountOp",
++ 211: "MessageType_StellarPaymentOp",
++ 212: "MessageType_StellarPathPaymentOp",
++ 213: "MessageType_StellarManageOfferOp",
++ 214: "MessageType_StellarCreatePassiveOfferOp",
++ 215: "MessageType_StellarSetOptionsOp",
++ 216: "MessageType_StellarChangeTrustOp",
++ 217: "MessageType_StellarAllowTrustOp",
++ 218: "MessageType_StellarAccountMergeOp",
++ 220: "MessageType_StellarManageDataOp",
++ 221: "MessageType_StellarBumpSequenceOp",
++ 230: "MessageType_StellarSignedTx",
++ 250: "MessageType_TronGetAddress",
++ 251: "MessageType_TronAddress",
++ 252: "MessageType_TronSignTx",
++ 253: "MessageType_TronSignedTx",
++ 303: "MessageType_CardanoSignTx",
++ 304: "MessageType_CardanoTxRequest",
++ 305: "MessageType_CardanoGetPublicKey",
++ 306: "MessageType_CardanoPublicKey",
++ 307: "MessageType_CardanoGetAddress",
++ 308: "MessageType_CardanoAddress",
++ 309: "MessageType_CardanoTxAck",
++ 310: "MessageType_CardanoSignedTx",
++ 350: "MessageType_OntologyGetAddress",
++ 351: "MessageType_OntologyAddress",
++ 352: "MessageType_OntologyGetPublicKey",
++ 353: "MessageType_OntologyPublicKey",
++ 354: "MessageType_OntologySignTransfer",
++ 355: "MessageType_OntologySignedTransfer",
++ 356: "MessageType_OntologySignWithdrawOng",
++ 357: "MessageType_OntologySignedWithdrawOng",
++ 358: "MessageType_OntologySignOntIdRegister",
++ 359: "MessageType_OntologySignedOntIdRegister",
++ 360: "MessageType_OntologySignOntIdAddAttributes",
++ 361: "MessageType_OntologySignedOntIdAddAttributes",
++ 400: "MessageType_RippleGetAddress",
++ 401: "MessageType_RippleAddress",
++ 402: "MessageType_RippleSignTx",
++ 403: "MessageType_RippleSignedTx",
++ 501: "MessageType_MoneroTransactionInitRequest",
++ 502: "MessageType_MoneroTransactionInitAck",
++ 503: "MessageType_MoneroTransactionSetInputRequest",
++ 504: "MessageType_MoneroTransactionSetInputAck",
++ 505: "MessageType_MoneroTransactionInputsPermutationRequest",
++ 506: "MessageType_MoneroTransactionInputsPermutationAck",
++ 507: "MessageType_MoneroTransactionInputViniRequest",
++ 508: "MessageType_MoneroTransactionInputViniAck",
++ 509: "MessageType_MoneroTransactionAllInputsSetRequest",
++ 510: "MessageType_MoneroTransactionAllInputsSetAck",
++ 511: "MessageType_MoneroTransactionSetOutputRequest",
++ 512: "MessageType_MoneroTransactionSetOutputAck",
++ 513: "MessageType_MoneroTransactionAllOutSetRequest",
++ 514: "MessageType_MoneroTransactionAllOutSetAck",
++ 515: "MessageType_MoneroTransactionSignInputRequest",
++ 516: "MessageType_MoneroTransactionSignInputAck",
++ 517: "MessageType_MoneroTransactionFinalRequest",
++ 518: "MessageType_MoneroTransactionFinalAck",
++ 530: "MessageType_MoneroKeyImageExportInitRequest",
++ 531: "MessageType_MoneroKeyImageExportInitAck",
++ 532: "MessageType_MoneroKeyImageSyncStepRequest",
++ 533: "MessageType_MoneroKeyImageSyncStepAck",
++ 534: "MessageType_MoneroKeyImageSyncFinalRequest",
++ 535: "MessageType_MoneroKeyImageSyncFinalAck",
++ 540: "MessageType_MoneroGetAddress",
++ 541: "MessageType_MoneroAddress",
++ 542: "MessageType_MoneroGetWatchKey",
++ 543: "MessageType_MoneroWatchKey",
++ 546: "MessageType_DebugMoneroDiagRequest",
++ 547: "MessageType_DebugMoneroDiagAck",
++ 550: "MessageType_MoneroGetTxKeyRequest",
++ 551: "MessageType_MoneroGetTxKeyAck",
++ 552: "MessageType_MoneroLiveRefreshStartRequest",
++ 553: "MessageType_MoneroLiveRefreshStartAck",
++ 554: "MessageType_MoneroLiveRefreshStepRequest",
++ 555: "MessageType_MoneroLiveRefreshStepAck",
++ 556: "MessageType_MoneroLiveRefreshFinalRequest",
++ 557: "MessageType_MoneroLiveRefreshFinalAck",
++ 600: "MessageType_EosGetPublicKey",
++ 601: "MessageType_EosPublicKey",
++ 602: "MessageType_EosSignTx",
++ 603: "MessageType_EosTxActionRequest",
++ 604: "MessageType_EosTxActionAck",
++ 605: "MessageType_EosSignedTx",
++ 700: "MessageType_BinanceGetAddress",
++ 701: "MessageType_BinanceAddress",
++ 702: "MessageType_BinanceGetPublicKey",
++ 703: "MessageType_BinancePublicKey",
++ 704: "MessageType_BinanceSignTx",
++ 705: "MessageType_BinanceTxRequest",
++ 706: "MessageType_BinanceTransferMsg",
++ 707: "MessageType_BinanceOrderMsg",
++ 708: "MessageType_BinanceCancelMsg",
++ 709: "MessageType_BinanceSignedTx",
++ }
++ MessageType_value = map[string]int32{
++ "MessageType_Initialize": 0,
++ "MessageType_Ping": 1,
++ "MessageType_Success": 2,
++ "MessageType_Failure": 3,
++ "MessageType_ChangePin": 4,
++ "MessageType_WipeDevice": 5,
++ "MessageType_GetEntropy": 9,
++ "MessageType_Entropy": 10,
++ "MessageType_LoadDevice": 13,
++ "MessageType_ResetDevice": 14,
++ "MessageType_Features": 17,
++ "MessageType_PinMatrixRequest": 18,
++ "MessageType_PinMatrixAck": 19,
++ "MessageType_Cancel": 20,
++ "MessageType_ClearSession": 24,
++ "MessageType_ApplySettings": 25,
++ "MessageType_ButtonRequest": 26,
++ "MessageType_ButtonAck": 27,
++ "MessageType_ApplyFlags": 28,
++ "MessageType_BackupDevice": 34,
++ "MessageType_EntropyRequest": 35,
++ "MessageType_EntropyAck": 36,
++ "MessageType_PassphraseRequest": 41,
++ "MessageType_PassphraseAck": 42,
++ "MessageType_PassphraseStateRequest": 77,
++ "MessageType_PassphraseStateAck": 78,
++ "MessageType_RecoveryDevice": 45,
++ "MessageType_WordRequest": 46,
++ "MessageType_WordAck": 47,
++ "MessageType_GetFeatures": 55,
++ "MessageType_SetU2FCounter": 63,
++ "MessageType_FirmwareErase": 6,
++ "MessageType_FirmwareUpload": 7,
++ "MessageType_FirmwareRequest": 8,
++ "MessageType_SelfTest": 32,
++ "MessageType_GetPublicKey": 11,
++ "MessageType_PublicKey": 12,
++ "MessageType_SignTx": 15,
++ "MessageType_TxRequest": 21,
++ "MessageType_TxAck": 22,
++ "MessageType_GetAddress": 29,
++ "MessageType_Address": 30,
++ "MessageType_SignMessage": 38,
++ "MessageType_VerifyMessage": 39,
++ "MessageType_MessageSignature": 40,
++ "MessageType_CipherKeyValue": 23,
++ "MessageType_CipheredKeyValue": 48,
++ "MessageType_SignIdentity": 53,
++ "MessageType_SignedIdentity": 54,
++ "MessageType_GetECDHSessionKey": 61,
++ "MessageType_ECDHSessionKey": 62,
++ "MessageType_CosiCommit": 71,
++ "MessageType_CosiCommitment": 72,
++ "MessageType_CosiSign": 73,
++ "MessageType_CosiSignature": 74,
++ "MessageType_DebugLinkDecision": 100,
++ "MessageType_DebugLinkGetState": 101,
++ "MessageType_DebugLinkState": 102,
++ "MessageType_DebugLinkStop": 103,
++ "MessageType_DebugLinkLog": 104,
++ "MessageType_DebugLinkMemoryRead": 110,
++ "MessageType_DebugLinkMemory": 111,
++ "MessageType_DebugLinkMemoryWrite": 112,
++ "MessageType_DebugLinkFlashErase": 113,
++ "MessageType_EthereumGetPublicKey": 450,
++ "MessageType_EthereumPublicKey": 451,
++ "MessageType_EthereumGetAddress": 56,
++ "MessageType_EthereumAddress": 57,
++ "MessageType_EthereumSignTx": 58,
++ "MessageType_EthereumTxRequest": 59,
++ "MessageType_EthereumTxAck": 60,
++ "MessageType_EthereumSignMessage": 64,
++ "MessageType_EthereumVerifyMessage": 65,
++ "MessageType_EthereumMessageSignature": 66,
++ "MessageType_NEMGetAddress": 67,
++ "MessageType_NEMAddress": 68,
++ "MessageType_NEMSignTx": 69,
++ "MessageType_NEMSignedTx": 70,
++ "MessageType_NEMDecryptMessage": 75,
++ "MessageType_NEMDecryptedMessage": 76,
++ "MessageType_LiskGetAddress": 114,
++ "MessageType_LiskAddress": 115,
++ "MessageType_LiskSignTx": 116,
++ "MessageType_LiskSignedTx": 117,
++ "MessageType_LiskSignMessage": 118,
++ "MessageType_LiskMessageSignature": 119,
++ "MessageType_LiskVerifyMessage": 120,
++ "MessageType_LiskGetPublicKey": 121,
++ "MessageType_LiskPublicKey": 122,
++ "MessageType_TezosGetAddress": 150,
++ "MessageType_TezosAddress": 151,
++ "MessageType_TezosSignTx": 152,
++ "MessageType_TezosSignedTx": 153,
++ "MessageType_TezosGetPublicKey": 154,
++ "MessageType_TezosPublicKey": 155,
++ "MessageType_StellarSignTx": 202,
++ "MessageType_StellarTxOpRequest": 203,
++ "MessageType_StellarGetAddress": 207,
++ "MessageType_StellarAddress": 208,
++ "MessageType_StellarCreateAccountOp": 210,
++ "MessageType_StellarPaymentOp": 211,
++ "MessageType_StellarPathPaymentOp": 212,
++ "MessageType_StellarManageOfferOp": 213,
++ "MessageType_StellarCreatePassiveOfferOp": 214,
++ "MessageType_StellarSetOptionsOp": 215,
++ "MessageType_StellarChangeTrustOp": 216,
++ "MessageType_StellarAllowTrustOp": 217,
++ "MessageType_StellarAccountMergeOp": 218,
++ "MessageType_StellarManageDataOp": 220,
++ "MessageType_StellarBumpSequenceOp": 221,
++ "MessageType_StellarSignedTx": 230,
++ "MessageType_TronGetAddress": 250,
++ "MessageType_TronAddress": 251,
++ "MessageType_TronSignTx": 252,
++ "MessageType_TronSignedTx": 253,
++ "MessageType_CardanoSignTx": 303,
++ "MessageType_CardanoTxRequest": 304,
++ "MessageType_CardanoGetPublicKey": 305,
++ "MessageType_CardanoPublicKey": 306,
++ "MessageType_CardanoGetAddress": 307,
++ "MessageType_CardanoAddress": 308,
++ "MessageType_CardanoTxAck": 309,
++ "MessageType_CardanoSignedTx": 310,
++ "MessageType_OntologyGetAddress": 350,
++ "MessageType_OntologyAddress": 351,
++ "MessageType_OntologyGetPublicKey": 352,
++ "MessageType_OntologyPublicKey": 353,
++ "MessageType_OntologySignTransfer": 354,
++ "MessageType_OntologySignedTransfer": 355,
++ "MessageType_OntologySignWithdrawOng": 356,
++ "MessageType_OntologySignedWithdrawOng": 357,
++ "MessageType_OntologySignOntIdRegister": 358,
++ "MessageType_OntologySignedOntIdRegister": 359,
++ "MessageType_OntologySignOntIdAddAttributes": 360,
++ "MessageType_OntologySignedOntIdAddAttributes": 361,
++ "MessageType_RippleGetAddress": 400,
++ "MessageType_RippleAddress": 401,
++ "MessageType_RippleSignTx": 402,
++ "MessageType_RippleSignedTx": 403,
++ "MessageType_MoneroTransactionInitRequest": 501,
++ "MessageType_MoneroTransactionInitAck": 502,
++ "MessageType_MoneroTransactionSetInputRequest": 503,
++ "MessageType_MoneroTransactionSetInputAck": 504,
++ "MessageType_MoneroTransactionInputsPermutationRequest": 505,
++ "MessageType_MoneroTransactionInputsPermutationAck": 506,
++ "MessageType_MoneroTransactionInputViniRequest": 507,
++ "MessageType_MoneroTransactionInputViniAck": 508,
++ "MessageType_MoneroTransactionAllInputsSetRequest": 509,
++ "MessageType_MoneroTransactionAllInputsSetAck": 510,
++ "MessageType_MoneroTransactionSetOutputRequest": 511,
++ "MessageType_MoneroTransactionSetOutputAck": 512,
++ "MessageType_MoneroTransactionAllOutSetRequest": 513,
++ "MessageType_MoneroTransactionAllOutSetAck": 514,
++ "MessageType_MoneroTransactionSignInputRequest": 515,
++ "MessageType_MoneroTransactionSignInputAck": 516,
++ "MessageType_MoneroTransactionFinalRequest": 517,
++ "MessageType_MoneroTransactionFinalAck": 518,
++ "MessageType_MoneroKeyImageExportInitRequest": 530,
++ "MessageType_MoneroKeyImageExportInitAck": 531,
++ "MessageType_MoneroKeyImageSyncStepRequest": 532,
++ "MessageType_MoneroKeyImageSyncStepAck": 533,
++ "MessageType_MoneroKeyImageSyncFinalRequest": 534,
++ "MessageType_MoneroKeyImageSyncFinalAck": 535,
++ "MessageType_MoneroGetAddress": 540,
++ "MessageType_MoneroAddress": 541,
++ "MessageType_MoneroGetWatchKey": 542,
++ "MessageType_MoneroWatchKey": 543,
++ "MessageType_DebugMoneroDiagRequest": 546,
++ "MessageType_DebugMoneroDiagAck": 547,
++ "MessageType_MoneroGetTxKeyRequest": 550,
++ "MessageType_MoneroGetTxKeyAck": 551,
++ "MessageType_MoneroLiveRefreshStartRequest": 552,
++ "MessageType_MoneroLiveRefreshStartAck": 553,
++ "MessageType_MoneroLiveRefreshStepRequest": 554,
++ "MessageType_MoneroLiveRefreshStepAck": 555,
++ "MessageType_MoneroLiveRefreshFinalRequest": 556,
++ "MessageType_MoneroLiveRefreshFinalAck": 557,
++ "MessageType_EosGetPublicKey": 600,
++ "MessageType_EosPublicKey": 601,
++ "MessageType_EosSignTx": 602,
++ "MessageType_EosTxActionRequest": 603,
++ "MessageType_EosTxActionAck": 604,
++ "MessageType_EosSignedTx": 605,
++ "MessageType_BinanceGetAddress": 700,
++ "MessageType_BinanceAddress": 701,
++ "MessageType_BinanceGetPublicKey": 702,
++ "MessageType_BinancePublicKey": 703,
++ "MessageType_BinanceSignTx": 704,
++ "MessageType_BinanceTxRequest": 705,
++ "MessageType_BinanceTransferMsg": 706,
++ "MessageType_BinanceOrderMsg": 707,
++ "MessageType_BinanceCancelMsg": 708,
++ "MessageType_BinanceSignedTx": 709,
++ }
++)
++
++func (x MessageType) Enum() *MessageType {
++ p := new(MessageType)
++ *p = x
++ return p
++}
++
++func (x MessageType) String() string {
++ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
++}
++
++func (MessageType) Descriptor() protoreflect.EnumDescriptor {
++ return file_messages_proto_enumTypes[0].Descriptor()
++}
++
++func (MessageType) Type() protoreflect.EnumType {
++ return &file_messages_proto_enumTypes[0]
++}
++
++func (x MessageType) Number() protoreflect.EnumNumber {
++ return protoreflect.EnumNumber(x)
++}
++
++// Deprecated: Do not use.
++func (x *MessageType) UnmarshalJSON(b []byte) error {
++ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
++ if err != nil {
++ return err
++ }
++ *x = MessageType(num)
++ return nil
++}
++
++// Deprecated: Use MessageType.Descriptor instead.
++func (MessageType) EnumDescriptor() ([]byte, []int) {
++ return file_messages_proto_rawDescGZIP(), []int{0}
++}
++
++var file_messages_proto_extTypes = []protoimpl.ExtensionInfo{
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50002,
++ Name: "hw.trezor.messages.wire_in",
++ Tag: "varint,50002,opt,name=wire_in",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50003,
++ Name: "hw.trezor.messages.wire_out",
++ Tag: "varint,50003,opt,name=wire_out",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50004,
++ Name: "hw.trezor.messages.wire_debug_in",
++ Tag: "varint,50004,opt,name=wire_debug_in",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50005,
++ Name: "hw.trezor.messages.wire_debug_out",
++ Tag: "varint,50005,opt,name=wire_debug_out",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50006,
++ Name: "hw.trezor.messages.wire_tiny",
++ Tag: "varint,50006,opt,name=wire_tiny",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50007,
++ Name: "hw.trezor.messages.wire_bootloader",
++ Tag: "varint,50007,opt,name=wire_bootloader",
++ Filename: "messages.proto",
++ },
++ {
++ ExtendedType: (*descriptorpb.EnumValueOptions)(nil),
++ ExtensionType: (*bool)(nil),
++ Field: 50008,
++ Name: "hw.trezor.messages.wire_no_fsm",
++ Tag: "varint,50008,opt,name=wire_no_fsm",
++ Filename: "messages.proto",
++ },
++}
++
++// Extension fields to descriptorpb.EnumValueOptions.
++var (
++ // optional bool wire_in = 50002;
++ E_WireIn = &file_messages_proto_extTypes[0] // message can be transmitted via wire from PC to TREZOR
++ // optional bool wire_out = 50003;
++ E_WireOut = &file_messages_proto_extTypes[1] // message can be transmitted via wire from TREZOR to PC
++ // optional bool wire_debug_in = 50004;
++ E_WireDebugIn = &file_messages_proto_extTypes[2] // message can be transmitted via debug wire from PC to TREZOR
++ // optional bool wire_debug_out = 50005;
++ E_WireDebugOut = &file_messages_proto_extTypes[3] // message can be transmitted via debug wire from TREZOR to PC
++ // optional bool wire_tiny = 50006;
++ E_WireTiny = &file_messages_proto_extTypes[4] // message is handled by TREZOR when the USB stack is in tiny mode
++ // optional bool wire_bootloader = 50007;
++ E_WireBootloader = &file_messages_proto_extTypes[5] // message is only handled by TREZOR Bootloader
++ // optional bool wire_no_fsm = 50008;
++ E_WireNoFsm = &file_messages_proto_extTypes[6] // message is not handled by TREZOR unless the USB stack is in tiny mode
++)
++
++var File_messages_proto protoreflect.FileDescriptor
++
++var file_messages_proto_rawDesc = []byte{
++ 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
++ 0x12, 0x12, 0x68, 0x77, 0x2e, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
++ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0xb9, 0x3f, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65,
++ 0x10, 0x00, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x1a, 0x0a, 0x10,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x67,
++ 0x10, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x10,
++ 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x10, 0x03,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x69, 0x6e, 0x10,
++ 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x69, 0x70, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63,
++ 0x65, 0x10, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72,
++ 0x6f, 0x70, 0x79, 0x10, 0x09, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f,
++ 0x70, 0x79, 0x10, 0x0a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x6f, 0x61, 0x64, 0x44, 0x65,
++ 0x76, 0x69, 0x63, 0x65, 0x10, 0x0d, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x65,
++ 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x0e, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
++ 0x1e, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46,
++ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x10, 0x11, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12,
++ 0x26, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50,
++ 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10,
++ 0x12, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78,
++ 0x41, 0x63, 0x6b, 0x10, 0x13, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0,
++ 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x10, 0x14, 0x1a, 0x08, 0x90, 0xb5, 0x18,
++ 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
++ 0x6e, 0x10, 0x18, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x65,
++ 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x10, 0x19, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23,
++ 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x75,
++ 0x74, 0x74, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x1a, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0x1b, 0x1a, 0x0c,
++ 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x70, 0x70, 0x6c,
++ 0x79, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x10, 0x1c, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22,
++ 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x61,
++ 0x63, 0x6b, 0x75, 0x70, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x22, 0x1a, 0x04, 0x90, 0xb5,
++ 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
++ 0x10, 0x23, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79, 0x41,
++ 0x63, 0x6b, 0x10, 0x24, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68,
++ 0x72, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x29, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x41, 0x63, 0x6b,
++ 0x10, 0x2a, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01,
++ 0x12, 0x2c, 0x0a, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
++ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x4d, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30,
++ 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x61,
++ 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x63, 0x6b,
++ 0x10, 0x4e, 0x1a, 0x0c, 0x90, 0xb5, 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01,
++ 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x10, 0x2d,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
++ 0x74, 0x10, 0x2e, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x57, 0x6f, 0x72, 0x64, 0x41, 0x63, 0x6b,
++ 0x10, 0x2f, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75,
++ 0x72, 0x65, 0x73, 0x10, 0x37, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65, 0x74, 0x55, 0x32,
++ 0x46, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x3f, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01,
++ 0x12, 0x27, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x45, 0x72, 0x61, 0x73, 0x65, 0x10, 0x06, 0x1a,
++ 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1a, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72,
++ 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x10, 0x07, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8,
++ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x46, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
++ 0x73, 0x74, 0x10, 0x08, 0x1a, 0x08, 0x98, 0xb5, 0x18, 0x01, 0xb8, 0xb5, 0x18, 0x01, 0x12, 0x22,
++ 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x65,
++ 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x10, 0x20, 0x1a, 0x08, 0x90, 0xb5, 0x18, 0x01, 0xb8, 0xb5,
++ 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x0b,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10,
++ 0x0c, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1c, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x0f, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x15,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1b, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x78, 0x41, 0x63, 0x6b, 0x10, 0x16, 0x1a, 0x04, 0x90,
++ 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x1d, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x1d, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x1e, 0x1a, 0x04,
++ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10,
++ 0x26, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x10, 0x27, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x28, 0x1a, 0x04,
++ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c,
++ 0x75, 0x65, 0x10, 0x17, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72,
++ 0x65, 0x64, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x10, 0x30, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x10, 0x35,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x49, 0x64, 0x65, 0x6e,
++ 0x74, 0x69, 0x74, 0x79, 0x10, 0x36, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x47, 0x65, 0x74, 0x45,
++ 0x43, 0x44, 0x48, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x10, 0x3d, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x43, 0x44, 0x48, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
++ 0x4b, 0x65, 0x79, 0x10, 0x3e, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x43,
++ 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x10, 0x47, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a,
++ 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73,
++ 0x69, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0x48, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x1e, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x10, 0x49, 0x1a, 0x04, 0x90,
++ 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x43, 0x6f, 0x73, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
++ 0x10, 0x4a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2f, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e,
++ 0x6b, 0x44, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0x64, 0x1a, 0x0c, 0xa0, 0xb5, 0x18,
++ 0x01, 0xb0, 0xb5, 0x18, 0x01, 0xc0, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x1d, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69,
++ 0x6e, 0x6b, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x10, 0x65, 0x1a, 0x08, 0xa0, 0xb5,
++ 0x18, 0x01, 0xb0, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x53,
++ 0x74, 0x61, 0x74, 0x65, 0x10, 0x66, 0x1a, 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75,
++ 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x10, 0x67, 0x1a, 0x04, 0xa0, 0xb5, 0x18,
++ 0x01, 0x12, 0x22, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4c, 0x6f, 0x67, 0x10, 0x68, 0x1a,
++ 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65,
++ 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x10, 0x6e, 0x1a, 0x04, 0xa0, 0xb5, 0x18, 0x01,
++ 0x12, 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x10,
++ 0x6f, 0x1a, 0x04, 0xa8, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b,
++ 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x10, 0x70, 0x1a, 0x04, 0xa0,
++ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x46, 0x6c, 0x61, 0x73,
++ 0x68, 0x45, 0x72, 0x61, 0x73, 0x65, 0x10, 0x71, 0x1a, 0x04, 0xa0, 0xb5, 0x18, 0x01, 0x12, 0x2b,
++ 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74,
++ 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
++ 0x65, 0x79, 0x10, 0xc2, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72,
++ 0x65, 0x75, 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xc3, 0x03, 0x1a,
++ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x47, 0x65, 0x74,
++ 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x38, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
++ 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45,
++ 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x39,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x53, 0x69,
++ 0x67, 0x6e, 0x54, 0x78, 0x10, 0x3a, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65,
++ 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x3b, 0x1a,
++ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x41,
++ 0x63, 0x6b, 0x10, 0x3c, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65,
++ 0x75, 0x6d, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x40, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x56, 0x65, 0x72,
++ 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x41, 0x1a, 0x04, 0x90, 0xb5,
++ 0x18, 0x01, 0x12, 0x2e, 0x0a, 0x24, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x42, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10,
++ 0x43, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
++ 0x73, 0x10, 0x44, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x1f, 0x0a, 0x15, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x53, 0x69, 0x67, 0x6e,
++ 0x54, 0x78, 0x10, 0x45, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x53, 0x69, 0x67,
++ 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x46, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a,
++ 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d,
++ 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x4b,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4e, 0x45, 0x4d, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
++ 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10, 0x4c, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x24, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10,
++ 0x72, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65,
++ 0x73, 0x73, 0x10, 0x73, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x20, 0x0a, 0x16, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x53, 0x69,
++ 0x67, 0x6e, 0x54, 0x78, 0x10, 0x74, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x18,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b,
++ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x75, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x25, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4c, 0x69, 0x73, 0x6b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x10,
++ 0x76, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x10, 0x77, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x10, 0x78, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1c,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b,
++ 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x79, 0x1a, 0x04,
++ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x4c, 0x69, 0x73, 0x6b, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
++ 0x79, 0x10, 0x7a, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x47, 0x65,
++ 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x96, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18,
++ 0x01, 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x97, 0x01,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x54,
++ 0x78, 0x10, 0x98, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x53,
++ 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0x99, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
++ 0x79, 0x10, 0x9a, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x65, 0x7a, 0x6f, 0x73, 0x50,
++ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0x9b, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xca,
++ 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x54, 0x78,
++ 0x4f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xcb, 0x01, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72,
++ 0x65, 0x73, 0x73, 0x10, 0xcf, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c,
++ 0x6c, 0x61, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xd0, 0x01, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
++ 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x70, 0x10, 0xd2, 0x01, 0x1a, 0x04, 0x90, 0xb5,
++ 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
++ 0x4f, 0x70, 0x10, 0xd3, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c,
++ 0x61, 0x72, 0x50, 0x61, 0x74, 0x68, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x10,
++ 0xd4, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x4d,
++ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x4f, 0x70, 0x10, 0xd5, 0x01, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a, 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x72, 0x65, 0x61,
++ 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4f, 0x66, 0x66, 0x65, 0x72, 0x4f, 0x70,
++ 0x10, 0xd6, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72,
++ 0x53, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x70, 0x10, 0xd7, 0x01, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x43, 0x68, 0x61, 0x6e,
++ 0x67, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x4f, 0x70, 0x10, 0xd8, 0x01, 0x1a, 0x04, 0x90, 0xb5,
++ 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x72,
++ 0x75, 0x73, 0x74, 0x4f, 0x70, 0x10, 0xd9, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2c,
++ 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74,
++ 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x65, 0x72, 0x67,
++ 0x65, 0x4f, 0x70, 0x10, 0xda, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c,
++ 0x6c, 0x61, 0x72, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4f, 0x70, 0x10,
++ 0xdc, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2c, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x42,
++ 0x75, 0x6d, 0x70, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4f, 0x70, 0x10, 0xdd, 0x01,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x53, 0x69, 0x67,
++ 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xe6, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x25,
++ 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72,
++ 0x6f, 0x6e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xfa, 0x01, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
++ 0x10, 0xfb, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x21, 0x0a, 0x16, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e, 0x53, 0x69, 0x67,
++ 0x6e, 0x54, 0x78, 0x10, 0xfc, 0x01, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x54, 0x72, 0x6f, 0x6e,
++ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xfd, 0x01, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xaf,
++ 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61,
++ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x54, 0x78,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xb0, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
++ 0x4b, 0x65, 0x79, 0x10, 0xb1, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64,
++ 0x61, 0x6e, 0x6f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xb2, 0x02, 0x1a,
++ 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x47, 0x65, 0x74, 0x41,
++ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xb3, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12,
++ 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43,
++ 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xb4, 0x02,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61, 0x6e, 0x6f, 0x54, 0x78, 0x41,
++ 0x63, 0x6b, 0x10, 0xb5, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x61,
++ 0x6e, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xb6, 0x02, 0x1a, 0x04, 0x98,
++ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x47, 0x65, 0x74, 0x41, 0x64,
++ 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xde, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26,
++ 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e,
++ 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xdf, 0x02,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x47, 0x65,
++ 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xe0, 0x02, 0x1a, 0x04, 0x90,
++ 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69,
++ 0x63, 0x4b, 0x65, 0x79, 0x10, 0xe1, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2b, 0x0a,
++ 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74,
++ 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
++ 0x72, 0x10, 0xe2, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f,
++ 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72,
++ 0x10, 0xe3, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2e, 0x0a, 0x23, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67,
++ 0x79, 0x53, 0x69, 0x67, 0x6e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x67,
++ 0x10, 0xe4, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67,
++ 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x4f,
++ 0x6e, 0x67, 0x10, 0xe5, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c,
++ 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x65, 0x67, 0x69,
++ 0x73, 0x74, 0x65, 0x72, 0x10, 0xe6, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a,
++ 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74,
++ 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x74, 0x49, 0x64,
++ 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0xe7, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x35, 0x0a, 0x2a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x4f, 0x6e, 0x74,
++ 0x49, 0x64, 0x41, 0x64, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x10,
++ 0xe8, 0x02, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x37, 0x0a, 0x2c, 0x4d, 0x65, 0x73, 0x73,
++ 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4f, 0x6e, 0x74, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
++ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x6e, 0x74, 0x49, 0x64, 0x41, 0x64, 0x64, 0x41, 0x74,
++ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x10, 0xe9, 0x02, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
++ 0x73, 0x10, 0x90, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65,
++ 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x91, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x23, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0x92, 0x03, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x52, 0x69, 0x70, 0x70, 0x6c, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x65,
++ 0x64, 0x54, 0x78, 0x10, 0x93, 0x03, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
++ 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x69,
++ 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xf5, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x2f, 0x0a, 0x24, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
++ 0x6f, 0x6e, 0x49, 0x6e, 0x69, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xf6, 0x03, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x37, 0x0a, 0x2c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
++ 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
++ 0x73, 0x74, 0x10, 0xf7, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
++ 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x49,
++ 0x6e, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xf8, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x40, 0x0a, 0x35, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69,
++ 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xf9, 0x03, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x3c, 0x0a, 0x31, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
++ 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x75, 0x74, 0x61,
++ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0xfa, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x69, 0x6e, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
++ 0x74, 0x10, 0xfb, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f,
++ 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74,
++ 0x56, 0x69, 0x6e, 0x69, 0x41, 0x63, 0x6b, 0x10, 0xfc, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x3b, 0x0a, 0x30, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x41, 0x6c, 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71,
++ 0x75, 0x65, 0x73, 0x74, 0x10, 0xfd, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x37, 0x0a,
++ 0x2c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e,
++ 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6c,
++ 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x53, 0x65, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xfe, 0x03,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
++ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xff, 0x03, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x53, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x80, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
++ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x53, 0x65, 0x74,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x81, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x41, 0x6c, 0x6c, 0x4f, 0x75, 0x74, 0x53, 0x65, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x82, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x38, 0x0a, 0x2d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
++ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x83, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
++ 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x63, 0x6b, 0x10, 0x84, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e,
++ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75,
++ 0x65, 0x73, 0x74, 0x10, 0x85, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
++ 0x72, 0x6f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6e,
++ 0x61, 0x6c, 0x41, 0x63, 0x6b, 0x10, 0x86, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x36,
++ 0x0a, 0x2b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f,
++ 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x6f,
++ 0x72, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x92, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x32, 0x0a, 0x27, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49,
++ 0x6d, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x41, 0x63,
++ 0x6b, 0x10, 0x93, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f,
++ 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x65, 0x70,
++ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x94, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01,
++ 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79,
++ 0x6e, 0x63, 0x53, 0x74, 0x65, 0x70, 0x41, 0x63, 0x6b, 0x10, 0x95, 0x04, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x12, 0x35, 0x0a, 0x2a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b, 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65,
++ 0x53, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
++ 0x10, 0x96, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x31, 0x0a, 0x26, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4b,
++ 0x65, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x61, 0x6c,
++ 0x41, 0x63, 0x6b, 0x10, 0x97, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
++ 0x72, 0x6f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x9c, 0x04, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65,
++ 0x73, 0x73, 0x10, 0x9d, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
++ 0x6f, 0x47, 0x65, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4b, 0x65, 0x79, 0x10, 0x9e, 0x04, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x57, 0x61, 0x74, 0x63, 0x68,
++ 0x4b, 0x65, 0x79, 0x10, 0x9f, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2d, 0x0a, 0x22,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75,
++ 0x67, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x44, 0x69, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
++ 0x73, 0x74, 0x10, 0xa2, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x44, 0x65, 0x62, 0x75, 0x67,
++ 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x44, 0x69, 0x61, 0x67, 0x41, 0x63, 0x6b, 0x10, 0xa3, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2c, 0x0a, 0x21, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x47, 0x65, 0x74, 0x54,
++ 0x78, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xa6, 0x04, 0x1a, 0x04,
++ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x47, 0x65, 0x74, 0x54, 0x78, 0x4b,
++ 0x65, 0x79, 0x41, 0x63, 0x6b, 0x10, 0xa7, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34,
++ 0x0a, 0x29, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f,
++ 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53,
++ 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xa8, 0x04, 0x1a, 0x04,
++ 0x90, 0xb5, 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65,
++ 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x63, 0x6b, 0x10, 0xa9, 0x04,
++ 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x33, 0x0a, 0x28, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65,
++ 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
++ 0x73, 0x74, 0x10, 0xaa, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x2f, 0x0a, 0x24, 0x4d,
++ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72,
++ 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x53, 0x74, 0x65, 0x70,
++ 0x41, 0x63, 0x6b, 0x10, 0xab, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x34, 0x0a, 0x29,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65,
++ 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x46, 0x69, 0x6e,
++ 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xac, 0x04, 0x1a, 0x04, 0x90, 0xb5,
++ 0x18, 0x01, 0x12, 0x30, 0x0a, 0x25, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
++ 0x65, 0x5f, 0x4d, 0x6f, 0x6e, 0x65, 0x72, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x52, 0x65, 0x66, 0x72,
++ 0x65, 0x73, 0x68, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x41, 0x63, 0x6b, 0x10, 0xad, 0x04, 0x1a, 0x04,
++ 0x98, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54,
++ 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
++ 0x4b, 0x65, 0x79, 0x10, 0xd8, 0x04, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x23, 0x0a, 0x18,
++ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x50,
++ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xd9, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18,
++ 0x01, 0x12, 0x20, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x45, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xda, 0x04, 0x1a, 0x04, 0x90,
++ 0xb5, 0x18, 0x01, 0x12, 0x29, 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x54, 0x78, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xdb, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x25,
++ 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f,
++ 0x73, 0x54, 0x78, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x10, 0xdc, 0x04, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x22, 0x0a, 0x17, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x45, 0x6f, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78,
++ 0x10, 0xdd, 0x04, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x28, 0x0a, 0x1d, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65,
++ 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0xbc, 0x05, 0x1a, 0x04, 0x90,
++ 0xb5, 0x18, 0x01, 0x12, 0x25, 0x0a, 0x1a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79,
++ 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
++ 0x73, 0x10, 0xbd, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x2a, 0x0a, 0x1f, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63,
++ 0x65, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xbe, 0x05,
++ 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
++ 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x50, 0x75, 0x62,
++ 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x10, 0xbf, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12,
++ 0x24, 0x0a, 0x19, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42,
++ 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x78, 0x10, 0xc0, 0x05, 0x1a,
++ 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
++ 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x78, 0x52, 0x65,
++ 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0xc1, 0x05, 0x1a, 0x04, 0x98, 0xb5, 0x18, 0x01, 0x12, 0x29,
++ 0x0a, 0x1e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69,
++ 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x73, 0x67,
++ 0x10, 0xc2, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65, 0x73,
++ 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65,
++ 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x10, 0xc3, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18,
++ 0x01, 0x12, 0x27, 0x0a, 0x1c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65,
++ 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4d, 0x73,
++ 0x67, 0x10, 0xc4, 0x05, 0x1a, 0x04, 0x90, 0xb5, 0x18, 0x01, 0x12, 0x26, 0x0a, 0x1b, 0x4d, 0x65,
++ 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x42, 0x69, 0x6e, 0x61, 0x6e, 0x63,
++ 0x65, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x10, 0xc5, 0x05, 0x1a, 0x04, 0x98, 0xb5,
++ 0x18, 0x01, 0x3a, 0x3c, 0x0a, 0x07, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x69, 0x6e, 0x12, 0x21, 0x2e,
++ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
++ 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
++ 0x18, 0xd2, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x77, 0x69, 0x72, 0x65, 0x49, 0x6e,
++ 0x3a, 0x3e, 0x0a, 0x08, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x12, 0x21, 0x2e, 0x67,
++ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
++ 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
++ 0xd3, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x77, 0x69, 0x72, 0x65, 0x4f, 0x75, 0x74,
++ 0x3a, 0x47, 0x0a, 0x0d, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69,
++ 0x6e, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
++ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74,
++ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd4, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x77, 0x69,
++ 0x72, 0x65, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x3a, 0x49, 0x0a, 0x0e, 0x77, 0x69, 0x72,
++ 0x65, 0x5f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x12, 0x21, 0x2e, 0x67, 0x6f,
++ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
++ 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd5,
++ 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x77, 0x69, 0x72, 0x65, 0x44, 0x65, 0x62, 0x75,
++ 0x67, 0x4f, 0x75, 0x74, 0x3a, 0x40, 0x0a, 0x09, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6e,
++ 0x79, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
++ 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74,
++ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd6, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x69,
++ 0x72, 0x65, 0x54, 0x69, 0x6e, 0x79, 0x3a, 0x4c, 0x0a, 0x0f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x62,
++ 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
++ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
++ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd7, 0x86, 0x03,
++ 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x77, 0x69, 0x72, 0x65, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f,
++ 0x61, 0x64, 0x65, 0x72, 0x3a, 0x43, 0x0a, 0x0b, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x6e, 0x6f, 0x5f,
++ 0x66, 0x73, 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
++ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f,
++ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd8, 0x86, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
++ 0x77, 0x69, 0x72, 0x65, 0x4e, 0x6f, 0x46, 0x73, 0x6d, 0x42, 0x6f, 0x0a, 0x23, 0x63, 0x6f, 0x6d,
++ 0x2e, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x74, 0x72, 0x65,
++ 0x7a, 0x6f, 0x72, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
++ 0x42, 0x0d, 0x54, 0x72, 0x65, 0x7a, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5a,
++ 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65,
++ 0x72, 0x65, 0x75, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
++ 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x75, 0x73, 0x62, 0x77, 0x61, 0x6c,
++ 0x6c, 0x65, 0x74, 0x2f, 0x74, 0x72, 0x65, 0x7a, 0x6f, 0x72,
++}
++
++var (
++ file_messages_proto_rawDescOnce sync.Once
++ file_messages_proto_rawDescData = file_messages_proto_rawDesc
++)
++
++func file_messages_proto_rawDescGZIP() []byte {
++ file_messages_proto_rawDescOnce.Do(func() {
++ file_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_proto_rawDescData)
++ })
++ return file_messages_proto_rawDescData
++}
++
++var file_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
++var file_messages_proto_goTypes = []any{
++ (MessageType)(0), // 0: hw.trezor.messages.MessageType
++ (*descriptorpb.EnumValueOptions)(nil), // 1: google.protobuf.EnumValueOptions
++}
++var file_messages_proto_depIdxs = []int32{
++ 1, // 0: hw.trezor.messages.wire_in:extendee -> google.protobuf.EnumValueOptions
++ 1, // 1: hw.trezor.messages.wire_out:extendee -> google.protobuf.EnumValueOptions
++ 1, // 2: hw.trezor.messages.wire_debug_in:extendee -> google.protobuf.EnumValueOptions
++ 1, // 3: hw.trezor.messages.wire_debug_out:extendee -> google.protobuf.EnumValueOptions
++ 1, // 4: hw.trezor.messages.wire_tiny:extendee -> google.protobuf.EnumValueOptions
++ 1, // 5: hw.trezor.messages.wire_bootloader:extendee -> google.protobuf.EnumValueOptions
++ 1, // 6: hw.trezor.messages.wire_no_fsm:extendee -> google.protobuf.EnumValueOptions
++ 7, // [7:7] is the sub-list for method output_type
++ 7, // [7:7] is the sub-list for method input_type
++ 7, // [7:7] is the sub-list for extension type_name
++ 0, // [0:7] is the sub-list for extension extendee
++ 0, // [0:0] is the sub-list for field type_name
++}
++
++func init() { file_messages_proto_init() }
++func file_messages_proto_init() {
++ if File_messages_proto != nil {
++ return
++ }
++ type x struct{}
++ out := protoimpl.TypeBuilder{
++ File: protoimpl.DescBuilder{
++ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
++ RawDescriptor: file_messages_proto_rawDesc,
++ NumEnums: 1,
++ NumMessages: 0,
++ NumExtensions: 7,
++ NumServices: 0,
++ },
++ GoTypes: file_messages_proto_goTypes,
++ DependencyIndexes: file_messages_proto_depIdxs,
++ EnumInfos: file_messages_proto_enumTypes,
++ ExtensionInfos: file_messages_proto_extTypes,
++ }.Build()
++ File_messages_proto = out.File
++ file_messages_proto_rawDesc = nil
++ file_messages_proto_goTypes = nil
++ file_messages_proto_depIdxs = nil
++}
+diff --git a/accounts/usbwallet/messages.proto b/accounts/usbwallet/messages.proto
+new file mode 100644
+index 0000000000..c232bef60d
+--- /dev/null
++++ b/accounts/usbwallet/messages.proto
+@@ -0,0 +1,267 @@
++// This file originates from the SatoshiLabs Trezor `common` repository at:
++// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
++// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
++
++syntax = "proto2";
++package hw.trezor.messages;
++
++/**
++ * Messages for TREZOR communication
++ */
++
++option go_package = "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor";
++
++// Sugar for easier handling in Java
++option java_package = "com.satoshilabs.trezor.lib.protobuf";
++option java_outer_classname = "TrezorMessage";
++
++
++import "google/protobuf/descriptor.proto";
++
++/**
++ * Options for specifying message direction and type of wire (normal/debug)
++ */
++extend google.protobuf.EnumValueOptions {
++ optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR
++ optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC
++ optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR
++ optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC
++ optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode
++ optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader
++ optional bool wire_no_fsm = 50008; // message is not handled by TREZOR unless the USB stack is in tiny mode
++}
++
++/**
++ * Mapping between TREZOR wire identifier (uint) and a protobuf message
++ */
++enum MessageType {
++
++ // Management
++ MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = true];
++ MessageType_Ping = 1 [(wire_in) = true];
++ MessageType_Success = 2 [(wire_out) = true];
++ MessageType_Failure = 3 [(wire_out) = true];
++ MessageType_ChangePin = 4 [(wire_in) = true];
++ MessageType_WipeDevice = 5 [(wire_in) = true];
++ MessageType_GetEntropy = 9 [(wire_in) = true];
++ MessageType_Entropy = 10 [(wire_out) = true];
++ MessageType_LoadDevice = 13 [(wire_in) = true];
++ MessageType_ResetDevice = 14 [(wire_in) = true];
++ MessageType_Features = 17 [(wire_out) = true];
++ MessageType_PinMatrixRequest = 18 [(wire_out) = true];
++ MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
++ MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true];
++ MessageType_ClearSession = 24 [(wire_in) = true];
++ MessageType_ApplySettings = 25 [(wire_in) = true];
++ MessageType_ButtonRequest = 26 [(wire_out) = true];
++ MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
++ MessageType_ApplyFlags = 28 [(wire_in) = true];
++ MessageType_BackupDevice = 34 [(wire_in) = true];
++ MessageType_EntropyRequest = 35 [(wire_out) = true];
++ MessageType_EntropyAck = 36 [(wire_in) = true];
++ MessageType_PassphraseRequest = 41 [(wire_out) = true];
++ MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
++ MessageType_PassphraseStateRequest = 77 [(wire_out) = true];
++ MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
++ MessageType_RecoveryDevice = 45 [(wire_in) = true];
++ MessageType_WordRequest = 46 [(wire_out) = true];
++ MessageType_WordAck = 47 [(wire_in) = true];
++ MessageType_GetFeatures = 55 [(wire_in) = true];
++ MessageType_SetU2FCounter = 63 [(wire_in) = true];
++
++ // Bootloader
++ MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true];
++ MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true];
++ MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true];
++ MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true];
++
++ // Bitcoin
++ MessageType_GetPublicKey = 11 [(wire_in) = true];
++ MessageType_PublicKey = 12 [(wire_out) = true];
++ MessageType_SignTx = 15 [(wire_in) = true];
++ MessageType_TxRequest = 21 [(wire_out) = true];
++ MessageType_TxAck = 22 [(wire_in) = true];
++ MessageType_GetAddress = 29 [(wire_in) = true];
++ MessageType_Address = 30 [(wire_out) = true];
++ MessageType_SignMessage = 38 [(wire_in) = true];
++ MessageType_VerifyMessage = 39 [(wire_in) = true];
++ MessageType_MessageSignature = 40 [(wire_out) = true];
++
++ // Crypto
++ MessageType_CipherKeyValue = 23 [(wire_in) = true];
++ MessageType_CipheredKeyValue = 48 [(wire_out) = true];
++ MessageType_SignIdentity = 53 [(wire_in) = true];
++ MessageType_SignedIdentity = 54 [(wire_out) = true];
++ MessageType_GetECDHSessionKey = 61 [(wire_in) = true];
++ MessageType_ECDHSessionKey = 62 [(wire_out) = true];
++ MessageType_CosiCommit = 71 [(wire_in) = true];
++ MessageType_CosiCommitment = 72 [(wire_out) = true];
++ MessageType_CosiSign = 73 [(wire_in) = true];
++ MessageType_CosiSignature = 74 [(wire_out) = true];
++
++ // Debug
++ MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
++ MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = true];
++ MessageType_DebugLinkState = 102 [(wire_debug_out) = true];
++ MessageType_DebugLinkStop = 103 [(wire_debug_in) = true];
++ MessageType_DebugLinkLog = 104 [(wire_debug_out) = true];
++ MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true];
++ MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true];
++ MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true];
++ MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true];
++
++ // Ethereum
++ MessageType_EthereumGetPublicKey = 450 [(wire_in) = true];
++ MessageType_EthereumPublicKey = 451 [(wire_out) = true];
++ MessageType_EthereumGetAddress = 56 [(wire_in) = true];
++ MessageType_EthereumAddress = 57 [(wire_out) = true];
++ MessageType_EthereumSignTx = 58 [(wire_in) = true];
++ MessageType_EthereumTxRequest = 59 [(wire_out) = true];
++ MessageType_EthereumTxAck = 60 [(wire_in) = true];
++ MessageType_EthereumSignMessage = 64 [(wire_in) = true];
++ MessageType_EthereumVerifyMessage = 65 [(wire_in) = true];
++ MessageType_EthereumMessageSignature = 66 [(wire_out) = true];
++
++ // NEM
++ MessageType_NEMGetAddress = 67 [(wire_in) = true];
++ MessageType_NEMAddress = 68 [(wire_out) = true];
++ MessageType_NEMSignTx = 69 [(wire_in) = true];
++ MessageType_NEMSignedTx = 70 [(wire_out) = true];
++ MessageType_NEMDecryptMessage = 75 [(wire_in) = true];
++ MessageType_NEMDecryptedMessage = 76 [(wire_out) = true];
++
++ // Lisk
++ MessageType_LiskGetAddress = 114 [(wire_in) = true];
++ MessageType_LiskAddress = 115 [(wire_out) = true];
++ MessageType_LiskSignTx = 116 [(wire_in) = true];
++ MessageType_LiskSignedTx = 117 [(wire_out) = true];
++ MessageType_LiskSignMessage = 118 [(wire_in) = true];
++ MessageType_LiskMessageSignature = 119 [(wire_out) = true];
++ MessageType_LiskVerifyMessage = 120 [(wire_in) = true];
++ MessageType_LiskGetPublicKey = 121 [(wire_in) = true];
++ MessageType_LiskPublicKey = 122 [(wire_out) = true];
++
++ // Tezos
++ MessageType_TezosGetAddress = 150 [(wire_in) = true];
++ MessageType_TezosAddress = 151 [(wire_out) = true];
++ MessageType_TezosSignTx = 152 [(wire_in) = true];
++ MessageType_TezosSignedTx = 153 [(wire_out) = true];
++ MessageType_TezosGetPublicKey = 154 [(wire_in) = true];
++ MessageType_TezosPublicKey = 155 [(wire_out) = true];
++
++ // Stellar
++ MessageType_StellarSignTx = 202 [(wire_in) = true];
++ MessageType_StellarTxOpRequest = 203 [(wire_out) = true];
++ MessageType_StellarGetAddress = 207 [(wire_in) = true];
++ MessageType_StellarAddress = 208 [(wire_out) = true];
++ MessageType_StellarCreateAccountOp = 210 [(wire_in) = true];
++ MessageType_StellarPaymentOp = 211 [(wire_in) = true];
++ MessageType_StellarPathPaymentOp = 212 [(wire_in) = true];
++ MessageType_StellarManageOfferOp = 213 [(wire_in) = true];
++ MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true];
++ MessageType_StellarSetOptionsOp = 215 [(wire_in) = true];
++ MessageType_StellarChangeTrustOp = 216 [(wire_in) = true];
++ MessageType_StellarAllowTrustOp = 217 [(wire_in) = true];
++ MessageType_StellarAccountMergeOp = 218 [(wire_in) = true];
++ // omitted: StellarInflationOp is not a supported operation, would be 219
++ MessageType_StellarManageDataOp = 220 [(wire_in) = true];
++ MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true];
++ MessageType_StellarSignedTx = 230 [(wire_out) = true];
++
++ // TRON
++ MessageType_TronGetAddress = 250 [(wire_in) = true];
++ MessageType_TronAddress = 251 [(wire_out) = true];
++ MessageType_TronSignTx = 252 [(wire_in) = true];
++ MessageType_TronSignedTx = 253 [(wire_out) = true];
++
++ // Cardano
++ // dropped Sign/VerifyMessage ids 300-302
++ MessageType_CardanoSignTx = 303 [(wire_in) = true];
++ MessageType_CardanoTxRequest = 304 [(wire_out) = true];
++ MessageType_CardanoGetPublicKey = 305 [(wire_in) = true];
++ MessageType_CardanoPublicKey = 306 [(wire_out) = true];
++ MessageType_CardanoGetAddress = 307 [(wire_in) = true];
++ MessageType_CardanoAddress = 308 [(wire_out) = true];
++ MessageType_CardanoTxAck = 309 [(wire_in) = true];
++ MessageType_CardanoSignedTx = 310 [(wire_out) = true];
++
++ // Ontology
++ MessageType_OntologyGetAddress = 350 [(wire_in) = true];
++ MessageType_OntologyAddress = 351 [(wire_out) = true];
++ MessageType_OntologyGetPublicKey = 352 [(wire_in) = true];
++ MessageType_OntologyPublicKey = 353 [(wire_out) = true];
++ MessageType_OntologySignTransfer = 354 [(wire_in) = true];
++ MessageType_OntologySignedTransfer = 355 [(wire_out) = true];
++ MessageType_OntologySignWithdrawOng = 356 [(wire_in) = true];
++ MessageType_OntologySignedWithdrawOng = 357 [(wire_out) = true];
++ MessageType_OntologySignOntIdRegister = 358 [(wire_in) = true];
++ MessageType_OntologySignedOntIdRegister = 359 [(wire_out) = true];
++ MessageType_OntologySignOntIdAddAttributes = 360 [(wire_in) = true];
++ MessageType_OntologySignedOntIdAddAttributes = 361 [(wire_out) = true];
++
++ // Ripple
++ MessageType_RippleGetAddress = 400 [(wire_in) = true];
++ MessageType_RippleAddress = 401 [(wire_out) = true];
++ MessageType_RippleSignTx = 402 [(wire_in) = true];
++ MessageType_RippleSignedTx = 403 [(wire_in) = true];
++
++ // Monero
++ MessageType_MoneroTransactionInitRequest = 501 [(wire_out) = true];
++ MessageType_MoneroTransactionInitAck = 502 [(wire_out) = true];
++ MessageType_MoneroTransactionSetInputRequest = 503 [(wire_out) = true];
++ MessageType_MoneroTransactionSetInputAck = 504 [(wire_out) = true];
++ MessageType_MoneroTransactionInputsPermutationRequest = 505 [(wire_out) = true];
++ MessageType_MoneroTransactionInputsPermutationAck = 506 [(wire_out) = true];
++ MessageType_MoneroTransactionInputViniRequest = 507 [(wire_out) = true];
++ MessageType_MoneroTransactionInputViniAck = 508 [(wire_out) = true];
++ MessageType_MoneroTransactionAllInputsSetRequest = 509 [(wire_out) = true];
++ MessageType_MoneroTransactionAllInputsSetAck = 510 [(wire_out) = true];
++ MessageType_MoneroTransactionSetOutputRequest = 511 [(wire_out) = true];
++ MessageType_MoneroTransactionSetOutputAck = 512 [(wire_out) = true];
++ MessageType_MoneroTransactionAllOutSetRequest = 513 [(wire_out) = true];
++ MessageType_MoneroTransactionAllOutSetAck = 514 [(wire_out) = true];
++ MessageType_MoneroTransactionSignInputRequest = 515 [(wire_out) = true];
++ MessageType_MoneroTransactionSignInputAck = 516 [(wire_out) = true];
++ MessageType_MoneroTransactionFinalRequest = 517 [(wire_out) = true];
++ MessageType_MoneroTransactionFinalAck = 518 [(wire_out) = true];
++ MessageType_MoneroKeyImageExportInitRequest = 530 [(wire_out) = true];
++ MessageType_MoneroKeyImageExportInitAck = 531 [(wire_out) = true];
++ MessageType_MoneroKeyImageSyncStepRequest = 532 [(wire_out) = true];
++ MessageType_MoneroKeyImageSyncStepAck = 533 [(wire_out) = true];
++ MessageType_MoneroKeyImageSyncFinalRequest = 534 [(wire_out) = true];
++ MessageType_MoneroKeyImageSyncFinalAck = 535 [(wire_out) = true];
++ MessageType_MoneroGetAddress = 540 [(wire_in) = true];
++ MessageType_MoneroAddress = 541 [(wire_out) = true];
++ MessageType_MoneroGetWatchKey = 542 [(wire_in) = true];
++ MessageType_MoneroWatchKey = 543 [(wire_out) = true];
++ MessageType_DebugMoneroDiagRequest = 546 [(wire_in) = true];
++ MessageType_DebugMoneroDiagAck = 547 [(wire_out) = true];
++ MessageType_MoneroGetTxKeyRequest = 550 [(wire_in) = true];
++ MessageType_MoneroGetTxKeyAck = 551 [(wire_out) = true];
++ MessageType_MoneroLiveRefreshStartRequest = 552 [(wire_in) = true];
++ MessageType_MoneroLiveRefreshStartAck = 553 [(wire_out) = true];
++ MessageType_MoneroLiveRefreshStepRequest = 554 [(wire_in) = true];
++ MessageType_MoneroLiveRefreshStepAck = 555 [(wire_out) = true];
++ MessageType_MoneroLiveRefreshFinalRequest = 556 [(wire_in) = true];
++ MessageType_MoneroLiveRefreshFinalAck = 557 [(wire_out) = true];
++
++ // EOS
++ MessageType_EosGetPublicKey = 600 [(wire_in) = true];
++ MessageType_EosPublicKey = 601 [(wire_out) = true];
++ MessageType_EosSignTx = 602 [(wire_in) = true];
++ MessageType_EosTxActionRequest = 603 [(wire_out) = true];
++ MessageType_EosTxActionAck = 604 [(wire_in) = true];
++ MessageType_EosSignedTx = 605 [(wire_out) = true];
++
++ // Binance
++ MessageType_BinanceGetAddress = 700 [(wire_in) = true];
++ MessageType_BinanceAddress = 701 [(wire_out) = true];
++ MessageType_BinanceGetPublicKey = 702 [(wire_in) = true];
++ MessageType_BinancePublicKey = 703 [(wire_out) = true];
++ MessageType_BinanceSignTx = 704 [(wire_in) = true];
++ MessageType_BinanceTxRequest = 705 [(wire_out) = true];
++ MessageType_BinanceTransferMsg = 706 [(wire_in) = true];
++ MessageType_BinanceOrderMsg = 707 [(wire_in) = true];
++ MessageType_BinanceCancelMsg = 708 [(wire_in) = true];
++ MessageType_BinanceSignedTx = 709 [(wire_out) = true];
++}
+diff --git a/accounts/usbwallet/trezor/trezor.go b/accounts/usbwallet/trezor/trezor.go
+deleted file mode 100644
+index 93aee3c289..0000000000
+--- a/accounts/usbwallet/trezor/trezor.go
++++ /dev/null
+@@ -1,70 +0,0 @@
+-// Copyright 2017 The go-ethereum Authors
+-// This file is part of the go-ethereum library.
+-//
+-// The go-ethereum library is free software: you can redistribute it and/or modify
+-// it under the terms of the GNU Lesser General Public License as published by
+-// the Free Software Foundation, either version 3 of the License, or
+-// (at your option) any later version.
+-//
+-// The go-ethereum library is distributed in the hope that it will be useful,
+-// but WITHOUT ANY WARRANTY; without even the implied warranty of
+-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-// GNU Lesser General Public License for more details.
+-//
+-// You should have received a copy of the GNU Lesser General Public License
+-// along with the go-ethereum library. If not, see .
+-
+-// This file contains the implementation for interacting with the Trezor hardware
+-// wallets. The wire protocol spec can be found on the SatoshiLabs website:
+-// https://docs.trezor.io/trezor-firmware/common/message-workflows.html
+-
+-// !!! STAHP !!!
+-//
+-// Before you touch the protocol files, you need to be aware of a breaking change
+-// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10->
+-// 2.1.0 (Model T). The Ethereum address representation was changed from the 20
+-// byte binary blob to a 42 byte hex string. The upstream protocol buffer files
+-// only support the new format, so blindly pulling in a new spec will break old
+-// devices!
+-//
+-// The Trezor devs had the foresight to add the string version as a new message
+-// code instead of replacing the binary one. This means that the proto file can
+-// actually define both the old and the new versions as optional. Please ensure
+-// that you add back the old addresses everywhere (to avoid name clash. use the
+-// addressBin and addressHex names).
+-//
+-// If in doubt, reach out to @karalabe.
+-
+-// To regenerate the protocol files in this package:
+-// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
+-// - Build with the usual `./configure && make` and ensure it's on your $PATH
+-// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
+-// - Grab the latest Go plugin `go get -u google.golang.org/protobuf/cmd/protoc-gen-go`
+-// - Vendor in the latest Go plugin `govendor fetch google.golang.org/protobuf/...`
+-
+-//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
+-
+-// Package trezor contains the wire protocol.
+-package trezor
+-
+-import (
+- "reflect"
+-
+- "google.golang.org/protobuf/proto"
+-)
+-
+-// Type returns the protocol buffer type number of a specific message. If the
+-// message is nil, this method panics!
+-func Type(msg proto.Message) uint16 {
+- return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()])
+-}
+-
+-// Name returns the friendly message type name of a specific protocol buffer
+-// type number.
+-func Name(kind uint16) string {
+- name := MessageType_name[int32(kind)]
+- if len(name) < 12 {
+- return name
+- }
+- return name[12:]
+-}
+diff --git a/accounts/usbwallet/trezor.go b/accounts/usbwallet/trezor.go
+index d4862d161b..93aee3c289 100644
+--- a/accounts/usbwallet/trezor.go
++++ b/accounts/usbwallet/trezor.go
+@@ -16,365 +16,55 @@
+
+ // This file contains the implementation for interacting with the Trezor hardware
+ // wallets. The wire protocol spec can be found on the SatoshiLabs website:
+-// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
+-
+-package usbwallet
++// https://docs.trezor.io/trezor-firmware/common/message-workflows.html
++
++// !!! STAHP !!!
++//
++// Before you touch the protocol files, you need to be aware of a breaking change
++// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10->
++// 2.1.0 (Model T). The Ethereum address representation was changed from the 20
++// byte binary blob to a 42 byte hex string. The upstream protocol buffer files
++// only support the new format, so blindly pulling in a new spec will break old
++// devices!
++//
++// The Trezor devs had the foresight to add the string version as a new message
++// code instead of replacing the binary one. This means that the proto file can
++// actually define both the old and the new versions as optional. Please ensure
++// that you add back the old addresses everywhere (to avoid name clash. use the
++// addressBin and addressHex names).
++//
++// If in doubt, reach out to @karalabe.
++
++// To regenerate the protocol files in this package:
++// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
++// - Build with the usual `./configure && make` and ensure it's on your $PATH
++// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
++// - Grab the latest Go plugin `go get -u google.golang.org/protobuf/cmd/protoc-gen-go`
++// - Vendor in the latest Go plugin `govendor fetch google.golang.org/protobuf/...`
++
++//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
++
++// Package trezor contains the wire protocol.
++package trezor
+
+ import (
+- "encoding/binary"
+- "errors"
+- "fmt"
+- "io"
+- "math"
+- "math/big"
++ "reflect"
+
+- "github.com/ethereum/go-ethereum/accounts"
+- "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor"
+- "github.com/ethereum/go-ethereum/common"
+- "github.com/ethereum/go-ethereum/common/hexutil"
+- "github.com/ethereum/go-ethereum/core/types"
+- "github.com/ethereum/go-ethereum/log"
+ "google.golang.org/protobuf/proto"
+ )
+
+-// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In
+-// this case, the calling application should display a pinpad and send back the
+-// encoded passphrase.
+-var ErrTrezorPINNeeded = errors.New("trezor: pin needed")
+-
+-// ErrTrezorPassphraseNeeded is returned if opening the trezor requires a passphrase
+-var ErrTrezorPassphraseNeeded = errors.New("trezor: passphrase needed")
+-
+-// errTrezorReplyInvalidHeader is the error message returned by a Trezor data exchange
+-// if the device replies with a mismatching header. This usually means the device
+-// is in browser mode.
+-var errTrezorReplyInvalidHeader = errors.New("trezor: invalid reply header")
+-
+-// trezorDriver implements the communication with a Trezor hardware wallet.
+-type trezorDriver struct {
+- device io.ReadWriter // USB device connection to communicate through
+- version [3]uint32 // Current version of the Trezor firmware
+- label string // Current textual label of the Trezor device
+- pinwait bool // Flags whether the device is waiting for PIN entry
+- passphrasewait bool // Flags whether the device is waiting for passphrase entry
+- failure error // Any failure that would make the device unusable
+- log log.Logger // Contextual logger to tag the trezor with its id
+-}
+-
+-// newTrezorDriver creates a new instance of a Trezor USB protocol driver.
+-func newTrezorDriver(logger log.Logger) driver {
+- return &trezorDriver{
+- log: logger,
+- }
+-}
+-
+-// Status implements accounts.Wallet, always whether the Trezor is opened, closed
+-// or whether the Ethereum app was not started on it.
+-func (w *trezorDriver) Status() (string, error) {
+- if w.failure != nil {
+- return fmt.Sprintf("Failed: %v", w.failure), w.failure
+- }
+- if w.device == nil {
+- return "Closed", w.failure
+- }
+- if w.pinwait {
+- return fmt.Sprintf("Trezor v%d.%d.%d '%s' waiting for PIN", w.version[0], w.version[1], w.version[2], w.label), w.failure
+- }
+- return fmt.Sprintf("Trezor v%d.%d.%d '%s' online", w.version[0], w.version[1], w.version[2], w.label), w.failure
+-}
+-
+-// Open implements usbwallet.driver, attempting to initialize the connection to
+-// the Trezor hardware wallet. Initializing the Trezor is a two or three phase operation:
+-// - The first phase is to initialize the connection and read the wallet's
+-// features. This phase is invoked if the provided passphrase is empty. The
+-// device will display the pinpad as a result and will return an appropriate
+-// error to notify the user that a second open phase is needed.
+-// - The second phase is to unlock access to the Trezor, which is done by the
+-// user actually providing a passphrase mapping a keyboard keypad to the pin
+-// number of the user (shuffled according to the pinpad displayed).
+-// - If needed the device will ask for passphrase which will require calling
+-// open again with the actual passphrase (3rd phase)
+-func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error {
+- w.device, w.failure = device, nil
+-
+- // If phase 1 is requested, init the connection and wait for user callback
+- if passphrase == "" && !w.passphrasewait {
+- // If we're already waiting for a PIN entry, insta-return
+- if w.pinwait {
+- return ErrTrezorPINNeeded
+- }
+- // Initialize a connection to the device
+- features := new(trezor.Features)
+- if _, err := w.trezorExchange(&trezor.Initialize{}, features); err != nil {
+- return err
+- }
+- w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()}
+- w.label = features.GetLabel()
+-
+- // Do a manual ping, forcing the device to ask for its PIN and Passphrase
+- askPin := true
+- askPassphrase := true
+- res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin, PassphraseProtection: &askPassphrase}, new(trezor.PinMatrixRequest), new(trezor.PassphraseRequest), new(trezor.Success))
+- if err != nil {
+- return err
+- }
+- // Only return the PIN request if the device wasn't unlocked until now
+- switch res {
+- case 0:
+- w.pinwait = true
+- return ErrTrezorPINNeeded
+- case 1:
+- w.pinwait = false
+- w.passphrasewait = true
+- return ErrTrezorPassphraseNeeded
+- case 2:
+- return nil // responded with trezor.Success
+- }
+- }
+- // Phase 2 requested with actual PIN entry
+- if w.pinwait {
+- w.pinwait = false
+- res, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success), new(trezor.PassphraseRequest))
+- if err != nil {
+- w.failure = err
+- return err
+- }
+- if res == 1 {
+- w.passphrasewait = true
+- return ErrTrezorPassphraseNeeded
+- }
+- } else if w.passphrasewait {
+- w.passphrasewait = false
+- if _, err := w.trezorExchange(&trezor.PassphraseAck{Passphrase: &passphrase}, new(trezor.Success)); err != nil {
+- w.failure = err
+- return err
+- }
+- }
+-
+- return nil
+-}
+-
+-// Close implements usbwallet.driver, cleaning up and metadata maintained within
+-// the Trezor driver.
+-func (w *trezorDriver) Close() error {
+- w.version, w.label, w.pinwait = [3]uint32{}, "", false
+- return nil
+-}
+-
+-// Heartbeat implements usbwallet.driver, performing a sanity check against the
+-// Trezor to see if it's still online.
+-func (w *trezorDriver) Heartbeat() error {
+- if _, err := w.trezorExchange(&trezor.Ping{}, new(trezor.Success)); err != nil {
+- w.failure = err
+- return err
+- }
+- return nil
+-}
+-
+-// Derive implements usbwallet.driver, sending a derivation request to the Trezor
+-// and returning the Ethereum address located on that derivation path.
+-func (w *trezorDriver) Derive(path accounts.DerivationPath) (common.Address, error) {
+- return w.trezorDerive(path)
+-}
+-
+-// SignTx implements usbwallet.driver, sending the transaction to the Trezor and
+-// waiting for the user to confirm or deny the transaction.
+-func (w *trezorDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
+- if w.device == nil {
+- return common.Address{}, nil, accounts.ErrWalletClosed
+- }
+- return w.trezorSign(path, tx, chainID)
+-}
+-
+-func (w *trezorDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) {
+- return nil, accounts.ErrNotSupported
+-}
+-
+-// trezorDerive sends a derivation request to the Trezor device and returns the
+-// Ethereum address located on that path.
+-func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, error) {
+- address := new(trezor.EthereumAddress)
+- if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil {
+- return common.Address{}, err
+- }
+- if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary formats
+- return common.BytesToAddress(addr), nil
+- }
+- if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal formats
+- return common.HexToAddress(addr), nil
+- }
+- return common.Address{}, errors.New("missing derived address")
+-}
+-
+-// trezorSign sends the transaction to the Trezor wallet, and waits for the user
+-// to confirm or deny the transaction.
+-func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
+- // Create the transaction initiation message
+- data := tx.Data()
+- length := uint32(len(data))
+-
+- request := &trezor.EthereumSignTx{
+- AddressN: derivationPath,
+- Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(),
+- GasPrice: tx.GasPrice().Bytes(),
+- GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(),
+- Value: tx.Value().Bytes(),
+- DataLength: &length,
+- }
+- if to := tx.To(); to != nil {
+- // Non contract deploy, set recipient explicitly
+- hex := to.Hex()
+- request.ToHex = &hex // Newer firmwares (old will ignore)
+- request.ToBin = (*to)[:] // Older firmwares (new will ignore)
+- }
+- if length > 1024 { // Send the data chunked if that was requested
+- request.DataInitialChunk, data = data[:1024], data[1024:]
+- } else {
+- request.DataInitialChunk, data = data, nil
+- }
+- if chainID != nil { // EIP-155 transaction, set chain ID explicitly (only 32 bit is supported!?)
+- id := uint32(chainID.Int64())
+- request.ChainId = &id
+- }
+- // Send the initiation message and stream content until a signature is returned
+- response := new(trezor.EthereumTxRequest)
+- if _, err := w.trezorExchange(request, response); err != nil {
+- return common.Address{}, nil, err
+- }
+- for response.DataLength != nil && int(*response.DataLength) <= len(data) {
+- chunk := data[:*response.DataLength]
+- data = data[*response.DataLength:]
+-
+- if _, err := w.trezorExchange(&trezor.EthereumTxAck{DataChunk: chunk}, response); err != nil {
+- return common.Address{}, nil, err
+- }
+- }
+- // Extract the Ethereum signature and do a sanity validation
+- if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 {
+- return common.Address{}, nil, errors.New("reply lacks signature")
+- } else if response.GetSignatureV() == 0 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
+- // for chainId >= (MaxUint32-36)/2, Trezor returns signature bit only
+- // https://github.com/trezor/trezor-mcu/pull/399
+- return common.Address{}, nil, errors.New("reply lacks signature")
+- }
+- signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV()))
+-
+- // Create the correct signer and signature transform based on the chain ID
+- var signer types.Signer
+- if chainID == nil {
+- signer = new(types.HomesteadSigner)
+- } else {
+- // Trezor backend does not support typed transactions yet.
+- signer = types.NewEIP155Signer(chainID)
+- // if chainId is above (MaxUint32 - 36) / 2 then the final v values is returned
+- // directly. Otherwise, the returned value is 35 + chainid * 2.
+- if signature[64] > 1 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
+- signature[64] -= byte(chainID.Uint64()*2 + 35)
+- }
+- }
+-
+- // Inject the final signature into the transaction and sanity check the sender
+- signed, err := tx.WithSignature(signer, signature)
+- if err != nil {
+- return common.Address{}, nil, err
+- }
+- sender, err := types.Sender(signer, signed)
+- if err != nil {
+- return common.Address{}, nil, err
+- }
+- return sender, signed, nil
+-}
+-
+-// trezorExchange performs a data exchange with the Trezor wallet, sending it a
+-// message and retrieving the response. If multiple responses are possible, the
+-// method will also return the index of the destination object used.
+-func (w *trezorDriver) trezorExchange(req proto.Message, results ...proto.Message) (int, error) {
+- // Construct the original message payload to chunk up
+- data, err := proto.Marshal(req)
+- if err != nil {
+- return 0, err
+- }
+- payload := make([]byte, 8+len(data))
+- copy(payload, []byte{0x23, 0x23})
+- binary.BigEndian.PutUint16(payload[2:], trezor.Type(req))
+- binary.BigEndian.PutUint32(payload[4:], uint32(len(data)))
+- copy(payload[8:], data)
+-
+- // Stream all the chunks to the device
+- chunk := make([]byte, 64)
+- chunk[0] = 0x3f // Report ID magic number
+-
+- for len(payload) > 0 {
+- // Construct the new message to stream, padding with zeroes if needed
+- if len(payload) > 63 {
+- copy(chunk[1:], payload[:63])
+- payload = payload[63:]
+- } else {
+- copy(chunk[1:], payload)
+- copy(chunk[1+len(payload):], make([]byte, 63-len(payload)))
+- payload = nil
+- }
+- // Send over to the device
+- w.log.Trace("Data chunk sent to the Trezor", "chunk", hexutil.Bytes(chunk))
+- if _, err := w.device.Write(chunk); err != nil {
+- return 0, err
+- }
+- }
+- // Stream the reply back from the wallet in 64 byte chunks
+- var (
+- kind uint16
+- reply []byte
+- )
+- for {
+- // Read the next chunk from the Trezor wallet
+- if _, err := io.ReadFull(w.device, chunk); err != nil {
+- return 0, err
+- }
+- w.log.Trace("Data chunk received from the Trezor", "chunk", hexutil.Bytes(chunk))
+-
+- // Make sure the transport header matches
+- if chunk[0] != 0x3f || (len(reply) == 0 && (chunk[1] != 0x23 || chunk[2] != 0x23)) {
+- return 0, errTrezorReplyInvalidHeader
+- }
+- // If it's the first chunk, retrieve the reply message type and total message length
+- var payload []byte
+-
+- if len(reply) == 0 {
+- kind = binary.BigEndian.Uint16(chunk[3:5])
+- reply = make([]byte, 0, int(binary.BigEndian.Uint32(chunk[5:9])))
+- payload = chunk[9:]
+- } else {
+- payload = chunk[1:]
+- }
+- // Append to the reply and stop when filled up
+- if left := cap(reply) - len(reply); left > len(payload) {
+- reply = append(reply, payload...)
+- } else {
+- reply = append(reply, payload[:left]...)
+- break
+- }
+- }
+- // Try to parse the reply into the requested reply message
+- if kind == uint16(trezor.MessageType_MessageType_Failure) {
+- // Trezor returned a failure, extract and return the message
+- failure := new(trezor.Failure)
+- if err := proto.Unmarshal(reply, failure); err != nil {
+- return 0, err
+- }
+- return 0, errors.New("trezor: " + failure.GetMessage())
+- }
+- if kind == uint16(trezor.MessageType_MessageType_ButtonRequest) {
+- // Trezor is waiting for user confirmation, ack and wait for the next message
+- return w.trezorExchange(&trezor.ButtonAck{}, results...)
+- }
+- for i, res := range results {
+- if trezor.Type(res) == kind {
+- return i, proto.Unmarshal(reply, res)
+- }
+- }
+- expected := make([]string, len(results))
+- for i, res := range results {
+- expected[i] = trezor.Name(trezor.Type(res))
+- }
+- return 0, fmt.Errorf("trezor: expected reply types %s, got %s", expected, trezor.Name(kind))
++// Type returns the protocol buffer type number of a specific message. If the
++// message is nil, this method panics!
++func Type(msg proto.Message) uint16 {
++ return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()])
++}
++
++// Name returns the friendly message type name of a specific protocol buffer
++// type number.
++func Name(kind uint16) string {
++ name := MessageType_name[int32(kind)]
++ if len(name) < 12 {
++ return name
++ }
++ return name[12:]
+ }
+diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go
+deleted file mode 100644
+index 0fd0415a9e..0000000000
+--- a/accounts/usbwallet/wallet.go
++++ /dev/null
+@@ -1,643 +0,0 @@
+-// Copyright 2017 The go-ethereum Authors
+-// This file is part of the go-ethereum library.
+-//
+-// The go-ethereum library is free software: you can redistribute it and/or modify
+-// it under the terms of the GNU Lesser General Public License as published by
+-// the Free Software Foundation, either version 3 of the License, or
+-// (at your option) any later version.
+-//
+-// The go-ethereum library is distributed in the hope that it will be useful,
+-// but WITHOUT ANY WARRANTY; without even the implied warranty of
+-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-// GNU Lesser General Public License for more details.
+-//
+-// You should have received a copy of the GNU Lesser General Public License
+-// along with the go-ethereum library. If not, see .
+-
+-// Package usbwallet implements support for USB hardware wallets.
+-package usbwallet
+-
+-import (
+- "context"
+- "fmt"
+- "io"
+- "math/big"
+- "sync"
+- "time"
+-
+- "github.com/ethereum/go-ethereum"
+- "github.com/ethereum/go-ethereum/accounts"
+- "github.com/ethereum/go-ethereum/common"
+- "github.com/ethereum/go-ethereum/core/types"
+- "github.com/ethereum/go-ethereum/crypto"
+- "github.com/ethereum/go-ethereum/log"
+- "github.com/karalabe/hid"
+-)
+-
+-// Maximum time between wallet health checks to detect USB unplugs.
+-const heartbeatCycle = time.Second
+-
+-// Minimum time to wait between self derivation attempts, even it the user is
+-// requesting accounts like crazy.
+-const selfDeriveThrottling = time.Second
+-
+-// driver defines the vendor specific functionality hardware wallets instances
+-// must implement to allow using them with the wallet lifecycle management.
+-type driver interface {
+- // Status returns a textual status to aid the user in the current state of the
+- // wallet. It also returns an error indicating any failure the wallet might have
+- // encountered.
+- Status() (string, error)
+-
+- // Open initializes access to a wallet instance. The passphrase parameter may
+- // or may not be used by the implementation of a particular wallet instance.
+- Open(device io.ReadWriter, passphrase string) error
+-
+- // Close releases any resources held by an open wallet instance.
+- Close() error
+-
+- // Heartbeat performs a sanity check against the hardware wallet to see if it
+- // is still online and healthy.
+- Heartbeat() error
+-
+- // Derive sends a derivation request to the USB device and returns the Ethereum
+- // address located on that path.
+- Derive(path accounts.DerivationPath) (common.Address, error)
+-
+- // SignTx sends the transaction to the USB device and waits for the user to confirm
+- // or deny the transaction.
+- SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error)
+-
+- SignTypedMessage(path accounts.DerivationPath, messageHash []byte, domainHash []byte) ([]byte, error)
+-}
+-
+-// wallet represents the common functionality shared by all USB hardware
+-// wallets to prevent reimplementing the same complex maintenance mechanisms
+-// for different vendors.
+-type wallet struct {
+- hub *Hub // USB hub scanning
+- driver driver // Hardware implementation of the low level device operations
+- url *accounts.URL // Textual URL uniquely identifying this wallet
+-
+- info hid.DeviceInfo // Known USB device infos about the wallet
+- device hid.Device // USB device advertising itself as a hardware wallet
+-
+- accounts []accounts.Account // List of derive accounts pinned on the hardware wallet
+- paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
+-
+- deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported)
+- deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported)
+- deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
+- deriveReq chan chan struct{} // Channel to request a self-derivation on
+- deriveQuit chan chan error // Channel to terminate the self-deriver with
+-
+- healthQuit chan chan error
+-
+- // Locking a hardware wallet is a bit special. Since hardware devices are lower
+- // performing, any communication with them might take a non negligible amount of
+- // time. Worse still, waiting for user confirmation can take arbitrarily long,
+- // but exclusive communication must be upheld during. Locking the entire wallet
+- // in the mean time however would stall any parts of the system that don't want
+- // to communicate, just read some state (e.g. list the accounts).
+- //
+- // As such, a hardware wallet needs two locks to function correctly. A state
+- // lock can be used to protect the wallet's software-side internal state, which
+- // must not be held exclusively during hardware communication. A communication
+- // lock can be used to achieve exclusive access to the device itself, this one
+- // however should allow "skipping" waiting for operations that might want to
+- // use the device, but can live without too (e.g. account self-derivation).
+- //
+- // Since we have two locks, it's important to know how to properly use them:
+- // - Communication requires the `device` to not change, so obtaining the
+- // commsLock should be done after having a stateLock.
+- // - Communication must not disable read access to the wallet state, so it
+- // must only ever hold a *read* lock to stateLock.
+- commsLock chan struct{} // Mutex (buf=1) for the USB comms without keeping the state locked
+- stateLock sync.RWMutex // Protects read and write access to the wallet struct fields
+-
+- log log.Logger // Contextual logger to tag the base with its id
+-}
+-
+-// URL implements accounts.Wallet, returning the URL of the USB hardware device.
+-func (w *wallet) URL() accounts.URL {
+- return *w.url // Immutable, no need for a lock
+-}
+-
+-// Status implements accounts.Wallet, returning a custom status message from the
+-// underlying vendor-specific hardware wallet implementation.
+-func (w *wallet) Status() (string, error) {
+- w.stateLock.RLock() // No device communication, state lock is enough
+- defer w.stateLock.RUnlock()
+-
+- status, failure := w.driver.Status()
+- if w.device == nil {
+- return "Closed", failure
+- }
+- return status, failure
+-}
+-
+-// Open implements accounts.Wallet, attempting to open a USB connection to the
+-// hardware wallet.
+-func (w *wallet) Open(passphrase string) error {
+- w.stateLock.Lock() // State lock is enough since there's no connection yet at this point
+- defer w.stateLock.Unlock()
+-
+- // If the device was already opened once, refuse to try again
+- if w.paths != nil {
+- return accounts.ErrWalletAlreadyOpen
+- }
+- // Make sure the actual device connection is done only once
+- if w.device == nil {
+- device, err := w.info.Open()
+- if err != nil {
+- return err
+- }
+- w.device = device
+- w.commsLock = make(chan struct{}, 1)
+- w.commsLock <- struct{}{} // Enable lock
+- }
+- // Delegate device initialization to the underlying driver
+- if err := w.driver.Open(w.device, passphrase); err != nil {
+- return err
+- }
+- // Connection successful, start life-cycle management
+- w.paths = make(map[common.Address]accounts.DerivationPath)
+-
+- w.deriveReq = make(chan chan struct{})
+- w.deriveQuit = make(chan chan error)
+- w.healthQuit = make(chan chan error)
+-
+- go w.heartbeat()
+- go w.selfDerive()
+-
+- // Notify anyone listening for wallet events that a new device is accessible
+- go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
+-
+- return nil
+-}
+-
+-// heartbeat is a health check loop for the USB wallets to periodically verify
+-// whether they are still present or if they malfunctioned.
+-func (w *wallet) heartbeat() {
+- w.log.Debug("USB wallet health-check started")
+- defer w.log.Debug("USB wallet health-check stopped")
+-
+- // Execute heartbeat checks until termination or error
+- var (
+- errc chan error
+- err error
+- )
+- for errc == nil && err == nil {
+- // Wait until termination is requested or the heartbeat cycle arrives
+- select {
+- case errc = <-w.healthQuit:
+- // Termination requested
+- continue
+- case <-time.After(heartbeatCycle):
+- // Heartbeat time
+- }
+- // Execute a tiny data exchange to see responsiveness
+- w.stateLock.RLock()
+- if w.device == nil {
+- // Terminated while waiting for the lock
+- w.stateLock.RUnlock()
+- continue
+- }
+- <-w.commsLock // Don't lock state while resolving version
+- err = w.driver.Heartbeat()
+- w.commsLock <- struct{}{}
+- w.stateLock.RUnlock()
+-
+- if err != nil {
+- w.stateLock.Lock() // Lock state to tear the wallet down
+- w.close()
+- w.stateLock.Unlock()
+- }
+- // Ignore non hardware related errors
+- err = nil
+- }
+- // In case of error, wait for termination
+- if err != nil {
+- w.log.Debug("USB wallet health-check failed", "err", err)
+- errc = <-w.healthQuit
+- }
+- errc <- err
+-}
+-
+-// Close implements accounts.Wallet, closing the USB connection to the device.
+-func (w *wallet) Close() error {
+- // Ensure the wallet was opened
+- w.stateLock.RLock()
+- hQuit, dQuit := w.healthQuit, w.deriveQuit
+- w.stateLock.RUnlock()
+-
+- // Terminate the health checks
+- var herr error
+- if hQuit != nil {
+- errc := make(chan error)
+- hQuit <- errc
+- herr = <-errc // Save for later, we *must* close the USB
+- }
+- // Terminate the self-derivations
+- var derr error
+- if dQuit != nil {
+- errc := make(chan error)
+- dQuit <- errc
+- derr = <-errc // Save for later, we *must* close the USB
+- }
+- // Terminate the device connection
+- w.stateLock.Lock()
+- defer w.stateLock.Unlock()
+-
+- w.healthQuit = nil
+- w.deriveQuit = nil
+- w.deriveReq = nil
+-
+- if err := w.close(); err != nil {
+- return err
+- }
+- if herr != nil {
+- return herr
+- }
+- return derr
+-}
+-
+-// close is the internal wallet closer that terminates the USB connection and
+-// resets all the fields to their defaults.
+-//
+-// Note, close assumes the state lock is held!
+-func (w *wallet) close() error {
+- // Allow duplicate closes, especially for health-check failures
+- if w.device == nil {
+- return nil
+- }
+- // Close the device, clear everything, then return
+- w.device.Close()
+- w.device = nil
+-
+- w.accounts, w.paths = nil, nil
+- return w.driver.Close()
+-}
+-
+-// Accounts implements accounts.Wallet, returning the list of accounts pinned to
+-// the USB hardware wallet. If self-derivation was enabled, the account list is
+-// periodically expanded based on current chain state.
+-func (w *wallet) Accounts() []accounts.Account {
+- // Attempt self-derivation if it's running
+- reqc := make(chan struct{}, 1)
+- select {
+- case w.deriveReq <- reqc:
+- // Self-derivation request accepted, wait for it
+- <-reqc
+- default:
+- // Self-derivation offline, throttled or busy, skip
+- }
+- // Return whatever account list we ended up with
+- w.stateLock.RLock()
+- defer w.stateLock.RUnlock()
+-
+- cpy := make([]accounts.Account, len(w.accounts))
+- copy(cpy, w.accounts)
+- return cpy
+-}
+-
+-// selfDerive is an account derivation loop that upon request attempts to find
+-// new non-zero accounts.
+-func (w *wallet) selfDerive() {
+- w.log.Debug("USB wallet self-derivation started")
+- defer w.log.Debug("USB wallet self-derivation stopped")
+-
+- // Execute self-derivations until termination or error
+- var (
+- reqc chan struct{}
+- errc chan error
+- err error
+- )
+- for errc == nil && err == nil {
+- // Wait until either derivation or termination is requested
+- select {
+- case errc = <-w.deriveQuit:
+- // Termination requested
+- continue
+- case reqc = <-w.deriveReq:
+- // Account discovery requested
+- }
+- // Derivation needs a chain and device access, skip if either unavailable
+- w.stateLock.RLock()
+- if w.device == nil || w.deriveChain == nil {
+- w.stateLock.RUnlock()
+- reqc <- struct{}{}
+- continue
+- }
+- select {
+- case <-w.commsLock:
+- default:
+- w.stateLock.RUnlock()
+- reqc <- struct{}{}
+- continue
+- }
+- // Device lock obtained, derive the next batch of accounts
+- var (
+- accs []accounts.Account
+- paths []accounts.DerivationPath
+-
+- nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...)
+- nextAddrs = append([]common.Address{}, w.deriveNextAddrs...)
+-
+- context = context.Background()
+- )
+- for i := 0; i < len(nextAddrs); i++ {
+- for empty := false; !empty; {
+- // Retrieve the next derived Ethereum account
+- if nextAddrs[i] == (common.Address{}) {
+- if nextAddrs[i], err = w.driver.Derive(nextPaths[i]); err != nil {
+- w.log.Warn("USB wallet account derivation failed", "err", err)
+- break
+- }
+- }
+- // Check the account's status against the current chain state
+- var (
+- balance *big.Int
+- nonce uint64
+- )
+- balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil)
+- if err != nil {
+- w.log.Warn("USB wallet balance retrieval failed", "err", err)
+- break
+- }
+- nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil)
+- if err != nil {
+- w.log.Warn("USB wallet nonce retrieval failed", "err", err)
+- break
+- }
+- // We've just self-derived a new account, start tracking it locally
+- // unless the account was empty.
+- path := make(accounts.DerivationPath, len(nextPaths[i]))
+- copy(path[:], nextPaths[i][:])
+- if balance.Sign() == 0 && nonce == 0 {
+- empty = true
+- // If it indeed was empty, make a log output for it anyway. In the case
+- // of legacy-ledger, the first account on the legacy-path will
+- // be shown to the user, even if we don't actively track it
+- if i < len(nextAddrs)-1 {
+- w.log.Info("Skipping tracking first account on legacy path, use personal.deriveAccount(,, false) to track",
+- "path", path, "address", nextAddrs[i])
+- break
+- }
+- }
+- paths = append(paths, path)
+- account := accounts.Account{
+- Address: nextAddrs[i],
+- URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
+- }
+- accs = append(accs, account)
+-
+- // Display a log message to the user for new (or previously empty accounts)
+- if _, known := w.paths[nextAddrs[i]]; !known || (!empty && nextAddrs[i] == w.deriveNextAddrs[i]) {
+- w.log.Info("USB wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce)
+- }
+- // Fetch the next potential account
+- if !empty {
+- nextAddrs[i] = common.Address{}
+- nextPaths[i][len(nextPaths[i])-1]++
+- }
+- }
+- }
+- // Self derivation complete, release device lock
+- w.commsLock <- struct{}{}
+- w.stateLock.RUnlock()
+-
+- // Insert any accounts successfully derived
+- w.stateLock.Lock()
+- for i := 0; i < len(accs); i++ {
+- if _, ok := w.paths[accs[i].Address]; !ok {
+- w.accounts = append(w.accounts, accs[i])
+- w.paths[accs[i].Address] = paths[i]
+- }
+- }
+- // Shift the self-derivation forward
+- // TODO(karalabe): don't overwrite changes from wallet.SelfDerive
+- w.deriveNextAddrs = nextAddrs
+- w.deriveNextPaths = nextPaths
+- w.stateLock.Unlock()
+-
+- // Notify the user of termination and loop after a bit of time (to avoid trashing)
+- reqc <- struct{}{}
+- if err == nil {
+- select {
+- case errc = <-w.deriveQuit:
+- // Termination requested, abort
+- case <-time.After(selfDeriveThrottling):
+- // Waited enough, willing to self-derive again
+- }
+- }
+- }
+- // In case of error, wait for termination
+- if err != nil {
+- w.log.Debug("USB wallet self-derivation failed", "err", err)
+- errc = <-w.deriveQuit
+- }
+- errc <- err
+-}
+-
+-// Contains implements accounts.Wallet, returning whether a particular account is
+-// or is not pinned into this wallet instance. Although we could attempt to resolve
+-// unpinned accounts, that would be an non-negligible hardware operation.
+-func (w *wallet) Contains(account accounts.Account) bool {
+- w.stateLock.RLock()
+- defer w.stateLock.RUnlock()
+-
+- _, exists := w.paths[account.Address]
+- return exists
+-}
+-
+-// Derive implements accounts.Wallet, deriving a new account at the specific
+-// derivation path. If pin is set to true, the account will be added to the list
+-// of tracked accounts.
+-func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
+- // Try to derive the actual account and update its URL if successful
+- w.stateLock.RLock() // Avoid device disappearing during derivation
+-
+- if w.device == nil {
+- w.stateLock.RUnlock()
+- return accounts.Account{}, accounts.ErrWalletClosed
+- }
+- <-w.commsLock // Avoid concurrent hardware access
+- address, err := w.driver.Derive(path)
+- w.commsLock <- struct{}{}
+-
+- w.stateLock.RUnlock()
+-
+- // If an error occurred or no pinning was requested, return
+- if err != nil {
+- return accounts.Account{}, err
+- }
+- account := accounts.Account{
+- Address: address,
+- URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
+- }
+- if !pin {
+- return account, nil
+- }
+- // Pinning needs to modify the state
+- w.stateLock.Lock()
+- defer w.stateLock.Unlock()
+-
+- if w.device == nil {
+- return accounts.Account{}, accounts.ErrWalletClosed
+- }
+-
+- if _, ok := w.paths[address]; !ok {
+- w.accounts = append(w.accounts, account)
+- w.paths[address] = make(accounts.DerivationPath, len(path))
+- copy(w.paths[address], path)
+- }
+- return account, nil
+-}
+-
+-// SelfDerive sets a base account derivation path from which the wallet attempts
+-// to discover non zero accounts and automatically add them to list of tracked
+-// accounts.
+-//
+-// Note, self derivation will increment the last component of the specified path
+-// opposed to descending into a child path to allow discovering accounts starting
+-// from non zero components.
+-//
+-// Some hardware wallets switched derivation paths through their evolution, so
+-// this method supports providing multiple bases to discover old user accounts
+-// too. Only the last base will be used to derive the next empty account.
+-//
+-// You can disable automatic account discovery by calling SelfDerive with a nil
+-// chain state reader.
+-func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) {
+- w.stateLock.Lock()
+- defer w.stateLock.Unlock()
+-
+- w.deriveNextPaths = make([]accounts.DerivationPath, len(bases))
+- for i, base := range bases {
+- w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base))
+- copy(w.deriveNextPaths[i][:], base[:])
+- }
+- w.deriveNextAddrs = make([]common.Address, len(bases))
+- w.deriveChain = chain
+-}
+-
+-// signHash implements accounts.Wallet, however signing arbitrary data is not
+-// supported for hardware wallets, so this method will always return an error.
+-func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) {
+- return nil, accounts.ErrNotSupported
+-}
+-
+-// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
+-func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
+- // Unless we are doing 712 signing, simply dispatch to signHash
+- if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) {
+- return w.signHash(account, crypto.Keccak256(data))
+- }
+-
+- // dispatch to 712 signing if the mimetype is TypedData and the format matches
+- w.stateLock.RLock() // Comms have own mutex, this is for the state fields
+- defer w.stateLock.RUnlock()
+-
+- // If the wallet is closed, abort
+- if w.device == nil {
+- return nil, accounts.ErrWalletClosed
+- }
+- // Make sure the requested account is contained within
+- path, ok := w.paths[account.Address]
+- if !ok {
+- return nil, accounts.ErrUnknownAccount
+- }
+- // All infos gathered and metadata checks out, request signing
+- <-w.commsLock
+- defer func() { w.commsLock <- struct{}{} }()
+-
+- // Ensure the device isn't screwed with while user confirmation is pending
+- // TODO(karalabe): remove if hotplug lands on Windows
+- w.hub.commsLock.Lock()
+- w.hub.commsPend++
+- w.hub.commsLock.Unlock()
+-
+- defer func() {
+- w.hub.commsLock.Lock()
+- w.hub.commsPend--
+- w.hub.commsLock.Unlock()
+- }()
+- // Sign the transaction
+- signature, err := w.driver.SignTypedMessage(path, data[2:34], data[34:66])
+- if err != nil {
+- return nil, err
+- }
+- return signature, nil
+-}
+-
+-// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given
+-// data with the given account using passphrase as extra authentication.
+-// Since USB wallets don't rely on passphrases, these are silently ignored.
+-func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) {
+- return w.SignData(account, mimeType, data)
+-}
+-
+-func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) {
+- return w.signHash(account, accounts.TextHash(text))
+-}
+-
+-// SignTx implements accounts.Wallet. It sends the transaction over to the Ledger
+-// wallet to request a confirmation from the user. It returns either the signed
+-// transaction or a failure if the user denied the transaction.
+-//
+-// Note, if the version of the Ethereum application running on the Ledger wallet is
+-// too old to sign EIP-155 transactions, but such is requested nonetheless, an error
+-// will be returned opposed to silently signing in Homestead mode.
+-func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
+- w.stateLock.RLock() // Comms have own mutex, this is for the state fields
+- defer w.stateLock.RUnlock()
+-
+- // If the wallet is closed, abort
+- if w.device == nil {
+- return nil, accounts.ErrWalletClosed
+- }
+- // Make sure the requested account is contained within
+- path, ok := w.paths[account.Address]
+- if !ok {
+- return nil, accounts.ErrUnknownAccount
+- }
+- // All infos gathered and metadata checks out, request signing
+- <-w.commsLock
+- defer func() { w.commsLock <- struct{}{} }()
+-
+- // Ensure the device isn't screwed with while user confirmation is pending
+- // TODO(karalabe): remove if hotplug lands on Windows
+- w.hub.commsLock.Lock()
+- w.hub.commsPend++
+- w.hub.commsLock.Unlock()
+-
+- defer func() {
+- w.hub.commsLock.Lock()
+- w.hub.commsPend--
+- w.hub.commsLock.Unlock()
+- }()
+- // Sign the transaction and verify the sender to avoid hardware fault surprises
+- sender, signed, err := w.driver.SignTx(path, tx, chainID)
+- if err != nil {
+- return nil, err
+- }
+- if sender != account.Address {
+- return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex())
+- }
+- return signed, nil
+-}
+-
+-// SignTextWithPassphrase implements accounts.Wallet, however signing arbitrary
+-// data is not supported for Ledger wallets, so this method will always return
+-// an error.
+-func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
+- return w.SignText(account, accounts.TextHash(text))
+-}
+-
+-// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given
+-// transaction with the given account using passphrase as extra authentication.
+-// Since USB wallets don't rely on passphrases, these are silently ignored.
+-func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
+- return w.SignTx(account, tx, chainID)
+-}
+diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go
+index 0000000000..b98c718806 100644
+--- a/beacon/engine/gen_epe.go
++++ b/beacon/engine/gen_epe.go
+@@ -16,24 +16,13 @@
+ // MarshalJSON marshals as JSON.
+ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
+ type ExecutionPayloadEnvelope struct {
+-<<<<<<< Conflict 1 of 2
+-+++++++ Contents of side #1
+ ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
+ BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
+- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
++ BlobsBundle *BlobsBundle `json:"blobsBundle"`
+ Requests []hexutil.Bytes `json:"executionRequests"`
+ Override bool `json:"shouldOverrideBuilder"`
+ Witness *hexutil.Bytes `json:"witness,omitempty"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"`
+-%%%%%%% Changes from base to side #2
+- ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
+- BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
+-- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+-+ BlobsBundle *BlobsBundle `json:"blobsBundle"`
+- Requests []hexutil.Bytes `json:"executionRequests"`
+- Override bool `json:"shouldOverrideBuilder"`
+- Witness *hexutil.Bytes `json:"witness,omitempty"`
+->>>>>>> Conflict 1 of 2 ends
+ }
+ var enc ExecutionPayloadEnvelope
+ enc.ExecutionPayload = e.ExecutionPayload
+@@ -54,24 +43,13 @@
+ // UnmarshalJSON unmarshals from JSON.
+ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
+ type ExecutionPayloadEnvelope struct {
+-<<<<<<< Conflict 2 of 2
+-+++++++ Contents of side #1
+ ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
+ BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
+- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
++ BlobsBundle *BlobsBundle `json:"blobsBundle"`
+ Requests []hexutil.Bytes `json:"executionRequests"`
+ Override *bool `json:"shouldOverrideBuilder"`
+ Witness *hexutil.Bytes `json:"witness,omitempty"`
+ ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"`
+-%%%%%%% Changes from base to side #2
+- ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
+- BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
+-- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
+-+ BlobsBundle *BlobsBundle `json:"blobsBundle"`
+- Requests []hexutil.Bytes `json:"executionRequests"`
+- Override *bool `json:"shouldOverrideBuilder"`
+- Witness *hexutil.Bytes `json:"witness,omitempty"`
+->>>>>>> Conflict 2 of 2 ends
+ }
+ var dec ExecutionPayloadEnvelope
+ if err := json.Unmarshal(input, &dec); err != nil {
+diff --git a/cmd/geth/config.go b/cmd/geth/config.go
+index 0000000000..b43caf1491 100644
+--- a/cmd/geth/config.go
++++ b/cmd/geth/config.go
+@@ -227,8 +227,18 @@
+ v := ctx.Uint64(utils.OverrideOsaka.Name)
+ cfg.Eth.OverrideOsaka = &v
+ }
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
++ if ctx.IsSet(utils.OverrideBPO1.Name) {
++ v := ctx.Uint64(utils.OverrideBPO1.Name)
++ cfg.Eth.OverrideBPO1 = &v
++ }
++ if ctx.IsSet(utils.OverrideBPO2.Name) {
++ v := ctx.Uint64(utils.OverrideBPO2.Name)
++ cfg.Eth.OverrideBPO2 = &v
++ }
++ if ctx.IsSet(utils.OverrideVerkle.Name) {
++ v := ctx.Uint64(utils.OverrideVerkle.Name)
++ cfg.Eth.OverrideVerkle = &v
++ }
+
+ if ctx.IsSet(utils.OverrideOptimismCanyon.Name) {
+ v := ctx.Uint64(utils.OverrideOptimismCanyon.Name)
+@@ -270,21 +280,6 @@
+ cfg.Eth.OverrideOptimismInterop = &v
+ }
+
+-%%%%%%% Changes from base to side #2
+-+ if ctx.IsSet(utils.OverrideBPO1.Name) {
+-+ v := ctx.Uint64(utils.OverrideBPO1.Name)
+-+ cfg.Eth.OverrideBPO1 = &v
+-+ }
+-+ if ctx.IsSet(utils.OverrideBPO2.Name) {
+-+ v := ctx.Uint64(utils.OverrideBPO2.Name)
+-+ cfg.Eth.OverrideBPO2 = &v
+-+ }
+->>>>>>> Conflict 1 of 1 ends
+- if ctx.IsSet(utils.OverrideVerkle.Name) {
+- v := ctx.Uint64(utils.OverrideVerkle.Name)
+- cfg.Eth.OverrideVerkle = &v
+- }
+-
+ // Start metrics export if enabled
+ utils.SetupMetrics(&cfg.Metrics)
+
+diff --git a/cmd/keeper/go.mod b/cmd/keeper/go.mod
+index d1649da43f..8b8f66d9b7 100644
+--- a/cmd/keeper/go.mod
++++ b/cmd/keeper/go.mod
+@@ -8,6 +8,7 @@
+ )
+
+ require (
++ github.com/BurntSushi/toml v1.4.0 // indirect
+ github.com/StackExchange/wmi v1.2.1 // indirect
+ github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
+ github.com/bits-and-blooms/bitset v1.20.0 // indirect
+@@ -18,7 +19,7 @@
+ github.com/deckarep/golang-set/v2 v2.6.0 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
+ github.com/emicklei/dot v1.6.2 // indirect
+- github.com/ethereum/c-kzg-4844/v2 v2.1.3 // indirect
++ github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab // indirect
+ github.com/ethereum/go-verkle v0.2.2 // indirect
+ github.com/ferranbt/fastssz v0.1.4 // indirect
+@@ -27,10 +28,13 @@
+ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
+ github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
+ github.com/holiman/uint256 v1.3.2 // indirect
++ github.com/klauspost/compress v1.17.11 // indirect
+ github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
+ github.com/mitchellh/mapstructure v1.4.1 // indirect
++ github.com/naoina/go-stringutil v0.1.0 // indirect
++ github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
+diff --git a/cmd/keeper/go.sum b/cmd/keeper/go.sum
+index e3bc204ba8..7b5d264617 100644
+--- a/cmd/keeper/go.sum
++++ b/cmd/keeper/go.sum
+@@ -1,5 +1,7 @@
+-github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
+-github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
++github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
++github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
++github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE=
++github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
+ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
+ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
+ github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
+@@ -32,8 +34,9 @@
+ github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
+ github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
++github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
++github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
+ github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
+ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
+@@ -42,8 +45,8 @@
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
+ github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
+ github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
+-github.com/ethereum/c-kzg-4844/v2 v2.1.3 h1:DQ21UU0VSsuGy8+pcMJHDS0CV1bKmJmxsJYK8l3MiLU=
+-github.com/ethereum/c-kzg-4844/v2 v2.1.3/go.mod h1:fyNcYI/yAuLWJxf4uzVtS8VDKeoAaRM8G/+ADz/pRdA=
++github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
++github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
+ github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
+@@ -68,8 +71,8 @@
+ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
+ github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
+ github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
+-github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
+-github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
++github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
++github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
+ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+ github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+@@ -90,12 +93,17 @@
+ github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
+ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
++github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
++github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
++github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
++github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
+ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
++github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
++github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+ github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM=
+ github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
+ github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
+diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
+index 0000000000..ca095389a3 100644
+--- a/cmd/utils/flags.go
++++ b/cmd/utils/flags.go
+@@ -1964,8 +1964,6 @@
+ cfg.EthDiscoveryURLs = SplitAndTrim(urls)
+ }
+ }
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+ // Only configure sequencer http flag if we're running in verifier mode i.e. --mine is disabled.
+ if ctx.IsSet(RollupSequencerHTTPFlag.Name) && !ctx.IsSet(MiningEnabledFlag.Name) {
+ cfg.RollupSequencerHTTP = ctx.String(RollupSequencerHTTPFlag.Name)
+@@ -1991,11 +1989,9 @@
+ cfg.RollupSequencerTxConditionalEnabled = ctx.Bool(RollupSequencerTxConditionalEnabledFlag.Name)
+ cfg.RollupSequencerTxConditionalCostRateLimit = ctx.Int(RollupSequencerTxConditionalCostRateLimitFlag.Name)
+
+-%%%%%%% Changes from base to side #2
+-+ if ctx.Bool(StateSizeTrackingFlag.Name) {
+-+ cfg.EnableStateSizeTracking = true
+-+ }
+->>>>>>> Conflict 1 of 1 ends
++ if ctx.Bool(StateSizeTrackingFlag.Name) {
++ cfg.EnableStateSizeTracking = true
++ }
+ // Override any default configs for hard coded networks.
+ switch {
+ case ctx.Bool(MainnetFlag.Name):
+diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
+index 0000000000..26ff6ca9aa 100644
+--- a/consensus/beacon/consensus.go
++++ b/consensus/beacon/consensus.go
+@@ -73,23 +73,6 @@
+ return &Beacon{ethone: ethone}
+ }
+
+-<<<<<<< Conflict 1 of 2
+-%%%%%%% Changes from base to side #1
+- // isPostMerge reports whether the given block number is assumed to be post-merge.
+- // Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
+- // PoA chain for unit testing purposes.
+- func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool {
+- mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0
+- return mergedAtGenesis ||
+- config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() ||
+-- config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime
+-+ config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime ||
+-+ // If OP-Stack then bedrock activation number determines when TTD (eth Merge) has been reached.
+-+ config.IsOptimismBedrock(new(big.Int).SetUint64(blockNum))
+- }
+-
+-+++++++ Contents of side #2
+->>>>>>> Conflict 1 of 2 ends
+ // Author implements consensus.Engine, returning the verified author of the block.
+ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
+ if !beacon.IsPoSHeader(header) {
+@@ -493,21 +476,7 @@
+ // the difficulty that a new block should have when created at time
+ // given the parent block's time and difficulty.
+ func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
+-<<<<<<< Conflict 2 of 2
+-+++++++ Contents of side #1
+- // The beacon engine requires access to total difficulties to be able to
+- // seal pre-merge and post-merge blocks. With the transition to removing
+- // old blocks, TDs become unaccessible, thus making TTD based pre-/post-
+- // merge decisions impossible.
+- //
+- // We do not need to seal non-merge blocks anymore live, but we do need
+- // to be able to generate test chains, thus we're reverting to a testing-
+- // settable field to direct that.
+- if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) {
+-%%%%%%% Changes from base to side #2
+-- if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) {
+-+ if !chain.Config().IsPostMerge(parent.Number.Uint64()+1, time) {
+->>>>>>> Conflict 2 of 2 ends
++ if !chain.Config().IsPostMerge(parent.Number.Uint64()+1, time) {
+ return beacon.ethone.CalcDifficulty(chain, time, parent)
+ }
+ return beaconDifficulty
+diff --git a/consensus/misc/create2deployer.go b/consensus/misc/create2deployer.go
+index dbbb26594c..a1cdb4530c 100644
+--- a/consensus/misc/create2deployer.go
++++ b/consensus/misc/create2deployer.go
+@@ -4,6 +4,7 @@
+ _ "embed"
+
+ "github.com/ethereum/go-ethereum/common"
++ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/log"
+@@ -35,5 +36,5 @@
+ return
+ }
+ log.Info("Setting Create2Deployer code", "address", create2DeployerAddress, "codeHash", create2DeployerCodeHash)
+- db.SetCode(create2DeployerAddress, create2DeployerCode)
++ db.SetCode(create2DeployerAddress, create2DeployerCode, tracing.CodeChangeUnspecified)
+ }
+diff --git a/consensus/misc/create2deployer_test.go b/consensus/misc/create2deployer_test.go
+index c547a90fea..f32c6f171f 100644
+--- a/consensus/misc/create2deployer_test.go
++++ b/consensus/misc/create2deployer_test.go
+@@ -7,6 +7,7 @@
+ "github.com/stretchr/testify/assert"
+
+ "github.com/ethereum/go-ethereum/common"
++ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/params"
+ )
+@@ -83,6 +84,8 @@
+ codeSet bool
+ }
+
++var _ vm.StateDB = (*stateDb)(nil)
++
+ func (s *stateDb) GetCodeSize(_ common.Address) int {
+ if s.codeExists {
+ return 1
+@@ -90,7 +93,7 @@
+ return 0
+ }
+
+-func (s *stateDb) SetCode(_ common.Address, _ []byte) []byte {
++func (s *stateDb) SetCode(_ common.Address, _ []byte, _ tracing.CodeChangeReason) []byte {
+ s.codeSet = true
+ return nil
+ }
+diff --git a/core/state_transition.go b/core/state_transition.go
+index 0000000000..925941b20e 100644
+--- a/core/state_transition.go
++++ b/core/state_transition.go
+@@ -164,25 +164,17 @@
+ // or the state prefetching.
+ SkipNonceChecks bool
+
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+- // When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
+- SkipFromEOACheck bool
++ // When set, the message is not treated as a transaction, and certain
++ // transaction-specific checks are skipped:
++ //
++ // - From is not verified to be an EOA
++ // - GasLimit is not checked against the protocol defined tx gaslimit
++ SkipTransactionChecks bool
+
+ IsSystemTx bool // IsSystemTx indicates the message, if also a deposit, does not emit gas usage.
+ IsDepositTx bool // IsDepositTx indicates the message is force-included and can persist a mint.
+ Mint *big.Int // Mint is the amount to mint before EVM processing, or nil if there is no minting.
+ RollupCostData types.RollupCostData // RollupCostData caches data to compute the fee we charge for data availability
+-%%%%%%% Changes from base to side #2
+-- // When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
+-- SkipFromEOACheck bool
+-+ // When set, the message is not treated as a transaction, and certain
+-+ // transaction-specific checks are skipped:
+-+ //
+-+ // - From is not verified to be an EOA
+-+ // - GasLimit is not checked against the protocol defined tx gaslimit
+-+ SkipTransactionChecks bool
+->>>>>>> Conflict 1 of 1 ends
+ }
+
+ // TransactionToMessage converts a transaction into a Message.
+@@ -286,7 +278,7 @@
+ mgval.Mul(mgval, st.msg.GasPrice)
+ var l1Cost *big.Int
+ var operatorCost *uint256.Int
+- if !st.msg.SkipNonceChecks && !st.msg.SkipFromEOACheck {
++ if !st.msg.SkipNonceChecks && !st.msg.SkipTransactionChecks {
+ if st.evm.Context.L1CostFunc != nil {
+ l1Cost = st.evm.Context.L1CostFunc(st.msg.RollupCostData, st.evm.Context.Time)
+ if l1Cost != nil {
+diff --git a/core/tracing/gen_balance_change_reason_stringer.go b/core/tracing/gen_balance_change_reason_stringer.go
+index 2c0ee58fe9..ce05cf5ca8 100644
+--- a/core/tracing/gen_balance_change_reason_stringer.go
++++ b/core/tracing/gen_balance_change_reason_stringer.go
+@@ -27,18 +27,22 @@
+ _ = x[BalanceMint-200]
+ }
+
+-const _BalanceChangeReason_name = "UnspecifiedBalanceIncreaseRewardMineUncleBalanceIncreaseRewardMineBlockBalanceIncreaseWithdrawalBalanceIncreaseGenesisBalanceBalanceIncreaseRewardTransactionFeeBalanceDecreaseGasBuyBalanceIncreaseGasReturnBalanceIncreaseDaoContractBalanceDecreaseDaoAccountTransferTouchAccountBalanceIncreaseSelfdestructBalanceDecreaseSelfdestructBalanceDecreaseSelfdestructBurnRevert"
++const (
++ _BalanceChangeReason_name_0 = "UnspecifiedBalanceIncreaseRewardMineUncleBalanceIncreaseRewardMineBlockBalanceIncreaseWithdrawalBalanceIncreaseGenesisBalanceBalanceIncreaseRewardTransactionFeeBalanceDecreaseGasBuyBalanceIncreaseGasReturnBalanceIncreaseDaoContractBalanceDecreaseDaoAccountTransferTouchAccountBalanceIncreaseSelfdestructBalanceDecreaseSelfdestructBalanceDecreaseSelfdestructBurnRevert"
++ _BalanceChangeReason_name_1 = "BalanceMint"
++)
+
+-var _BalanceChangeReason_index = [...]uint16{0, 11, 41, 71, 96, 125, 160, 181, 205, 231, 256, 264, 276, 303, 330, 361, 367}
++var (
++ _BalanceChangeReason_index_0 = [...]uint16{0, 11, 41, 71, 96, 125, 160, 181, 205, 231, 256, 264, 276, 303, 330, 361, 367}
++)
+
+ func (i BalanceChangeReason) String() string {
+- // OP-Stack addition
+- if i == BalanceMint {
+- return "BalanceMint"
+- }
+-
+- if i >= BalanceChangeReason(len(_BalanceChangeReason_index)-1) {
++ switch {
++ case i <= 15:
++ return _BalanceChangeReason_name_0[_BalanceChangeReason_index_0[i]:_BalanceChangeReason_index_0[i+1]]
++ case i == 200:
++ return _BalanceChangeReason_name_1
++ default:
+ return "BalanceChangeReason(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+- return _BalanceChangeReason_name[_BalanceChangeReason_index[i]:_BalanceChangeReason_index[i+1]]
+ }
+diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go
+index 0000000000..84700339a6 100644
+--- a/core/txpool/blobpool/blobpool.go
++++ b/core/txpool/blobpool/blobpool.go
+@@ -58,20 +58,6 @@
+ // tiny overflows causing all txs to move a shelf higher, wasting disk space.
+ txAvgSize = 4 * 1024
+
+-<<<<<<< Conflict 1 of 5
+-%%%%%%% Changes from base to side #1
+-+ // txBlobOverhead is an approximation of the overhead that an additional blob
+-+ // has on transaction size. This is added to the slotter to avoid tiny
+-+ // overflows causing all txs to move a shelf higher, wasting disk space. A
+-+ // small buffer is added to the proof overhead.
+-+ txBlobOverhead = uint32(kzg4844.CellProofsPerBlob*len(kzg4844.Proof{}) + 64)
+-+
+- // txMaxSize is the maximum size a single transaction can have, outside
+- // the included blobs. Since blob transactions are pulled instead of pushed,
+- // and only a small metadata is kept in ram, the rest is on disk, there is
+- // no critical limit that should be enforced. Still, capping it to some sane
+- // limit can never hurt.
+-+++++++ Contents of side #2
+ // txBlobOverhead is an approximation of the overhead that an additional blob
+ // has on transaction size. This is added to the slotter to avoid tiny
+ // overflows causing all txs to move a shelf higher, wasting disk space. A
+@@ -83,7 +69,6 @@
+ // small metadata is kept in ram, the rest is on disk, there is no critical
+ // limit that should be enforced. Still, capping it to some sane limit can
+ // never hurt, which is aligned with maxBlobsPerTx constraint enforced internally.
+->>>>>>> Conflict 1 of 5 ends
+ txMaxSize = 1024 * 1024
+
+ // maxBlobsPerTx is the maximum number of blobs that a single transaction can
+@@ -107,13 +92,6 @@
+ // limboedTransactionStore is the subfolder containing the currently included
+ // but not yet finalized transaction blobs.
+ limboedTransactionStore = "limbo"
+-<<<<<<< Conflict 2 of 5
+-%%%%%%% Changes from base to side #1
+-+
+-+ // storeVersion is the current slotter layout used for the billy.Database
+-+ // store.
+-+ storeVersion = 1
+-+++++++ Contents of side #2
+
+ // storeVersion is the current slotter layout used for the billy.Database
+ // store.
+@@ -123,7 +101,6 @@
+ // the pool will still accept and convert legacy blob transactions. After this
+ // window, all legacy blob transactions will be rejected.
+ conversionTimeWindow = time.Hour * 2
+->>>>>>> Conflict 2 of 5 ends
+ )
+
+ // blobTxMeta is the minimal subset of types.BlobTx necessary to validate and
+@@ -437,19 +414,6 @@
+ if err != nil {
+ return err
+ }
+-<<<<<<< Conflict 3 of 5
+-%%%%%%% Changes from base to side #1
+- p.head, p.state = head, state
+-
+-+ // Create new slotter for pre-Osaka blob configuration.
+-+ slotter := newSlotter(eip4844.LatestMaxBlobsPerBlock(p.chain.Config()))
+-+
+-+ // See if we need to migrate the queue blob store after fusaka
+-+ slotter, err = tryMigrate(p.chain.Config(), slotter, queuedir)
+-+ if err != nil {
+-+ return err
+-+ }
+-+++++++ Contents of side #2
+ p.head.Store(head)
+ p.state = state
+
+@@ -461,7 +425,6 @@
+ if err != nil {
+ return err
+ }
+->>>>>>> Conflict 3 of 5 ends
+ // Index all transactions on disk and delete anything unprocessable
+ var fails []uint64
+ index := func(id uint64, size uint32, blob []byte) {
+@@ -492,13 +455,7 @@
+ p.recheck(addr, nil)
+ }
+ var (
+-<<<<<<< Conflict 4 of 5
+-+++++++ Contents of side #1
+- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, p.head.Time+1))
+-%%%%%%% Changes from base to side #2
+-- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head))
+-+ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), head))
+->>>>>>> Conflict 4 of 5 ends
++ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), head, head.Time+1))
+ blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
+ )
+ if head.ExcessBlobGas != nil {
+@@ -2232,13 +2189,8 @@
+ p.spent = make(map[common.Address]*uint256.Int)
+
+ var (
+-<<<<<<< Conflict 5 of 5
+-+++++++ Contents of side #1
+- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, p.head.Time))
+-%%%%%%% Changes from base to side #2
+-- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head))
+-+ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head.Load()))
+->>>>>>> Conflict 5 of 5 ends
++ head = p.head.Load()
++ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), head, head.Time))
+ blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
+ )
+ p.evict = newPriceHeap(basefee, blobfee, p.index)
+diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go
+index 0000000000..48f20342b6 100644
+--- a/core/txpool/legacypool/list.go
++++ b/core/txpool/legacypool/list.go
+@@ -373,12 +373,7 @@
+ if overflow {
+ return false, nil
+ }
+-<<<<<<< Conflict 1 of 1
+-%%%%%%% Changes from base to side #1
+-+ l.txCosts[tx.Hash()] = cost // OP-Stack addition
+- l.totalcost.Add(l.totalcost, cost)
+--
+-+++++++ Contents of side #2
++ l.txCosts[tx.Hash()] = cost // OP-Stack addition
+ total, overflow := new(uint256.Int).AddOverflow(l.totalcost, cost)
+ if overflow {
+ return false, nil
+@@ -390,7 +385,6 @@
+ l.subTotalCost([]*types.Transaction{old})
+ }
+
+->>>>>>> Conflict 1 of 1 ends
+ // Otherwise overwrite the old transaction with the current one
+ l.txs.Put(tx)
+ if l.costcap.Cmp(cost) < 0 {
+diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go
+index 0000000000..cdde7a6963 100644
+--- a/core/txpool/subpool.go
++++ b/core/txpool/subpool.go
+@@ -80,21 +80,13 @@
+ BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction
+ GasLimitCap uint64 // Maximum gas can be used for a single transaction execution (0 means no limit)
+
+-<<<<<<< Conflict 1 of 1
+-%%%%%%% Changes from base to side #1
+- OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling)
+- OnlyBlobTxs bool // Return only blob transactions (block blob-space filling)
+-+
+-+ // OP Stack additions
+-+ // Maximum l1 data size allowed for an included transaction (for throttling
+-+ // when batcher is backlogged). Ignored if nil.
+-+ MaxDATxSize *big.Int
+-+++++++ Contents of side #2
+- // When BlobTxs true, return only blob transactions (block blob-space filling)
+- // when false, return only non-blob txs (peer-join announces, block space filling)
+- BlobTxs bool
+- BlobVersion byte // Blob tx version to include. 0 means pre-Osaka, 1 means Osaka and later
+->>>>>>> Conflict 1 of 1 ends
++ OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling)
++ OnlyBlobTxs bool // Return only blob transactions (block blob-space filling)
++
++ // OP Stack additions
++ // Maximum l1 data size allowed for an included transaction (for throttling
++ // when batcher is backlogged). Ignored if nil.
++ MaxDATxSize *big.Int
+ }
+
+ // TxMetadata denotes the metadata of a transaction.
+diff --git a/core/txpool/validation_op_test.go b/core/txpool/validation_op_test.go
+new file mode 100644
+index 0000000000..36f6e78a3a
+--- /dev/null
++++ b/core/txpool/validation_op_test.go
+@@ -0,0 +1,112 @@
++// Copyright 2025 The go-ethereum Authors
++// This file is part of the go-ethereum library.
++//
++// The go-ethereum library is free software: you can redistribute it and/or modify
++// it under the terms of the GNU Lesser General Public License as published by
++// the Free Software Foundation, either version 3 of the License, or
++// (at your option) any later version.
++//
++// The go-ethereum library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++// GNU Lesser General Public License for more details.
++//
++// You should have received a copy of the GNU Lesser General Public License
++// along with the go-ethereum library. If not, see .
++
++package txpool
++
++import (
++ "errors"
++ "math/big"
++ "testing"
++
++ "github.com/ethereum/go-ethereum/common"
++ "github.com/ethereum/go-ethereum/core/types"
++ "github.com/ethereum/go-ethereum/crypto"
++ "github.com/ethereum/go-ethereum/params"
++)
++
++func TestValidateTransactionMaxTxGasLimit(t *testing.T) {
++ // Create a test private key and signer
++ key, _ := crypto.GenerateKey()
++ signer := types.NewEIP155Signer(big.NewInt(1))
++
++ tests := []struct {
++ name string
++ maxTxGasLimit uint64
++ txGasLimit uint64
++ expectError bool
++ expectedError error
++ }{
++ {
++ name: "No limit set",
++ maxTxGasLimit: 0,
++ txGasLimit: 1000000,
++ expectError: false,
++ },
++ {
++ name: "Under limit",
++ maxTxGasLimit: 100000,
++ txGasLimit: 50000,
++ expectError: false,
++ },
++ {
++ name: "At limit",
++ maxTxGasLimit: 100000,
++ txGasLimit: 100000,
++ expectError: false,
++ },
++ {
++ name: "Over limit",
++ maxTxGasLimit: 100000,
++ txGasLimit: 150000,
++ expectError: true,
++ expectedError: ErrTxGasLimitExceeded,
++ },
++ }
++
++ for _, test := range tests {
++ t.Run(test.name, func(t *testing.T) {
++ // Create test transaction with specified gas limit
++ tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), test.txGasLimit, big.NewInt(1000000000), nil)
++
++ // Sign the transaction
++ signedTx, err := types.SignTx(tx, signer, key)
++ if err != nil {
++ t.Fatalf("Failed to sign transaction: %v", err)
++ }
++
++ // Create minimal validation options
++ opts := &ValidationOptions{
++ Config: params.TestChainConfig,
++ Accept: 1 << types.LegacyTxType,
++ MaxSize: 32 * 1024,
++ MinTip: big.NewInt(0),
++ MaxTxGasLimit: test.maxTxGasLimit,
++ }
++
++ // Create test header with high gas limit to not interfere
++ header := &types.Header{
++ Number: big.NewInt(1),
++ GasLimit: 10000000,
++ Time: 0,
++ Difficulty: big.NewInt(0),
++ }
++
++ err = ValidateTransaction(signedTx, header, signer, opts)
++
++ if test.expectError {
++ if err == nil {
++ t.Errorf("Expected error but got none")
++ } else if !errors.Is(err, test.expectedError) {
++ t.Errorf("Expected error %v, got %v", test.expectedError, err)
++ }
++ } else {
++ if err != nil {
++ t.Errorf("Unexpected error: %v", err)
++ }
++ }
++ })
++ }
++}
+diff --git a/core/txpool/validation_test.go b/core/txpool/validation_test.go
+index 0000000000..3945b548c1 100644
+--- a/core/txpool/validation_test.go
++++ b/core/txpool/validation_test.go
+@@ -1,5 +1,3 @@
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+ // Copyright 2025 The go-ethereum Authors
+ // This file is part of the go-ethereum library.
+ //
+@@ -19,213 +17,99 @@
+ package txpool
+
+ import (
++ "crypto/ecdsa"
+ "errors"
++ "math"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
++ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+ )
+
+-func TestValidateTransactionMaxTxGasLimit(t *testing.T) {
+- // Create a test private key and signer
+- key, _ := crypto.GenerateKey()
+- signer := types.NewEIP155Signer(big.NewInt(1))
++func TestValidateTransactionEIP2681(t *testing.T) {
++ key, err := crypto.GenerateKey()
++ if err != nil {
++ t.Fatal(err)
++ }
++
++ head := &types.Header{
++ Number: big.NewInt(1),
++ GasLimit: 5000000,
++ Time: 1,
++ Difficulty: big.NewInt(1),
++ }
++
++ signer := types.LatestSigner(params.TestChainConfig)
++
++ // Create validation options
++ opts := &ValidationOptions{
++ Config: params.TestChainConfig,
++ Accept: 0xFF, // Accept all transaction types
++ MaxSize: 32 * 1024,
++ MaxBlobCount: 6,
++ MinTip: big.NewInt(0),
++ }
+
+ tests := []struct {
+- name string
+- maxTxGasLimit uint64
+- txGasLimit uint64
+- expectError bool
+- expectedError error
++ name string
++ nonce uint64
++ wantErr error
+ }{
+ {
+- name: "No limit set",
+- maxTxGasLimit: 0,
+- txGasLimit: 1000000,
+- expectError: false,
+- },
+- {
+- name: "Under limit",
+- maxTxGasLimit: 100000,
+- txGasLimit: 50000,
+- expectError: false,
+- },
+- {
+- name: "At limit",
+- maxTxGasLimit: 100000,
+- txGasLimit: 100000,
+- expectError: false,
+- },
+- {
+- name: "Over limit",
+- maxTxGasLimit: 100000,
+- txGasLimit: 150000,
+- expectError: true,
+- expectedError: ErrTxGasLimitExceeded,
++ name: "normal nonce",
++ nonce: 42,
++ wantErr: nil,
++ },
++ {
++ name: "max allowed nonce (2^64-2)",
++ nonce: math.MaxUint64 - 1,
++ wantErr: nil,
++ },
++ {
++ name: "EIP-2681 nonce overflow (2^64-1)",
++ nonce: math.MaxUint64,
++ wantErr: core.ErrNonceMax,
+ },
+ }
+
+- for _, test := range tests {
+- t.Run(test.name, func(t *testing.T) {
+- // Create test transaction with specified gas limit
+- tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), test.txGasLimit, big.NewInt(1000000000), nil)
+-
+- // Sign the transaction
+- signedTx, err := types.SignTx(tx, signer, key)
+- if err != nil {
+- t.Fatalf("Failed to sign transaction: %v", err)
+- }
+-
+- // Create minimal validation options
+- opts := &ValidationOptions{
+- Config: params.TestChainConfig,
+- Accept: 1 << types.LegacyTxType,
+- MaxSize: 32 * 1024,
+- MinTip: big.NewInt(0),
+- MaxTxGasLimit: test.maxTxGasLimit,
+- }
+-
+- // Create test header with high gas limit to not interfere
+- header := &types.Header{
+- Number: big.NewInt(1),
+- GasLimit: 10000000,
+- Time: 0,
+- Difficulty: big.NewInt(0),
+- }
+-
+- err = ValidateTransaction(signedTx, header, signer, opts)
+-
+- if test.expectError {
++ for _, tt := range tests {
++ t.Run(tt.name, func(t *testing.T) {
++ tx := createTestTransaction(key, tt.nonce)
++ err := ValidateTransaction(tx, head, signer, opts)
++
++ if tt.wantErr == nil {
++ if err != nil {
++ t.Errorf("ValidateTransaction() error = %v, wantErr nil", err)
++ }
++ } else {
+ if err == nil {
+- t.Errorf("Expected error but got none")
+- } else if !errors.Is(err, test.expectedError) {
+- t.Errorf("Expected error %v, got %v", test.expectedError, err)
+- }
+- } else {
+- if err != nil {
+- t.Errorf("Unexpected error: %v", err)
++ t.Errorf("ValidateTransaction() error = nil, wantErr %v", tt.wantErr)
++ } else if !errors.Is(err, tt.wantErr) {
++ t.Errorf("ValidateTransaction() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ }
+ })
+ }
+ }
+-%%%%%%% Changes from base to side #2
+-+// Copyright 2025 The go-ethereum Authors
+-+// This file is part of the go-ethereum library.
+-+//
+-+// The go-ethereum library is free software: you can redistribute it and/or modify
+-+// it under the terms of the GNU Lesser General Public License as published by
+-+// the Free Software Foundation, either version 3 of the License, or
+-+// (at your option) any later version.
+-+//
+-+// The go-ethereum library is distributed in the hope that it will be useful,
+-+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+-+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-+// GNU Lesser General Public License for more details.
+-+//
+-+// You should have received a copy of the GNU Lesser General Public License
+-+// along with the go-ethereum library. If not, see .
+-+
+-+package txpool
+-+
+-+import (
+-+ "crypto/ecdsa"
+-+ "errors"
+-+ "math"
+-+ "math/big"
+-+ "testing"
+-+
+-+ "github.com/ethereum/go-ethereum/common"
+-+ "github.com/ethereum/go-ethereum/core"
+-+ "github.com/ethereum/go-ethereum/core/types"
+-+ "github.com/ethereum/go-ethereum/crypto"
+-+ "github.com/ethereum/go-ethereum/params"
+-+)
+-+
+-+func TestValidateTransactionEIP2681(t *testing.T) {
+-+ key, err := crypto.GenerateKey()
+-+ if err != nil {
+-+ t.Fatal(err)
+-+ }
+-+
+-+ head := &types.Header{
+-+ Number: big.NewInt(1),
+-+ GasLimit: 5000000,
+-+ Time: 1,
+-+ Difficulty: big.NewInt(1),
+-+ }
+-+
+-+ signer := types.LatestSigner(params.TestChainConfig)
+-+
+-+ // Create validation options
+-+ opts := &ValidationOptions{
+-+ Config: params.TestChainConfig,
+-+ Accept: 0xFF, // Accept all transaction types
+-+ MaxSize: 32 * 1024,
+-+ MaxBlobCount: 6,
+-+ MinTip: big.NewInt(0),
+-+ }
+-+
+-+ tests := []struct {
+-+ name string
+-+ nonce uint64
+-+ wantErr error
+-+ }{
+-+ {
+-+ name: "normal nonce",
+-+ nonce: 42,
+-+ wantErr: nil,
+-+ },
+-+ {
+-+ name: "max allowed nonce (2^64-2)",
+-+ nonce: math.MaxUint64 - 1,
+-+ wantErr: nil,
+-+ },
+-+ {
+-+ name: "EIP-2681 nonce overflow (2^64-1)",
+-+ nonce: math.MaxUint64,
+-+ wantErr: core.ErrNonceMax,
+-+ },
+-+ }
+-+
+-+ for _, tt := range tests {
+-+ t.Run(tt.name, func(t *testing.T) {
+-+ tx := createTestTransaction(key, tt.nonce)
+-+ err := ValidateTransaction(tx, head, signer, opts)
+-+
+-+ if tt.wantErr == nil {
+-+ if err != nil {
+-+ t.Errorf("ValidateTransaction() error = %v, wantErr nil", err)
+-+ }
+-+ } else {
+-+ if err == nil {
+-+ t.Errorf("ValidateTransaction() error = nil, wantErr %v", tt.wantErr)
+-+ } else if !errors.Is(err, tt.wantErr) {
+-+ t.Errorf("ValidateTransaction() error = %v, wantErr %v", err, tt.wantErr)
+-+ }
+-+ }
+-+ })
+-+ }
+-+}
+-+
+-+// createTestTransaction creates a basic transaction for testing
+-+func createTestTransaction(key *ecdsa.PrivateKey, nonce uint64) *types.Transaction {
+-+ to := common.HexToAddress("0x0000000000000000000000000000000000000001")
+-+
+-+ txdata := &types.LegacyTx{
+-+ Nonce: nonce,
+-+ To: &to,
+-+ Value: big.NewInt(1000),
+-+ Gas: 21000,
+-+ GasPrice: big.NewInt(1),
+-+ Data: nil,
+-+ }
+-+
+-+ tx := types.NewTx(txdata)
+-+ signedTx, _ := types.SignTx(tx, types.HomesteadSigner{}, key)
+-+ return signedTx
+-+}
+->>>>>>> Conflict 1 of 1 ends
++
++// createTestTransaction creates a basic transaction for testing
++func createTestTransaction(key *ecdsa.PrivateKey, nonce uint64) *types.Transaction {
++ to := common.HexToAddress("0x0000000000000000000000000000000000000001")
++
++ txdata := &types.LegacyTx{
++ Nonce: nonce,
++ To: &to,
++ Value: big.NewInt(1000),
++ Gas: 21000,
++ GasPrice: big.NewInt(1),
++ Data: nil,
++ }
++
++ tx := types.NewTx(txdata)
++ signedTx, _ := types.SignTx(tx, types.HomesteadSigner{}, key)
++ return signedTx
++}
+diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go
+index b3735d7156..486acc0370 100644
+--- a/core/types/gen_receipt_json.go
++++ b/core/types/gen_receipt_json.go
+@@ -72,6 +72,8 @@
+ enc.OperatorFeeScalar = (*hexutil.Uint64)(r.OperatorFeeScalar)
+ enc.OperatorFeeConstant = (*hexutil.Uint64)(r.OperatorFeeConstant)
+ enc.DAFootprintGasScalar = (*hexutil.Uint64)(r.DAFootprintGasScalar)
++ enc.OperatorFeeScalar = (*hexutil.Uint64)(r.OperatorFeeScalar)
++ enc.OperatorFeeConstant = (*hexutil.Uint64)(r.OperatorFeeConstant)
+ return json.Marshal(&enc)
+ }
+
+diff --git a/eth/api_debug.go b/eth/api_debug.go
+index 0000000000..6680d692ca 100644
+--- a/eth/api_debug.go
++++ b/eth/api_debug.go
+@@ -24,7 +24,6 @@
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/stateless"
+@@ -448,52 +447,6 @@
+ }
+ return api.eth.blockchain.GetTrieFlushInterval().String(), nil
+ }
+-<<<<<<< Conflict 1 of 1
+-%%%%%%% Changes from base to side #1
+-+
+-+func (api *DebugAPI) ExecutionWitness(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*stateless.ExecutionWitness, error) {
+-+ block, err := api.eth.APIBackend.BlockByNumberOrHash(ctx, blockNrOrHash)
+-+ if err != nil {
+-+ return nil, fmt.Errorf("failed to retrieve block: %w", err)
+-+ }
+-+ if block == nil {
+-+ return nil, fmt.Errorf("block not found: %s", blockNrOrHash.String())
+-+ }
+-+
+-+ witness, err := generateWitness(api.eth.blockchain, block)
+-+ return witness.ToExecutionWitness(), err
+-+}
+-+
+-+func generateWitness(blockchain *core.BlockChain, block *types.Block) (*stateless.Witness, error) {
+-+ witness, err := stateless.NewWitness(block.Header(), blockchain)
+-+ if err != nil {
+-+ return nil, fmt.Errorf("failed to create witness: %w", err)
+-+ }
+-+
+-+ parentHeader := witness.Headers[0]
+-+ statedb, err := blockchain.StateAt(parentHeader.Root)
+-+ if err != nil {
+-+ return nil, fmt.Errorf("failed to retrieve parent state: %w", err)
+-+ }
+-+
+-+ statedb.StartPrefetcher("debug_execution_witness", witness, nil)
+-+ defer statedb.StopPrefetcher()
+-+
+-+ res, err := blockchain.Processor().Process(block, statedb, *blockchain.GetVMConfig())
+-+ if err != nil {
+-+ return nil, fmt.Errorf("failed to process block %d: %w", block.Number(), err)
+-+ }
+-+
+-+ // OP-Stack warning: below has the side-effect of including the withdrawals storage-root
+-+ // into the execution witness through the storage lookup by ValidateState, triggering the pre-fetcher.
+-+ // The Process function only runs through Finalize steps, not through FinalizeAndAssemble, missing merkleization.
+-+ if err := blockchain.Validator().ValidateState(block, statedb, res, false); err != nil {
+-+ return nil, fmt.Errorf("failed to validate block %d: %w", block.Number(), err)
+-+ }
+-+
+-+ return witness, nil
+-+}
+-+++++++ Contents of side #2
+
+ // StateSize returns the current state size statistics from the state size tracker.
+ // Returns an error if the state size tracker is not initialized or if stats are not ready.
+@@ -582,4 +535,3 @@
+
+ return result.Witness().ToExtWitness(), nil
+ }
+->>>>>>> Conflict 1 of 1 ends
+diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go
+index fe1fcef68c..034026b366 100644
+--- a/eth/api_debug_test.go
++++ b/eth/api_debug_test.go
+@@ -40,7 +40,6 @@
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
+ "github.com/stretchr/testify/assert"
+- "github.com/stretchr/testify/require"
+ )
+
+ var dumper = spew.ConfigState{Indent: " "}
+@@ -336,30 +335,3 @@
+ }
+ })
+ }
+-
+-func TestExecutionWitness(t *testing.T) {
+- t.Parallel()
+-
+- // Create a database pre-initialize with a genesis block
+- db := rawdb.NewMemoryDatabase()
+- gspec := &core.Genesis{
+- Config: params.TestChainConfig,
+- Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
+- }
+- chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil)
+-
+- blockNum := 10
+- _, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blockNum, nil)
+- if _, err := chain.InsertChain(bs); err != nil {
+- panic(err)
+- }
+-
+- block := chain.GetBlockByNumber(uint64(blockNum - 1))
+- require.NotNil(t, block)
+-
+- witness, err := generateWitness(chain, block)
+- require.NoError(t, err)
+-
+- _, _, err = core.ExecuteStateless(params.TestChainConfig, *chain.GetVMConfig(), block, witness)
+- require.NoError(t, err)
+-}
+diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go
+index 0000000000..a263f41f0b 100644
+--- a/eth/catalyst/api.go
++++ b/eth/catalyst/api.go
+@@ -673,52 +673,24 @@
+
+ // NewPayloadV4 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
+ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) {
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+- if params.Withdrawals == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
+- }
+- if params.ExcessBlobGas == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
+- }
+- if params.BlobGasUsed == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
+- }
+-
+- if versionedHashes == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
+- }
+- if beaconRoot == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
+- }
+- if executionRequests == nil {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague"))
+- }
+-
+- if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
+- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads"))
+- }
+-
+-%%%%%%% Changes from base to side #2
+- switch {
+- case params.Withdrawals == nil:
+- return invalidStatus, paramsErr("nil withdrawals post-shanghai")
+- case params.ExcessBlobGas == nil:
+- return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
+- case params.BlobGasUsed == nil:
+- return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
+- case versionedHashes == nil:
+- return invalidStatus, paramsErr("nil versionedHashes post-cancun")
+- case beaconRoot == nil:
+- return invalidStatus, paramsErr("nil beaconRoot post-cancun")
+- case executionRequests == nil:
+- return invalidStatus, paramsErr("nil executionRequests post-prague")
+-- case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka):
+-- return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
+-+ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+-+ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads")
+- }
+->>>>>>> Conflict 1 of 1 ends
++ switch {
++ case params.Withdrawals == nil:
++ return invalidStatus, paramsErr("nil withdrawals post-shanghai")
++ case params.ExcessBlobGas == nil:
++ return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
++ case params.BlobGasUsed == nil:
++ return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
++ case versionedHashes == nil:
++ return invalidStatus, paramsErr("nil versionedHashes post-cancun")
++ case beaconRoot == nil:
++ return invalidStatus, paramsErr("nil beaconRoot post-cancun")
++ case executionRequests == nil:
++ return invalidStatus, paramsErr("nil executionRequests post-prague")
++ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka):
++ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
++ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
++ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads")
++ }
+ requests := convertRequests(executionRequests)
+ if err := validateRequests(requests); err != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err)
+diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go
+index 0000000000..d538a57c1c 100644
+--- a/eth/catalyst/api_test.go
++++ b/eth/catalyst/api_test.go
+@@ -448,21 +448,7 @@
+ t.Fatal("can't create node:", err)
+ }
+
+-<<<<<<< Conflict 1 of 1
+-%%%%%%% Changes from base to side #1
+-- mcfg := miner.DefaultConfig
+-- ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: ethconfig.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg}
+-+ // OP-Stack test modification: default eth config is moved to startEthService, for reuse.
+-+++++++ Contents of side #2
+- ethcfg := ðconfig.Config{
+- Genesis: genesis,
+- SyncMode: ethconfig.FullSync,
+- TrieTimeout: time.Minute,
+- TrieDirtyCache: 256,
+- TrieCleanCache: 256,
+- Miner: miner.DefaultConfig,
+- }
+->>>>>>> Conflict 1 of 1 ends
++ // OP-Stack test modification: default eth config is moved to startEthService, for reuse.
+ ethservice, err := eth.New(n, ethcfg)
+ if err != nil {
+ t.Fatal("can't create eth service:", err)
+diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
+index 0000000000..30ec163a88 100644
+--- a/eth/ethconfig/gen_config.go
++++ b/eth/ethconfig/gen_config.go
+@@ -17,8 +17,6 @@
+ // MarshalTOML marshals as TOML.
+ func (c Config) MarshalTOML() (interface{}, error) {
+ type Config struct {
+-<<<<<<< Conflict 1 of 2
+-+++++++ Contents of side #1
+ Genesis *core.Genesis `toml:",omitempty"`
+ NetworkId uint64
+ SyncMode SyncMode
+@@ -46,17 +44,23 @@
+ SnapshotCache int
+ Preimages bool
+ FilterLogCacheSize int
++ LogQueryLimit int
+ Miner miner.Config
+ TxPool legacypool.Config
+ BlobPool blobpool.Config
+ GPO gasprice.Config
+ EnablePreimageRecording bool
++ EnableWitnessStats bool
++ StatelessSelfValidation bool
++ EnableStateSizeTracking bool
+ VMTrace string
+ VMTraceJsonConfig string
+ RPCGasCap uint64
+ RPCEVMTimeout time.Duration
+ RPCTxFeeCap float64
+ OverrideOsaka *uint64 `toml:",omitempty"`
++ OverrideBPO1 *uint64 `toml:",omitempty"`
++ OverrideBPO2 *uint64 `toml:",omitempty"`
+ OverrideVerkle *uint64 `toml:",omitempty"`
+ OverrideOptimismCanyon *uint64 `toml:",omitempty"`
+ OverrideOptimismEcotone *uint64 `toml:",omitempty"`
+@@ -79,53 +83,6 @@
+ RollupHaltOnIncompatibleProtocolVersion string
+ InteropMessageRPC string `toml:",omitempty"`
+ InteropMempoolFiltering bool `toml:",omitempty"`
+-%%%%%%% Changes from base to side #2
+- Genesis *core.Genesis `toml:",omitempty"`
+- NetworkId uint64
+- SyncMode SyncMode
+- HistoryMode history.HistoryMode
+- EthDiscoveryURLs []string
+- SnapDiscoveryURLs []string
+- NoPruning bool
+- NoPrefetch bool
+- TxLookupLimit uint64 `toml:",omitempty"`
+- TransactionHistory uint64 `toml:",omitempty"`
+- LogHistory uint64 `toml:",omitempty"`
+- LogNoHistory bool `toml:",omitempty"`
+- LogExportCheckpoints string
+- StateHistory uint64 `toml:",omitempty"`
+- StateScheme string `toml:",omitempty"`
+- RequiredBlocks map[uint64]common.Hash `toml:"-"`
+- SkipBcVersionCheck bool `toml:"-"`
+- DatabaseHandles int `toml:"-"`
+- DatabaseCache int
+- DatabaseFreezer string
+- DatabaseEra string
+- TrieCleanCache int
+- TrieDirtyCache int
+- TrieTimeout time.Duration
+- SnapshotCache int
+- Preimages bool
+- FilterLogCacheSize int
+-+ LogQueryLimit int
+- Miner miner.Config
+- TxPool legacypool.Config
+- BlobPool blobpool.Config
+- GPO gasprice.Config
+- EnablePreimageRecording bool
+-+ EnableWitnessStats bool
+-+ StatelessSelfValidation bool
+-+ EnableStateSizeTracking bool
+- VMTrace string
+- VMTraceJsonConfig string
+- RPCGasCap uint64
+- RPCEVMTimeout time.Duration
+- RPCTxFeeCap float64
+- OverrideOsaka *uint64 `toml:",omitempty"`
+-+ OverrideBPO1 *uint64 `toml:",omitempty"`
+-+ OverrideBPO2 *uint64 `toml:",omitempty"`
+- OverrideVerkle *uint64 `toml:",omitempty"`
+->>>>>>> Conflict 1 of 2 ends
+ }
+ var enc Config
+ enc.Genesis = c.Genesis
+@@ -200,8 +157,6 @@
+ // UnmarshalTOML unmarshals from TOML.
+ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
+ type Config struct {
+-<<<<<<< Conflict 2 of 2
+-+++++++ Contents of side #1
+ Genesis *core.Genesis `toml:",omitempty"`
+ NetworkId *uint64
+ SyncMode *SyncMode
+@@ -229,17 +184,23 @@
+ SnapshotCache *int
+ Preimages *bool
+ FilterLogCacheSize *int
++ LogQueryLimit *int
+ Miner *miner.Config
+ TxPool *legacypool.Config
+ BlobPool *blobpool.Config
+ GPO *gasprice.Config
+ EnablePreimageRecording *bool
++ EnableWitnessStats *bool
++ StatelessSelfValidation *bool
++ EnableStateSizeTracking *bool
+ VMTrace *string
+ VMTraceJsonConfig *string
+ RPCGasCap *uint64
+ RPCEVMTimeout *time.Duration
+ RPCTxFeeCap *float64
+ OverrideOsaka *uint64 `toml:",omitempty"`
++ OverrideBPO1 *uint64 `toml:",omitempty"`
++ OverrideBPO2 *uint64 `toml:",omitempty"`
+ OverrideVerkle *uint64 `toml:",omitempty"`
+ OverrideOptimismCanyon *uint64 `toml:",omitempty"`
+ OverrideOptimismEcotone *uint64 `toml:",omitempty"`
+@@ -262,53 +223,6 @@
+ RollupHaltOnIncompatibleProtocolVersion *string
+ InteropMessageRPC *string `toml:",omitempty"`
+ InteropMempoolFiltering *bool `toml:",omitempty"`
+-%%%%%%% Changes from base to side #2
+- Genesis *core.Genesis `toml:",omitempty"`
+- NetworkId *uint64
+- SyncMode *SyncMode
+- HistoryMode *history.HistoryMode
+- EthDiscoveryURLs []string
+- SnapDiscoveryURLs []string
+- NoPruning *bool
+- NoPrefetch *bool
+- TxLookupLimit *uint64 `toml:",omitempty"`
+- TransactionHistory *uint64 `toml:",omitempty"`
+- LogHistory *uint64 `toml:",omitempty"`
+- LogNoHistory *bool `toml:",omitempty"`
+- LogExportCheckpoints *string
+- StateHistory *uint64 `toml:",omitempty"`
+- StateScheme *string `toml:",omitempty"`
+- RequiredBlocks map[uint64]common.Hash `toml:"-"`
+- SkipBcVersionCheck *bool `toml:"-"`
+- DatabaseHandles *int `toml:"-"`
+- DatabaseCache *int
+- DatabaseFreezer *string
+- DatabaseEra *string
+- TrieCleanCache *int
+- TrieDirtyCache *int
+- TrieTimeout *time.Duration
+- SnapshotCache *int
+- Preimages *bool
+- FilterLogCacheSize *int
+-+ LogQueryLimit *int
+- Miner *miner.Config
+- TxPool *legacypool.Config
+- BlobPool *blobpool.Config
+- GPO *gasprice.Config
+- EnablePreimageRecording *bool
+-+ EnableWitnessStats *bool
+-+ StatelessSelfValidation *bool
+-+ EnableStateSizeTracking *bool
+- VMTrace *string
+- VMTraceJsonConfig *string
+- RPCGasCap *uint64
+- RPCEVMTimeout *time.Duration
+- RPCTxFeeCap *float64
+- OverrideOsaka *uint64 `toml:",omitempty"`
+-+ OverrideBPO1 *uint64 `toml:",omitempty"`
+-+ OverrideBPO2 *uint64 `toml:",omitempty"`
+- OverrideVerkle *uint64 `toml:",omitempty"`
+->>>>>>> Conflict 2 of 2 ends
+ }
+ var dec Config
+ if err := unmarshal(&dec); err != nil {
+diff --git a/go.mod b/go.mod
+index 0000000000..8b147c68af 100644
+--- a/go.mod
++++ b/go.mod
+@@ -22,16 +22,9 @@
+ github.com/deckarep/golang-set/v2 v2.6.0
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
+ github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0
+-<<<<<<< Conflict 1 of 2
+-+++++++ Contents of side #1
+ github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
+ github.com/ethereum/c-kzg-4844/v2 v2.1.5
+-%%%%%%% Changes from base to side #2
+- github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
+-- github.com/ethereum/c-kzg-4844/v2 v2.1.0
+-+ github.com/ethereum/c-kzg-4844/v2 v2.1.3
+-+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab
+->>>>>>> Conflict 1 of 2 ends
++ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab
+ github.com/ethereum/go-verkle v0.2.2
+ github.com/fatih/color v1.16.0
+ github.com/ferranbt/fastssz v0.1.4
+@@ -53,7 +46,6 @@
+ github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
+ github.com/jackpal/go-nat-pmp v1.0.2
+ github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
+- github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52
+ github.com/klauspost/compress v1.17.11
+ github.com/kylelemons/godebug v1.1.0
+ github.com/mattn/go-colorable v0.1.13
+@@ -69,13 +61,7 @@
+ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
+ github.com/status-im/keycard-go v0.2.0
+ github.com/stretchr/testify v1.10.0
+-<<<<<<< Conflict 2 of 2
+-%%%%%%% Changes from base to side #1
+-- github.com/supranational/blst v0.3.14
+-+ github.com/supranational/blst v0.3.15
+-+++++++ Contents of side #2
+ github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe
+->>>>>>> Conflict 2 of 2 ends
+ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
+ github.com/urfave/cli/v2 v2.27.5
+ go.uber.org/automaxprocs v1.5.2
+diff --git a/go.sum b/go.sum
+index 0000000000..099b1a6f15 100644
+--- a/go.sum
++++ b/go.sum
+@@ -115,18 +115,10 @@
+ github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
+ github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
+ github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
+-<<<<<<< Conflict 1 of 2
+-%%%%%%% Changes from base to side #1
+--github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w=
+--github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E=
+-+github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
+-+github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
+-+++++++ Contents of side #2
+-github.com/ethereum/c-kzg-4844/v2 v2.1.3 h1:DQ21UU0VSsuGy8+pcMJHDS0CV1bKmJmxsJYK8l3MiLU=
+-github.com/ethereum/c-kzg-4844/v2 v2.1.3/go.mod h1:fyNcYI/yAuLWJxf4uzVtS8VDKeoAaRM8G/+ADz/pRdA=
++github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
++github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
+->>>>>>> Conflict 1 of 2 ends
+ github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
+ github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
+ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+@@ -226,8 +218,6 @@
+ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+-github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=
+-github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8=
+ github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
+ github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
+ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+@@ -365,16 +355,8 @@
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+-<<<<<<< Conflict 2 of 2
+-%%%%%%% Changes from base to side #1
+--github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo=
+--github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+-+github.com/supranational/blst v0.3.15 h1:rd9viN6tfARE5wv3KZJ9H8e1cg0jXW8syFCcsbHa76o=
+-+github.com/supranational/blst v0.3.15/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+-+++++++ Contents of side #2
+ github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw=
+ github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+->>>>>>> Conflict 2 of 2 ends
+ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
+ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
+ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+diff --git a/miner/miner.go b/miner/miner.go
+index 0000000000..eff79fa472 100644
+--- a/miner/miner.go
++++ b/miner/miner.go
+@@ -83,15 +83,8 @@
+
+ // DefaultConfig contains default settings for miner.
+ var DefaultConfig = Config{
+-<<<<<<< Conflict 1 of 1
+-+++++++ Contents of side #1
+- GasCeil: 45_000_000,
++ GasCeil: 60_000_000,
+ GasPrice: big.NewInt(params.Wei),
+-%%%%%%% Changes from base to side #2
+-- GasCeil: 45_000_000,
+-+ GasCeil: 60_000_000,
+- GasPrice: big.NewInt(params.GWei / 1000),
+->>>>>>> Conflict 1 of 1 ends
+
+ // The default recommit time is chosen as two seconds since
+ // consensus-layer usually will wait a half slot of time(6s)
+diff --git a/params/config.go b/params/config.go
+index b90cc2c2ff..79d7a7c2ab 100644
+--- a/params/config.go
++++ b/params/config.go
+@@ -802,7 +802,9 @@
+ mergedAtGenesis := c.TerminalTotalDifficulty != nil && c.TerminalTotalDifficulty.Sign() == 0
+ return mergedAtGenesis ||
+ c.MergeNetsplitBlock != nil && blockNum >= c.MergeNetsplitBlock.Uint64() ||
+- c.ShanghaiTime != nil && timestamp >= *c.ShanghaiTime
++ c.ShanghaiTime != nil && timestamp >= *c.ShanghaiTime ||
++ // If OP-Stack then bedrock activation number determines when TTD (eth Merge) has been reached.
++ c.IsOptimismBedrock(new(big.Int).SetUint64(blockNum))
+ }
+
+ // IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
index 366cce89fd..26ff6ca9aa 100644
--- a/consensus/beacon/consensus.go
+++ b/consensus/beacon/consensus.go
@@ -73,18 +73,6 @@ func New(ethone consensus.Engine) *Beacon {
return &Beacon{ethone: ethone}
}
-// isPostMerge reports whether the given block number is assumed to be post-merge.
-// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
-// PoA chain for unit testing purposes.
-func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool {
- mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0
- return mergedAtGenesis ||
- config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() ||
- config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime ||
- // If OP-Stack then bedrock activation number determines when TTD (eth Merge) has been reached.
- config.IsOptimismBedrock(new(big.Int).SetUint64(blockNum))
-}
-
// Author implements consensus.Engine, returning the verified author of the block.
func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
if !beacon.IsPoSHeader(header) {
@@ -351,7 +339,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
// Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the beacon protocol. The changes are done inline.
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
- if !isPostMerge(chain.Config(), header.Number.Uint64(), header.Time) {
+ if !chain.Config().IsPostMerge(header.Number.Uint64(), header.Time) {
return beacon.ethone.Prepare(chain, header)
}
header.Difficulty = beaconDifficulty
@@ -488,15 +476,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash {
// the difficulty that a new block should have when created at time
// given the parent block's time and difficulty.
func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
- // The beacon engine requires access to total difficulties to be able to
- // seal pre-merge and post-merge blocks. With the transition to removing
- // old blocks, TDs become unaccessible, thus making TTD based pre-/post-
- // merge decisions impossible.
- //
- // We do not need to seal non-merge blocks anymore live, but we do need
- // to be able to generate test chains, thus we're reverting to a testing-
- // settable field to direct that.
- if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) {
+ if !chain.Config().IsPostMerge(parent.Number.Uint64()+1, time) {
return beacon.ethone.CalcDifficulty(chain, time, parent)
}
return beaconDifficulty
diff --git a/consensus/misc/create2deployer.go b/consensus/misc/create2deployer.go
index dbbb26594c..a1cdb4530c 100644
--- a/consensus/misc/create2deployer.go
+++ b/consensus/misc/create2deployer.go
@@ -4,6 +4,7 @@ import (
_ "embed"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
@@ -35,5 +36,5 @@ func EnsureCreate2Deployer(c *params.ChainConfig, timestamp uint64, db vm.StateD
return
}
log.Info("Setting Create2Deployer code", "address", create2DeployerAddress, "codeHash", create2DeployerCodeHash)
- db.SetCode(create2DeployerAddress, create2DeployerCode)
+ db.SetCode(create2DeployerAddress, create2DeployerCode, tracing.CodeChangeUnspecified)
}
diff --git a/consensus/misc/create2deployer_test.go b/consensus/misc/create2deployer_test.go
index c547a90fea..f32c6f171f 100644
--- a/consensus/misc/create2deployer_test.go
+++ b/consensus/misc/create2deployer_test.go
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
@@ -83,6 +84,8 @@ type stateDb struct {
codeSet bool
}
+var _ vm.StateDB = (*stateDb)(nil)
+
func (s *stateDb) GetCodeSize(_ common.Address) int {
if s.codeExists {
return 1
@@ -90,7 +93,7 @@ func (s *stateDb) GetCodeSize(_ common.Address) int {
return 0
}
-func (s *stateDb) SetCode(_ common.Address, _ []byte) []byte {
+func (s *stateDb) SetCode(_ common.Address, _ []byte, _ tracing.CodeChangeReason) []byte {
s.codeSet = true
return nil
}
diff --git a/core/bench_test.go b/core/bench_test.go
index 2830022662..932188f8e2 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -301,7 +301,7 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin
func benchWriteChain(b *testing.B, full bool, count uint64) {
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false)
if err != nil {
b.Fatalf("error opening database: %v", err)
@@ -326,9 +326,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
db.Close()
options := DefaultConfig().WithArchive(true)
b.ReportAllocs()
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
pdb, err = pebble.New(dir, 1024, 128, "", false)
if err != nil {
b.Fatalf("error opening database: %v", err)
diff --git a/core/blockchain.go b/core/blockchain.go
index 365b864dc0..c6289afba3 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -21,7 +21,6 @@ import (
"errors"
"fmt"
"io"
- "math"
"math/big"
"runtime"
"slices"
@@ -168,10 +167,13 @@ type BlockChainConfig struct {
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
TrieJournalDirectory string // Directory path to the journal used for persisting trie data across node restarts
- Preimages bool // Whether to store preimage of trie key to the disk
- StateHistory uint64 // Number of blocks from head whose state histories are reserved.
- StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
- ArchiveMode bool // Whether to enable the archive mode
+ Preimages bool // Whether to store preimage of trie key to the disk
+ StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top
+ ArchiveMode bool // Whether to enable the archive mode
+
+ // Number of blocks from the chain head for which state histories are retained.
+ // If set to 0, all state histories across the entire chain will be retained;
+ StateHistory uint64
// State snapshot related options
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
@@ -193,6 +195,9 @@ type BlockChainConfig struct {
// If the value is zero, all transactions of the entire chain will be indexed.
// If the value is -1, indexing is disabled.
TxLookupLimit int64
+
+ // StateSizeTracking indicates whether the state size tracking is enabled.
+ StateSizeTracking bool
}
// DefaultConfig returns the default config.
@@ -330,6 +335,7 @@ type BlockChain struct {
prefetcher Prefetcher
processor Processor // Block transaction processor interface
logger *tracing.Hooks
+ stateSizer *state.SizeTracker // State size tracking
lastForkReadyAlert time.Time // Last time there was a fork readiness print out
}
@@ -525,6 +531,17 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine,
if bc.cfg.TxLookupLimit >= 0 {
bc.txIndexer = newTxIndexer(uint64(bc.cfg.TxLookupLimit), bc)
}
+
+ // Start state size tracker
+ if bc.cfg.StateSizeTracking {
+ stateSizer, err := state.NewSizeTracker(bc.db, bc.triedb)
+ if err == nil {
+ bc.stateSizer = stateSizer
+ log.Info("Enabled state size metrics")
+ } else {
+ log.Info("Failed to setup size tracker", "err", err)
+ }
+ }
return bc, nil
}
@@ -1254,6 +1271,10 @@ func (bc *BlockChain) stopWithoutSaving() {
// Signal shutdown to all goroutines.
bc.InterruptInsert(true)
+ // Stop state size tracker
+ if bc.stateSizer != nil {
+ bc.stateSizer.Stop()
+ }
// Now wait for all chain modifications to end and persistent goroutines to exit.
//
// Note: Close waits for the mutex to become available, i.e. any running chain
@@ -1591,10 +1612,14 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
log.Crit("Failed to write block into disk", "err", err)
}
// Commit all cached state changes into underlying memory database.
- root, err := statedb.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time()))
+ root, stateUpdate, err := statedb.CommitWithUpdate(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()), bc.chainConfig.IsCancun(block.Number(), block.Time()))
if err != nil {
return err
}
+ // Emit the state update to the state sizestats if it's active
+ if bc.stateSizer != nil {
+ bc.stateSizer.Notify(stateUpdate)
+ }
// If node is running in path mode, skip explicit gc operation
// which is unnecessary in this mode.
if bc.triedb.Scheme() == rawdb.PathScheme {
@@ -1889,7 +1914,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
}
// The traced section of block import.
start := time.Now()
- res, err := bc.processBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1)
+ res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1)
if err != nil {
return nil, it.index, err
}
@@ -1955,9 +1980,13 @@ type blockProcessingResult struct {
witness *stateless.Witness
}
-// processBlock executes and validates the given block. If there was no error
+func (bpr *blockProcessingResult) Witness() *stateless.Witness {
+ return bpr.witness
+}
+
+// ProcessBlock executes and validates the given block. If there was no error
// it writes the block and associated state to database.
-func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) {
+func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) {
var (
err error
startTime = time.Now()
@@ -2135,7 +2164,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
}
// Report the collected witness statistics
if witnessStats != nil {
- witnessStats.ReportMetrics()
+ witnessStats.ReportMetrics(block.NumberU64())
}
// Update the metrics touched during block commit
@@ -2641,13 +2670,11 @@ func (bc *BlockChain) reportBlock(block *types.Block, res *ProcessResult, err er
// logForkReadiness will write a log when a future fork is scheduled, but not
// active. This is useful so operators know their client is ready for the fork.
func (bc *BlockChain) logForkReadiness(block *types.Block) {
- config := bc.Config()
- current, last := config.LatestFork(block.Time()), config.LatestFork(math.MaxUint64)
+ current := bc.Config().LatestFork(block.Time())
- // Short circuit if the timestamp of the last fork is undefined,
- // or if the network has already passed the last configured fork.
- t := config.Timestamp(last)
- if t == nil || current >= last {
+ // Short circuit if the timestamp of the last fork is undefined.
+ t := bc.Config().Timestamp(current + 1)
+ if t == nil {
return
}
at := time.Unix(int64(*t), 0)
@@ -2657,7 +2684,7 @@ func (bc *BlockChain) logForkReadiness(block *types.Block) {
// - Enough time has passed since last alert
now := time.Now()
if now.Before(at) && now.After(bc.lastForkReadyAlert.Add(forkReadyInterval)) {
- log.Info("Ready for fork activation", "fork", last, "date", at.Format(time.RFC822),
+ log.Info("Ready for fork activation", "fork", current+1, "date", at.Format(time.RFC822),
"remaining", time.Until(at).Round(time.Second), "timestamp", at.Unix())
bc.lastForkReadyAlert = time.Now()
}
@@ -2799,3 +2826,8 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load())
}
+
+// StateSizer returns the state size tracker, or nil if it's not initialized
+func (bc *BlockChain) StateSizer() *state.SizeTracker {
+ return bc.stateSizer
+}
diff --git a/core/filtermaps/math.go b/core/filtermaps/math.go
index 33ac07f721..68fd6debd6 100644
--- a/core/filtermaps/math.go
+++ b/core/filtermaps/math.go
@@ -22,7 +22,7 @@ import (
"fmt"
"hash/fnv"
"math"
- "sort"
+ "slices"
"github.com/ethereum/go-ethereum/common"
)
@@ -245,7 +245,7 @@ func (p *Params) potentialMatches(rows []FilterRow, mapIndex uint32, logValue co
panic("potentialMatches: insufficient list of row alternatives")
}
}
- sort.Sort(results)
+ slices.Sort(results)
// remove duplicates
j := 0
for i, match := range results {
@@ -260,12 +260,7 @@ func (p *Params) potentialMatches(rows []FilterRow, mapIndex uint32, logValue co
// potentialMatches is a strictly monotonically increasing list of log value
// indices in the range of a filter map that are potential matches for certain
// filter criteria.
-// potentialMatches implements sort.Interface.
// Note that nil is used as a wildcard and therefore means that all log value
// indices in the filter map range are potential matches. If there are no
// potential matches in the given map's range then an empty slice should be used.
type potentialMatches []uint64
-
-func (p potentialMatches) Len() int { return len(p) }
-func (p potentialMatches) Less(i, j int) bool { return p[i] < p[j] }
-func (p potentialMatches) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
diff --git a/core/genesis.go b/core/genesis.go
index 737e9ae1f4..8c55ca36a3 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -168,7 +168,7 @@ func hashAlloc(ga *types.GenesisAlloc, isVerkle, isIsthmus bool) (common.Hash, c
if account.Balance != nil {
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
}
- statedb.SetCode(addr, account.Code)
+ statedb.SetCode(addr, account.Code, tracing.CodeChangeGenesis)
statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
for key, value := range account.Storage {
statedb.SetState(addr, key, value)
@@ -206,7 +206,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database, isIsthmus bool)
// already captures the allocations.
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance), tracing.BalanceIncreaseGenesisBalance)
}
- statedb.SetCode(addr, account.Code)
+ statedb.SetCode(addr, account.Code, tracing.CodeChangeGenesis)
statedb.SetNonce(addr, account.Nonce, tracing.NonceChangeGenesis)
for key, value := range account.Storage {
statedb.SetState(addr, key, value)
@@ -291,6 +291,8 @@ func (e *GenesisMismatchError) Error() string {
// ChainOverrides contains the changes to chain config.
type ChainOverrides struct {
OverrideOsaka *uint64
+ OverrideBPO1 *uint64
+ OverrideBPO2 *uint64
OverrideVerkle *uint64
// OP-Stack additions
@@ -340,6 +342,12 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o.OverrideOsaka != nil {
cfg.OsakaTime = o.OverrideOsaka
}
+ if o.OverrideBPO1 != nil {
+ cfg.BPO1Time = o.OverrideBPO1
+ }
+ if o.OverrideBPO2 != nil {
+ cfg.BPO2Time = o.OverrideBPO2
+ }
if o.OverrideVerkle != nil {
cfg.VerkleTime = o.OverrideVerkle
}
@@ -663,6 +671,11 @@ func (g *Genesis) toBlockWithRoot(stateRoot, storageRootMessagePasser common.Has
if head.BlobGasUsed == nil {
head.BlobGasUsed = new(uint64)
}
+ } else {
+ if g.ExcessBlobGas != nil {
+ log.Warn("Invalid genesis, unexpected ExcessBlobGas set before Cancun, allowing it for testing purposes")
+ head.ExcessBlobGas = g.ExcessBlobGas
+ }
}
if conf.IsPrague(num, g.Timestamp) {
head.RequestsHash = &types.EmptyRequestsHash
diff --git a/core/overlay/state_transition.go b/core/overlay/state_transition.go
index 90b5c9431a..67ca0f9671 100644
--- a/core/overlay/state_transition.go
+++ b/core/overlay/state_transition.go
@@ -60,6 +60,7 @@ func (ts *TransitionState) Copy() *TransitionState {
CurrentSlotHash: ts.CurrentSlotHash,
CurrentPreimageOffset: ts.CurrentPreimageOffset,
StorageProcessed: ts.StorageProcessed,
+ BaseRoot: ts.BaseRoot,
}
if ts.CurrentAccountAddress != nil {
addr := *ts.CurrentAccountAddress
diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go
index 150d2ee315..68ce051f1a 100644
--- a/core/rawdb/accessors_chain_test.go
+++ b/core/rawdb/accessors_chain_test.go
@@ -248,7 +248,7 @@ func TestBadBlockStorage(t *testing.T) {
}
for i := 0; i < len(badBlocks)-1; i++ {
if badBlocks[i].NumberU64() < badBlocks[i+1].NumberU64() {
- t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, i+1, badBlocks[i].NumberU64(), badBlocks[i+1].NumberU64())
+ t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, badBlocks[i].NumberU64(), i+1, badBlocks[i+1].NumberU64())
}
}
@@ -519,7 +519,7 @@ func TestWriteAncientHeaderChain(t *testing.T) {
t.Fatalf("unexpected body returned")
}
if blob := ReadReceiptsRLP(db, header.Hash(), header.Number.Uint64()); len(blob) != 0 {
- t.Fatalf("unexpected body returned")
+ t.Fatalf("unexpected receipts returned")
}
}
}
diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go
index 7dae87a98f..aaec9f6cbb 100644
--- a/core/rawdb/accessors_metadata.go
+++ b/core/rawdb/accessors_metadata.go
@@ -177,16 +177,3 @@ func UpdateUncleanShutdownMarker(db ethdb.KeyValueStore) {
log.Warn("Failed to write unclean-shutdown marker", "err", err)
}
}
-
-// ReadTransitionStatus retrieves the eth2 transition status from the database
-func ReadTransitionStatus(db ethdb.KeyValueReader) []byte {
- data, _ := db.Get(transitionStatusKey)
- return data
-}
-
-// WriteTransitionStatus stores the eth2 transition status to the database
-func WriteTransitionStatus(db ethdb.KeyValueWriter, data []byte) {
- if err := db.Put(transitionStatusKey, data); err != nil {
- log.Crit("Failed to store the eth2 transition status", "err", err)
- }
-}
diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go
index e154ab527b..7d8b266c15 100644
--- a/core/rawdb/accessors_trie.go
+++ b/core/rawdb/accessors_trie.go
@@ -150,7 +150,7 @@ func HasTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash c
if len(blob) == 0 {
return false
}
- return crypto.Keccak256Hash(blob) == hash // exists but not match
+ return crypto.Keccak256Hash(blob) == hash // exist and match
default:
panic(fmt.Sprintf("Unknown scheme %v", scheme))
}
@@ -173,7 +173,7 @@ func ReadTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash
return nil
}
if crypto.Keccak256Hash(blob) != hash {
- return nil // exists but not match
+ return nil // exist but not match
}
return blob
default:
diff --git a/core/rawdb/ancienttest/testsuite.go b/core/rawdb/ancienttest/testsuite.go
index e33e768947..7512c1f44b 100644
--- a/core/rawdb/ancienttest/testsuite.go
+++ b/core/rawdb/ancienttest/testsuite.go
@@ -48,12 +48,16 @@ func basicRead(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
)
defer db.Close()
- db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
+ if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < len(data); i++ {
- op.AppendRaw("a", uint64(i), data[i])
+ if err := op.AppendRaw("a", uint64(i), data[i]); err != nil {
+ return err
+ }
}
return nil
- })
+ }); err != nil {
+ t.Fatalf("Failed to write ancient data %v", err)
+ }
db.TruncateTail(10)
db.TruncateHead(90)
@@ -109,12 +113,16 @@ func batchRead(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
)
defer db.Close()
- db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
+ if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), data[i])
+ if err := op.AppendRaw("a", uint64(i), data[i]); err != nil {
+ return err
+ }
}
return nil
- })
+ }); err != nil {
+ t.Fatalf("Failed to write ancient data %v", err)
+ }
db.TruncateTail(10)
db.TruncateHead(90)
@@ -189,7 +197,9 @@ func basicWrite(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
// The ancient write to tables should be aligned
_, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), dataA[i])
+ if err := op.AppendRaw("a", uint64(i), dataA[i]); err != nil {
+ return err
+ }
}
return nil
})
@@ -200,8 +210,12 @@ func basicWrite(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
// Test normal ancient write
size, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), dataA[i])
- op.AppendRaw("b", uint64(i), dataB[i])
+ if err := op.AppendRaw("a", uint64(i), dataA[i]); err != nil {
+ return err
+ }
+ if err := op.AppendRaw("b", uint64(i), dataB[i]); err != nil {
+ return err
+ }
}
return nil
})
@@ -217,8 +231,12 @@ func basicWrite(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
db.TruncateHead(90)
_, err = db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 90; i < 100; i++ {
- op.AppendRaw("a", uint64(i), dataA[i])
- op.AppendRaw("b", uint64(i), dataB[i])
+ if err := op.AppendRaw("a", uint64(i), dataA[i]); err != nil {
+ return err
+ }
+ if err := op.AppendRaw("b", uint64(i), dataB[i]); err != nil {
+ return err
+ }
}
return nil
})
@@ -227,11 +245,15 @@ func basicWrite(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
}
// Write should work after truncating everything
- db.TruncateTail(0)
+ db.TruncateHead(0)
_, err = db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), dataA[i])
- op.AppendRaw("b", uint64(i), dataB[i])
+ if err := op.AppendRaw("a", uint64(i), dataA[i]); err != nil {
+ return err
+ }
+ if err := op.AppendRaw("b", uint64(i), dataB[i]); err != nil {
+ return err
+ }
}
return nil
})
@@ -245,14 +267,18 @@ func nonMutable(t *testing.T, newFn func(kinds []string) ethdb.AncientStore) {
defer db.Close()
// We write 100 zero-bytes to the freezer and immediately mutate the slice
- db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
+ if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
data := make([]byte, 100)
- op.AppendRaw("a", uint64(0), data)
+ if err := op.AppendRaw("a", uint64(0), data); err != nil {
+ return err
+ }
for i := range data {
data[i] = 0xff
}
return nil
- })
+ }); err != nil {
+ t.Fatalf("Failed to write ancient data %v", err)
+ }
// Now read it.
data, err := db.Ancient("a", uint64(0))
if err != nil {
@@ -275,23 +301,31 @@ func TestResettableAncientSuite(t *testing.T, newFn func(kinds []string) ethdb.R
)
defer db.Close()
- db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
+ if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), data[i])
+ if err := op.AppendRaw("a", uint64(i), data[i]); err != nil {
+ return err
+ }
}
return nil
- })
+ }); err != nil {
+ t.Fatalf("Failed to write ancient data %v", err)
+ }
db.TruncateTail(10)
db.TruncateHead(90)
// Ancient write should work after resetting
db.Reset()
- db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
+ if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
for i := 0; i < 100; i++ {
- op.AppendRaw("a", uint64(i), data[i])
+ if err := op.AppendRaw("a", uint64(i), data[i]); err != nil {
+ return err
+ }
}
return nil
- })
+ }); err != nil {
+ t.Fatalf("Failed to write ancient data %v", err)
+ }
})
}
diff --git a/core/rawdb/freezer_test.go b/core/rawdb/freezer_test.go
index b8a3d4a6d2..fab3319a2a 100644
--- a/core/rawdb/freezer_test.go
+++ b/core/rawdb/freezer_test.go
@@ -239,7 +239,7 @@ func TestFreezerConcurrentModifyTruncate(t *testing.T) {
// fails, otherwise it succeeds. In either case, the freezer should be positioned
// at 10 after both operations are done.
if truncateErr != nil {
- t.Fatal("concurrent truncate failed:", err)
+ t.Fatal("concurrent truncate failed:", truncateErr)
}
if !(errors.Is(modifyErr, nil) || errors.Is(modifyErr, errOutOrderInsertion)) {
t.Fatal("wrong error from concurrent modify:", modifyErr)
diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go
index 3588063468..9a17e1c173 100644
--- a/core/rawdb/schema.go
+++ b/core/rawdb/schema.go
@@ -95,7 +95,7 @@ var (
uncleanShutdownKey = []byte("unclean-shutdown") // config prefix for the db
// transitionStatusKey tracks the eth2 transition status.
- transitionStatusKey = []byte("eth2-transition")
+ transitionStatusKey = []byte("eth2-transition") // deprecated
// snapSyncStatusFlagKey flags that status of snap sync.
snapSyncStatusFlagKey = []byte("SnapSyncStatus")
diff --git a/core/rlp_test.go b/core/rlp_test.go
index 72d3840746..b8db087276 100644
--- a/core/rlp_test.go
+++ b/core/rlp_test.go
@@ -153,8 +153,7 @@ func BenchmarkHashing(b *testing.B) {
var got common.Hash
var hasher = sha3.NewLegacyKeccak256()
b.Run("iteratorhashing", func(b *testing.B) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
var hash common.Hash
it, err := rlp.NewListIterator(bodyRlp)
if err != nil {
@@ -176,8 +175,7 @@ func BenchmarkHashing(b *testing.B) {
})
var exp common.Hash
b.Run("fullbodyhashing", func(b *testing.B) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
var body types.Body
rlp.DecodeBytes(bodyRlp, &body)
for _, tx := range body.Transactions {
@@ -186,8 +184,7 @@ func BenchmarkHashing(b *testing.B) {
}
})
b.Run("fullblockhashing", func(b *testing.B) {
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
var block types.Block
rlp.DecodeBytes(blockRlp, &block)
for _, tx := range block.Transactions() {
diff --git a/core/state/snapshot/difflayer_test.go b/core/state/snapshot/difflayer_test.go
index b212098e75..2c868b3010 100644
--- a/core/state/snapshot/difflayer_test.go
+++ b/core/state/snapshot/difflayer_test.go
@@ -229,8 +229,7 @@ func BenchmarkSearch(b *testing.B) {
layer = fill(layer)
}
key := crypto.Keccak256Hash([]byte{0x13, 0x38})
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
layer.AccountRLP(key)
}
}
@@ -269,8 +268,7 @@ func BenchmarkSearchSlot(b *testing.B) {
for i := 0; i < 128; i++ {
layer = fill(layer)
}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
layer.Storage(accountKey, storageKey)
}
}
@@ -300,9 +298,7 @@ func BenchmarkFlatten(b *testing.B) {
}
return newDiffLayer(parent, common.Hash{}, accounts, storage)
}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- b.StopTimer()
+ for b.Loop() {
var layer snapshot
layer = emptyLayer()
for i := 1; i < 128; i++ {
@@ -352,9 +348,7 @@ func BenchmarkJournal(b *testing.B) {
for i := 1; i < 128; i++ {
layer = fill(layer)
}
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
layer.Journal(new(bytes.Buffer))
}
}
diff --git a/core/state/snapshot/iterator_test.go b/core/state/snapshot/iterator_test.go
index 2e882f484e..dd6c4cf968 100644
--- a/core/state/snapshot/iterator_test.go
+++ b/core/state/snapshot/iterator_test.go
@@ -928,7 +928,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) {
head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
b.Run("binary iterator keys", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
got := 0
it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
for it.Next() {
@@ -940,7 +940,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) {
}
})
b.Run("binary iterator values", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
got := 0
it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
for it.Next() {
@@ -953,7 +953,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) {
}
})
b.Run("fast iterator keys", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{})
defer it.Release()
@@ -967,7 +967,7 @@ func BenchmarkAccountIteratorTraversal(b *testing.B) {
}
})
b.Run("fast iterator values", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{})
defer it.Release()
@@ -1025,7 +1025,7 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) {
head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
b.Run("binary iterator (keys)", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
got := 0
it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
for it.Next() {
@@ -1037,7 +1037,7 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) {
}
})
b.Run("binary iterator (values)", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
got := 0
it := head.(*diffLayer).newBinaryAccountIterator(common.Hash{})
for it.Next() {
@@ -1051,7 +1051,7 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) {
}
})
b.Run("fast iterator (keys)", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{})
defer it.Release()
@@ -1065,7 +1065,7 @@ func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) {
}
})
b.Run("fast iterator (values)", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{})
defer it.Release()
diff --git a/core/state/state_object.go b/core/state/state_object.go
index 767f469bfd..2938750503 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -333,7 +333,7 @@ func (s *stateObject) updateTrie() (Trie, error) {
continue
}
if !exist {
- log.Error("Storage slot is not found in pending area", s.address, "slot", key)
+ log.Error("Storage slot is not found in pending area", "address", s.address, "slot", key)
continue
}
if (value != common.Hash{}) {
diff --git a/core/state/state_object_test.go b/core/state/state_object_test.go
index 42fd778025..0237f0580d 100644
--- a/core/state/state_object_test.go
+++ b/core/state/state_object_test.go
@@ -25,7 +25,7 @@ import (
func BenchmarkCutOriginal(b *testing.B) {
value := common.HexToHash("0x01")
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
bytes.TrimLeft(value[:], "\x00")
}
}
@@ -33,14 +33,14 @@ func BenchmarkCutOriginal(b *testing.B) {
func BenchmarkCutsetterFn(b *testing.B) {
value := common.HexToHash("0x01")
cutSetFn := func(r rune) bool { return r == 0 }
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
bytes.TrimLeftFunc(value[:], cutSetFn)
}
}
func BenchmarkCutCustomTrim(b *testing.B) {
value := common.HexToHash("0x01")
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
common.TrimLeftZeroes(value[:])
}
}
diff --git a/core/state/state_sizer.go b/core/state/state_sizer.go
new file mode 100644
index 0000000000..2066c94845
--- /dev/null
+++ b/core/state/state_sizer.go
@@ -0,0 +1,638 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package state
+
+import (
+ "container/heap"
+ "errors"
+ "fmt"
+ "maps"
+ "runtime"
+ "slices"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/triedb"
+ "golang.org/x/sync/errgroup"
+)
+
+const (
+ statEvictThreshold = 128 // the depth of statistic to be preserved
+)
+
+// Database key scheme for states.
+var (
+ accountKeySize = int64(len(rawdb.SnapshotAccountPrefix) + common.HashLength)
+ storageKeySize = int64(len(rawdb.SnapshotStoragePrefix) + common.HashLength*2)
+ accountTrienodePrefixSize = int64(len(rawdb.TrieNodeAccountPrefix))
+ storageTrienodePrefixSize = int64(len(rawdb.TrieNodeStoragePrefix) + common.HashLength)
+ codeKeySize = int64(len(rawdb.CodePrefix) + common.HashLength)
+)
+
+// SizeStats represents either the current state size statistics or the size
+// differences resulting from a state transition.
+type SizeStats struct {
+ StateRoot common.Hash // State root hash at the time of measurement
+ BlockNumber uint64 // Associated block number at the time of measurement
+
+ Accounts int64 // Total number of accounts in the state
+ AccountBytes int64 // Total storage size used by all account data (in bytes)
+ Storages int64 // Total number of storage slots across all accounts
+ StorageBytes int64 // Total storage size used by all storage slot data (in bytes)
+ AccountTrienodes int64 // Total number of account trie nodes in the state
+ AccountTrienodeBytes int64 // Total storage size occupied by account trie nodes (in bytes)
+ StorageTrienodes int64 // Total number of storage trie nodes in the state
+ StorageTrienodeBytes int64 // Total storage size occupied by storage trie nodes (in bytes)
+ ContractCodes int64 // Total number of contract codes in the state
+ ContractCodeBytes int64 // Total size of all contract code (in bytes)
+}
+
+func (s SizeStats) String() string {
+ return fmt.Sprintf("Accounts: %d(%s), Storages: %d(%s), AccountTrienodes: %d(%s), StorageTrienodes: %d(%s), Codes: %d(%s)",
+ s.Accounts, common.StorageSize(s.AccountBytes),
+ s.Storages, common.StorageSize(s.StorageBytes),
+ s.AccountTrienodes, common.StorageSize(s.AccountTrienodeBytes),
+ s.StorageTrienodes, common.StorageSize(s.StorageTrienodeBytes),
+ s.ContractCodes, common.StorageSize(s.ContractCodeBytes),
+ )
+}
+
+// add applies the given state diffs and produces a new version of the statistics.
+func (s SizeStats) add(diff SizeStats) SizeStats {
+ s.StateRoot = diff.StateRoot
+ s.BlockNumber = diff.BlockNumber
+
+ s.Accounts += diff.Accounts
+ s.AccountBytes += diff.AccountBytes
+ s.Storages += diff.Storages
+ s.StorageBytes += diff.StorageBytes
+ s.AccountTrienodes += diff.AccountTrienodes
+ s.AccountTrienodeBytes += diff.AccountTrienodeBytes
+ s.StorageTrienodes += diff.StorageTrienodes
+ s.StorageTrienodeBytes += diff.StorageTrienodeBytes
+ s.ContractCodes += diff.ContractCodes
+ s.ContractCodeBytes += diff.ContractCodeBytes
+ return s
+}
+
+// calSizeStats measures the state size changes of the provided state update.
+func calSizeStats(update *stateUpdate) (SizeStats, error) {
+ stats := SizeStats{
+ BlockNumber: update.blockNumber,
+ StateRoot: update.root,
+ }
+
+ // Measure the account changes
+ for addr, oldValue := range update.accountsOrigin {
+ addrHash := crypto.Keccak256Hash(addr.Bytes())
+ newValue, exists := update.accounts[addrHash]
+ if !exists {
+ return SizeStats{}, fmt.Errorf("account %x not found", addr)
+ }
+ oldLen, newLen := len(oldValue), len(newValue)
+
+ switch {
+ case oldLen > 0 && newLen == 0:
+ // Account deletion
+ stats.Accounts -= 1
+ stats.AccountBytes -= accountKeySize + int64(oldLen)
+ case oldLen == 0 && newLen > 0:
+ // Account creation
+ stats.Accounts += 1
+ stats.AccountBytes += accountKeySize + int64(newLen)
+ default:
+ // Account update
+ stats.AccountBytes += int64(newLen - oldLen)
+ }
+ }
+
+ // Measure storage changes
+ for addr, slots := range update.storagesOrigin {
+ addrHash := crypto.Keccak256Hash(addr.Bytes())
+ subset, exists := update.storages[addrHash]
+ if !exists {
+ return SizeStats{}, fmt.Errorf("storage %x not found", addr)
+ }
+ for key, oldValue := range slots {
+ var (
+ exists bool
+ newValue []byte
+ )
+ if update.rawStorageKey {
+ newValue, exists = subset[crypto.Keccak256Hash(key.Bytes())]
+ } else {
+ newValue, exists = subset[key]
+ }
+ if !exists {
+ return SizeStats{}, fmt.Errorf("storage slot %x-%x not found", addr, key)
+ }
+ oldLen, newLen := len(oldValue), len(newValue)
+
+ switch {
+ case oldLen > 0 && newLen == 0:
+ // Storage deletion
+ stats.Storages -= 1
+ stats.StorageBytes -= storageKeySize + int64(oldLen)
+ case oldLen == 0 && newLen > 0:
+ // Storage creation
+ stats.Storages += 1
+ stats.StorageBytes += storageKeySize + int64(newLen)
+ default:
+ // Storage update
+ stats.StorageBytes += int64(newLen - oldLen)
+ }
+ }
+ }
+
+ // Measure trienode changes
+ for owner, subset := range update.nodes.Sets {
+ var (
+ keyPrefix int64
+ isAccount = owner == (common.Hash{})
+ )
+ if isAccount {
+ keyPrefix = accountTrienodePrefixSize
+ } else {
+ keyPrefix = storageTrienodePrefixSize
+ }
+
+ // Iterate over Origins since every modified node has an origin entry
+ for path, oldNode := range subset.Origins {
+ newNode, exists := subset.Nodes[path]
+ if !exists {
+ return SizeStats{}, fmt.Errorf("node %x-%v not found", owner, path)
+ }
+ keySize := keyPrefix + int64(len(path))
+
+ switch {
+ case len(oldNode) > 0 && len(newNode.Blob) == 0:
+ // Node deletion
+ if isAccount {
+ stats.AccountTrienodes -= 1
+ stats.AccountTrienodeBytes -= keySize + int64(len(oldNode))
+ } else {
+ stats.StorageTrienodes -= 1
+ stats.StorageTrienodeBytes -= keySize + int64(len(oldNode))
+ }
+ case len(oldNode) == 0 && len(newNode.Blob) > 0:
+ // Node creation
+ if isAccount {
+ stats.AccountTrienodes += 1
+ stats.AccountTrienodeBytes += keySize + int64(len(newNode.Blob))
+ } else {
+ stats.StorageTrienodes += 1
+ stats.StorageTrienodeBytes += keySize + int64(len(newNode.Blob))
+ }
+ default:
+ // Node update
+ if isAccount {
+ stats.AccountTrienodeBytes += int64(len(newNode.Blob) - len(oldNode))
+ } else {
+ stats.StorageTrienodeBytes += int64(len(newNode.Blob) - len(oldNode))
+ }
+ }
+ }
+ }
+
+ // Measure code changes. Note that the reported contract code size may be slightly
+ // inaccurate due to database deduplication (code is stored by its hash). However,
+ // this deviation is negligible and acceptable for measurement purposes.
+ for _, code := range update.codes {
+ stats.ContractCodes += 1
+ stats.ContractCodeBytes += codeKeySize + int64(len(code.blob))
+ }
+ return stats, nil
+}
+
+type stateSizeQuery struct {
+ root *common.Hash // nil means latest
+ err error // non-nil if the state size is not yet initialized
+ result chan *SizeStats // nil means the state is unknown
+}
+
+// SizeTracker handles the state size initialization and tracks of state size metrics.
+type SizeTracker struct {
+ db ethdb.KeyValueStore
+ triedb *triedb.Database
+ abort chan struct{}
+ aborted chan struct{}
+ updateCh chan *stateUpdate
+ queryCh chan *stateSizeQuery
+}
+
+// NewSizeTracker creates a new state size tracker and starts it automatically
+func NewSizeTracker(db ethdb.KeyValueStore, triedb *triedb.Database) (*SizeTracker, error) {
+ if triedb.Scheme() != rawdb.PathScheme {
+ return nil, errors.New("state size tracker is not compatible with hash mode")
+ }
+ t := &SizeTracker{
+ db: db,
+ triedb: triedb,
+ abort: make(chan struct{}),
+ aborted: make(chan struct{}),
+ updateCh: make(chan *stateUpdate),
+ queryCh: make(chan *stateSizeQuery),
+ }
+ go t.run()
+ return t, nil
+}
+
+func (t *SizeTracker) Stop() {
+ close(t.abort)
+ <-t.aborted
+}
+
+// sizeStatsHeap is a heap.Interface implementation over statesize statistics for
+// retrieving the oldest statistics for eviction.
+type sizeStatsHeap []SizeStats
+
+func (h sizeStatsHeap) Len() int { return len(h) }
+func (h sizeStatsHeap) Less(i, j int) bool { return h[i].BlockNumber < h[j].BlockNumber }
+func (h sizeStatsHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
+
+func (h *sizeStatsHeap) Push(x any) {
+ *h = append(*h, x.(SizeStats))
+}
+
+func (h *sizeStatsHeap) Pop() any {
+ old := *h
+ n := len(old)
+ x := old[n-1]
+ *h = old[0 : n-1]
+ return x
+}
+
+// run performs the state size initialization and handles updates
+func (t *SizeTracker) run() {
+ defer close(t.aborted)
+
+ var last common.Hash
+ stats, err := t.init() // launch background thread for state size init
+ if err != nil {
+ return
+ }
+ h := sizeStatsHeap(slices.Collect(maps.Values(stats)))
+ heap.Init(&h)
+
+ for {
+ select {
+ case u := <-t.updateCh:
+ base, found := stats[u.originRoot]
+ if !found {
+ log.Debug("Ignored the state size without parent", "parent", u.originRoot, "root", u.root, "number", u.blockNumber)
+ continue
+ }
+ diff, err := calSizeStats(u)
+ if err != nil {
+ continue
+ }
+ stat := base.add(diff)
+ stats[u.root] = stat
+ last = u.root
+
+ heap.Push(&h, stats[u.root])
+ for u.blockNumber-h[0].BlockNumber > statEvictThreshold {
+ delete(stats, h[0].StateRoot)
+ heap.Pop(&h)
+ }
+ log.Debug("Update state size", "number", stat.BlockNumber, "root", stat.StateRoot, "stat", stat)
+
+ case r := <-t.queryCh:
+ var root common.Hash
+ if r.root != nil {
+ root = *r.root
+ } else {
+ root = last
+ }
+ if s, ok := stats[root]; ok {
+ r.result <- &s
+ } else {
+ r.result <- nil
+ }
+
+ case <-t.abort:
+ return
+ }
+ }
+}
+
+type buildResult struct {
+ stat SizeStats
+ root common.Hash
+ blockNumber uint64
+ elapsed time.Duration
+ err error
+}
+
+func (t *SizeTracker) init() (map[common.Hash]SizeStats, error) {
+ // Wait for snapshot completion and then init
+ ticker := time.NewTicker(10 * time.Second)
+ defer ticker.Stop()
+
+wait:
+ for {
+ select {
+ case <-ticker.C:
+ if t.triedb.SnapshotCompleted() {
+ break wait
+ }
+ case <-t.updateCh:
+ continue
+ case r := <-t.queryCh:
+ r.err = errors.New("state size is not initialized yet")
+ r.result <- nil
+ case <-t.abort:
+ return nil, errors.New("size tracker closed")
+ }
+ }
+
+ var (
+ updates = make(map[common.Hash]*stateUpdate)
+ children = make(map[common.Hash][]common.Hash)
+ done chan buildResult
+ )
+
+ for {
+ select {
+ case u := <-t.updateCh:
+ updates[u.root] = u
+ children[u.originRoot] = append(children[u.originRoot], u.root)
+ log.Debug("Received state update", "root", u.root, "blockNumber", u.blockNumber)
+
+ case r := <-t.queryCh:
+ r.err = errors.New("state size is not initialized yet")
+ r.result <- nil
+
+ case <-ticker.C:
+ // Only check timer if build hasn't started yet
+ if done != nil {
+ continue
+ }
+ root := rawdb.ReadSnapshotRoot(t.db)
+ if root == (common.Hash{}) {
+ continue
+ }
+ entry, exists := updates[root]
+ if !exists {
+ continue
+ }
+ done = make(chan buildResult)
+ go t.build(entry.root, entry.blockNumber, done)
+ log.Info("Measuring persistent state size", "root", root.Hex(), "number", entry.blockNumber)
+
+ case result := <-done:
+ if result.err != nil {
+ return nil, result.err
+ }
+ var (
+ stats = make(map[common.Hash]SizeStats)
+ apply func(root common.Hash, stat SizeStats) error
+ )
+ apply = func(root common.Hash, base SizeStats) error {
+ for _, child := range children[root] {
+ entry, ok := updates[child]
+ if !ok {
+ return fmt.Errorf("the state update is not found, %x", child)
+ }
+ diff, err := calSizeStats(entry)
+ if err != nil {
+ return err
+ }
+ stats[child] = base.add(diff)
+ if err := apply(child, stats[child]); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ if err := apply(result.root, result.stat); err != nil {
+ return nil, err
+ }
+
+ // Set initial latest stats
+ stats[result.root] = result.stat
+ log.Info("Measured persistent state size", "root", result.root, "number", result.blockNumber, "stat", result.stat, "elapsed", common.PrettyDuration(result.elapsed))
+ return stats, nil
+
+ case <-t.abort:
+ return nil, errors.New("size tracker closed")
+ }
+ }
+}
+
+func (t *SizeTracker) build(root common.Hash, blockNumber uint64, done chan buildResult) {
+ // Metrics will be directly updated by each goroutine
+ var (
+ accounts, accountBytes int64
+ storages, storageBytes int64
+ codes, codeBytes int64
+
+ accountTrienodes, accountTrienodeBytes int64
+ storageTrienodes, storageTrienodeBytes int64
+
+ group errgroup.Group
+ start = time.Now()
+ )
+
+ // Start all table iterations concurrently with direct metric updates
+ group.Go(func() error {
+ count, bytes, err := t.iterateTableParallel(t.abort, rawdb.SnapshotAccountPrefix, "account")
+ if err != nil {
+ return err
+ }
+ accounts, accountBytes = count, bytes
+ return nil
+ })
+
+ group.Go(func() error {
+ count, bytes, err := t.iterateTableParallel(t.abort, rawdb.SnapshotStoragePrefix, "storage")
+ if err != nil {
+ return err
+ }
+ storages, storageBytes = count, bytes
+ return nil
+ })
+
+ group.Go(func() error {
+ count, bytes, err := t.iterateTableParallel(t.abort, rawdb.TrieNodeAccountPrefix, "accountnode")
+ if err != nil {
+ return err
+ }
+ accountTrienodes, accountTrienodeBytes = count, bytes
+ return nil
+ })
+
+ group.Go(func() error {
+ count, bytes, err := t.iterateTableParallel(t.abort, rawdb.TrieNodeStoragePrefix, "storagenode")
+ if err != nil {
+ return err
+ }
+ storageTrienodes, storageTrienodeBytes = count, bytes
+ return nil
+ })
+
+ group.Go(func() error {
+ count, bytes, err := t.iterateTable(t.abort, rawdb.CodePrefix, "contractcode")
+ if err != nil {
+ return err
+ }
+ codes, codeBytes = count, bytes
+ return nil
+ })
+
+ // Wait for all goroutines to complete
+ if err := group.Wait(); err != nil {
+ done <- buildResult{err: err}
+ } else {
+ stat := SizeStats{
+ StateRoot: root,
+ BlockNumber: blockNumber,
+ Accounts: accounts,
+ AccountBytes: accountBytes,
+ Storages: storages,
+ StorageBytes: storageBytes,
+ AccountTrienodes: accountTrienodes,
+ AccountTrienodeBytes: accountTrienodeBytes,
+ StorageTrienodes: storageTrienodes,
+ StorageTrienodeBytes: storageTrienodeBytes,
+ ContractCodes: codes,
+ ContractCodeBytes: codeBytes,
+ }
+ done <- buildResult{
+ root: root,
+ blockNumber: blockNumber,
+ stat: stat,
+ elapsed: time.Since(start),
+ }
+ }
+}
+
+// iterateTable performs iteration over a specific table and returns the results.
+func (t *SizeTracker) iterateTable(closed chan struct{}, prefix []byte, name string) (int64, int64, error) {
+ var (
+ start = time.Now()
+ logged = time.Now()
+ count, bytes int64
+ )
+
+ iter := t.db.NewIterator(prefix, nil)
+ defer iter.Release()
+
+ log.Debug("Iterating state", "category", name)
+ for iter.Next() {
+ count++
+ bytes += int64(len(iter.Key()) + len(iter.Value()))
+
+ if time.Since(logged) > time.Second*8 {
+ logged = time.Now()
+
+ select {
+ case <-closed:
+ log.Debug("State iteration cancelled", "category", name)
+ return 0, 0, errors.New("size tracker closed")
+ default:
+ log.Debug("Iterating state", "category", name, "count", count, "size", common.StorageSize(bytes))
+ }
+ }
+ }
+ // Check for iterator errors
+ if err := iter.Error(); err != nil {
+ log.Error("Iterator error", "category", name, "err", err)
+ return 0, 0, err
+ }
+ log.Debug("Finished state iteration", "category", name, "count", count, "size", common.StorageSize(bytes), "elapsed", common.PrettyDuration(time.Since(start)))
+ return count, bytes, nil
+}
+
+// iterateTableParallel performs parallel iteration over a table by splitting into
+// hex ranges. For storage tables, it splits on the first byte of the account hash
+// (after the prefix).
+func (t *SizeTracker) iterateTableParallel(closed chan struct{}, prefix []byte, name string) (int64, int64, error) {
+ var (
+ totalCount int64
+ totalBytes int64
+
+ start = time.Now()
+ workers = runtime.NumCPU()
+ group errgroup.Group
+ mu sync.Mutex
+ )
+ group.SetLimit(workers)
+ log.Debug("Starting parallel state iteration", "category", name, "workers", workers)
+
+ if len(prefix) > 0 {
+ if blob, err := t.db.Get(prefix); err == nil && len(blob) > 0 {
+ // If there's a direct hit on the prefix, include it in the stats
+ totalCount = 1
+ totalBytes = int64(len(prefix) + len(blob))
+ }
+ }
+ for i := 0; i < 256; i++ {
+ h := byte(i)
+ group.Go(func() error {
+ count, bytes, err := t.iterateTable(closed, slices.Concat(prefix, []byte{h}), fmt.Sprintf("%s-%02x", name, h))
+ if err != nil {
+ return err
+ }
+ mu.Lock()
+ totalCount += count
+ totalBytes += bytes
+ mu.Unlock()
+ return nil
+ })
+ }
+ if err := group.Wait(); err != nil {
+ return 0, 0, err
+ }
+ log.Debug("Finished parallel state iteration", "category", name, "count", totalCount, "size", common.StorageSize(totalBytes), "elapsed", common.PrettyDuration(time.Since(start)))
+ return totalCount, totalBytes, nil
+}
+
+// Notify is an async method used to send the state update to the size tracker.
+// It ignores empty updates (where no state changes occurred).
+// If the channel is full, it drops the update to avoid blocking.
+func (t *SizeTracker) Notify(update *stateUpdate) {
+ if update == nil || update.empty() {
+ return
+ }
+ select {
+ case t.updateCh <- update:
+ case <-t.abort:
+ return
+ }
+}
+
+// Query returns the state size specified by the root, or nil if not available.
+// If the root is nil, query the size of latest chain head;
+// If the root is non-nil, query the size of the specified state;
+func (t *SizeTracker) Query(root *common.Hash) (*SizeStats, error) {
+ r := &stateSizeQuery{
+ root: root,
+ result: make(chan *SizeStats, 1),
+ }
+ select {
+ case <-t.aborted:
+ return nil, errors.New("state sizer has been closed")
+ case t.queryCh <- r:
+ return <-r.result, r.err
+ }
+}
diff --git a/core/state/state_sizer_test.go b/core/state/state_sizer_test.go
new file mode 100644
index 0000000000..cab0c38163
--- /dev/null
+++ b/core/state/state_sizer_test.go
@@ -0,0 +1,231 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package state
+
+import (
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
+)
+
+func TestSizeTracker(t *testing.T) {
+ db := rawdb.NewMemoryDatabase()
+ defer db.Close()
+
+ tdb := triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.Defaults})
+ sdb := NewDatabase(tdb, nil)
+
+ // Generate 50 blocks to establish a baseline
+ baselineBlockNum := uint64(50)
+ currentRoot := types.EmptyRootHash
+
+ addr1 := common.BytesToAddress([]byte{1, 0, 0, 1})
+ addr2 := common.BytesToAddress([]byte{1, 0, 0, 2})
+ addr3 := common.BytesToAddress([]byte{1, 0, 0, 3})
+
+ // Create initial state with fixed accounts
+ state, _ := New(currentRoot, sdb)
+ state.AddBalance(addr1, uint256.NewInt(1000), tracing.BalanceChangeUnspecified)
+ state.SetNonce(addr1, 1, tracing.NonceChangeUnspecified)
+ state.SetState(addr1, common.HexToHash("0x1111"), common.HexToHash("0xaaaa"))
+ state.SetState(addr1, common.HexToHash("0x2222"), common.HexToHash("0xbbbb"))
+
+ state.AddBalance(addr2, uint256.NewInt(2000), tracing.BalanceChangeUnspecified)
+ state.SetNonce(addr2, 2, tracing.NonceChangeUnspecified)
+ state.SetCode(addr2, []byte{0x60, 0x80, 0x60, 0x40, 0x52}, tracing.CodeChangeUnspecified)
+
+ state.AddBalance(addr3, uint256.NewInt(3000), tracing.BalanceChangeUnspecified)
+ state.SetNonce(addr3, 3, tracing.NonceChangeUnspecified)
+
+ currentRoot, _, err := state.CommitWithUpdate(1, true, false)
+ if err != nil {
+ t.Fatalf("Failed to commit initial state: %v", err)
+ }
+ if err := tdb.Commit(currentRoot, false); err != nil {
+ t.Fatalf("Failed to commit initial trie: %v", err)
+ }
+
+ for i := 1; i < 50; i++ { // blocks 2-50
+ blockNum := uint64(i + 1)
+
+ newState, err := New(currentRoot, sdb)
+ if err != nil {
+ t.Fatalf("Failed to create new state at block %d: %v", blockNum, err)
+ }
+ testAddr := common.BigToAddress(uint256.NewInt(uint64(i + 100)).ToBig())
+ newState.AddBalance(testAddr, uint256.NewInt(uint64((i+1)*1000)), tracing.BalanceChangeUnspecified)
+ newState.SetNonce(testAddr, uint64(i+10), tracing.NonceChangeUnspecified)
+
+ if i%2 == 0 {
+ newState.SetState(addr1, common.BigToHash(uint256.NewInt(uint64(i+0x1000)).ToBig()), common.BigToHash(uint256.NewInt(uint64(i+0x2000)).ToBig()))
+ }
+ if i%3 == 0 {
+ newState.SetCode(testAddr, []byte{byte(i), 0x60, 0x80, byte(i + 1), 0x52}, tracing.CodeChangeUnspecified)
+ }
+ root, _, err := newState.CommitWithUpdate(blockNum, true, false)
+ if err != nil {
+ t.Fatalf("Failed to commit state at block %d: %v", blockNum, err)
+ }
+ if err := tdb.Commit(root, false); err != nil {
+ t.Fatalf("Failed to commit trie at block %d: %v", blockNum, err)
+ }
+ currentRoot = root
+ }
+ baselineRoot := currentRoot
+
+ // Wait for snapshot completion
+ for !tdb.SnapshotCompleted() {
+ time.Sleep(100 * time.Millisecond)
+ }
+
+ // Calculate baseline from the intermediate persisted state
+ baselineTracker := &SizeTracker{
+ db: db,
+ triedb: tdb,
+ abort: make(chan struct{}),
+ }
+ done := make(chan buildResult)
+
+ go baselineTracker.build(baselineRoot, baselineBlockNum, done)
+ var baselineResult buildResult
+ select {
+ case baselineResult = <-done:
+ if baselineResult.err != nil {
+ t.Fatalf("Failed to get baseline stats: %v", baselineResult.err)
+ }
+ case <-time.After(30 * time.Second):
+ t.Fatal("Timeout waiting for baseline stats")
+ }
+ baseline := baselineResult.stat
+
+ // Now start the tracker and notify it of updates that happen AFTER the baseline
+ tracker, err := NewSizeTracker(db, tdb)
+ if err != nil {
+ t.Fatalf("Failed to create size tracker: %v", err)
+ }
+ defer tracker.Stop()
+
+ var trackedUpdates []SizeStats
+ currentRoot = baselineRoot
+
+ // Generate additional blocks beyond the baseline and track them
+ for i := 49; i < 130; i++ { // blocks 51-132
+ blockNum := uint64(i + 2)
+ newState, err := New(currentRoot, sdb)
+ if err != nil {
+ t.Fatalf("Failed to create new state at block %d: %v", blockNum, err)
+ }
+ testAddr := common.BigToAddress(uint256.NewInt(uint64(i + 100)).ToBig())
+ newState.AddBalance(testAddr, uint256.NewInt(uint64((i+1)*1000)), tracing.BalanceChangeUnspecified)
+ newState.SetNonce(testAddr, uint64(i+10), tracing.NonceChangeUnspecified)
+
+ if i%2 == 0 {
+ newState.SetState(addr1, common.BigToHash(uint256.NewInt(uint64(i+0x1000)).ToBig()), common.BigToHash(uint256.NewInt(uint64(i+0x2000)).ToBig()))
+ }
+ if i%3 == 0 {
+ newState.SetCode(testAddr, []byte{byte(i), 0x60, 0x80, byte(i + 1), 0x52}, tracing.CodeChangeUnspecified)
+ }
+ root, update, err := newState.CommitWithUpdate(blockNum, true, false)
+ if err != nil {
+ t.Fatalf("Failed to commit state at block %d: %v", blockNum, err)
+ }
+ if err := tdb.Commit(root, false); err != nil {
+ t.Fatalf("Failed to commit trie at block %d: %v", blockNum, err)
+ }
+
+ diff, err := calSizeStats(update)
+ if err != nil {
+ t.Fatalf("Failed to calculate size stats for block %d: %v", blockNum, err)
+ }
+ trackedUpdates = append(trackedUpdates, diff)
+ tracker.Notify(update)
+ currentRoot = root
+ }
+ finalRoot := rawdb.ReadSnapshotRoot(db)
+
+ // Ensure all commits are flushed to disk
+ if err := tdb.Close(); err != nil {
+ t.Fatalf("Failed to close triedb: %v", err)
+ }
+ // Reopen the database to simulate a restart
+ tdb = triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.Defaults})
+ defer tdb.Close()
+
+ finalTracker := &SizeTracker{
+ db: db,
+ triedb: tdb,
+ abort: make(chan struct{}),
+ }
+ finalDone := make(chan buildResult)
+
+ go finalTracker.build(finalRoot, uint64(132), finalDone)
+ var result buildResult
+ select {
+ case result = <-finalDone:
+ if result.err != nil {
+ t.Fatalf("Failed to build final stats: %v", result.err)
+ }
+ case <-time.After(30 * time.Second):
+ t.Fatal("Timeout waiting for final stats")
+ }
+ actualStats := result.stat
+
+ expectedStats := baseline
+ for _, diff := range trackedUpdates {
+ expectedStats = expectedStats.add(diff)
+ }
+
+ // The final measured stats should match our calculated expected stats exactly
+ if actualStats.Accounts != expectedStats.Accounts {
+ t.Errorf("Account count mismatch: baseline(%d) + tracked_changes = %d, but final_measurement = %d", baseline.Accounts, expectedStats.Accounts, actualStats.Accounts)
+ }
+ if actualStats.AccountBytes != expectedStats.AccountBytes {
+ t.Errorf("Account bytes mismatch: expected %d, got %d", expectedStats.AccountBytes, actualStats.AccountBytes)
+ }
+ if actualStats.Storages != expectedStats.Storages {
+ t.Errorf("Storage count mismatch: baseline(%d) + tracked_changes = %d, but final_measurement = %d", baseline.Storages, expectedStats.Storages, actualStats.Storages)
+ }
+ if actualStats.StorageBytes != expectedStats.StorageBytes {
+ t.Errorf("Storage bytes mismatch: expected %d, got %d", expectedStats.StorageBytes, actualStats.StorageBytes)
+ }
+ if actualStats.ContractCodes != expectedStats.ContractCodes {
+ t.Errorf("Contract code count mismatch: baseline(%d) + tracked_changes = %d, but final_measurement = %d", baseline.ContractCodes, expectedStats.ContractCodes, actualStats.ContractCodes)
+ }
+ if actualStats.ContractCodeBytes != expectedStats.ContractCodeBytes {
+ t.Errorf("Contract code bytes mismatch: expected %d, got %d", expectedStats.ContractCodeBytes, actualStats.ContractCodeBytes)
+ }
+ // TODO: failed on github actions, need to investigate
+ // if actualStats.AccountTrienodes != expectedStats.AccountTrienodes {
+ // t.Errorf("Account trie nodes mismatch: expected %d, got %d", expectedStats.AccountTrienodes, actualStats.AccountTrienodes)
+ // }
+ // if actualStats.AccountTrienodeBytes != expectedStats.AccountTrienodeBytes {
+ // t.Errorf("Account trie node bytes mismatch: expected %d, got %d", expectedStats.AccountTrienodeBytes, actualStats.AccountTrienodeBytes)
+ // }
+ if actualStats.StorageTrienodes != expectedStats.StorageTrienodes {
+ t.Errorf("Storage trie nodes mismatch: expected %d, got %d", expectedStats.StorageTrienodes, actualStats.StorageTrienodes)
+ }
+ if actualStats.StorageTrienodeBytes != expectedStats.StorageTrienodeBytes {
+ t.Errorf("Storage trie node bytes mismatch: expected %d, got %d", expectedStats.StorageTrienodeBytes, actualStats.StorageTrienodeBytes)
+ }
+}
diff --git a/core/state/statedb.go b/core/state/statedb.go
index b278e762aa..897e5df91c 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -498,7 +498,7 @@ func (s *StateDB) SetNonce(addr common.Address, nonce uint64, reason tracing.Non
}
}
-func (s *StateDB) SetCode(addr common.Address, code []byte) (prev []byte) {
+func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeChangeReason) (prev []byte) {
stateObject := s.getOrNewStateObject(addr)
if stateObject != nil {
return stateObject.SetCode(crypto.Keccak256Hash(code), code)
@@ -1195,7 +1195,7 @@ func (s *StateDB) GetTrie() Trie {
// commit gathers the state mutations accumulated along with the associated
// trie changes, resetting all internal flags with the new state as the base.
-func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool) (*stateUpdate, error) {
+func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool, blockNumber uint64) (*stateUpdate, error) {
// Short circuit in case any database failure occurred earlier.
if s.dbErr != nil {
return nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
@@ -1347,13 +1347,13 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool) (*stateU
origin := s.originalRoot
s.originalRoot = root
- return newStateUpdate(noStorageWiping, origin, root, deletes, updates, nodes), nil
+ return newStateUpdate(noStorageWiping, origin, root, blockNumber, deletes, updates, nodes), nil
}
// commitAndFlush is a wrapper of commit which also commits the state mutations
// to the configured data stores.
func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (*stateUpdate, error) {
- ret, err := s.commit(deleteEmptyObjects, noStorageWiping)
+ ret, err := s.commit(deleteEmptyObjects, noStorageWiping, block)
if err != nil {
return nil, err
}
@@ -1418,6 +1418,16 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool, noStorageWiping
return ret.root, nil
}
+// CommitWithUpdate writes the state mutations and returns both the root hash and the state update.
+// This is useful for tracking state changes at the blockchain level.
+func (s *StateDB) CommitWithUpdate(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, *stateUpdate, error) {
+ ret, err := s.commitAndFlush(block, deleteEmptyObjects, noStorageWiping)
+ if err != nil {
+ return common.Hash{}, nil, err
+ }
+ return ret.root, ret, nil
+}
+
// Prepare handles the preparatory steps for executing a state transition with.
// This method must be invoked before state transition.
//
diff --git a/core/state/statedb_fuzz_test.go b/core/state/statedb_fuzz_test.go
index 7dada63d45..f4761bd10c 100644
--- a/core/state/statedb_fuzz_test.go
+++ b/core/state/statedb_fuzz_test.go
@@ -89,7 +89,7 @@ func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction
code := make([]byte, 16)
binary.BigEndian.PutUint64(code, uint64(a.args[0]))
binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
- s.SetCode(addr, code)
+ s.SetCode(addr, code, tracing.CodeChangeUnspecified)
},
args: make([]int64, 2),
},
diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go
index 3d1ef15031..d2595bcefe 100644
--- a/core/state/statedb_hooked.go
+++ b/core/state/statedb_hooked.go
@@ -189,14 +189,20 @@ func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tr
}
}
-func (s *hookedStateDB) SetCode(address common.Address, code []byte) []byte {
- prev := s.inner.SetCode(address, code)
- if s.hooks.OnCodeChange != nil {
+func (s *hookedStateDB) SetCode(address common.Address, code []byte, reason tracing.CodeChangeReason) []byte {
+ prev := s.inner.SetCode(address, code, reason)
+ if s.hooks.OnCodeChangeV2 != nil || s.hooks.OnCodeChange != nil {
prevHash := types.EmptyCodeHash
if len(prev) != 0 {
prevHash = crypto.Keccak256Hash(prev)
}
- s.hooks.OnCodeChange(address, prevHash, prev, crypto.Keccak256Hash(code), code)
+ codeHash := crypto.Keccak256Hash(code)
+
+ if s.hooks.OnCodeChangeV2 != nil {
+ s.hooks.OnCodeChangeV2(address, prevHash, prev, codeHash, code, reason)
+ } else if s.hooks.OnCodeChange != nil {
+ s.hooks.OnCodeChange(address, prevHash, prev, codeHash, code)
+ }
}
return prev
}
@@ -224,8 +230,12 @@ func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
}
- if s.hooks.OnCodeChange != nil && len(prevCode) > 0 {
- s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
+ if len(prevCode) > 0 {
+ if s.hooks.OnCodeChangeV2 != nil {
+ s.hooks.OnCodeChangeV2(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil, tracing.CodeChangeSelfDestruct)
+ } else if s.hooks.OnCodeChange != nil {
+ s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
+ }
}
return prev
@@ -242,12 +252,16 @@ func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, b
prev, changed := s.inner.SelfDestruct6780(address)
- if s.hooks.OnBalanceChange != nil && changed && !prev.IsZero() {
+ if s.hooks.OnBalanceChange != nil && !prev.IsZero() {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
}
- if s.hooks.OnCodeChange != nil && changed && len(prevCode) > 0 {
- s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
+ if changed && len(prevCode) > 0 {
+ if s.hooks.OnCodeChangeV2 != nil {
+ s.hooks.OnCodeChangeV2(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil, tracing.CodeChangeSelfDestruct)
+ } else if s.hooks.OnCodeChange != nil {
+ s.hooks.OnCodeChange(address, prevCodeHash, prevCode, types.EmptyCodeHash, nil)
+ }
}
return prev, changed
diff --git a/core/state/statedb_hooked_test.go b/core/state/statedb_hooked_test.go
index f319b0e63c..bacb7baee1 100644
--- a/core/state/statedb_hooked_test.go
+++ b/core/state/statedb_hooked_test.go
@@ -114,7 +114,7 @@ func TestHooks(t *testing.T) {
sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer)
sdb.SetNonce(common.Address{0xaa}, 1337, tracing.NonceChangeGenesis)
- sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37})
+ sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37}, tracing.CodeChangeUnspecified)
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11"))
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22"))
sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x01"))
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index 6e4207c53c..320f7f0d68 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -65,7 +65,7 @@ func TestUpdateLeaks(t *testing.T) {
state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
}
if i%3 == 0 {
- state.SetCode(addr, []byte{i, i, i, i, i})
+ state.SetCode(addr, []byte{i, i, i, i, i}, tracing.CodeChangeUnspecified)
}
}
@@ -101,7 +101,7 @@ func TestIntermediateLeaks(t *testing.T) {
state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak})
}
if i%3 == 0 {
- state.SetCode(addr, []byte{i, i, i, i, i, tweak})
+ state.SetCode(addr, []byte{i, i, i, i, i, tweak}, tracing.CodeChangeUnspecified)
}
}
@@ -374,7 +374,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
code := make([]byte, 16)
binary.BigEndian.PutUint64(code, uint64(a.args[0]))
binary.BigEndian.PutUint64(code[8:], uint64(a.args[1]))
- s.SetCode(addr, code)
+ s.SetCode(addr, code, tracing.CodeChangeUnspecified)
},
args: make([]int64, 2),
},
@@ -403,7 +403,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
// which would cause a difference in state when unrolling
// the journal. (CreateContact assumes created was false prior to
// invocation, and the journal rollback sets it to false).
- s.SetCode(addr, []byte{1})
+ s.SetCode(addr, []byte{1}, tracing.CodeChangeUnspecified)
}
},
},
@@ -731,7 +731,7 @@ func TestCopyCommitCopy(t *testing.T) {
sval := common.HexToHash("bbb")
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
@@ -772,7 +772,7 @@ func TestCopyCommitCopy(t *testing.T) {
t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval)
}
if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) {
- t.Fatalf("second copy committed storage slot mismatch: have %x, want %x", val, sval)
+ t.Fatalf("second copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
}
// Commit state, ensure states can be loaded from disk
root, _ := state.Commit(0, false, false)
@@ -804,7 +804,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
sval := common.HexToHash("bbb")
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
@@ -859,7 +859,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval)
}
if val := copyThree.GetCommittedState(addr, skey); val != (common.Hash{}) {
- t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval)
+ t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
}
}
@@ -874,7 +874,7 @@ func TestCommitCopy(t *testing.T) {
sval1, sval2 := common.HexToHash("b1"), common.HexToHash("b2")
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata
state.SetState(addr, skey1, sval1) // Change the storage trie
if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 {
@@ -912,10 +912,10 @@ func TestCommitCopy(t *testing.T) {
}
// Slots cached in the stateDB, available after commit
if val := copied.GetState(addr, skey2); val != sval2 {
- t.Fatalf("unexpected storage slot: have %x", sval1)
+ t.Fatalf("unexpected storage slot: have %x, want %x", val, sval2)
}
if val := copied.GetCommittedState(addr, skey2); val != sval2 {
- t.Fatalf("unexpected storage slot: have %x", val)
+ t.Fatalf("unexpected storage slot: have %x, want %x", val, sval2)
}
}
@@ -987,10 +987,10 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
addr := common.BytesToAddress([]byte("so"))
{
state.SetBalance(addr, uint256.NewInt(1), tracing.BalanceChangeUnspecified)
- state.SetCode(addr, []byte{1, 2, 3})
+ state.SetCode(addr, []byte{1, 2, 3}, tracing.CodeChangeUnspecified)
a2 := common.BytesToAddress([]byte("another"))
state.SetBalance(a2, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
- state.SetCode(a2, []byte{1, 2, 4})
+ state.SetCode(a2, []byte{1, 2, 4}, tracing.CodeChangeUnspecified)
root, _ = state.Commit(0, false, false)
t.Logf("root: %x", root)
// force-flush
diff --git a/core/state/stateupdate.go b/core/state/stateupdate.go
index 75c4ca028c..a62e2b2d2d 100644
--- a/core/state/stateupdate.go
+++ b/core/state/stateupdate.go
@@ -64,8 +64,10 @@ type accountUpdate struct {
// execution. It contains information about mutated contract codes, accounts,
// and storage slots, along with their original values.
type stateUpdate struct {
- originRoot common.Hash // hash of the state before applying mutation
- root common.Hash // hash of the state after applying mutation
+ originRoot common.Hash // hash of the state before applying mutation
+ root common.Hash // hash of the state after applying mutation
+ blockNumber uint64 // Associated block number
+
accounts map[common.Hash][]byte // accounts stores mutated accounts in 'slim RLP' encoding
accountsOrigin map[common.Address][]byte // accountsOrigin stores the original values of mutated accounts in 'slim RLP' encoding
@@ -95,7 +97,7 @@ func (sc *stateUpdate) empty() bool {
//
// rawStorageKey is a flag indicating whether to use the raw storage slot key or
// the hash of the slot key for constructing state update object.
-func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash, deletes map[common.Hash]*accountDelete, updates map[common.Hash]*accountUpdate, nodes *trienode.MergedNodeSet) *stateUpdate {
+func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash, blockNumber uint64, deletes map[common.Hash]*accountDelete, updates map[common.Hash]*accountUpdate, nodes *trienode.MergedNodeSet) *stateUpdate {
var (
accounts = make(map[common.Hash][]byte)
accountsOrigin = make(map[common.Address][]byte)
@@ -164,6 +166,7 @@ func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash
return &stateUpdate{
originRoot: originRoot,
root: root,
+ blockNumber: blockNumber,
accounts: accounts,
accountsOrigin: accountsOrigin,
storages: storages,
diff --git a/core/state/trie_prefetcher_test.go b/core/state/trie_prefetcher_test.go
index 4d1b627c4d..41349c0c0e 100644
--- a/core/state/trie_prefetcher_test.go
+++ b/core/state/trie_prefetcher_test.go
@@ -39,7 +39,7 @@ func filledStateDB() *StateDB {
sval := common.HexToHash("bbb")
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
for i := 0; i < 100; i++ {
sk := common.BigToHash(big.NewInt(int64(i)))
@@ -81,7 +81,7 @@ func TestVerklePrefetcher(t *testing.T) {
sval := testrand.Hash()
state.SetBalance(addr, uint256.NewInt(42), tracing.BalanceChangeUnspecified) // Change the account trie
- state.SetCode(addr, []byte("hello")) // Change an external metadata
+ state.SetCode(addr, []byte("hello"), tracing.CodeChangeUnspecified) // Change an external metadata
state.SetState(addr, skey, sval) // Change the storage trie
root, _ := state.Commit(0, true, false)
diff --git a/core/state_transition.go b/core/state_transition.go
index 688d57404a..925941b20e 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -164,8 +164,12 @@ type Message struct {
// or the state prefetching.
SkipNonceChecks bool
- // When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
- SkipFromEOACheck bool
+ // When set, the message is not treated as a transaction, and certain
+ // transaction-specific checks are skipped:
+ //
+ // - From is not verified to be an EOA
+ // - GasLimit is not checked against the protocol defined tx gaslimit
+ SkipTransactionChecks bool
IsSystemTx bool // IsSystemTx indicates the message, if also a deposit, does not emit gas usage.
IsDepositTx bool // IsDepositTx indicates the message is force-included and can persist a mint.
@@ -187,7 +191,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
AccessList: tx.AccessList(),
SetCodeAuthorizations: tx.SetCodeAuthorizations(),
SkipNonceChecks: false,
- SkipFromEOACheck: false,
+ SkipTransactionChecks: false,
BlobHashes: tx.BlobHashes(),
BlobGasFeeCap: tx.BlobGasFeeCap(),
@@ -274,7 +278,7 @@ func (st *stateTransition) buyGas() error {
mgval.Mul(mgval, st.msg.GasPrice)
var l1Cost *big.Int
var operatorCost *uint256.Int
- if !st.msg.SkipNonceChecks && !st.msg.SkipFromEOACheck {
+ if !st.msg.SkipNonceChecks && !st.msg.SkipTransactionChecks {
if st.evm.Context.L1CostFunc != nil {
l1Cost = st.evm.Context.L1CostFunc(st.msg.RollupCostData, st.evm.Context.Time)
if l1Cost != nil {
@@ -365,7 +369,12 @@ func (st *stateTransition) preCheck() error {
msg.From.Hex(), stNonce)
}
}
- if !msg.SkipFromEOACheck {
+ isOsaka := st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time)
+ if !msg.SkipTransactionChecks {
+ // Verify tx gas limit does not exceed EIP-7825 cap.
+ if isOsaka && msg.GasLimit > params.MaxTxGas {
+ return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
+ }
// Make sure the sender is an EOA
code := st.state.GetCode(msg.From)
_, delegated := types.ParseDelegation(code)
@@ -399,7 +408,6 @@ func (st *stateTransition) preCheck() error {
}
}
// Check the blob version validity
- isOsaka := st.evm.ChainConfig().IsOsaka(st.evm.Context.BlockNumber, st.evm.Context.Time)
if msg.BlobHashes != nil {
// The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally
// has it as a non-nillable value, so any msg derived from blob transaction has it non-nil.
@@ -443,10 +451,6 @@ func (st *stateTransition) preCheck() error {
return fmt.Errorf("%w (sender %v)", ErrEmptyAuthList, msg.From)
}
}
- // Verify tx gas limit does not exceed EIP-7825 cap.
- if isOsaka && msg.GasLimit > params.MaxTxGas {
- return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, msg.GasLimit)
- }
return st.buyGas()
}
@@ -759,12 +763,12 @@ func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization)
st.state.SetNonce(authority, auth.Nonce+1, tracing.NonceChangeAuthorization)
if auth.Address == (common.Address{}) {
// Delegation to zero address means clear.
- st.state.SetCode(authority, nil)
+ st.state.SetCode(authority, nil, tracing.CodeChangeAuthorizationClear)
return nil
}
// Otherwise install delegation to auth.Address.
- st.state.SetCode(authority, types.AddressToDelegation(auth.Address))
+ st.state.SetCode(authority, types.AddressToDelegation(auth.Address), tracing.CodeChangeAuthorization)
return nil
}
diff --git a/core/stateless/encoding.go b/core/stateless/encoding.go
index b5174ab586..bdd5641fca 100644
--- a/core/stateless/encoding.go
+++ b/core/stateless/encoding.go
@@ -25,16 +25,16 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
-// toExtWitness converts our internal witness representation to the consensus one.
-func (w *Witness) toExtWitness() *extWitness {
- ext := &extWitness{
+// ToExtWitness converts our internal witness representation to the consensus one.
+func (w *Witness) ToExtWitness() *ExtWitness {
+ ext := &ExtWitness{
Headers: w.Headers,
}
- ext.Codes = make([][]byte, 0, len(w.Codes))
+ ext.Codes = make([]hexutil.Bytes, 0, len(w.Codes))
for code := range w.Codes {
ext.Codes = append(ext.Codes, []byte(code))
}
- ext.State = make([][]byte, 0, len(w.State))
+ ext.State = make([]hexutil.Bytes, 0, len(w.State))
for node := range w.State {
ext.State = append(ext.State, []byte(node))
}
@@ -42,7 +42,7 @@ func (w *Witness) toExtWitness() *extWitness {
}
// fromExtWitness converts the consensus witness format into our internal one.
-func (w *Witness) fromExtWitness(ext *extWitness) error {
+func (w *Witness) fromExtWitness(ext *ExtWitness) error {
w.Headers = ext.Headers
w.Codes = make(map[string]struct{}, len(ext.Codes))
@@ -58,23 +58,24 @@ func (w *Witness) fromExtWitness(ext *extWitness) error {
// EncodeRLP serializes a witness as RLP.
func (w *Witness) EncodeRLP(wr io.Writer) error {
- return rlp.Encode(wr, w.toExtWitness())
+ return rlp.Encode(wr, w.ToExtWitness())
}
// DecodeRLP decodes a witness from RLP.
func (w *Witness) DecodeRLP(s *rlp.Stream) error {
- var ext extWitness
+ var ext ExtWitness
if err := s.Decode(&ext); err != nil {
return err
}
return w.fromExtWitness(&ext)
}
-// extWitness is a witness RLP encoding for transferring across clients.
-type extWitness struct {
- Headers []*types.Header
- Codes [][]byte
- State [][]byte
+// ExtWitness is a witness RLP encoding for transferring across clients.
+type ExtWitness struct {
+ Headers []*types.Header `json:"headers"`
+ Codes []hexutil.Bytes `json:"codes"`
+ State []hexutil.Bytes `json:"state"`
+ Keys []hexutil.Bytes `json:"keys"`
}
// ExecutionWitness is a witness json encoding for transferring across clients
diff --git a/core/stateless/stats.go b/core/stateless/stats.go
index adc898929b..94f5587f99 100644
--- a/core/stateless/stats.go
+++ b/core/stateless/stats.go
@@ -17,76 +17,37 @@
package stateless
import (
+ "encoding/json"
"maps"
"slices"
"sort"
+ "strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
-var (
- accountTrieDepthAvg = metrics.NewRegisteredGauge("witness/trie/account/depth/avg", nil)
- accountTrieDepthMin = metrics.NewRegisteredGauge("witness/trie/account/depth/min", nil)
- accountTrieDepthMax = metrics.NewRegisteredGauge("witness/trie/account/depth/max", nil)
+var accountTrieLeavesAtDepth [16]*metrics.Counter
+var storageTrieLeavesAtDepth [16]*metrics.Counter
- storageTrieDepthAvg = metrics.NewRegisteredGauge("witness/trie/storage/depth/avg", nil)
- storageTrieDepthMin = metrics.NewRegisteredGauge("witness/trie/storage/depth/min", nil)
- storageTrieDepthMax = metrics.NewRegisteredGauge("witness/trie/storage/depth/max", nil)
-)
-
-// depthStats tracks min/avg/max statistics for trie access depths.
-type depthStats struct {
- totalDepth int64
- samples int64
- minDepth int64
- maxDepth int64
-}
-
-// newDepthStats creates a new depthStats with default values.
-func newDepthStats() *depthStats {
- return &depthStats{minDepth: -1}
-}
-
-// add records a new depth sample.
-func (d *depthStats) add(n int64) {
- if n < 0 {
- return
- }
- d.totalDepth += n
- d.samples++
-
- if d.minDepth == -1 || n < d.minDepth {
- d.minDepth = n
+func init() {
+ for i := 0; i < 16; i++ {
+ accountTrieLeavesAtDepth[i] = metrics.NewRegisteredCounter("witness/trie/account/leaves/depth_"+strconv.Itoa(i), nil)
+ storageTrieLeavesAtDepth[i] = metrics.NewRegisteredCounter("witness/trie/storage/leaves/depth_"+strconv.Itoa(i), nil)
}
- if n > d.maxDepth {
- d.maxDepth = n
- }
-}
-
-// report uploads the collected statistics into the provided gauges.
-func (d *depthStats) report(maxGauge, minGauge, avgGauge *metrics.Gauge) {
- if d.samples == 0 {
- return
- }
- maxGauge.Update(d.maxDepth)
- minGauge.Update(d.minDepth)
- avgGauge.Update(d.totalDepth / d.samples)
}
// WitnessStats aggregates statistics for account and storage trie accesses.
type WitnessStats struct {
- accountTrie *depthStats
- storageTrie *depthStats
+ accountTrieLeaves [16]int64
+ storageTrieLeaves [16]int64
}
// NewWitnessStats creates a new WitnessStats collector.
func NewWitnessStats() *WitnessStats {
- return &WitnessStats{
- accountTrie: newDepthStats(),
- storageTrie: newDepthStats(),
- }
+ return &WitnessStats{}
}
// Add records trie access depths from the given node paths.
@@ -102,16 +63,30 @@ func (s *WitnessStats) Add(nodes map[string][]byte, owner common.Hash) {
// The last path is always a leaf.
if i == len(paths)-1 || !strings.HasPrefix(paths[i+1], paths[i]) {
if owner == (common.Hash{}) {
- s.accountTrie.add(int64(len(path)))
+ s.accountTrieLeaves[len(path)] += 1
} else {
- s.storageTrie.add(int64(len(path)))
+ s.storageTrieLeaves[len(path)] += 1
}
}
}
}
// ReportMetrics reports the collected statistics to the global metrics registry.
-func (s *WitnessStats) ReportMetrics() {
- s.accountTrie.report(accountTrieDepthMax, accountTrieDepthMin, accountTrieDepthAvg)
- s.storageTrie.report(storageTrieDepthMax, storageTrieDepthMin, storageTrieDepthAvg)
+func (s *WitnessStats) ReportMetrics(blockNumber uint64) {
+ // Encode the metrics as JSON for easier consumption
+ accountLeavesJson, _ := json.Marshal(s.accountTrieLeaves)
+ storageLeavesJson, _ := json.Marshal(s.storageTrieLeaves)
+
+ // Log account trie depth statistics
+ log.Info("Account trie depth stats",
+ "block", blockNumber,
+ "leavesAtDepth", string(accountLeavesJson))
+ log.Info("Storage trie depth stats",
+ "block", blockNumber,
+ "leavesAtDepth", string(storageLeavesJson))
+
+ for i := 0; i < 16; i++ {
+ accountTrieLeavesAtDepth[i].Inc(s.accountTrieLeaves[i])
+ storageTrieLeavesAtDepth[i].Inc(s.storageTrieLeaves[i])
+ }
}
diff --git a/core/stateless/stats_test.go b/core/stateless/stats_test.go
index 51c78cc9c9..e77084df5d 100644
--- a/core/stateless/stats_test.go
+++ b/core/stateless/stats_test.go
@@ -24,27 +24,32 @@ import (
func TestWitnessStatsAdd(t *testing.T) {
tests := []struct {
- name string
- nodes map[string][]byte
- owner common.Hash
- expectedAccountDepth int64
- expectedStorageDepth int64
+ name string
+ nodes map[string][]byte
+ owner common.Hash
+ expectedAccountLeaves map[int64]int64
+ expectedStorageLeaves map[int64]int64
}{
{
- name: "empty nodes",
- nodes: map[string][]byte{},
- owner: common.Hash{},
- expectedAccountDepth: 0,
- expectedStorageDepth: 0,
+ name: "empty nodes",
+ nodes: map[string][]byte{},
+ owner: common.Hash{},
+ },
+ {
+ name: "single account trie leaf at depth 0",
+ nodes: map[string][]byte{
+ "": []byte("data"),
+ },
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{0: 1},
},
{
name: "single account trie leaf",
nodes: map[string][]byte{
"abc": []byte("data"),
},
- owner: common.Hash{},
- expectedAccountDepth: 3,
- expectedStorageDepth: 0,
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{3: 1},
},
{
name: "account trie with internal nodes",
@@ -53,9 +58,8 @@ func TestWitnessStatsAdd(t *testing.T) {
"ab": []byte("data2"),
"abc": []byte("data3"),
},
- owner: common.Hash{},
- expectedAccountDepth: 3, // Only "abc" is a leaf
- expectedStorageDepth: 0,
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{3: 1}, // Only "abc" is a leaf
},
{
name: "multiple account trie branches",
@@ -67,9 +71,8 @@ func TestWitnessStatsAdd(t *testing.T) {
"bc": []byte("data5"),
"bcd": []byte("data6"),
},
- owner: common.Hash{},
- expectedAccountDepth: 6, // "abc" (3) + "bcd" (3) = 6
- expectedStorageDepth: 0,
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{3: 2}, // "abc" (3) + "bcd" (3)
},
{
name: "siblings are all leaves",
@@ -78,9 +81,8 @@ func TestWitnessStatsAdd(t *testing.T) {
"ab": []byte("data2"),
"ac": []byte("data3"),
},
- owner: common.Hash{},
- expectedAccountDepth: 6, // 2 + 2 + 2 = 6
- expectedStorageDepth: 0,
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{2: 3},
},
{
name: "storage trie leaves",
@@ -90,9 +92,8 @@ func TestWitnessStatsAdd(t *testing.T) {
"123": []byte("data3"),
"124": []byte("data4"),
},
- owner: common.HexToHash("0x1234"),
- expectedAccountDepth: 0,
- expectedStorageDepth: 6, // "123" (3) + "124" (3) = 6
+ owner: common.HexToHash("0x1234"),
+ expectedStorageLeaves: map[int64]int64{3: 2}, // "123" (3) + "124" (3)
},
{
name: "complex trie structure",
@@ -107,9 +108,8 @@ func TestWitnessStatsAdd(t *testing.T) {
"235": []byte("data8"),
"3": []byte("data9"),
},
- owner: common.Hash{},
- expectedAccountDepth: 13, // "123"(3) + "124"(3) + "234"(3) + "235"(3) + "3"(1) = 13
- expectedStorageDepth: 0,
+ owner: common.Hash{},
+ expectedAccountLeaves: map[int64]int64{1: 1, 3: 4}, // "123"(3) + "124"(3) + "234"(3) + "235"(3) + "3"(1)
},
}
@@ -118,14 +118,23 @@ func TestWitnessStatsAdd(t *testing.T) {
stats := NewWitnessStats()
stats.Add(tt.nodes, tt.owner)
+ var expectedAccountTrieLeaves [16]int64
+ for depth, count := range tt.expectedAccountLeaves {
+ expectedAccountTrieLeaves[depth] = count
+ }
+ var expectedStorageTrieLeaves [16]int64
+ for depth, count := range tt.expectedStorageLeaves {
+ expectedStorageTrieLeaves[depth] = count
+ }
+
// Check account trie depth
- if stats.accountTrie.totalDepth != tt.expectedAccountDepth {
- t.Errorf("Account trie total depth = %d, want %d", stats.accountTrie.totalDepth, tt.expectedAccountDepth)
+ if stats.accountTrieLeaves != expectedAccountTrieLeaves {
+ t.Errorf("Account trie total depth = %v, want %v", stats.accountTrieLeaves, expectedAccountTrieLeaves)
}
// Check storage trie depth
- if stats.storageTrie.totalDepth != tt.expectedStorageDepth {
- t.Errorf("Storage trie total depth = %d, want %d", stats.storageTrie.totalDepth, tt.expectedStorageDepth)
+ if stats.storageTrieLeaves != expectedStorageTrieLeaves {
+ t.Errorf("Storage trie total depth = %v, want %v", stats.storageTrieLeaves, expectedStorageTrieLeaves)
}
})
}
@@ -144,11 +153,10 @@ func TestWitnessStatsMinMax(t *testing.T) {
}, common.Hash{})
// Only "abcde" is a leaf (depth 5)
- if stats.accountTrie.minDepth != 5 {
- t.Errorf("Account trie min depth = %d, want %d", stats.accountTrie.minDepth, 5)
- }
- if stats.accountTrie.maxDepth != 5 {
- t.Errorf("Account trie max depth = %d, want %d", stats.accountTrie.maxDepth, 5)
+ for i, v := range stats.accountTrieLeaves {
+ if v != 0 && i != 5 {
+ t.Errorf("leaf found at invalid depth %d", i)
+ }
}
// Add more leaves with different depths
@@ -158,11 +166,10 @@ func TestWitnessStatsMinMax(t *testing.T) {
}, common.Hash{})
// Now we have leaves at depths 1, 2, and 5
- if stats.accountTrie.minDepth != 1 {
- t.Errorf("Account trie min depth after update = %d, want %d", stats.accountTrie.minDepth, 1)
- }
- if stats.accountTrie.maxDepth != 5 {
- t.Errorf("Account trie max depth after update = %d, want %d", stats.accountTrie.maxDepth, 5)
+ for i, v := range stats.accountTrieLeaves {
+ if v != 0 && (i != 5 && i != 2 && i != 1) {
+ t.Errorf("leaf found at invalid depth %d", i)
+ }
}
}
@@ -179,7 +186,12 @@ func TestWitnessStatsAverage(t *testing.T) {
// All are leaves: 2 + 2 + 3 + 4 = 11 total, 4 samples
expectedAvg := int64(11) / int64(4)
- actualAvg := stats.accountTrie.totalDepth / stats.accountTrie.samples
+ var actualAvg, totalSamples int64
+ for i, c := range stats.accountTrieLeaves {
+ actualAvg += c * int64(i)
+ totalSamples += c
+ }
+ actualAvg = actualAvg / totalSamples
if actualAvg != expectedAvg {
t.Errorf("Account trie average depth = %d, want %d", actualAvg, expectedAvg)
diff --git a/core/stateless/witness.go b/core/stateless/witness.go
index 371a128f48..588c895a2f 100644
--- a/core/stateless/witness.go
+++ b/core/stateless/witness.go
@@ -100,6 +100,10 @@ func (w *Witness) AddState(nodes map[string][]byte) {
}
}
+func (w *Witness) AddKey() {
+ panic("not yet implemented")
+}
+
// Copy deep-copies the witness object. Witness.Block isn't deep-copied as it
// is never mutated by Witness
func (w *Witness) Copy() *Witness {
diff --git a/core/tracing/CHANGELOG.md b/core/tracing/CHANGELOG.md
index a14e123d99..a94fa81b55 100644
--- a/core/tracing/CHANGELOG.md
+++ b/core/tracing/CHANGELOG.md
@@ -4,6 +4,27 @@ All notable changes to the tracing interface will be documented in this file.
## [Unreleased]
+### Deprecated methods
+
+- `OnCodeChange(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte)`: This hook is deprecated in favor of `OnCodeChangeV2` which includes a reason parameter ([#32525](https://github.com/ethereum/go-ethereum/pull/32525)).
+
+### New methods
+
+- `OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason)`: This hook is called when a code change occurs. It is a successor to `OnCodeChange` with an additional reason parameter ([#32525](https://github.com/ethereum/go-ethereum/pull/32525)).
+
+### New types
+
+- `CodeChangeReason` is a new type used to provide a reason for code changes. It includes various reasons such as contract creation, genesis initialization, EIP-7702 authorization, self-destruct, and revert operations ([#32525](https://github.com/ethereum/go-ethereum/pull/32525)).
+
+## [v1.15.4](https://github.com/ethereum/go-ethereum/releases/tag/v1.15.4)
+
+### Modified types
+
+- `GasChangeReason` has been extended with auto-generated String() methods for better debugging and logging ([#31234](https://github.com/ethereum/go-ethereum/pull/31234)).
+- `NonceChangeReason` has been extended with auto-generated String() methods for better debugging and logging ([#31234](https://github.com/ethereum/go-ethereum/pull/31234)).
+
+## [v1.15.0](https://github.com/ethereum/go-ethereum/releases/tag/v1.15.0)
+
The tracing interface has been extended with backwards-compatible changes to support more use-cases and simplify tracer code. The most notable change is a state journaling library which emits reverse events when a call is reverted.
### Deprecated methods
@@ -23,8 +44,13 @@ The tracing interface has been extended with backwards-compatible changes to sup
### Modified types
-- `VMContext.StateDB` has been extended with `GetCodeHash(addr common.Address) common.Hash` method used to retrieve the code hash an account.
+- `VMContext.StateDB` has been extended with the following method:
+ - `GetCodeHash(addr common.Address) common.Hash` method used to retrieve the code hash of an account.
+- `BlockEvent` has been modified:
+ - The `TD` (Total Difficulty) field has been removed ([#30744](https://github.com/ethereum/go-ethereum/pull/30744)).
- `BalanceChangeReason` has been extended with the `BalanceChangeRevert` reason. More on that below.
+- `GasChangeReason` has been extended with the following reason:
+ - `GasChangeTxDataFloor` is the amount of extra gas the transaction has to pay to reach the minimum gas requirement for the transaction data. This change will always be a negative change.
### State journaling
@@ -49,21 +75,34 @@ The state changes that are covered by the journaling library are:
- `OnCodeChange`
- `OnStorageChange`
-## [v1.14.9](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.9)
-
-### Modified types
+## [v1.14.12](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.12)
-- `GasChangeReason` has been extended with the following reasons which will be enabled only post-Verkle. There shouldn't be any gas changes with those reasons prior to the fork.
- - `GasChangeWitnessContractCollisionCheck` flags the event of adding to the witness when checking for contract address collision.
+This release contains a change in behavior for `OnCodeChange` hook and an extension to the StateDB interface.
-## [v1.14.12]
+### Modified types
-This release contains a change in behavior for `OnCodeChange` hook.
+- `VMContext.StateDB` has been extended with the following method:
+ - `GetTransientState(addr common.Address, slot common.Hash) common.Hash` method used to access contract transient storage ([#30531](https://github.com/ethereum/go-ethereum/pull/30531)).
### `OnCodeChange` change
The `OnCodeChange` hook is now called when the code of a contract is removed due to a selfdestruct. Previously, no code change was emitted on such occasions.
+## [v1.14.10](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.10)
+
+### Modified types
+
+- `OpContext` has been extended with the following method:
+ - `ContractCode() []byte` provides access to the contract bytecode within the OpContext interface ([#30466](https://github.com/ethereum/go-ethereum/pull/30466)).
+
+## [v1.14.9](https://github.com/ethereum/go-ethereum/releases/tag/v1.14.9)
+
+### Modified types
+
+- `GasChangeReason` has been extended with the following reasons which will be enabled only post-Verkle. There shouldn't be any gas changes with those reasons prior to the fork.
+ - `GasChangeWitnessContractCollisionCheck` flags the event of adding to the witness when checking for contract address collision.
+
+
## [v1.14.4]
This release contained only minor extensions to the tracing interface.
@@ -148,7 +187,12 @@ The hooks `CaptureStart` and `CaptureEnd` have been removed. These hooks signale
- `CaptureState` -> `OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error)`. `op` is of type `byte` which can be cast to `vm.OpCode` when necessary. A `*vm.ScopeContext` is not passed anymore. It is replaced by `tracing.OpContext` which offers access to the memory, stack and current contract.
- `CaptureFault` -> `OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error)`. Similar to above.
-[unreleased]: https://github.com/ethereum/go-ethereum/compare/v1.14.8...master
-[v1.14.0]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.0
-[v1.14.3]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.3
+[unreleased]: https://github.com/ethereum/go-ethereum/compare/v1.16.3...master
+[v1.15.4]: https://github.com/ethereum/go-ethereum/releases/tag/v1.15.4
+[v1.15.0]: https://github.com/ethereum/go-ethereum/releases/tag/v1.15.0
+[v1.14.12]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.12
+[v1.14.10]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.10
+[v1.14.9]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.9
[v1.14.4]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.4
+[v1.14.3]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.3
+[v1.14.0]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.0
diff --git a/core/tracing/gen_balance_change_reason_stringer.go b/core/tracing/gen_balance_change_reason_stringer.go
index 2c0ee58fe9..ce05cf5ca8 100644
--- a/core/tracing/gen_balance_change_reason_stringer.go
+++ b/core/tracing/gen_balance_change_reason_stringer.go
@@ -27,18 +27,22 @@ func _() {
_ = x[BalanceMint-200]
}
-const _BalanceChangeReason_name = "UnspecifiedBalanceIncreaseRewardMineUncleBalanceIncreaseRewardMineBlockBalanceIncreaseWithdrawalBalanceIncreaseGenesisBalanceBalanceIncreaseRewardTransactionFeeBalanceDecreaseGasBuyBalanceIncreaseGasReturnBalanceIncreaseDaoContractBalanceDecreaseDaoAccountTransferTouchAccountBalanceIncreaseSelfdestructBalanceDecreaseSelfdestructBalanceDecreaseSelfdestructBurnRevert"
+const (
+ _BalanceChangeReason_name_0 = "UnspecifiedBalanceIncreaseRewardMineUncleBalanceIncreaseRewardMineBlockBalanceIncreaseWithdrawalBalanceIncreaseGenesisBalanceBalanceIncreaseRewardTransactionFeeBalanceDecreaseGasBuyBalanceIncreaseGasReturnBalanceIncreaseDaoContractBalanceDecreaseDaoAccountTransferTouchAccountBalanceIncreaseSelfdestructBalanceDecreaseSelfdestructBalanceDecreaseSelfdestructBurnRevert"
+ _BalanceChangeReason_name_1 = "BalanceMint"
+)
-var _BalanceChangeReason_index = [...]uint16{0, 11, 41, 71, 96, 125, 160, 181, 205, 231, 256, 264, 276, 303, 330, 361, 367}
+var (
+ _BalanceChangeReason_index_0 = [...]uint16{0, 11, 41, 71, 96, 125, 160, 181, 205, 231, 256, 264, 276, 303, 330, 361, 367}
+)
func (i BalanceChangeReason) String() string {
- // OP-Stack addition
- if i == BalanceMint {
- return "BalanceMint"
- }
-
- if i >= BalanceChangeReason(len(_BalanceChangeReason_index)-1) {
+ switch {
+ case i <= 15:
+ return _BalanceChangeReason_name_0[_BalanceChangeReason_index_0[i]:_BalanceChangeReason_index_0[i+1]]
+ case i == 200:
+ return _BalanceChangeReason_name_1
+ default:
return "BalanceChangeReason(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _BalanceChangeReason_name[_BalanceChangeReason_index[i]:_BalanceChangeReason_index[i+1]]
}
diff --git a/core/tracing/gen_code_change_reason_stringer.go b/core/tracing/gen_code_change_reason_stringer.go
new file mode 100644
index 0000000000..9372954063
--- /dev/null
+++ b/core/tracing/gen_code_change_reason_stringer.go
@@ -0,0 +1,29 @@
+// Code generated by "stringer -type=CodeChangeReason -trimprefix=CodeChange -output gen_code_change_reason_stringer.go"; DO NOT EDIT.
+
+package tracing
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[CodeChangeUnspecified-0]
+ _ = x[CodeChangeContractCreation-1]
+ _ = x[CodeChangeGenesis-2]
+ _ = x[CodeChangeAuthorization-3]
+ _ = x[CodeChangeAuthorizationClear-4]
+ _ = x[CodeChangeSelfDestruct-5]
+ _ = x[CodeChangeRevert-6]
+}
+
+const _CodeChangeReason_name = "UnspecifiedContractCreationGenesisAuthorizationAuthorizationClearSelfDestructRevert"
+
+var _CodeChangeReason_index = [...]uint8{0, 11, 27, 34, 47, 65, 77, 83}
+
+func (i CodeChangeReason) String() string {
+ if i >= CodeChangeReason(len(_CodeChangeReason_index)-1) {
+ return "CodeChangeReason(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _CodeChangeReason_name[_CodeChangeReason_index[i]:_CodeChangeReason_index[i+1]]
+}
diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go
index ebc561c293..e1e17c4ed4 100644
--- a/core/tracing/hooks.go
+++ b/core/tracing/hooks.go
@@ -177,6 +177,9 @@ type (
// CodeChangeHook is called when the code of an account changes.
CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte)
+ // CodeChangeHookV2 is called when the code of an account changes.
+ CodeChangeHookV2 = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason)
+
// StorageChangeHook is called when the storage of an account changes.
StorageChangeHook = func(addr common.Address, slot common.Hash, prev, new common.Hash)
@@ -211,6 +214,7 @@ type Hooks struct {
OnNonceChange NonceChangeHook
OnNonceChangeV2 NonceChangeHookV2
OnCodeChange CodeChangeHook
+ OnCodeChangeV2 CodeChangeHookV2
OnStorageChange StorageChangeHook
OnLog LogHook
// Block hash read
@@ -375,3 +379,31 @@ const (
// It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal).
NonceChangeRevert NonceChangeReason = 6
)
+
+// CodeChangeReason is used to indicate the reason for a code change.
+type CodeChangeReason byte
+
+//go:generate go run golang.org/x/tools/cmd/stringer -type=CodeChangeReason -trimprefix=CodeChange -output gen_code_change_reason_stringer.go
+
+const (
+ CodeChangeUnspecified CodeChangeReason = 0
+
+ // CodeChangeContractCreation is when a new contract is deployed via CREATE/CREATE2 operations.
+ CodeChangeContractCreation CodeChangeReason = 1
+
+ // CodeChangeGenesis is when contract code is set during blockchain genesis or initial setup.
+ CodeChangeGenesis CodeChangeReason = 2
+
+ // CodeChangeAuthorization is when code is set via EIP-7702 Set Code Authorization.
+ CodeChangeAuthorization CodeChangeReason = 3
+
+ // CodeChangeAuthorizationClear is when EIP-7702 delegation is cleared by setting to zero address.
+ CodeChangeAuthorizationClear CodeChangeReason = 4
+
+ // CodeChangeSelfDestruct is when contract code is cleared due to self-destruct.
+ CodeChangeSelfDestruct CodeChangeReason = 5
+
+ // CodeChangeRevert is emitted when the code is reverted back to a previous value due to call failure.
+ // It is only emitted when the tracer has opted in to use the journaling wrapper (WrapWithJournal).
+ CodeChangeRevert CodeChangeReason = 6
+)
diff --git a/core/tracing/journal.go b/core/tracing/journal.go
index a402f1ac09..62a70d6c27 100644
--- a/core/tracing/journal.go
+++ b/core/tracing/journal.go
@@ -42,12 +42,15 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
return nil, errors.New("wrapping nil tracer")
}
// No state change to journal, return the wrapped hooks as is
- if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnStorageChange == nil {
+ if hooks.OnBalanceChange == nil && hooks.OnNonceChange == nil && hooks.OnNonceChangeV2 == nil && hooks.OnCodeChange == nil && hooks.OnCodeChangeV2 == nil && hooks.OnStorageChange == nil {
return hooks, nil
}
if hooks.OnNonceChange != nil && hooks.OnNonceChangeV2 != nil {
return nil, errors.New("cannot have both OnNonceChange and OnNonceChangeV2")
}
+ if hooks.OnCodeChange != nil && hooks.OnCodeChangeV2 != nil {
+ return nil, errors.New("cannot have both OnCodeChange and OnCodeChangeV2")
+ }
// Create a new Hooks instance and copy all hooks
wrapped := *hooks
@@ -72,6 +75,9 @@ func WrapWithJournal(hooks *Hooks) (*Hooks, error) {
if hooks.OnCodeChange != nil {
wrapped.OnCodeChange = j.OnCodeChange
}
+ if hooks.OnCodeChangeV2 != nil {
+ wrapped.OnCodeChangeV2 = j.OnCodeChangeV2
+ }
if hooks.OnStorageChange != nil {
wrapped.OnStorageChange = j.OnStorageChange
}
@@ -174,6 +180,19 @@ func (j *journal) OnCodeChange(addr common.Address, prevCodeHash common.Hash, pr
}
}
+func (j *journal) OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason) {
+ j.entries = append(j.entries, codeChange{
+ addr: addr,
+ prevCodeHash: prevCodeHash,
+ prevCode: prevCode,
+ newCodeHash: codeHash,
+ newCode: code,
+ })
+ if j.hooks.OnCodeChangeV2 != nil {
+ j.hooks.OnCodeChangeV2(addr, prevCodeHash, prevCode, codeHash, code, reason)
+ }
+}
+
func (j *journal) OnStorageChange(addr common.Address, slot common.Hash, prev, new common.Hash) {
j.entries = append(j.entries, storageChange{addr: addr, slot: slot, prev: prev, new: new})
if j.hooks.OnStorageChange != nil {
@@ -225,7 +244,9 @@ func (n nonceChange) revert(hooks *Hooks) {
}
func (c codeChange) revert(hooks *Hooks) {
- if hooks.OnCodeChange != nil {
+ if hooks.OnCodeChangeV2 != nil {
+ hooks.OnCodeChangeV2(c.addr, c.newCodeHash, c.newCode, c.prevCodeHash, c.prevCode, CodeChangeRevert)
+ } else if hooks.OnCodeChange != nil {
hooks.OnCodeChange(c.addr, c.newCodeHash, c.newCode, c.prevCodeHash, c.prevCode)
}
}
diff --git a/core/tracing/journal_test.go b/core/tracing/journal_test.go
index 99447e1e1d..e00447f5f3 100644
--- a/core/tracing/journal_test.go
+++ b/core/tracing/journal_test.go
@@ -23,6 +23,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
)
type testTracer struct {
@@ -56,6 +57,11 @@ func (t *testTracer) OnCodeChange(addr common.Address, prevCodeHash common.Hash,
t.code = code
}
+func (t *testTracer) OnCodeChangeV2(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason CodeChangeReason) {
+ t.t.Logf("OnCodeChangeV2(%v, %v -> %v, %v)", addr, prevCodeHash, codeHash, reason)
+ t.code = code
+}
+
func (t *testTracer) OnStorageChange(addr common.Address, slot common.Hash, prev common.Hash, new common.Hash) {
t.t.Logf("OnStorageCodeChange(%v, %v, %v -> %v)", addr, slot, prev, new)
if t.storage == nil {
@@ -232,6 +238,27 @@ func TestOnNonceChangeV2(t *testing.T) {
}
}
+func TestOnCodeChangeV2(t *testing.T) {
+ tr := &testTracer{t: t}
+ wr, err := WrapWithJournal(&Hooks{OnCodeChangeV2: tr.OnCodeChangeV2})
+ if err != nil {
+ t.Fatalf("failed to wrap test tracer: %v", err)
+ }
+
+ addr := common.HexToAddress("0x1234")
+ code := []byte{1, 2, 3}
+ {
+ wr.OnEnter(2, 0, addr, addr, nil, 1000, big.NewInt(0))
+ wr.OnCodeChangeV2(addr, common.Hash{}, nil, crypto.Keccak256Hash(code), code, CodeChangeContractCreation)
+ wr.OnExit(2, nil, 100, nil, true)
+ }
+
+ // After revert, code should be nil
+ if tr.code != nil {
+ t.Fatalf("unexpected code after revert: %v", tr.code)
+ }
+}
+
func TestAllHooksCalled(t *testing.T) {
tracer := newTracerAllHooks()
hooks := tracer.hooks()
@@ -253,10 +280,6 @@ func TestAllHooksCalled(t *testing.T) {
if field.Type.Kind() != reflect.Func {
continue
}
- // Skip non-hooks, i.e. Copy
- if field.Name == "copy" {
- continue
- }
// Skip if field is not set
if wrappedValue.Field(i).IsNil() {
continue
@@ -298,6 +321,7 @@ func newTracerAllHooks() *tracerAllHooks {
t.hooksCalled[hooksType.Field(i).Name] = false
}
delete(t.hooksCalled, "OnNonceChange")
+ delete(t.hooksCalled, "OnCodeChange")
return t
}
@@ -322,7 +346,7 @@ func (t *tracerAllHooks) hooks() *Hooks {
hooksValue := reflect.ValueOf(h).Elem()
for i := 0; i < hooksValue.NumField(); i++ {
field := hooksValue.Type().Field(i)
- if field.Name == "OnNonceChange" {
+ if field.Name == "OnNonceChange" || field.Name == "OnCodeChange" {
continue
}
hookMethod := reflect.MakeFunc(field.Type, func(args []reflect.Value) []reflect.Value {
diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go
index 0e9c258ac4..84700339a6 100644
--- a/core/txpool/blobpool/blobpool.go
+++ b/core/txpool/blobpool/blobpool.go
@@ -21,12 +21,15 @@ import (
"container/heap"
"errors"
"fmt"
+ "maps"
"math"
"math/big"
"os"
"path/filepath"
+ "slices"
"sort"
"sync"
+ "sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -61,11 +64,11 @@ const (
// small buffer is added to the proof overhead.
txBlobOverhead = uint32(kzg4844.CellProofsPerBlob*len(kzg4844.Proof{}) + 64)
- // txMaxSize is the maximum size a single transaction can have, outside
- // the included blobs. Since blob transactions are pulled instead of pushed,
- // and only a small metadata is kept in ram, the rest is on disk, there is
- // no critical limit that should be enforced. Still, capping it to some sane
- // limit can never hurt.
+ // txMaxSize is the maximum size a single transaction can have, including the
+ // blobs. Since blob transactions are pulled instead of pushed, and only a
+ // small metadata is kept in ram, the rest is on disk, there is no critical
+ // limit that should be enforced. Still, capping it to some sane limit can
+ // never hurt, which is aligned with maxBlobsPerTx constraint enforced internally.
txMaxSize = 1024 * 1024
// maxBlobsPerTx is the maximum number of blobs that a single transaction can
@@ -93,6 +96,11 @@ const (
// storeVersion is the current slotter layout used for the billy.Database
// store.
storeVersion = 1
+
+ // conversionTimeWindow defines the period after the Osaka fork during which
+ // the pool will still accept and convert legacy blob transactions. After this
+ // window, all legacy blob transactions will be rejected.
+ conversionTimeWindow = time.Hour * 2
)
// blobTxMeta is the minimal subset of types.BlobTx necessary to validate and
@@ -102,6 +110,7 @@ const (
type blobTxMeta struct {
hash common.Hash // Transaction hash to maintain the lookup table
vhashes []common.Hash // Blob versioned hashes to maintain the lookup table
+ version byte // Blob transaction version to determine proof type
id uint64 // Storage ID in the pool's persistent store
storageSize uint32 // Byte size in the pool's persistent store
@@ -125,10 +134,16 @@ type blobTxMeta struct {
// newBlobTxMeta retrieves the indexed metadata fields from a blob transaction
// and assembles a helper struct to track in memory.
+// Requires the transaction to have a sidecar (or that we introduce a special version tag for no-sidecar).
func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transaction) *blobTxMeta {
+ if tx.BlobTxSidecar() == nil {
+ // This should never happen, as the pool only admits blob transactions with a sidecar
+ panic("missing blob tx sidecar")
+ }
meta := &blobTxMeta{
hash: tx.Hash(),
vhashes: tx.BlobHashes(),
+ version: tx.BlobTxSidecar().Version,
id: id,
storageSize: storageSize,
size: size,
@@ -322,12 +337,13 @@ type BlobPool struct {
stored uint64 // Useful data size of all transactions on disk
limbo *limbo // Persistent data store for the non-finalized blobs
- signer types.Signer // Transaction signer to use for sender recovery
- chain BlockChain // Chain object to access the state through
+ signer types.Signer // Transaction signer to use for sender recovery
+ chain BlockChain // Chain object to access the state through
+ cQueue *conversionQueue // The queue for performing legacy sidecar conversion (TODO: remove after Osaka)
- head *types.Header // Current head of the chain
- state *state.StateDB // Current state at the head of the chain
- gasTip *uint256.Int // Currently accepted minimum gas tip
+ head atomic.Pointer[types.Header] // Current head of the chain
+ state *state.StateDB // Current state at the head of the chain
+ gasTip atomic.Pointer[uint256.Int] // Currently accepted minimum gas tip
lookup *lookup // Lookup table mapping blobs to txs and txs to billy entries
index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce
@@ -352,6 +368,7 @@ func New(config Config, chain BlockChain, hasPendingAuth func(common.Address) bo
hasPendingAuth: hasPendingAuth,
signer: types.LatestSigner(chain.Config()),
chain: chain,
+ cQueue: newConversionQueue(), // Deprecate it after the osaka fork
lookup: newLookup(),
index: make(map[common.Address][]*blobTxMeta),
spent: make(map[common.Address]*uint256.Int),
@@ -397,7 +414,8 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
if err != nil {
return err
}
- p.head, p.state = head, state
+ p.head.Store(head)
+ p.state = state
// Create new slotter for pre-Osaka blob configuration.
slotter := newSlotter(eip4844.LatestMaxBlobsPerBlock(p.chain.Config()))
@@ -437,11 +455,11 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
p.recheck(addr, nil)
}
var (
- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, p.head.Time+1))
+ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), head, head.Time+1))
blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
)
- if p.head.ExcessBlobGas != nil {
- blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(p.chain.Config(), p.head))
+ if head.ExcessBlobGas != nil {
+ blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(p.chain.Config(), head))
}
p.evict = newPriceHeap(basefee, blobfee, p.index)
@@ -471,6 +489,9 @@ func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserver txpool.Reser
// Close closes down the underlying persistent store.
func (p *BlobPool) Close() error {
+ // Terminate the conversion queue
+ p.cQueue.close()
+
var errs []error
if p.limbo != nil { // Close might be invoked due to error in constructor, before p,limbo is set
if err := p.limbo.Close(); err != nil {
@@ -829,7 +850,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
log.Error("Failed to reset blobpool state", "err", err)
return
}
- p.head = newHead
+ p.head.Store(newHead)
p.state = statedb
// Run the reorg between the old and new head and figure out which accounts
@@ -852,7 +873,7 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
}
}
// Flush out any blobs from limbo that are older than the latest finality
- if p.chain.Config().IsCancun(p.head.Number, p.head.Time) {
+ if p.chain.Config().IsCancun(newHead.Number, newHead.Time) {
p.limbo.finalize(p.chain.CurrentFinalBlock())
}
// Reset the price heap for the new set of basefee/blobfee pairs
@@ -868,6 +889,172 @@ func (p *BlobPool) Reset(oldHead, newHead *types.Header) {
basefeeGauge.Update(int64(basefee.Uint64()))
blobfeeGauge.Update(int64(blobfee.Uint64()))
p.updateStorageMetrics()
+
+ // Perform the conversion logic at the fork boundary
+ if !p.chain.Config().IsOsaka(oldHead.Number, oldHead.Time) && p.chain.Config().IsOsaka(newHead.Number, newHead.Time) {
+ // Deep copy all indexed transaction metadata.
+ var (
+ ids = make(map[common.Address]map[uint64]uint64)
+ txs = make(map[common.Address]map[uint64]common.Hash)
+ )
+ for sender, list := range p.index {
+ ids[sender] = make(map[uint64]uint64)
+ txs[sender] = make(map[uint64]common.Hash)
+ for _, m := range list {
+ ids[sender][m.nonce] = m.id
+ txs[sender][m.nonce] = m.hash
+ }
+ }
+ // Initiate the background conversion thread.
+ p.cQueue.launchBillyConversion(func() {
+ p.convertLegacySidecars(ids, txs)
+ })
+ }
+}
+
+// compareAndSwap checks if the specified transaction is still tracked in the pool
+// and replace the metadata accordingly. It should only be used in the fork boundary
+// bulk conversion. If it fails for some reason, the subsequent txs won't be dropped
+// for simplicity which we assume it's very likely to happen.
+//
+// The returned flag indicates whether the replacement succeeded.
+func (p *BlobPool) compareAndSwap(address common.Address, hash common.Hash, blob []byte, oldID uint64, oldStorageSize uint32) bool {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ newId, err := p.store.Put(blob)
+ if err != nil {
+ log.Error("Failed to store transaction", "hash", hash, "err", err)
+ return false
+ }
+ newSize := uint64(len(blob))
+ newStorageSize := p.store.Size(newId)
+
+ // Terminate the procedure if the transaction was already evicted. The
+ // newly added blob should be removed before return.
+ if !p.lookup.update(hash, newId, newSize) {
+ if derr := p.store.Delete(newId); derr != nil {
+ log.Error("Failed to delete the dangling blob tx", "err", derr)
+ } else {
+ log.Warn("Deleted the dangling blob tx", "id", newId)
+ }
+ return false
+ }
+ // Update the metadata of blob transaction
+ for _, meta := range p.index[address] {
+ if meta.hash == hash {
+ meta.id = newId
+ meta.version = types.BlobSidecarVersion1
+ meta.storageSize = newStorageSize
+ meta.size = newSize
+
+ p.stored += uint64(newStorageSize)
+ p.stored -= uint64(oldStorageSize)
+ break
+ }
+ }
+ if err := p.store.Delete(oldID); err != nil {
+ log.Error("Failed to delete the legacy transaction", "hash", hash, "id", oldID, "err", err)
+ }
+ return true
+}
+
+// convertLegacySidecar fetches transaction data from the store, performs an
+// on-the-fly conversion. This function is intended for use only during the
+// Osaka fork transition period.
+//
+// The returned flag indicates whether the replacement succeeds or not.
+func (p *BlobPool) convertLegacySidecar(sender common.Address, hash common.Hash, id uint64) bool {
+ start := time.Now()
+
+ // Retrieves the legacy blob transaction from the underlying store with
+ // read lock held, preventing any potential data race around the slot
+ // specified by the id.
+ p.lock.RLock()
+ data, err := p.store.Get(id)
+ if err != nil {
+ p.lock.RUnlock()
+ // The transaction may have been evicted simultaneously, safe to skip conversion.
+ log.Debug("Blob transaction is missing", "hash", hash, "id", id, "err", err)
+ return false
+ }
+ oldStorageSize := p.store.Size(id)
+ p.lock.RUnlock()
+
+ // Decode the transaction, the failure is not expected and report the error
+ // loudly if possible. If the blob transaction in this slot is corrupted,
+ // leave it in the store, it will be dropped during the next pool
+ // initialization.
+ var tx types.Transaction
+ if err = rlp.DecodeBytes(data, &tx); err != nil {
+ log.Error("Blob transaction is corrupted", "hash", hash, "id", id, "err", err)
+ return false
+ }
+
+ // Skip conversion if the transaction does not match the expected hash, or if it was
+ // already converted. This can occur if the original transaction was evicted from the
+ // pool and the slot was reused by a new one.
+ if tx.Hash() != hash {
+ log.Warn("Blob transaction was replaced", "hash", hash, "id", id, "stored", tx.Hash())
+ return false
+ }
+ sc := tx.BlobTxSidecar()
+ if sc.Version >= types.BlobSidecarVersion1 {
+ log.Debug("Skipping conversion of blob tx", "hash", hash, "id", id)
+ return false
+ }
+
+ // Perform the sidecar conversion, the failure is not expected and report the error
+ // loudly if possible.
+ if err := tx.BlobTxSidecar().ToV1(); err != nil {
+ log.Error("Failed to convert blob transaction", "hash", hash, "err", err)
+ return false
+ }
+
+ // Encode the converted transaction, the failure is not expected and report
+ // the error loudly if possible.
+ blob, err := rlp.EncodeToBytes(&tx)
+ if err != nil {
+ log.Error("Failed to encode blob transaction", "hash", tx.Hash(), "err", err)
+ return false
+ }
+
+ // Replace the legacy blob transaction with the converted format.
+ if !p.compareAndSwap(sender, hash, blob, id, oldStorageSize) {
+ log.Error("Failed to replace the legacy transaction", "hash", hash)
+ return false
+ }
+ log.Debug("Converted legacy blob transaction", "hash", hash, "elapsed", common.PrettyDuration(time.Since(start)))
+ return true
+}
+
+// convertLegacySidecars converts all given transactions to sidecar version 1.
+//
+// If any of them fails to be converted, the subsequent transactions will still
+// be processed, as we assume the failure is very unlikely to happen. If happens,
+// these transactions will be stuck in the pool until eviction.
+func (p *BlobPool) convertLegacySidecars(ids map[common.Address]map[uint64]uint64, txs map[common.Address]map[uint64]common.Hash) {
+ var (
+ start = time.Now()
+ success int
+ failure int
+ )
+ for addr, list := range txs {
+ // Transactions evicted from the pool must be contiguous, if in any case,
+ // the transactions are gapped with each other, they will be discarded.
+ nonces := slices.Collect(maps.Keys(list))
+ slices.Sort(nonces)
+
+ // Convert the txs with nonce order
+ for _, nonce := range nonces {
+ if p.convertLegacySidecar(addr, list[nonce], ids[addr][nonce]) {
+ success++
+ } else {
+ failure++
+ }
+ }
+ }
+ log.Info("Completed blob transaction conversion", "discarded", failure, "injected", success, "elapsed", common.PrettyDuration(time.Since(start)))
}
// reorg assembles all the transactors and missing transactions between an old
@@ -1015,6 +1202,21 @@ func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error {
// TODO: seems like an easy optimization here would be getting the serialized tx
// from limbo instead of re-serializing it here.
+ // Converts reorged-out legacy blob transactions to the new format to prevent
+ // them from becoming stuck in the pool until eviction.
+ //
+ // Performance note: Conversion takes ~140ms (Mac M1 Pro). Since a maximum of
+ // 9 legacy blob transactions are allowed in a block pre-Osaka, an adversary
+ // could theoretically halt a Geth node for ~1.2s by reorging per block. However,
+ // this attack is financially inefficient to execute.
+ head := p.head.Load()
+ if p.chain.Config().IsOsaka(head.Number, head.Time) && tx.BlobTxSidecar().Version == types.BlobSidecarVersion0 {
+ if err := tx.BlobTxSidecar().ToV1(); err != nil {
+ log.Error("Failed to convert the legacy sidecar", "err", err)
+ return err
+ }
+ log.Info("Legacy blob transaction is reorged", "hash", tx.Hash())
+ }
// Serialize the transaction back into the primary datastore.
blob, err := rlp.EncodeToBytes(tx)
if err != nil {
@@ -1053,14 +1255,15 @@ func (p *BlobPool) SetGasTip(tip *big.Int) {
defer p.lock.Unlock()
// Store the new minimum gas tip
- old := p.gasTip
- p.gasTip = uint256.MustFromBig(tip)
+ old := p.gasTip.Load()
+ newTip := uint256.MustFromBig(tip)
+ p.gasTip.Store(newTip)
// If the min miner fee increased, remove transactions below the new threshold
- if old == nil || p.gasTip.Cmp(old) > 0 {
+ if old == nil || newTip.Cmp(old) > 0 {
for addr, txs := range p.index {
for i, tx := range txs {
- if tx.execTipCap.Cmp(p.gasTip) < 0 {
+ if tx.execTipCap.Cmp(newTip) < 0 {
// Drop the offending transaction
var (
ids = []uint64{tx.id}
@@ -1120,10 +1323,10 @@ func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error {
Config: p.chain.Config(),
Accept: 1 << types.BlobTxType,
MaxSize: txMaxSize,
- MinTip: p.gasTip.ToBig(),
+ MinTip: p.gasTip.Load().ToBig(),
MaxBlobCount: maxBlobsPerTx,
}
- return txpool.ValidateTransaction(tx, p.head, p.signer, opts)
+ return txpool.ValidateTransaction(tx, p.head.Load(), p.signer, opts)
}
// checkDelegationLimit determines if the tx sender is delegated or has a
@@ -1161,10 +1364,10 @@ func (p *BlobPool) checkDelegationLimit(tx *types.Transaction) error {
// validateTx checks whether a transaction is valid according to the consensus
// rules and adheres to some heuristic limits of the local node (price and size).
+//
+// This function assumes the static validation has been performed already and
+// only runs the stateful checks with lock protection.
func (p *BlobPool) validateTx(tx *types.Transaction) error {
- if err := p.ValidateTxBasics(tx); err != nil {
- return err
- }
// Ensure the transaction adheres to the stateful pool filters (nonce, balance)
stateOpts := &txpool.ValidationOptionsWithState{
State: p.state,
@@ -1319,9 +1522,20 @@ func (p *BlobPool) GetMetadata(hash common.Hash) *txpool.TxMetadata {
}
// GetBlobs returns a number of blobs and proofs for the given versioned hashes.
+// Blobpool must place responses in the order given in the request, using null
+// for any missing blobs.
+//
+// For instance, if the request is [A_versioned_hash, B_versioned_hash,
+// C_versioned_hash] and blobpool has data for blobs A and C, but doesn't have
+// data for B, the response MUST be [A, null, C].
+//
// This is a utility method for the engine API, enabling consensus clients to
// retrieve blobs from the pools directly instead of the network.
-func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blob, []kzg4844.Commitment, [][]kzg4844.Proof, error) {
+//
+// The version argument specifies the type of proofs to return, either the
+// blob proofs (version 0) or the cell proofs (version 1). Proofs conversion is
+// CPU intensive, so only done if explicitly requested with the convert flag.
+func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte, convert bool) ([]*kzg4844.Blob, []kzg4844.Commitment, [][]kzg4844.Proof, error) {
var (
blobs = make([]*kzg4844.Blob, len(vhashes))
commitments = make([]kzg4844.Commitment, len(vhashes))
@@ -1333,31 +1547,36 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blo
for i, h := range vhashes {
indices[h] = append(indices[h], i)
}
+
for _, vhash := range vhashes {
- // Skip duplicate vhash that was already resolved in a previous iteration
if _, ok := filled[vhash]; ok {
+ // Skip vhash that was already resolved in a previous iteration
continue
}
- // Retrieve the corresponding blob tx with the vhash
+
+ // Retrieve the corresponding blob tx with the vhash.
p.lock.RLock()
txID, exists := p.lookup.storeidOfBlob(vhash)
p.lock.RUnlock()
if !exists {
- return nil, nil, nil, fmt.Errorf("blob with vhash %x is not found", vhash)
+ continue
}
data, err := p.store.Get(txID)
if err != nil {
- return nil, nil, nil, err
+ log.Error("Tracked blob transaction missing from store", "id", txID, "err", err)
+ continue
}
// Decode the blob transaction
tx := new(types.Transaction)
if err := rlp.DecodeBytes(data, tx); err != nil {
- return nil, nil, nil, err
+ log.Error("Blobs corrupted for traced transaction", "id", txID, "err", err)
+ continue
}
sidecar := tx.BlobTxSidecar()
if sidecar == nil {
- return nil, nil, nil, fmt.Errorf("blob tx without sidecar %x", tx.Hash())
+ log.Error("Blob tx without sidecar", "hash", tx.Hash(), "id", txID)
+ continue
}
// Traverse the blobs in the transaction
for i, hash := range tx.BlobHashes() {
@@ -1365,6 +1584,14 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blo
if !ok {
continue // non-interesting blob
}
+ // Mark hash as seen.
+ filled[hash] = struct{}{}
+ if sidecar.Version != version && !convert {
+ // Skip blobs with incompatible version. Note we still track the blob hash
+ // in `filled` here, ensuring that we do not resolve this tx another time.
+ continue
+ }
+ // Get or convert the proof.
var pf []kzg4844.Proof
switch version {
case types.BlobSidecarVersion0:
@@ -1397,7 +1624,6 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blo
commitments[index] = sidecar.Commitments[i]
proofs[index] = pf
}
- filled[hash] = struct{}{}
}
}
return blobs, commitments, proofs, nil
@@ -1418,48 +1644,59 @@ func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
return available
}
-// convertSidecar converts the legacy sidecar in the submitted transactions
-// if Osaka fork has been activated.
-func (p *BlobPool) convertSidecar(txs []*types.Transaction) ([]*types.Transaction, []error) {
- head := p.chain.CurrentBlock()
- if !p.chain.Config().IsOsaka(head.Number, head.Time) {
- return txs, make([]error, len(txs))
+// preCheck performs the static validation upon the provided tx and converts
+// the legacy sidecars if Osaka fork has been activated with a short time window.
+//
+// This function is pure static and lock free.
+func (p *BlobPool) preCheck(tx *types.Transaction) error {
+ var (
+ head = p.head.Load()
+ isOsaka = p.chain.Config().IsOsaka(head.Number, head.Time)
+ deadline time.Time
+ )
+ if isOsaka {
+ deadline = time.Unix(int64(*p.chain.Config().OsakaTime), 0).Add(conversionTimeWindow)
}
- var errs []error
- for _, tx := range txs {
- sidecar := tx.BlobTxSidecar()
- if sidecar == nil {
- errs = append(errs, errors.New("missing sidecar in blob transaction"))
- continue
- }
- if sidecar.Version == types.BlobSidecarVersion0 {
- if err := sidecar.ToV1(); err != nil {
- errs = append(errs, err)
- continue
- }
+ // Validate the transaction statically at first to avoid unnecessary
+ // conversion. This step doesn't require lock protection.
+ if err := p.ValidateTxBasics(tx); err != nil {
+ return err
+ }
+ // Before the Osaka fork, reject the blob txs with cell proofs
+ if !isOsaka {
+ if tx.BlobTxSidecar().Version == types.BlobSidecarVersion0 {
+ return nil
+ } else {
+ return errors.New("cell proof is not supported yet")
}
- errs = append(errs, nil)
}
- return txs, errs
+ // After the Osaka fork, reject the legacy blob txs if the conversion
+ // time window is passed.
+ if tx.BlobTxSidecar().Version == types.BlobSidecarVersion1 {
+ return nil
+ }
+ if head.Time > uint64(deadline.Unix()) {
+ return errors.New("legacy blob tx is not supported")
+ }
+ // Convert the legacy sidecar after Osaka fork. This could be a long
+ // procedure which takes a few seconds, even minutes if there is a long
+ // queue. Fortunately it will only block the routine of the source peer
+ // announcing the tx, without affecting other parts.
+ return p.cQueue.convert(tx)
}
// Add inserts a set of blob transactions into the pool if they pass validation (both
// consensus validity and pool restrictions).
-//
-// Note, if sync is set the method will block until all internal maintenance
-// related to the add is finished. Only use this during tests for determinism.
func (p *BlobPool) Add(txs []*types.Transaction, sync bool) []error {
var (
- errs []error
- adds = make([]*types.Transaction, 0, len(txs))
+ errs []error = make([]error, len(txs))
+ adds = make([]*types.Transaction, 0, len(txs))
)
- txs, errs = p.convertSidecar(txs)
for i, tx := range txs {
- if errs[i] != nil {
+ if errs[i] = p.preCheck(tx); errs[i] != nil {
continue
}
- errs[i] = p.add(tx)
- if errs[i] == nil {
+ if errs[i] = p.add(tx); errs[i] == nil {
adds = append(adds, tx.WithoutBlobTxSidecar())
}
}
@@ -1699,7 +1936,7 @@ func (p *BlobPool) drop() {
func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
// If only plain transactions are requested, this pool is unsuitable as it
// contains none, don't even bother.
- if filter.OnlyPlainTxs {
+ if !filter.BlobTxs {
return nil
}
// Track the amount of time waiting to retrieve the list of pending blob txs
@@ -1720,6 +1957,11 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx
for addr, txs := range p.index {
lazies := make([]*txpool.LazyTransaction, 0, len(txs))
for _, tx := range txs {
+ // Skip v0 or v1 blob transactions depending on the filter
+ if tx.version != filter.BlobVersion {
+ break // skip the rest because of nonce ordering
+ }
+
// If transaction filtering was requested, discard badly priced ones
if filter.MinTip != nil && filter.BaseFee != nil {
if tx.execFeeCap.Lt(filter.BaseFee) {
@@ -1947,7 +2189,8 @@ func (p *BlobPool) Clear() {
p.spent = make(map[common.Address]*uint256.Int)
var (
- basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head, p.head.Time))
+ head = p.head.Load()
+ basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), head, head.Time))
blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice)
)
p.evict = newPriceHeap(basefee, blobfee, p.index)
diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go
index 551c854d9b..652aa64c72 100644
--- a/core/txpool/blobpool/blobpool_test.go
+++ b/core/txpool/blobpool/blobpool_test.go
@@ -24,6 +24,7 @@ import (
"fmt"
"math"
"math/big"
+ "math/rand"
"os"
"path/filepath"
"reflect"
@@ -41,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/billy"
@@ -86,6 +88,12 @@ type testBlockChain struct {
statedb *state.StateDB
blocks map[uint64]*types.Block
+
+ blockTime *uint64
+}
+
+func (bc *testBlockChain) setHeadTime(time uint64) {
+ bc.blockTime = &time
}
func (bc *testBlockChain) Config() *params.ChainConfig {
@@ -103,6 +111,10 @@ func (bc *testBlockChain) CurrentBlock() *types.Header {
blockTime = *bc.config.CancunTime + 1
gasLimit = uint64(30_000_000)
)
+ if bc.blockTime != nil {
+ blockTime = *bc.blockTime
+ }
+
lo := new(big.Int)
hi := new(big.Int).Mul(big.NewInt(5714), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))
@@ -262,8 +274,8 @@ func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap
return makeUnsignedTxWithTestBlob(nonce, gasTipCap, gasFeeCap, blobFeeCap, rnd.Intn(len(testBlobs)))
}
-// makeUnsignedTx is a utility method to construct a random blob transaction
-// without signing it.
+// makeUnsignedTxWithTestBlob is a utility method to construct a random blob transaction
+// with a specific test blob without signing it.
func makeUnsignedTxWithTestBlob(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, blobIdx int) *types.BlobTx {
return &types.BlobTx{
ChainID: uint256.MustFromBig(params.MainnetChainConfig.ChainID),
@@ -421,11 +433,11 @@ func verifyBlobRetrievals(t *testing.T, pool *BlobPool) {
hashes = append(hashes, tx.vhashes...)
}
}
- blobs1, _, proofs1, err := pool.GetBlobs(hashes, types.BlobSidecarVersion0)
+ blobs1, _, proofs1, err := pool.GetBlobs(hashes, types.BlobSidecarVersion0, false)
if err != nil {
t.Fatal(err)
}
- blobs2, _, proofs2, err := pool.GetBlobs(hashes, types.BlobSidecarVersion1)
+ blobs2, _, proofs2, err := pool.GetBlobs(hashes, types.BlobSidecarVersion1, false)
if err != nil {
t.Fatal(err)
}
@@ -439,22 +451,18 @@ func verifyBlobRetrievals(t *testing.T, pool *BlobPool) {
return
}
for i, hash := range hashes {
- // If an item is missing, but shouldn't, error
- if blobs1[i] == nil || proofs1[i] == nil {
- t.Errorf("tracked blob retrieval failed: item %d, hash %x", i, hash)
- continue
- }
- if blobs2[i] == nil || proofs2[i] == nil {
+ // If an item is missing from both, but shouldn't, error
+ if (blobs1[i] == nil || proofs1[i] == nil) && (blobs2[i] == nil || proofs2[i] == nil) {
t.Errorf("tracked blob retrieval failed: item %d, hash %x", i, hash)
continue
}
// Item retrieved, make sure it matches the expectation
index := testBlobIndices[hash]
- if *blobs1[i] != *testBlobs[index] || proofs1[i][0] != testBlobProofs[index] {
+ if blobs1[i] != nil && (*blobs1[i] != *testBlobs[index] || proofs1[i][0] != testBlobProofs[index]) {
t.Errorf("retrieved blob or proof mismatch: item %d, hash %x", i, hash)
continue
}
- if *blobs2[i] != *testBlobs[index] || !slices.Equal(proofs2[i], testBlobCellProofs[index]) {
+ if blobs2[i] != nil && (*blobs2[i] != *testBlobs[index] || !slices.Equal(proofs2[i], testBlobCellProofs[index])) {
t.Errorf("retrieved blob or proof mismatch: item %d, hash %x", i, hash)
continue
}
@@ -1750,8 +1758,8 @@ func TestAdd(t *testing.T) {
// Add each transaction one by one, verifying the pool internals in between
for j, add := range tt.adds {
signed, _ := types.SignNewTx(keys[add.from], types.LatestSigner(params.MainnetChainConfig), add.tx)
- if err := pool.add(signed); !errors.Is(err, add.err) {
- t.Errorf("test %d, tx %d: adding transaction error mismatch: have %v, want %v", i, j, err, add.err)
+ if errs := pool.Add([]*types.Transaction{signed}, true); !errors.Is(errs[0], add.err) {
+ t.Errorf("test %d, tx %d: adding transaction error mismatch: have %v, want %v", i, j, errs[0], add.err)
}
if add.err == nil {
size, exist := pool.lookup.sizeOfTx(signed.Hash())
@@ -1798,9 +1806,14 @@ func TestAdd(t *testing.T) {
}
}
-// Tests that adding the transactions with legacy sidecar and expect them to
-// be converted to new format correctly.
+// Tests that transactions with legacy sidecars are accepted within the
+// conversion window but rejected after it has passed.
func TestAddLegacyBlobTx(t *testing.T) {
+ testAddLegacyBlobTx(t, true) // conversion window has not yet passed
+ testAddLegacyBlobTx(t, false) // conversion window passed
+}
+
+func testAddLegacyBlobTx(t *testing.T, accept bool) {
var (
key1, _ = crypto.GenerateKey()
key2, _ = crypto.GenerateKey()
@@ -1820,6 +1833,15 @@ func TestAddLegacyBlobTx(t *testing.T) {
blobfee: uint256.NewInt(105),
statedb: statedb,
}
+ var timeDiff uint64
+ if accept {
+ timeDiff = uint64(conversionTimeWindow.Seconds()) - 1
+ } else {
+ timeDiff = uint64(conversionTimeWindow.Seconds()) + 1
+ }
+ time := *params.MergedTestChainConfig.OsakaTime + timeDiff
+ chain.setHeadTime(time)
+
pool := New(Config{Datadir: t.TempDir()}, chain, nil)
if err := pool.Init(1, chain.CurrentBlock(), newReserver()); err != nil {
t.Fatalf("failed to create blob pool: %v", err)
@@ -1829,12 +1851,15 @@ func TestAddLegacyBlobTx(t *testing.T) {
var (
tx1 = makeMultiBlobTx(0, 1, 1000, 100, 6, 0, key1, types.BlobSidecarVersion0)
tx2 = makeMultiBlobTx(0, 1, 800, 70, 6, 6, key2, types.BlobSidecarVersion0)
- tx3 = makeMultiBlobTx(1, 1, 800, 70, 6, 12, key2, types.BlobSidecarVersion1)
+ txs = []*types.Transaction{tx1, tx2}
)
- errs := pool.Add([]*types.Transaction{tx1, tx2, tx3}, true)
+ errs := pool.Add(txs, true)
for _, err := range errs {
- if err != nil {
- t.Fatalf("failed to add tx: %v", err)
+ if accept && err != nil {
+ t.Fatalf("expected tx add to succeed, %v", err)
+ }
+ if !accept && err == nil {
+ t.Fatal("expected tx add to fail")
}
}
verifyPoolInternals(t, pool)
@@ -1923,10 +1948,11 @@ func TestGetBlobs(t *testing.T) {
}
cases := []struct {
- start int
- limit int
- version byte
- expErr bool
+ start int
+ limit int
+ fillRandom bool // Whether to randomly fill some of the requested blobs with unknowns
+ version byte // Blob sidecar version to request
+ convert bool // Whether to convert version on retrieval
}{
{
start: 0, limit: 6,
@@ -1936,6 +1962,14 @@ func TestGetBlobs(t *testing.T) {
start: 0, limit: 6,
version: types.BlobSidecarVersion1,
},
+ {
+ start: 0, limit: 6, fillRandom: true,
+ version: types.BlobSidecarVersion0,
+ },
+ {
+ start: 0, limit: 6, fillRandom: true,
+ version: types.BlobSidecarVersion1,
+ },
{
start: 3, limit: 9,
version: types.BlobSidecarVersion0,
@@ -1944,6 +1978,14 @@ func TestGetBlobs(t *testing.T) {
start: 3, limit: 9,
version: types.BlobSidecarVersion1,
},
+ {
+ start: 3, limit: 9, fillRandom: true,
+ version: types.BlobSidecarVersion0,
+ },
+ {
+ start: 3, limit: 9, fillRandom: true,
+ version: types.BlobSidecarVersion1,
+ },
{
start: 3, limit: 15,
version: types.BlobSidecarVersion0,
@@ -1952,6 +1994,14 @@ func TestGetBlobs(t *testing.T) {
start: 3, limit: 15,
version: types.BlobSidecarVersion1,
},
+ {
+ start: 3, limit: 15, fillRandom: true,
+ version: types.BlobSidecarVersion0,
+ },
+ {
+ start: 3, limit: 15, fillRandom: true,
+ version: types.BlobSidecarVersion1,
+ },
{
start: 0, limit: 18,
version: types.BlobSidecarVersion0,
@@ -1961,57 +2011,268 @@ func TestGetBlobs(t *testing.T) {
version: types.BlobSidecarVersion1,
},
{
- start: 18, limit: 20,
+ start: 0, limit: 18, fillRandom: true,
version: types.BlobSidecarVersion0,
- expErr: true,
+ },
+ {
+ start: 0, limit: 18, fillRandom: true,
+ version: types.BlobSidecarVersion1,
+ },
+ {
+ start: 0, limit: 18, fillRandom: true,
+ version: types.BlobSidecarVersion1,
+ convert: true, // Convert some version 0 blobs to version 1 while retrieving
},
}
for i, c := range cases {
- var vhashes []common.Hash
+ var (
+ vhashes []common.Hash
+ filled = make(map[int]struct{})
+ )
+ if c.fillRandom {
+ filled[len(vhashes)] = struct{}{}
+ vhashes = append(vhashes, testrand.Hash())
+ }
for j := c.start; j < c.limit; j++ {
vhashes = append(vhashes, testBlobVHashes[j])
+ if c.fillRandom && rand.Intn(2) == 0 {
+ filled[len(vhashes)] = struct{}{}
+ vhashes = append(vhashes, testrand.Hash())
+ }
+ }
+ if c.fillRandom {
+ filled[len(vhashes)] = struct{}{}
+ vhashes = append(vhashes, testrand.Hash())
+ }
+ blobs, _, proofs, err := pool.GetBlobs(vhashes, c.version, c.convert)
+ if err != nil {
+ t.Errorf("Unexpected error for case %d, %v", i, err)
}
- blobs, _, proofs, err := pool.GetBlobs(vhashes, c.version)
- if c.expErr {
- if err == nil {
- t.Errorf("Unexpected return, want error for case %d", i)
- }
- } else {
- if err != nil {
- t.Errorf("Unexpected error for case %d, %v", i, err)
- }
- // Cross validate what we received vs what we wanted
- length := c.limit - c.start
- if len(blobs) != length || len(proofs) != length {
- t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want %d", len(blobs), len(proofs), length)
+ // Cross validate what we received vs what we wanted
+ length := c.limit - c.start
+ wantLen := length + len(filled)
+ if len(blobs) != wantLen || len(proofs) != wantLen {
+ t.Errorf("retrieved blobs/proofs size mismatch: have %d/%d, want %d", len(blobs), len(proofs), wantLen)
+ continue
+ }
+
+ var unknown int
+ for j := 0; j < len(blobs); j++ {
+ testBlobIndex := c.start + j - unknown
+ if _, exist := filled[j]; exist {
+ if blobs[j] != nil || proofs[j] != nil {
+ t.Errorf("Unexpected blob and proof, item %d", j)
+ }
+ unknown++
continue
}
- for j := 0; j < len(blobs); j++ {
- // If an item is missing, but shouldn't, error
- if blobs[j] == nil || proofs[j] == nil {
+ // If an item is missing, but shouldn't, error
+ if blobs[j] == nil || proofs[j] == nil {
+ // This is only an error if there was no version mismatch
+ if c.convert ||
+ (c.version == types.BlobSidecarVersion1 && 6 <= testBlobIndex && testBlobIndex < 12) ||
+ (c.version == types.BlobSidecarVersion0 && (testBlobIndex < 6 || 12 <= testBlobIndex)) {
t.Errorf("tracked blob retrieval failed: item %d, hash %x", j, vhashes[j])
- continue
}
- // Item retrieved, make sure the blob matches the expectation
- if *blobs[j] != *testBlobs[c.start+j] {
- t.Errorf("retrieved blob mismatch: item %d, hash %x", j, vhashes[j])
- continue
+ continue
+ }
+ // Item retrieved, make sure the blob matches the expectation
+ if *blobs[j] != *testBlobs[testBlobIndex] {
+ t.Errorf("retrieved blob mismatch: item %d, hash %x", j, vhashes[j])
+ continue
+ }
+ // Item retrieved, make sure the proof matches the expectation
+ if c.version == types.BlobSidecarVersion0 {
+ if proofs[j][0] != testBlobProofs[testBlobIndex] {
+ t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
}
- // Item retrieved, make sure the proof matches the expectation
- if c.version == types.BlobSidecarVersion0 {
- if proofs[j][0] != testBlobProofs[c.start+j] {
- t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
- }
- } else {
- want, _ := kzg4844.ComputeCellProofs(blobs[j])
- if !reflect.DeepEqual(want, proofs[j]) {
- t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
- }
+ } else {
+ want, _ := kzg4844.ComputeCellProofs(blobs[j])
+ if !reflect.DeepEqual(want, proofs[j]) {
+ t.Errorf("retrieved proof mismatch: item %d, hash %x", j, vhashes[j])
}
}
}
}
+ pool.Close()
+}
+
+// TestSidecarConversion will verify that after the Osaka fork, all legacy
+// sidecars in the pool are successfully convert to v1 sidecars.
+func TestSidecarConversion(t *testing.T) {
+ // log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true)))
+
+ // Create a temporary folder for the persistent backend
+ storage := t.TempDir()
+ os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700)
+
+ var (
+ preOsakaTxs = make(types.Transactions, 10)
+ postOsakaTxs = make(types.Transactions, 3)
+ keys = make([]*ecdsa.PrivateKey, len(preOsakaTxs)+len(postOsakaTxs))
+ addrs = make([]common.Address, len(preOsakaTxs)+len(postOsakaTxs))
+ statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
+ )
+ for i := range keys {
+ keys[i], _ = crypto.GenerateKey()
+ addrs[i] = crypto.PubkeyToAddress(keys[i].PublicKey)
+ statedb.AddBalance(addrs[i], uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
+ }
+ for i := range preOsakaTxs {
+ preOsakaTxs[i] = makeMultiBlobTx(0, 1, 1000, 100, 2, 0, keys[i], types.BlobSidecarVersion0)
+ }
+ for i := range postOsakaTxs {
+ if i == 0 {
+ // First has a v0 sidecar.
+ postOsakaTxs[i] = makeMultiBlobTx(0, 1, 1000, 100, 1, 0, keys[len(preOsakaTxs)+i], types.BlobSidecarVersion0)
+ }
+ postOsakaTxs[i] = makeMultiBlobTx(0, 1, 1000, 100, 1, 0, keys[len(preOsakaTxs)+i], types.BlobSidecarVersion1)
+ }
+ statedb.Commit(0, true, false)
+
+ // Test plan:
+ // 1) Create a bunch v0 sidecar txs and add to pool before Osaka.
+ // 2) Pass in new Osaka header to activate the conversion thread.
+ // 3) Continue adding both v0 and v1 transactions to the pool.
+ // 4) Verify that as additional blocks come in, transactions involved in the
+ // migration are correctly discarded.
+
+ config := ¶ms.ChainConfig{
+ ChainID: big.NewInt(1),
+ LondonBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ CancunTime: newUint64(0),
+ PragueTime: newUint64(0),
+ OsakaTime: newUint64(1),
+ BlobScheduleConfig: params.DefaultBlobSchedule,
+ }
+ chain := &testBlockChain{
+ config: config,
+ basefee: uint256.NewInt(1050),
+ blobfee: uint256.NewInt(105),
+ statedb: statedb,
+ blocks: make(map[uint64]*types.Block),
+ }
+
+ // Create 3 blocks:
+ // - the current block, before Osaka
+ // - the first block after Osaka
+ // - another post-Osaka block with several transactions in it
+ header0 := chain.CurrentBlock()
+ header0.Time = 0
+ chain.blocks[0] = types.NewBlockWithHeader(header0)
+
+ header1 := chain.CurrentBlock()
+ header1.Number = big.NewInt(1)
+ header1.Time = 1
+ chain.blocks[1] = types.NewBlockWithHeader(header1)
+
+ header2 := chain.CurrentBlock()
+ header2.Time = 2
+ header2.Number = big.NewInt(2)
+
+ // Make a copy of one of the pre-Osaka transactions and convert it to v1 here
+ // so that we can add it to the pool later and ensure a duplicate is not added
+ // by the conversion queue.
+ tx := preOsakaTxs[len(preOsakaTxs)-1]
+ sc := *tx.BlobTxSidecar() // copy sidecar
+ sc.ToV1()
+ tx.WithBlobTxSidecar(&sc)
+
+ block2 := types.NewBlockWithHeader(header2).WithBody(types.Body{Transactions: append(postOsakaTxs, tx)})
+ chain.blocks[2] = block2
+
+ pool := New(Config{Datadir: storage}, chain, nil)
+ if err := pool.Init(1, header0, newReserver()); err != nil {
+ t.Fatalf("failed to create blob pool: %v", err)
+ }
+
+ errs := pool.Add(preOsakaTxs, true)
+ for i, err := range errs {
+ if err != nil {
+ t.Errorf("failed to insert blob tx from %s: %s", addrs[i], errs[i])
+ }
+ }
+
+ // Kick off migration.
+ pool.Reset(header0, header1)
+
+ // Add the v0 sidecar tx, but don't block so we can keep doing other stuff
+ // while it converts the sidecar.
+ addDone := make(chan struct{})
+ go func() {
+ pool.Add(types.Transactions{postOsakaTxs[0]}, false)
+ close(addDone)
+ }()
+
+ // Add the post-Osaka v1 sidecar txs.
+ errs = pool.Add(postOsakaTxs[1:], false)
+ for _, err := range errs {
+ if err != nil {
+ t.Fatalf("expected tx add to succeed: %v", err)
+ }
+ }
+
+ // Wait for the first tx's conversion to complete, then check that all
+ // transactions added after Osaka can be accounted for in the pool.
+ <-addDone
+ pending := pool.Pending(txpool.PendingFilter{BlobTxs: true, BlobVersion: types.BlobSidecarVersion1})
+ for _, tx := range postOsakaTxs {
+ from, _ := pool.signer.Sender(tx)
+ if len(pending[from]) != 1 || pending[from][0].Hash != tx.Hash() {
+ t.Fatalf("expected post-Osaka txs to be pending")
+ }
+ }
+
+ // Now update the pool with the next block. This should cause the pool to
+ // clear out the post-Osaka txs since they were included in block 2. Since the
+ // test blockchain doesn't manage nonces, we'll just do that manually before
+ // the reset is called. Don't forget about the pre-Osaka transaction we also
+ // added to block 2!
+ for i := range postOsakaTxs {
+ statedb.SetNonce(addrs[len(preOsakaTxs)+i], 1, tracing.NonceChangeEoACall)
+ }
+ statedb.SetNonce(addrs[len(preOsakaTxs)-1], 1, tracing.NonceChangeEoACall)
+ pool.Reset(header1, block2.Header())
+
+ // Now verify no post-Osaka transactions are tracked by the pool.
+ for i, tx := range postOsakaTxs {
+ if pool.Get(tx.Hash()) != nil {
+ t.Fatalf("expected txs added post-osaka to have been placed in limbo due to inclusion in a block: index %d, hash %s", i, tx.Hash())
+ }
+ }
+
+ // Wait for the pool migration to complete.
+ <-pool.cQueue.anyBillyConversionDone
+
+ // Verify all transactions in the pool were converted and verify the
+ // subsequent cell proofs.
+ count, _ := pool.Stats()
+ if count != len(preOsakaTxs)-1 {
+ t.Errorf("expected pending count to match initial tx count: pending=%d, expected=%d", count, len(preOsakaTxs)-1)
+ }
+ for addr, acc := range pool.index {
+ for _, m := range acc {
+ if m.version != types.BlobSidecarVersion1 {
+ t.Errorf("expected sidecar to have been converted: from %s, hash %s", addr, m.hash)
+ }
+ tx := pool.Get(m.hash)
+ if tx == nil {
+ t.Errorf("failed to get tx by hash: %s", m.hash)
+ }
+ sc := tx.BlobTxSidecar()
+ if err := kzg4844.VerifyCellProofs(sc.Blobs, sc.Commitments, sc.Proofs); err != nil {
+ t.Errorf("failed to verify cell proofs for tx %s after conversion: %s", m.hash, err)
+ }
+ }
+ }
+
+ verifyPoolInternals(t, pool)
+
+ // Launch conversion a second time.
+ // This is just a sanity check to ensure we can handle it.
+ pool.Reset(header0, header1)
pool.Close()
}
@@ -2098,3 +2359,5 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) {
}
}
}
+
+func newUint64(val uint64) *uint64 { return &val }
diff --git a/core/txpool/blobpool/conversion.go b/core/txpool/blobpool/conversion.go
new file mode 100644
index 0000000000..95828d83b2
--- /dev/null
+++ b/core/txpool/blobpool/conversion.go
@@ -0,0 +1,203 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package blobpool
+
+import (
+ "errors"
+ "slices"
+ "sync/atomic"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+)
+
+// maxPendingConversionTasks caps the number of pending conversion tasks. This
+// prevents excessive memory usage; the worst-case scenario (2k transactions
+// with 6 blobs each) would consume approximately 1.5GB of memory.
+const maxPendingConversionTasks = 2048
+
+// txConvert represents a conversion task with an attached legacy blob transaction.
+type txConvert struct {
+ tx *types.Transaction // Legacy blob transaction
+ done chan error // Channel for signaling back if the conversion succeeds
+}
+
+// conversionQueue is a dedicated queue for converting legacy blob transactions
+// received from the network after the Osaka fork. Since conversion is expensive,
+// it is performed in the background by a single thread, ensuring the main Geth
+// process is not overloaded.
+type conversionQueue struct {
+ tasks chan *txConvert
+ startBilly chan func()
+ quit chan struct{}
+ closed chan struct{}
+
+ billyQueue []func()
+ billyTaskDone chan struct{}
+
+ // This channel will be closed when the first billy conversion finishes.
+ // It's added for unit tests to synchronize with the conversion progress.
+ anyBillyConversionDone chan struct{}
+}
+
+// newConversionQueue constructs the conversion queue.
+func newConversionQueue() *conversionQueue {
+ q := &conversionQueue{
+ tasks: make(chan *txConvert),
+ startBilly: make(chan func()),
+ quit: make(chan struct{}),
+ closed: make(chan struct{}),
+ anyBillyConversionDone: make(chan struct{}),
+ }
+ go q.loop()
+ return q
+}
+
+// convert accepts a legacy blob transaction with version-0 blobs and queues it
+// for conversion.
+//
+// This function may block for a long time until the transaction is processed.
+func (q *conversionQueue) convert(tx *types.Transaction) error {
+ done := make(chan error, 1)
+ select {
+ case q.tasks <- &txConvert{tx: tx, done: done}:
+ return <-done
+ case <-q.closed:
+ return errors.New("conversion queue closed")
+ }
+}
+
+// launchBillyConversion starts a conversion task in the background.
+func (q *conversionQueue) launchBillyConversion(fn func()) error {
+ select {
+ case q.startBilly <- fn:
+ return nil
+ case <-q.closed:
+ return errors.New("conversion queue closed")
+ }
+}
+
+// close terminates the conversion queue.
+func (q *conversionQueue) close() {
+ select {
+ case <-q.closed:
+ return
+ default:
+ close(q.quit)
+ <-q.closed
+ }
+}
+
+// run converts a batch of legacy blob txs to the new cell proof format.
+func (q *conversionQueue) run(tasks []*txConvert, done chan struct{}, interrupt *atomic.Int32) {
+ defer close(done)
+
+ for _, t := range tasks {
+ if interrupt != nil && interrupt.Load() != 0 {
+ t.done <- errors.New("conversion is interrupted")
+ continue
+ }
+ sidecar := t.tx.BlobTxSidecar()
+ if sidecar == nil {
+ t.done <- errors.New("tx without sidecar")
+ continue
+ }
+ // Run the conversion, the original sidecar will be mutated in place
+ start := time.Now()
+ err := sidecar.ToV1()
+ t.done <- err
+ log.Trace("Converted legacy blob tx", "hash", t.tx.Hash(), "err", err, "elapsed", common.PrettyDuration(time.Since(start)))
+ }
+}
+
+func (q *conversionQueue) loop() {
+ defer close(q.closed)
+
+ var (
+ done chan struct{} // Non-nil if background routine is active
+ interrupt *atomic.Int32 // Flag to signal conversion interruption
+
+ // The pending tasks for sidecar conversion. We assume the number of legacy
+ // blob transactions requiring conversion will not be excessive. However,
+ // a hard cap is applied as a protective measure.
+ txTasks []*txConvert
+
+ firstBilly = true
+ )
+
+ for {
+ select {
+ case t := <-q.tasks:
+ if len(txTasks) >= maxPendingConversionTasks {
+ t.done <- errors.New("conversion queue is overloaded")
+ continue
+ }
+ txTasks = append(txTasks, t)
+
+ // Launch the background conversion thread if it's idle
+ if done == nil {
+ done, interrupt = make(chan struct{}), new(atomic.Int32)
+
+ tasks := slices.Clone(txTasks)
+ txTasks = txTasks[:0]
+ go q.run(tasks, done, interrupt)
+ }
+
+ case <-done:
+ done, interrupt = nil, nil
+
+ case fn := <-q.startBilly:
+ q.billyQueue = append(q.billyQueue, fn)
+ q.runNextBillyTask()
+
+ case <-q.billyTaskDone:
+ if firstBilly {
+ close(q.anyBillyConversionDone)
+ firstBilly = false
+ }
+ q.runNextBillyTask()
+
+ case <-q.quit:
+ if done != nil {
+ log.Debug("Waiting for blob proof conversion to exit")
+ interrupt.Store(1)
+ <-done
+ }
+ if q.billyTaskDone != nil {
+ log.Debug("Waiting for blobpool billy conversion to exit")
+ <-q.billyTaskDone
+ }
+ return
+ }
+ }
+}
+
+func (q *conversionQueue) runNextBillyTask() {
+ if len(q.billyQueue) == 0 {
+ q.billyTaskDone = nil
+ return
+ }
+
+ fn := q.billyQueue[0]
+ q.billyQueue = append(q.billyQueue[:0], q.billyQueue[1:]...)
+
+ done := make(chan struct{})
+ go func() { defer close(done); fn() }()
+ q.billyTaskDone = done
+}
diff --git a/core/txpool/blobpool/conversion_test.go b/core/txpool/blobpool/conversion_test.go
new file mode 100644
index 0000000000..a9fd26dbaf
--- /dev/null
+++ b/core/txpool/blobpool/conversion_test.go
@@ -0,0 +1,101 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package blobpool
+
+import (
+ "crypto/ecdsa"
+ "crypto/sha256"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
+)
+
+// createV1BlobTx creates a blob transaction with version 1 sidecar for testing.
+func createV1BlobTx(nonce uint64, key *ecdsa.PrivateKey) *types.Transaction {
+ blob := &kzg4844.Blob{byte(nonce)}
+ commitment, _ := kzg4844.BlobToCommitment(blob)
+ cellProofs, _ := kzg4844.ComputeCellProofs(blob)
+
+ blobtx := &types.BlobTx{
+ ChainID: uint256.MustFromBig(params.MainnetChainConfig.ChainID),
+ Nonce: nonce,
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.NewInt(1000),
+ Gas: 21000,
+ BlobFeeCap: uint256.NewInt(100),
+ BlobHashes: []common.Hash{kzg4844.CalcBlobHashV1(sha256.New(), &commitment)},
+ Value: uint256.NewInt(100),
+ Sidecar: types.NewBlobTxSidecar(types.BlobSidecarVersion1, []kzg4844.Blob{*blob}, []kzg4844.Commitment{commitment}, cellProofs),
+ }
+ return types.MustSignNewTx(key, types.LatestSigner(params.MainnetChainConfig), blobtx)
+}
+
+func TestConversionQueueBasic(t *testing.T) {
+ queue := newConversionQueue()
+ defer queue.close()
+
+ key, _ := crypto.GenerateKey()
+ tx := makeTx(0, 1, 1, 1, key)
+ if err := queue.convert(tx); err != nil {
+ t.Fatalf("Expected successful conversion, got error: %v", err)
+ }
+ if tx.BlobTxSidecar().Version != types.BlobSidecarVersion1 {
+ t.Errorf("Expected sidecar version to be %d, got %d", types.BlobSidecarVersion1, tx.BlobTxSidecar().Version)
+ }
+}
+
+func TestConversionQueueV1BlobTx(t *testing.T) {
+ queue := newConversionQueue()
+ defer queue.close()
+
+ key, _ := crypto.GenerateKey()
+ tx := createV1BlobTx(0, key)
+ version := tx.BlobTxSidecar().Version
+
+ err := queue.convert(tx)
+ if err != nil {
+ t.Fatalf("Expected successful conversion, got error: %v", err)
+ }
+ if tx.BlobTxSidecar().Version != version {
+ t.Errorf("Expected sidecar version to remain %d, got %d", version, tx.BlobTxSidecar().Version)
+ }
+}
+
+func TestConversionQueueClosed(t *testing.T) {
+ queue := newConversionQueue()
+
+ // Close the queue first
+ queue.close()
+ key, _ := crypto.GenerateKey()
+ tx := makeTx(0, 1, 1, 1, key)
+
+ err := queue.convert(tx)
+ if err == nil {
+ t.Fatal("Expected error when converting on closed queue, got nil")
+ }
+}
+
+func TestConversionQueueDoubleClose(t *testing.T) {
+ queue := newConversionQueue()
+ queue.close()
+ queue.close() // Should not panic
+}
diff --git a/core/txpool/blobpool/lookup.go b/core/txpool/blobpool/lookup.go
index 7607cd487a..874ca85b8c 100644
--- a/core/txpool/blobpool/lookup.go
+++ b/core/txpool/blobpool/lookup.go
@@ -110,3 +110,13 @@ func (l *lookup) untrack(tx *blobTxMeta) {
}
}
}
+
+// update updates the transaction index. It should only be used in the conversion.
+func (l *lookup) update(hash common.Hash, id uint64, size uint64) bool {
+ meta, exists := l.txIndex[hash]
+ if !exists {
+ return false
+ }
+ meta.id, meta.size = id, size
+ return true
+}
diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go
index 9202479274..18adb0c996 100644
--- a/core/txpool/legacypool/legacypool.go
+++ b/core/txpool/legacypool/legacypool.go
@@ -574,7 +574,7 @@ func (pool *LegacyPool) RollupCostFunc() txpool.RollupCostFunc {
func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
// If only blob transactions are requested, this pool is unsuitable as it
// contains none, don't even bother.
- if filter.OnlyBlobTxs {
+ if filter.BlobTxs {
return nil
}
pool.mu.Lock()
diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go
index 0c42aed5b5..35f8aa919f 100644
--- a/core/txpool/legacypool/legacypool_test.go
+++ b/core/txpool/legacypool/legacypool_test.go
@@ -2377,8 +2377,8 @@ func TestSetCodeTransactions(t *testing.T) {
pending: 1,
run: func(name string) {
aa := common.Address{0xaa, 0xaa}
- statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...))
- statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)})
+ statedb.SetCode(addrA, append(types.DelegationPrefix, aa.Bytes()...), tracing.CodeChangeUnspecified)
+ statedb.SetCode(aa, []byte{byte(vm.ADDRESS), byte(vm.PUSH0), byte(vm.SSTORE)}, tracing.CodeChangeUnspecified)
// Send gapped transaction, it should be rejected.
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), keyA)); !errors.Is(err, ErrOutOfOrderTxFromDelegated) {
@@ -2402,7 +2402,7 @@ func TestSetCodeTransactions(t *testing.T) {
}
// Reset the delegation, avoid leaking state into the other tests
- statedb.SetCode(addrA, nil)
+ statedb.SetCode(addrA, nil, tracing.CodeChangeUnspecified)
},
},
{
@@ -2668,7 +2668,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) {
}
// Simulate the chain moving
blockchain.statedb.SetNonce(addrA, 1, tracing.NonceChangeAuthorization)
- blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address))
+ blockchain.statedb.SetCode(addrA, types.AddressToDelegation(auth.Address), tracing.CodeChangeUnspecified)
<-pool.requestReset(nil, nil)
// Set an authorization for 0x00
auth, _ = types.SignSetCode(keyA, types.SetCodeAuthorization{
@@ -2686,7 +2686,7 @@ func TestSetCodeTransactionsReorg(t *testing.T) {
}
// Simulate the chain moving
blockchain.statedb.SetNonce(addrA, 2, tracing.NonceChangeAuthorization)
- blockchain.statedb.SetCode(addrA, nil)
+ blockchain.statedb.SetCode(addrA, nil, tracing.CodeChangeUnspecified)
<-pool.requestReset(nil, nil)
// Now send two transactions from addrA
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1000), keyA)); err != nil {
diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go
index 89ffafe657..48f20342b6 100644
--- a/core/txpool/legacypool/list.go
+++ b/core/txpool/legacypool/list.go
@@ -367,8 +367,6 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa
if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 {
return false, nil
}
- // Old is being replaced, subtract old cost
- l.subTotalCost([]*types.Transaction{old})
}
// Add new tx cost to totalcost
cost, overflow := txpool.TotalTxCost(tx, l.rollupCostFn())
@@ -376,7 +374,17 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa
return false, nil
}
l.txCosts[tx.Hash()] = cost // OP-Stack addition
- l.totalcost.Add(l.totalcost, cost)
+ total, overflow := new(uint256.Int).AddOverflow(l.totalcost, cost)
+ if overflow {
+ return false, nil
+ }
+ l.totalcost = total
+
+ // Old is being replaced, subtract old cost
+ if old != nil {
+ l.subTotalCost([]*types.Transaction{old})
+ }
+
// Otherwise overwrite the old transaction with the current one
l.txs.Put(tx)
if l.costcap.Cmp(cost) < 0 {
diff --git a/core/txpool/validation.go b/core/txpool/validation.go
index d76af9cab5..b9277fd2d9 100644
--- a/core/txpool/validation.go
+++ b/core/txpool/validation.go
@@ -151,6 +151,10 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
if _, err := types.Sender(signer, tx); err != nil {
return fmt.Errorf("%w: %v", ErrInvalidSender, err)
}
+ // Limit nonce to 2^64-1 per EIP-2681
+ if tx.Nonce()+1 < tx.Nonce() {
+ return core.ErrNonceMax
+ }
// Ensure the transaction has more gas than the bare minimum needed to cover
// the transaction metadata
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, rules.IsIstanbul, rules.IsShanghai)
@@ -211,16 +215,14 @@ func validateBlobTx(tx *types.Transaction, head *types.Header, opts *ValidationO
return err
}
// Fork-specific sidecar checks, including proof verification.
- if opts.Config.IsOsaka(head.Number, head.Time) {
+ if sidecar.Version == types.BlobSidecarVersion1 {
return validateBlobSidecarOsaka(sidecar, hashes)
+ } else {
+ return validateBlobSidecarLegacy(sidecar, hashes)
}
- return validateBlobSidecarLegacy(sidecar, hashes)
}
func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
- if sidecar.Version != types.BlobSidecarVersion0 {
- return fmt.Errorf("invalid sidecar version pre-osaka: %v", sidecar.Version)
- }
if len(sidecar.Proofs) != len(hashes) {
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes))
}
@@ -233,9 +235,6 @@ func validateBlobSidecarLegacy(sidecar *types.BlobTxSidecar, hashes []common.Has
}
func validateBlobSidecarOsaka(sidecar *types.BlobTxSidecar, hashes []common.Hash) error {
- if sidecar.Version != types.BlobSidecarVersion1 {
- return fmt.Errorf("invalid sidecar version post-osaka: %v", sidecar.Version)
- }
if len(sidecar.Proofs) != len(hashes)*kzg4844.CellProofsPerBlob {
return fmt.Errorf("invalid number of %d blob proofs expected %d", len(sidecar.Proofs), len(hashes)*kzg4844.CellProofsPerBlob)
}
diff --git a/core/txpool/validation_op_test.go b/core/txpool/validation_op_test.go
new file mode 100644
index 0000000000..36f6e78a3a
--- /dev/null
+++ b/core/txpool/validation_op_test.go
@@ -0,0 +1,112 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package txpool
+
+import (
+ "errors"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func TestValidateTransactionMaxTxGasLimit(t *testing.T) {
+ // Create a test private key and signer
+ key, _ := crypto.GenerateKey()
+ signer := types.NewEIP155Signer(big.NewInt(1))
+
+ tests := []struct {
+ name string
+ maxTxGasLimit uint64
+ txGasLimit uint64
+ expectError bool
+ expectedError error
+ }{
+ {
+ name: "No limit set",
+ maxTxGasLimit: 0,
+ txGasLimit: 1000000,
+ expectError: false,
+ },
+ {
+ name: "Under limit",
+ maxTxGasLimit: 100000,
+ txGasLimit: 50000,
+ expectError: false,
+ },
+ {
+ name: "At limit",
+ maxTxGasLimit: 100000,
+ txGasLimit: 100000,
+ expectError: false,
+ },
+ {
+ name: "Over limit",
+ maxTxGasLimit: 100000,
+ txGasLimit: 150000,
+ expectError: true,
+ expectedError: ErrTxGasLimitExceeded,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ // Create test transaction with specified gas limit
+ tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), test.txGasLimit, big.NewInt(1000000000), nil)
+
+ // Sign the transaction
+ signedTx, err := types.SignTx(tx, signer, key)
+ if err != nil {
+ t.Fatalf("Failed to sign transaction: %v", err)
+ }
+
+ // Create minimal validation options
+ opts := &ValidationOptions{
+ Config: params.TestChainConfig,
+ Accept: 1 << types.LegacyTxType,
+ MaxSize: 32 * 1024,
+ MinTip: big.NewInt(0),
+ MaxTxGasLimit: test.maxTxGasLimit,
+ }
+
+ // Create test header with high gas limit to not interfere
+ header := &types.Header{
+ Number: big.NewInt(1),
+ GasLimit: 10000000,
+ Time: 0,
+ Difficulty: big.NewInt(0),
+ }
+
+ err = ValidateTransaction(signedTx, header, signer, opts)
+
+ if test.expectError {
+ if err == nil {
+ t.Errorf("Expected error but got none")
+ } else if !errors.Is(err, test.expectedError) {
+ t.Errorf("Expected error %v, got %v", test.expectedError, err)
+ }
+ } else {
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ }
+ })
+ }
+}
diff --git a/core/txpool/validation_test.go b/core/txpool/validation_test.go
index 36f6e78a3a..3945b548c1 100644
--- a/core/txpool/validation_test.go
+++ b/core/txpool/validation_test.go
@@ -17,96 +17,99 @@
package txpool
import (
+ "crypto/ecdsa"
"errors"
+ "math"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
-func TestValidateTransactionMaxTxGasLimit(t *testing.T) {
- // Create a test private key and signer
- key, _ := crypto.GenerateKey()
- signer := types.NewEIP155Signer(big.NewInt(1))
+func TestValidateTransactionEIP2681(t *testing.T) {
+ key, err := crypto.GenerateKey()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ head := &types.Header{
+ Number: big.NewInt(1),
+ GasLimit: 5000000,
+ Time: 1,
+ Difficulty: big.NewInt(1),
+ }
+
+ signer := types.LatestSigner(params.TestChainConfig)
+
+ // Create validation options
+ opts := &ValidationOptions{
+ Config: params.TestChainConfig,
+ Accept: 0xFF, // Accept all transaction types
+ MaxSize: 32 * 1024,
+ MaxBlobCount: 6,
+ MinTip: big.NewInt(0),
+ }
tests := []struct {
- name string
- maxTxGasLimit uint64
- txGasLimit uint64
- expectError bool
- expectedError error
+ name string
+ nonce uint64
+ wantErr error
}{
{
- name: "No limit set",
- maxTxGasLimit: 0,
- txGasLimit: 1000000,
- expectError: false,
+ name: "normal nonce",
+ nonce: 42,
+ wantErr: nil,
},
{
- name: "Under limit",
- maxTxGasLimit: 100000,
- txGasLimit: 50000,
- expectError: false,
+ name: "max allowed nonce (2^64-2)",
+ nonce: math.MaxUint64 - 1,
+ wantErr: nil,
},
{
- name: "At limit",
- maxTxGasLimit: 100000,
- txGasLimit: 100000,
- expectError: false,
- },
- {
- name: "Over limit",
- maxTxGasLimit: 100000,
- txGasLimit: 150000,
- expectError: true,
- expectedError: ErrTxGasLimitExceeded,
+ name: "EIP-2681 nonce overflow (2^64-1)",
+ nonce: math.MaxUint64,
+ wantErr: core.ErrNonceMax,
},
}
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- // Create test transaction with specified gas limit
- tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), test.txGasLimit, big.NewInt(1000000000), nil)
-
- // Sign the transaction
- signedTx, err := types.SignTx(tx, signer, key)
- if err != nil {
- t.Fatalf("Failed to sign transaction: %v", err)
- }
-
- // Create minimal validation options
- opts := &ValidationOptions{
- Config: params.TestChainConfig,
- Accept: 1 << types.LegacyTxType,
- MaxSize: 32 * 1024,
- MinTip: big.NewInt(0),
- MaxTxGasLimit: test.maxTxGasLimit,
- }
-
- // Create test header with high gas limit to not interfere
- header := &types.Header{
- Number: big.NewInt(1),
- GasLimit: 10000000,
- Time: 0,
- Difficulty: big.NewInt(0),
- }
-
- err = ValidateTransaction(signedTx, header, signer, opts)
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tx := createTestTransaction(key, tt.nonce)
+ err := ValidateTransaction(tx, head, signer, opts)
- if test.expectError {
- if err == nil {
- t.Errorf("Expected error but got none")
- } else if !errors.Is(err, test.expectedError) {
- t.Errorf("Expected error %v, got %v", test.expectedError, err)
+ if tt.wantErr == nil {
+ if err != nil {
+ t.Errorf("ValidateTransaction() error = %v, wantErr nil", err)
}
} else {
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
+ if err == nil {
+ t.Errorf("ValidateTransaction() error = nil, wantErr %v", tt.wantErr)
+ } else if !errors.Is(err, tt.wantErr) {
+ t.Errorf("ValidateTransaction() error = %v, wantErr %v", err, tt.wantErr)
}
}
})
}
}
+
+// createTestTransaction creates a basic transaction for testing
+func createTestTransaction(key *ecdsa.PrivateKey, nonce uint64) *types.Transaction {
+ to := common.HexToAddress("0x0000000000000000000000000000000000000001")
+
+ txdata := &types.LegacyTx{
+ Nonce: nonce,
+ To: &to,
+ Value: big.NewInt(1000),
+ Gas: 21000,
+ GasPrice: big.NewInt(1),
+ Data: nil,
+ }
+
+ tx := types.NewTx(txdata)
+ signedTx, _ := types.SignTx(tx, types.HomesteadSigner{}, key)
+ return signedTx
+}
diff --git a/core/types/block_test.go b/core/types/block_test.go
index 67694b022f..c479eac5df 100644
--- a/core/types/block_test.go
+++ b/core/types/block_test.go
@@ -263,9 +263,8 @@ var benchBuffer = bytes.NewBuffer(make([]byte, 0, 32000))
func BenchmarkEncodeBlock(b *testing.B) {
block := makeBenchBlock()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
benchBuffer.Reset()
if err := rlp.Encode(benchBuffer, block); err != nil {
b.Fatal(err)
diff --git a/core/types/bloom9_test.go b/core/types/bloom9_test.go
index 07f6446a97..ceb6797e1f 100644
--- a/core/types/bloom9_test.go
+++ b/core/types/bloom9_test.go
@@ -78,7 +78,7 @@ func TestBloomExtensively(t *testing.T) {
func BenchmarkBloom9(b *testing.B) {
test := []byte("testestestest")
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Bloom9(test)
}
}
@@ -86,7 +86,7 @@ func BenchmarkBloom9(b *testing.B) {
func BenchmarkBloom9Lookup(b *testing.B) {
toTest := []byte("testtest")
bloom := new(Bloom)
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
bloom.Test(toTest)
}
}
@@ -128,7 +128,7 @@ func BenchmarkCreateBloom(b *testing.B) {
}
b.Run("small-createbloom", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
for _, receipt := range rSmall {
receipt.Bloom = CreateBloom(receipt)
}
@@ -144,7 +144,7 @@ func BenchmarkCreateBloom(b *testing.B) {
})
b.Run("large-createbloom", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
for _, receipt := range rLarge {
receipt.Bloom = CreateBloom(receipt)
}
@@ -163,13 +163,11 @@ func BenchmarkCreateBloom(b *testing.B) {
receipt.Bloom = CreateBloom(receipt)
}
b.ReportAllocs()
- b.ResetTimer()
var bl Bloom
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
bl = MergeBloom(rSmall)
}
- b.StopTimer()
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes())
@@ -182,13 +180,11 @@ func BenchmarkCreateBloom(b *testing.B) {
receipt.Bloom = CreateBloom(receipt)
}
b.ReportAllocs()
- b.ResetTimer()
var bl Bloom
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
bl = MergeBloom(rLarge)
}
- b.StopTimer()
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes())
diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go
index b3735d7156..486acc0370 100644
--- a/core/types/gen_receipt_json.go
+++ b/core/types/gen_receipt_json.go
@@ -72,6 +72,8 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
enc.OperatorFeeScalar = (*hexutil.Uint64)(r.OperatorFeeScalar)
enc.OperatorFeeConstant = (*hexutil.Uint64)(r.OperatorFeeConstant)
enc.DAFootprintGasScalar = (*hexutil.Uint64)(r.DAFootprintGasScalar)
+ enc.OperatorFeeScalar = (*hexutil.Uint64)(r.OperatorFeeScalar)
+ enc.OperatorFeeConstant = (*hexutil.Uint64)(r.OperatorFeeConstant)
return json.Marshal(&enc)
}
diff --git a/core/types/hashing_test.go b/core/types/hashing_test.go
index c846ecd0c5..54adbc73e8 100644
--- a/core/types/hashing_test.go
+++ b/core/types/hashing_test.go
@@ -84,9 +84,8 @@ func BenchmarkDeriveSha200(b *testing.B) {
var exp common.Hash
var got common.Hash
b.Run("std_trie", func(b *testing.B) {
- b.ResetTimer()
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
exp = types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil)))
}
})
@@ -94,7 +93,7 @@ func BenchmarkDeriveSha200(b *testing.B) {
b.Run("stack_trie", func(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
got = types.DeriveSha(txs, trie.NewStackTrie(nil))
}
})
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index cc41674dfd..2d854ae345 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -591,7 +591,7 @@ func BenchmarkHash(b *testing.B) {
GasTipCap: big.NewInt(500),
GasFeeCap: big.NewInt(500),
})
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
signer.Hash(tx)
}
}
@@ -614,7 +614,7 @@ func BenchmarkEffectiveGasTip(b *testing.B) {
b.Run("Original", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
_, err := tx.EffectiveGasTip(baseFee.ToBig())
if err != nil {
b.Fatal(err)
@@ -625,7 +625,7 @@ func BenchmarkEffectiveGasTip(b *testing.B) {
b.Run("IntoMethod", func(b *testing.B) {
b.ReportAllocs()
dst := new(uint256.Int)
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
err := tx.calcEffectiveGasTip(dst, baseFee)
if err != nil {
b.Fatal(err)
@@ -729,7 +729,7 @@ func BenchmarkEffectiveGasTipCmp(b *testing.B) {
b.Run("Original", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
tx.EffectiveGasTipCmp(other, baseFee)
}
})
diff --git a/core/types/types_test.go b/core/types/types_test.go
index 1fb386d5de..96d0444994 100644
--- a/core/types/types_test.go
+++ b/core/types/types_test.go
@@ -126,7 +126,7 @@ func benchRLP(b *testing.B, encode bool) {
b.Run(tc.name, func(b *testing.B) {
b.ReportAllocs()
var null = &devnull{}
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
rlp.Encode(null, tc.obj)
}
b.SetBytes(int64(null.len / b.N))
@@ -136,7 +136,7 @@ func benchRLP(b *testing.B, encode bool) {
// Test decoding
b.Run(tc.name, func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
if err := rlp.DecodeBytes(data, tc.obj); err != nil {
b.Fatal(err)
}
diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go
index 584e790433..254cf753d7 100644
--- a/core/verkle_witness_test.go
+++ b/core/verkle_witness_test.go
@@ -232,7 +232,7 @@ func TestProcessParentBlockHash(t *testing.T) {
// etc
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
statedb.SetNonce(params.HistoryStorageAddress, 1, tracing.NonceChangeUnspecified)
- statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
+ statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode, tracing.CodeChangeUnspecified)
// Process n blocks, from 1 .. num
var num = 2
for i := 1; i <= num; i++ {
diff --git a/core/vm/analysis_legacy_test.go b/core/vm/analysis_legacy_test.go
index f84a4abc92..75d8a495fa 100644
--- a/core/vm/analysis_legacy_test.go
+++ b/core/vm/analysis_legacy_test.go
@@ -65,21 +65,17 @@ func BenchmarkJumpdestAnalysis_1200k(bench *testing.B) {
// 1.4 ms
code := make([]byte, analysisCodeSize)
bench.SetBytes(analysisCodeSize)
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
codeBitmap(code)
}
- bench.StopTimer()
}
func BenchmarkJumpdestHashing_1200k(bench *testing.B) {
// 4 ms
code := make([]byte, analysisCodeSize)
bench.SetBytes(analysisCodeSize)
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
crypto.Keccak256Hash(code)
}
- bench.StopTimer()
}
func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
@@ -91,8 +87,7 @@ func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
code[i] = byte(op)
}
bits := make(BitVec, len(code)/8+1+4)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
clear(bits)
codeBitmapInternal(code, bits)
}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 18dfb9a9d2..eee22a43f9 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -24,11 +24,13 @@ import (
"maps"
"math"
"math/big"
+ "math/bits"
"github.com/consensys/gnark-crypto/ecc"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
+ patched_big "github.com/ethereum/go-bigmodexpfix/src/math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/bitutil"
"github.com/ethereum/go-ethereum/core/tracing"
@@ -38,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/crypto/secp256r1"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/ripemd160"
)
@@ -485,21 +488,7 @@ type bigModExp struct {
eip7883 bool
}
-var (
- big1 = big.NewInt(1)
- big3 = big.NewInt(3)
- big7 = big.NewInt(7)
- big20 = big.NewInt(20)
- big32 = big.NewInt(32)
- big64 = big.NewInt(64)
- big96 = big.NewInt(96)
- big480 = big.NewInt(480)
- big1024 = big.NewInt(1024)
- big3072 = big.NewInt(3072)
- big199680 = big.NewInt(199680)
-)
-
-// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198
+// byzantiumMultComplexity implements the bigModexp multComplexity formula, as defined in EIP-198.
//
// def mult_complexity(x):
// if x <= 64: return x ** 2
@@ -507,120 +496,221 @@ var (
// else: return x ** 2 // 16 + 480 * x - 199680
//
// where is x is max(length_of_MODULUS, length_of_BASE)
-func modexpMultComplexity(x *big.Int) *big.Int {
+// returns MaxUint64 if an overflow occurred.
+func byzantiumMultComplexity(x uint64) uint64 {
switch {
- case x.Cmp(big64) <= 0:
- x.Mul(x, x) // x ** 2
- case x.Cmp(big1024) <= 0:
- // (x ** 2 // 4 ) + ( 96 * x - 3072)
- x = new(big.Int).Add(
- new(big.Int).Rsh(new(big.Int).Mul(x, x), 2),
- new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
- )
+ case x <= 64:
+ return x * x
+ case x <= 1024:
+ // x^2 / 4 + 96*x - 3072
+ return x*x/4 + 96*x - 3072
+
default:
- // (x ** 2 // 16) + (480 * x - 199680)
- x = new(big.Int).Add(
- new(big.Int).Rsh(new(big.Int).Mul(x, x), 4),
- new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
- )
+ // For large x, use uint256 arithmetic to avoid overflow
+ // x^2 / 16 + 480*x - 199680
+
+ // xSqr = x^2 / 16
+ carry, xSqr := bits.Mul64(x, x)
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ xSqr = xSqr >> 4
+
+ // Calculate 480 * x (can't overflow if x^2 didn't overflow)
+ x480 := x * 480
+ // Calculate 480 * x - 199680 (will not underflow, since x > 1024)
+ x480 = x480 - 199680
+
+ // xSqr + x480
+ sum, carry := bits.Add64(xSqr, x480, 0)
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ return sum
+ }
+}
+
+// berlinMultComplexity implements the multiplication complexity formula for Berlin.
+//
+// def mult_complexity(x):
+//
+// ceiling(x/8)^2
+//
+// where is x is max(length_of_MODULUS, length_of_BASE)
+func berlinMultComplexity(x uint64) uint64 {
+ // x = (x + 7) / 8
+ x, carry := bits.Add64(x, 7, 0)
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ x /= 8
+
+ // x^2
+ carry, x = bits.Mul64(x, x)
+ if carry != 0 {
+ return math.MaxUint64
}
return x
}
+// osakaMultComplexity implements the multiplication complexity formula for Osaka.
+//
+// For x <= 32: returns 16
+// For x > 32: returns 2 * ceiling(x/8)^2
+func osakaMultComplexity(x uint64) uint64 {
+ if x <= 32 {
+ return 16
+ }
+ // For x > 32, return 2 * berlinMultComplexity(x)
+ result := berlinMultComplexity(x)
+ carry, result := bits.Mul64(result, 2)
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ return result
+}
+
+// modexpIterationCount calculates the number of iterations for the modexp precompile.
+// This is the adjusted exponent length used in gas calculation.
+func modexpIterationCount(expLen uint64, expHead uint256.Int, multiplier uint64) uint64 {
+ var iterationCount uint64
+
+ // For large exponents (expLen > 32), add (expLen - 32) * multiplier
+ if expLen > 32 {
+ carry, count := bits.Mul64(expLen-32, multiplier)
+ if carry > 0 {
+ return math.MaxUint64
+ }
+ iterationCount = count
+ }
+ // Add the MSB position - 1 if expHead is non-zero
+ if bitLen := expHead.BitLen(); bitLen > 0 {
+ count, carry := bits.Add64(iterationCount, uint64(bitLen-1), 0)
+ if carry > 0 {
+ return math.MaxUint64
+ }
+ iterationCount = count
+ }
+
+ return max(iterationCount, 1)
+}
+
+// byzantiumModexpGas calculates the gas cost for the modexp precompile using Byzantium rules.
+func byzantiumModexpGas(baseLen, expLen, modLen uint64, expHead uint256.Int) uint64 {
+ const (
+ multiplier = 8
+ divisor = 20
+ )
+
+ maxLen := max(baseLen, modLen)
+ multComplexity := byzantiumMultComplexity(maxLen)
+ if multComplexity == math.MaxUint64 {
+ return math.MaxUint64
+ }
+ iterationCount := modexpIterationCount(expLen, expHead, multiplier)
+
+ // Calculate gas: (multComplexity * iterationCount) / divisor
+ carry, gas := bits.Mul64(iterationCount, multComplexity)
+ gas /= divisor
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ return gas
+}
+
+// berlinModexpGas calculates the gas cost for the modexp precompile using Berlin rules.
+func berlinModexpGas(baseLen, expLen, modLen uint64, expHead uint256.Int) uint64 {
+ const (
+ multiplier = 8
+ divisor = 3
+ minGas = 200
+ )
+
+ maxLen := max(baseLen, modLen)
+ multComplexity := berlinMultComplexity(maxLen)
+ if multComplexity == math.MaxUint64 {
+ return math.MaxUint64
+ }
+ iterationCount := modexpIterationCount(expLen, expHead, multiplier)
+
+ // Calculate gas: (multComplexity * iterationCount) / divisor
+ carry, gas := bits.Mul64(iterationCount, multComplexity)
+ gas /= divisor
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ return max(gas, minGas)
+}
+
+// osakaModexpGas calculates the gas cost for the modexp precompile using Osaka rules.
+func osakaModexpGas(baseLen, expLen, modLen uint64, expHead uint256.Int) uint64 {
+ const (
+ multiplier = 16
+ minGas = 500
+ )
+
+ maxLen := max(baseLen, modLen)
+ multComplexity := osakaMultComplexity(maxLen)
+ if multComplexity == math.MaxUint64 {
+ return math.MaxUint64
+ }
+ iterationCount := modexpIterationCount(expLen, expHead, multiplier)
+
+ // Calculate gas: multComplexity * iterationCount
+ carry, gas := bits.Mul64(iterationCount, multComplexity)
+ if carry != 0 {
+ return math.MaxUint64
+ }
+ return max(gas, minGas)
+}
+
// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bigModExp) RequiredGas(input []byte) uint64 {
- var (
- baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
- expLen = new(big.Int).SetBytes(getData(input, 32, 32))
- modLen = new(big.Int).SetBytes(getData(input, 64, 32))
- )
+ // Parse input lengths
+ baseLenBig := new(uint256.Int).SetBytes(getData(input, 0, 32))
+ expLenBig := new(uint256.Int).SetBytes(getData(input, 32, 32))
+ modLenBig := new(uint256.Int).SetBytes(getData(input, 64, 32))
+
+ // Convert to uint64, capping at max value
+ baseLen := baseLenBig.Uint64()
+ if !baseLenBig.IsUint64() {
+ baseLen = math.MaxUint64
+ }
+ expLen := expLenBig.Uint64()
+ if !expLenBig.IsUint64() {
+ expLen = math.MaxUint64
+ }
+ modLen := modLenBig.Uint64()
+ if !modLenBig.IsUint64() {
+ modLen = math.MaxUint64
+ }
+
+ // Skip the header
if len(input) > 96 {
input = input[96:]
} else {
input = input[:0]
}
+
// Retrieve the head 32 bytes of exp for the adjusted exponent length
- var expHead *big.Int
- if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
- expHead = new(big.Int)
- } else {
- if expLen.Cmp(big32) > 0 {
- expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32))
- } else {
- expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
- }
- }
- // Calculate the adjusted exponent length
- var msb int
- if bitlen := expHead.BitLen(); bitlen > 0 {
- msb = bitlen - 1
- }
- adjExpLen := new(big.Int)
- if expLen.Cmp(big32) > 0 {
- adjExpLen.Sub(expLen, big32)
- if c.eip7883 {
- adjExpLen.Lsh(adjExpLen, 4)
+ var expHead uint256.Int
+ if uint64(len(input)) > baseLen {
+ if expLen > 32 {
+ expHead.SetBytes(getData(input, baseLen, 32))
} else {
- adjExpLen.Lsh(adjExpLen, 3)
+ // TODO: Check that if expLen < baseLen, then getData will return an empty slice
+ expHead.SetBytes(getData(input, baseLen, expLen))
}
}
- adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
- // Calculate the gas cost of the operation
- gas := new(big.Int)
- if modLen.Cmp(baseLen) < 0 {
- gas.Set(baseLen)
- } else {
- gas.Set(modLen)
- }
-
- maxLenOver32 := gas.Cmp(big32) > 0
- if c.eip2565 {
- // EIP-2565 (Berlin fork) has three changes:
- //
- // 1. Different multComplexity (inlined here)
- // in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
- //
- // def mult_complexity(x):
- // ceiling(x/8)^2
- //
- // where is x is max(length_of_MODULUS, length_of_BASE)
- gas.Add(gas, big7)
- gas.Rsh(gas, 3)
- gas.Mul(gas, gas)
-
- var minPrice uint64 = 200
- if c.eip7883 {
- minPrice = 500
- if maxLenOver32 {
- gas.Add(gas, gas)
- } else {
- gas = big.NewInt(16)
- }
- }
- if adjExpLen.Cmp(big1) > 0 {
- gas.Mul(gas, adjExpLen)
- }
- // 2. Different divisor (`GQUADDIVISOR`) (3)
- if !c.eip7883 {
- gas.Div(gas, big3)
- }
- if gas.BitLen() > 64 {
- return math.MaxUint64
- }
- return max(minPrice, gas.Uint64())
- }
-
- // Pre-Berlin logic.
- gas = modexpMultComplexity(gas)
- if adjExpLen.Cmp(big1) > 0 {
- gas.Mul(gas, adjExpLen)
- }
- gas.Div(gas, big20)
- if gas.BitLen() > 64 {
- return math.MaxUint64
+ // Choose the appropriate gas calculation based on the EIP flags
+ if c.eip7883 {
+ return osakaModexpGas(baseLen, expLen, modLen, expHead)
+ } else if c.eip2565 {
+ return berlinModexpGas(baseLen, expLen, modLen, expHead)
+ } else {
+ return byzantiumModexpGas(baseLen, expLen, modLen, expHead)
}
- return gas.Uint64()
}
func (c *bigModExp) Run(input []byte) ([]byte, error) {
@@ -649,9 +739,9 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
}
// Retrieve the operands and execute the exponentiation
var (
- base = new(big.Int).SetBytes(getData(input, 0, baseLen))
- exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
- mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
+ base = new(patched_big.Int).SetBytes(getData(input, 0, baseLen))
+ exp = new(patched_big.Int).SetBytes(getData(input, baseLen, expLen))
+ mod = new(patched_big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
v []byte
)
switch {
diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go
index 2596c52298..2ee4ebc77e 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -129,7 +129,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
p := allPrecompiles[common.HexToAddress(addr)]
in := common.Hex2Bytes(test.Input)
- gas := p.RequiredGas(in) - 1
+ gas := test.Gas - 1
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
_, _, err := RunPrecompiledContract(p, in, gas, nil)
@@ -178,12 +178,10 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
bench.Run(fmt.Sprintf("%s-Gas=%d", test.Name, reqGas), func(bench *testing.B) {
bench.ReportAllocs()
start := time.Now()
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
copy(data, in)
res, _, err = RunPrecompiledContract(p, data, reqGas, nil)
}
- bench.StopTimer()
elapsed := uint64(time.Since(start))
if elapsed < 1 {
elapsed = 1
@@ -268,6 +266,30 @@ func TestPrecompiledModExpOOG(t *testing.T) {
for _, test := range modexpTests {
testPrecompiledOOG("05", test, t)
}
+ modexpTestsEIP2565, err := loadJson("modexp_eip2565")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, test := range modexpTestsEIP2565 {
+ testPrecompiledOOG("f5", test, t)
+ }
+ modexpTestsEIP7883, err := loadJson("modexp_eip7883")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, test := range modexpTestsEIP7883 {
+ testPrecompiledOOG("f6", test, t)
+ }
+ gasCostTest := precompiledTest{
+ Input: "000000000000000000000000000000000000000000000000000000000000082800000000000000000000000000000000000000000000000040000000000000090000000000000000000000000000000000000000000000000000000000000600000000adadadad00000000ff31ff00000006ffffffffffffffffffffffffffffffffffffffff0000000000000004ffffffffffffff0000000000000000000000000000000000000000d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0000001000200fefffeff01000100000000000000ffff01000100ffffffff01000100ffffffff0000050001000100fefffdff02000300ff000000000000012b000000000000090000000000000000000000000000000000000000000000000000ffffff000000000200fffffeff00000001000000000001000200fefffeff010001000000000000000000423034000000000011006161ffbf640053004f00ff00fffffffffffffff3ff00000000000f00002dffffffffff0000000000000000000061999999999999999999999999899961ffffffff0100010000000000000000000000000600000000adadadad00000000ffff00000006fffffdffffffffffffffffffffffffffffffffff0000000000000004ffffffffffffff000000000000000000000000000000000000000098000000966375726c2f66000030000000000011006161ffbf640053004f002d00000000a200000000000000ff1818183fffffffff3a6e756c6c2c22223a6e7500006c2000000000002d2d0000000000000000000144ccef0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000fdff000000ff00290001000009000000000000000000000000000000000000000000000000a50004ff2800000000000000000000000000000000000000000000000001000000000000090000000000000000000000030000000000000000002b00000000000000000600000000adadadad00000000ffff00000006ffffffffffffffffffffffffffffffffffffffff0000000000000004ffffffffffffff0000000000000000000000000000000000000000d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d000000000717a1a001a1a1a1a1a1a000000121212121212121212121212121212121212121212d0d0d0d01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212373800002d35373837346137346161610000000000000000d0d0d0d0d0d0d0d0002d3533321a1a000000d0d0d0d0d0d0d0d0d0d0d0d0d0d000000000717a1a001a1a1a1a1a1a000000121212121212121212121212121212121212121212d0d0d0d012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121a1212121212121212000000000000000000000000d0d0d0d0d0d0d0d0002d3533321a1a0000000000000000000000003300000001000f5b00001100712c6eff9e61000000000061000000fbffff1a1a3a6e353900756c6c7d3b00000000009100002d35ff00600000000000000000002d3533321a1a1a1a3a6e353900756c6c7d3b000000000091373800002d3537383734613734616161d0d0d0d0d000000000717a1a001a1a1a1a1a1a000000121212121212121212121212121212121212121212d0d0d0d012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121a1212121212121212000000000000000000000000d0d0d0d0d0d0d0d0002d3533321a1a0000000000000000000000003300000001000f5b00001100712c6eff9e61000000000061000000fbffff1a1a3a6e353900756c6c7d3b00000000009100002d35ff00600000000000000000002d3533321a1a1a1a3a6e353900756c6c7d3b000000000091373800002d353738373461373461616100000000000000000000000000000000000000000000000001000000000000090000000000000000000000030000000000000000002b00000000000000000600000000adadadad00000000ffff00000006ffffffffffffffffffffffffffffffffffffffff0000000000000004ffffffffffffff0000000000000000000000000000000000000000d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d000000000717a1a001a1a1a1a1a1a000000121212121212121212121212121212121212121212d0d0d0d01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212373800002d35373837346137346161610000000000000000d0d0d0d0d0d0d0d0002d3533321a1a000000d0d0d0d0d0d0d0d0d0d0d0d0d0d000000000717a1a001a1a1a1a1a1a000000121212121212121212121212121212121212121212d0d0d0d012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121a1212121212121212000000000000000000000000d0d0d0d0d0d0d0d0002d3533321a1a0000000000000000000000003300000001000f5b00001100712c6eff9e61000000000061000000fbffff1a1a3a6e353900756c6c7d3b00000000009100002d35ff00600000000000000000002d3533321a1a1a1a3a6e353900756c6c7d3b000000000091373800002d3537383734613734616161d0d0d0d0d000000000717a1a001a1a1a1a1a1a0000001212121212121212121212121212121212121212000000000000003300000001000f5b00001100712c6eff9e61000000000061000000fbffff1a1a3a6e353900756c6c7d3b00000000009100002d35ff00600000000000000000002d3533321a1a1a1a3a6e353900756c6c7d3b000000000091373800002d3537383734613734616161",
+ Expected: "000000000000000000000000000000000000000000000000",
+ Name: "oss_fuzz_gas_calc",
+ Gas: 18446744073709551615,
+ NoBenchmark: false,
+ }
+ testPrecompiledOOG("05", gasCostTest, t)
+ testPrecompiledOOG("f5", gasCostTest, t)
+ testPrecompiledOOG("f6", gasCostTest, t)
}
// Tests the sample inputs from the elliptic curve scalar multiplication EIP 213.
diff --git a/core/vm/eips.go b/core/vm/eips.go
index 10ca1fe9ab..d7ed18648e 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -294,7 +294,7 @@ func opBlobBaseFee(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
return nil, nil
}
-// opCLZ implements the CLZ opcode (count leading zero bytes)
+// opCLZ implements the CLZ opcode (count leading zero bits)
func opCLZ(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
x := scope.Stack.peek()
x.SetUint64(256 - uint64(x.BitLen()))
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 05ba870b96..d6e8542aac 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -621,7 +621,7 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b
}
}
- evm.StateDB.SetCode(address, ret)
+ evm.StateDB.SetCode(address, ret, tracing.CodeChangeContractCreation)
return ret, nil
}
diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go
index f5e8b58eb8..b9f0ba4cb7 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/gas_table_test.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@@ -87,7 +88,7 @@ func TestEIP2200(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
statedb.CreateAccount(address)
- statedb.SetCode(address, hexutil.MustDecode(tt.input))
+ statedb.SetCode(address, hexutil.MustDecode(tt.input), tracing.CodeChangeUnspecified)
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
statedb.Finalise(true) // Push the state into the "original" slot
@@ -139,7 +140,7 @@ func TestCreateGas(t *testing.T) {
address := common.BytesToAddress([]byte("contract"))
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
statedb.CreateAccount(address)
- statedb.SetCode(address, hexutil.MustDecode(tt.code))
+ statedb.SetCode(address, hexutil.MustDecode(tt.code), tracing.CodeChangeUnspecified)
statedb.Finalise(true)
vmctx := BlockContext{
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index cd31829a7e..72f561f4bf 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -291,15 +291,13 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
intArgs[i] = new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
}
pc := uint64(0)
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
for _, arg := range intArgs {
stack.push(arg)
}
op(&pc, evm, scope)
stack.pop()
}
- bench.StopTimer()
for i, arg := range args {
want := new(uint256.Int).SetBytes(common.Hex2Bytes(arg))
@@ -551,8 +549,7 @@ func BenchmarkOpMstore(bench *testing.B) {
memStart := new(uint256.Int)
value := new(uint256.Int).SetUint64(0x1337)
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
stack.push(value)
stack.push(memStart)
opMstore(&pc, evm, &ScopeContext{mem, stack, nil})
@@ -609,8 +606,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
pc := uint64(0)
start := new(uint256.Int)
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
stack.push(uint256.NewInt(32))
stack.push(start)
opKeccak256(&pc, evm, &ScopeContext{mem, stack, nil})
diff --git a/core/vm/interface.go b/core/vm/interface.go
index 42a72db482..d7f4c10e1f 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -43,7 +43,7 @@ type StateDB interface {
GetCode(common.Address) []byte
// SetCode sets the new code for the address, and returns the previous code, if any.
- SetCode(common.Address, []byte) []byte
+ SetCode(common.Address, []byte, tracing.CodeChangeReason) []byte
GetCodeSize(common.Address) int
AddRefund(uint64)
diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go
index 8ed512316b..79531f78d2 100644
--- a/core/vm/interpreter_test.go
+++ b/core/vm/interpreter_test.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@@ -45,7 +46,7 @@ func TestLoopInterrupt(t *testing.T) {
for i, tt := range loopInterruptTests {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
statedb.CreateAccount(address)
- statedb.SetCode(address, common.Hex2Bytes(tt))
+ statedb.SetCode(address, common.Hex2Bytes(tt), tracing.CodeChangeUnspecified)
statedb.Finalise(true)
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{})
@@ -89,8 +90,7 @@ func BenchmarkInterpreter(b *testing.B) {
stack.push(uint256.NewInt(123))
stack.push(uint256.NewInt(123))
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
gasSStoreEIP3529(evm, contract, stack, mem, 1234)
}
}
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 9d984291f2..b40e99d047 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -139,7 +140,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil)
cfg.State.CreateAccount(address)
// set the receiver's (the executing contract) code for execution.
- cfg.State.SetCode(address, code)
+ cfg.State.SetCode(address, code, tracing.CodeChangeUnspecified)
// Call the code with the given configuration.
ret, leftOverGas, err := vmenv.Call(
cfg.Origin,
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index d75a5b0459..ddd32df039 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -114,7 +114,7 @@ func TestCall(t *testing.T) {
byte(vm.PUSH1), 32,
byte(vm.PUSH1), 0,
byte(vm.RETURN),
- })
+ }, tracing.CodeChangeUnspecified)
ret, _, err := Call(address, nil, &Config{State: state})
if err != nil {
@@ -150,8 +150,7 @@ func BenchmarkCall(b *testing.B) {
b.Fatal(err)
}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
for j := 0; j < 400; j++ {
Execute(code, cpurchase, nil)
Execute(code, creceived, nil)
@@ -167,7 +166,7 @@ func benchmarkEVM_Create(bench *testing.B, code string) {
)
statedb.CreateAccount(sender)
- statedb.SetCode(receiver, common.FromHex(code))
+ statedb.SetCode(receiver, common.FromHex(code), tracing.CodeChangeUnspecified)
runtimeConfig := Config{
Origin: sender,
State: statedb,
@@ -190,11 +189,9 @@ func benchmarkEVM_Create(bench *testing.B, code string) {
EVMConfig: vm.Config{},
}
// Warm up the intpools and stuff
- bench.ResetTimer()
- for i := 0; i < bench.N; i++ {
+ for bench.Loop() {
Call(receiver, []byte{}, &runtimeConfig)
}
- bench.StopTimer()
}
func BenchmarkEVM_CREATE_500(bench *testing.B) {
@@ -232,9 +229,8 @@ func BenchmarkEVM_SWAP1(b *testing.B) {
b.Run("10k", func(b *testing.B) {
contractCode := swapContract(10_000)
- state.SetCode(contractAddr, contractCode)
-
- for i := 0; i < b.N; i++ {
+ state.SetCode(contractAddr, contractCode, tracing.CodeChangeUnspecified)
+ for b.Loop() {
_, _, err := Call(contractAddr, []byte{}, &Config{State: state})
if err != nil {
b.Fatal(err)
@@ -263,9 +259,8 @@ func BenchmarkEVM_RETURN(b *testing.B) {
b.ReportAllocs()
contractCode := returnContract(n)
- state.SetCode(contractAddr, contractCode)
-
- for i := 0; i < b.N; i++ {
+ state.SetCode(contractAddr, contractCode, tracing.CodeChangeUnspecified)
+ for b.Loop() {
ret, _, err := Call(contractAddr, []byte{}, &Config{State: state})
if err != nil {
b.Fatal(err)
@@ -422,17 +417,17 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
byte(vm.PUSH1), 0x00,
byte(vm.PUSH1), 0x00,
byte(vm.REVERT),
- })
+ }, tracing.CodeChangeUnspecified)
}
//cfg.State.CreateAccount(cfg.Origin)
// set the receiver's (the executing contract) code for execution.
- cfg.State.SetCode(destination, code)
+ cfg.State.SetCode(destination, code, tracing.CodeChangeUnspecified)
Call(destination, nil, cfg)
b.Run(name, func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Call(destination, nil, cfg)
}
})
@@ -772,12 +767,12 @@ func TestRuntimeJSTracer(t *testing.T) {
for i, jsTracer := range jsTracers {
for j, tc := range tests {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
- statedb.SetCode(main, tc.code)
- statedb.SetCode(common.HexToAddress("0xbb"), calleeCode)
- statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
- statedb.SetCode(common.HexToAddress("0xdd"), calleeCode)
- statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
- statedb.SetCode(common.HexToAddress("0xff"), suicideCode)
+ statedb.SetCode(main, tc.code, tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xbb"), calleeCode, tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xcc"), calleeCode, tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xdd"), calleeCode, tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xee"), calleeCode, tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xff"), suicideCode, tracing.CodeChangeUnspecified)
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil, params.MergedTestChainConfig)
if err != nil {
@@ -862,8 +857,8 @@ func BenchmarkTracerStepVsCallFrame(b *testing.B) {
// delegation designator incurs the correct amount of gas based on the tracer.
func TestDelegatedAccountAccessCost(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
- statedb.SetCode(common.HexToAddress("0xff"), types.AddressToDelegation(common.HexToAddress("0xaa")))
- statedb.SetCode(common.HexToAddress("0xaa"), program.New().Return(0, 0).Bytes())
+ statedb.SetCode(common.HexToAddress("0xff"), types.AddressToDelegation(common.HexToAddress("0xaa")), tracing.CodeChangeUnspecified)
+ statedb.SetCode(common.HexToAddress("0xaa"), program.New().Return(0, 0).Bytes(), tracing.CodeChangeUnspecified)
for i, tc := range []struct {
code []byte
diff --git a/core/vm/testdata/precompiles/modexp_eip2565.json b/core/vm/testdata/precompiles/modexp_eip2565.json
index c55441439e..24455eeca7 100644
--- a/core/vm/testdata/precompiles/modexp_eip2565.json
+++ b/core/vm/testdata/precompiles/modexp_eip2565.json
@@ -117,5 +117,215 @@
"Name": "nagydani-5-pow0x10001",
"Gas": 87381,
"NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000007d7d7d83828282348286877d7d827d407d797d7d7d7d7d7d7d7d7d7d7d5b00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4000007d7d7d83828282348286877d7d82",
+ "Expected": "36a385a417859b5e178d3ab9",
+ "Name": "marius-1-even",
+ "Gas": 2057,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d80000000000000000000000000000000000000000000000000000000000000010ffffffffffffffff76ffffffffffffff1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c76ec7c7c7c7ffffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7ffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c76ec7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7ffffffffff3f000000000000000000000000",
+ "Expected": "c3745de81615f80088ffffffffffffff",
+ "Name": "guido-1-even",
+ "Gas": 2298,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d80000000000000000000000000000000000000000000000000000000000000010e0060000a921212121212121ff0000212b212121ffff1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f00feffff212121212121ffffffff1fe1e0e0e01e1f1f169f1f1f1f490afcefffffffffffffffff82828282828282828282828282828282828282828200ffff28ff2b212121ffff1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1fffffffffff0afceffffff7ffffffffff7c8282828282a1828282828282828282828282828200ffff28ff2b212121ffff1f1f1f1f1f1fd11f1f1f1f1f1f1f1f1f1f1fffffffffffffffff21212121212121fb2121212121ffff1f1f1f1f1f1f1f1fffaf82828282828200ffff28ff2b21828200",
+ "Expected": "458ef0af2549d46d24c89079499479e1",
+ "Name": "guido-2-even",
+ "Gas": 2300,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001e7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002cb0193585a48e18aad777e9c1b54221a0f58140392e4f091cd5f42b2e8644a9384fbd58ae1edec2477ebf7edbf7c0a3f8bd21d1890ee87646feab3c47be716f842cc3da9b940af312dc54450a960e3fc0b86e56abddd154068e10571a96fff6259431632bc15695c6c8679057e66c2c25c127e97e64ee5de6ea1fc0a4a0e431343fed1daafa072c238a45841da86a9806680bc9f298411173210790359209cd454b5af7b4d5688b4403924e5f863d97e2c5349e1a04b54fcf385b1e9d7714bab8fbf5835f6ff9ed575e77dff7af5cbb641db5d537933bae1fa6555d6c12d6fb31ca27b57771f4aebfbe0bf95e8990c0108ffe7cbdaf370be52cf3ade594543af75ad9329d2d11a402270b5b9a6bf4b83307506e118fca4862749d04e916fc7a039f0d13f2a02e0eedb800199ec95df15b4ccd8669b52586879624d51219e72102fad810b5909b1e372ddf33888fb9beb09b416e4164966edbabd89e4a286be36277fc576ed519a15643dac602e92b63d0b9121f0491da5b16ef793a967f096d80b6c81ecaaffad7e3f06a4a5ac2796f1ed9f68e6a0fd5cf191f0c5c2eec338952ff8d31abc68bf760febeb57e088995ba1d7726a2fdd6d8ca28a181378b8b4ab699bfd4b696739bbf17a9eb2df6251143046137fdbbfacac312ebf67a67da9741b596000000000000419a2917c61722b0713d3b00a2f0e1dd5aebbbe09615de424700eea3c3020fe6e9ea5de9fa1ace781df28b21f746d2ab61d0da496e08473c90ff7dfe25b43bcde76f4bafb82e0975bea75f5a0591dba80ba2fff80a07d8853bea5be13ab326ba70c57b153acc646151948d1cf061ca31b02d4719fac710e7c723ca44f5b1737824b7ccc74ba5bff980aabdbf267621cafc3d6dcc29d0ca9c16839a92ed34de136da7900aa3ee43d21aa57498981124357cf0ca9b86f9a8d3f9c604ca00c726e48f7a9945021ea6dfff92d6b2d6514693169ca133e993541bfa4c4c191de806aa80c48109bcfc9901eccfdeb2395ab75fe63c67de900829d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "1194e971c875bb45f030316793bc6916343335b18670dfad7a4646fba99749b30283b78b818836de7400ff1a68ddad1a2dd850ec0f227441e2d4d13f5ee4b5d7a856db0a9ad1f86987e1f117d70f9e6a1a2b8d083fa82653aa16f1773b6deb2ed8a1f9e7f3a5db121c4a0c91cb954e2ec53e63422efe86c7984d79cd0e7b5e3eb8ca4980551d63f302c7d72500a84baf12c82fc7bd9b5c2ab8b9c33baf1df28b2031c58a8b2928a42c9f456e98874e22fe13cf17aa5915b11bb108b6ae40842d434604ccddcb4f64324c67b2dde32e6cd759d964f17d9cdf0046cd0ed3588e1fc4b88f67a5d4f3a870aad1cba89ead265d6ad327c8ea7ff54fe4b5e7dbe87c5c59c468543eab3675751111bfa1d6c51daf789d41dc21fd8ba9e05490f881a973a3c1567ff3129a49aa6658cf06f0a79530a7256ce5a07c2a77b4306383d538866bba376d90621c4f82d1f5f32304ee2b7170805d42418fc6967642e5648d8c64fe9c0fdff2d7c114a47add7767c8fccb8808de8c3c6e1a8880c05e16fafc1513fded8eba222dcaaa809bdb36999cc27ab8d0055009e9690e8a35b859df865dc510d25c7812d8eebbb35607ad595573f0fabd1b57970a2bc113ac6f0ca01e985032b9c2c139316ac099ed1632d2bc0fcc341343d303db2a9c3cf2ad572c6c43084b08d458bf822e92da16079f39cdb0dd10ef47f87ecae404117fc72660372cee9ea42266e7f8d973e7f6b09930ca5f96e04976bf23b9d356bbd2429597b04b7663e0e1a1228f4dfda3b854233e4888dc60c6886c1e0e8aec1705f681027b1e0b3017337557f107ef5cd272df5fd31dfec2bdffe163a8369895ffe124c0aa0ee00ca0fe1db4d5cf37b4af0e49bd73a89d88ced3d88f8e6f00d8e61ad09946d0e72cd3e25bc688a021a83758b5023daae7c269a6cbbd447aba5da7629b75801e1654ce85b8e21ccb9865654f8662e538625d75fea31000000000000000000000000000000000000000000000",
+ "Name": "guido-3-even",
+ "Gas": 5400,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000181000000000000000000000000000000000000000000000000000000000000000801ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2cffffffffffffffffffffffffffffffffffffffffffffffffffffffff3b10000000006c01ffffffffffffffffffffffffffffffffffffffffffffffdffffb97ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3bffffffffffffffffffffffffffffffffffffffffffffffffffffffffebafd93b37ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5bb6affffffff3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2a",
+ "Expected": "0000000000000001",
+ "Name": "guido-4-even",
+ "Gas": 1026,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c51f81bcdfc324a0dff2b5bec9d92e21cbebc4d5e29d3a3d30de3e03fbeab8d7f2ee5f854d076701c8753d72779187e404f9b2fb705c495137d78551250314a463ef5a213fe22de1cea28d60f518364ff95fe0b73660793e3efcfbe31bda68aeccc21cc9477a6aea5df8cae73422b700c47e54d892691e099167e77befc94780a920ae4155769cd69c30626f054134b5f003772473f57f84837402df6d166e66303f01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c954b27ac388a17c8e9a7ba12a968f288f3308d6fe7bcdf28e685e9a2e00d8be1af19726b7662016d6404f9336493ad633777feb88c9d02a1d2428e566ac38f42c0bb66d2962ec349088ce0d03b35bf27f6114414ef558c87ad8e543754a352f7dffcaca429690688595ab1d1b349d9295b480a82f43ac5c9112fe40720545cc78501cd8b42f3605212fe06a835c9cbc0328e07e94aedb2ac11f6d6649e7fcd8c43",
+ "Expected": "120cf297dbe810911c7d060e109e03699ccefa00a257d296c5a14b4180776c5f7c0d7f1cd789c694807689729af267b53f00373f395dee264a3daba11fcac1fa8875aee0950acd8fa656f1fc58077a7549d794dd160506ecea1acc9c0cda13795749c94f9973b683ce2162866e8d6b5b1165a4c7fa4234964d394d6ec4e0113698b89d173e24a962dd7a41a1819b0fef188ef64e7ee264595dce0d76fbc3ba42d5de833b143c8744366effede8bc8197e8f747ff8cdbc0bf1a93560bec960ca9",
+ "Name": "marcin-1-base-heavy",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000080001020304050607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001020304050607",
+ "Expected": "0000000000000000",
+ "Name": "marcin-1-exp-heavy",
+ "Gas": 215,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000028e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c000102030405060701fffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c950001020304050607",
+ "Expected": "1abce71dc2205cce4eb6934397a88136f94641342e283cbcd30e929e85605c6718ed67f475192ffd",
+ "Name": "marcin-1-balanced",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000019800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000198e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c51f81bcdfc324a0dff2b5bec9d92e21cbebc4d5e29d3a3d30de3e03fbeab8d7f2ee5f854d076701c8753d72779187e404f9b2fb705c495137d78551250314a463ef5a213fe22de1cea28d60f518364ff95fe0b73660793e3efcfbe31bda68aeccc21cc9477a6aea5df8cae73422b700c47e54d892691e099167e77befc94780a920ae4155769cd69c30626f054134b5f003772473f57f84837402df6d166e663c29021b0e084f7dc16f6ec88cc597f1aea9f8e0b9501e0f7a546805d2a20eeda0bf080aeb3ed7ea6f9174d804bd242f0b31ff1ea24800344abb580cd87f61ca75a013a87733553966400242399dee3760877fead2cd87287747155e47a854acb50fe07922f57ae3b4553201bfd7c11aca85e1541f91db8e62dca9c418dc5feae086c9487350539c884510044efce5e3f2aaffca4215c12b9044506375097fecd9b22e2ef46f01f1af8aff742aebf96bdcaf55a341600971dc62555376b9e98a8000102030405060708090a0b0c0d0e0f101112131415161703f01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c954b27ac388a17c8e9a7ba12a968f288f3308d6fe7bcdf28e685e9a2e00d8be1af19726b7662016d6404f9336493ad633777feb88c9d02a1d2428e566ac38f42c0bb66d2962ec349088ce0d03b35bf27f6114414ef558c87ad8e543754a352f7dffcaca429690688595ab1d1b349d9295b480a82f43ac5c9112fe40720545cc78501cd8b42f3605212fe06a835c9cbc0328e07e94aedb2ac11f6d6649e7fcd8c43ddce2bd0cdc6c22c4dcd345735040d5bfe3f09b7c61362089f728e2222db96cab2f2c2ccf43574f9e119f4860fd0f1b6036a43ad9db8a428ea09a4ee385112f3fe9c6656ea2cec604cbb5a9227526653bfa7035e4ae80010b1ba16a76608d5dde0a62bc019e9047b5ec05b1005fd017366130a4ba555e7be654561ee3f539c93cb2c9988fca71bf0ad9c4a426b924641a28e1e4adb93609bfa5b2bc81714cbba1110208b86d7b87be28bdf63a62e33ae81dbcc43de9192bd192c40e85faab539000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "817d05c4d540ace3f250fd082e2deb8c2097410fcfe4ce40862cfa015b7f62a7bb72ec1af2915cad66294447b45d177fe759eb80370b0dbd3c0e1c448d54db81eadc11e40c19e394d066a5c019c443798a98d4afd116fc220593d42fbf191b6af0ae75410badb641187ba24a0b968f742a75e2822853f137151d9ea972fd1f36b7c7cc4e71355ecf50648aec094b864cfae9316c0a7be3ddb8ab2d0050b2a029ee956c2366d49430c8f889f29ab514aea8e5b8dec40ba1b49432e30aee32ec45e96dd548205a79d8f8f918eed46acb2115c59086b1011b1d2b093cea723535c3d95efc8e51a7da43b80586d69eb7f213dfb06f7a8e789a9472392bd224411b50f8ca6f2862bcd63431912d1ff99c8d76408245da9e4bea649f0eb930b32922f2d0a345a206160be44d418f1a6c74bd49c4618392ef9350b264a461dfc684c7343211e27675b027054f1cb3d4a5b1a066d3a3ea2eed9caf13251d8be936818f15274e8e3d7539b7c5f216cef327a270fd2a886fbf679c163fb5806249f2c74da5ee0e3ffe9ad1fde2634b29b35da6da6d184ab6ae70199229",
+ "Name": "marcin-2-base-heavy",
+ "Gas": 867,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000010000102030405060708090a0b0c0d0e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000102030405060708090a0b0c0d0e0f",
+ "Expected": "00000000000000000000000000000000",
+ "Name": "marcin-2-exp-heavy",
+ "Gas": 852,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c000102030405060708090a0b0c0d0e0f10111213141516172bfffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "86bef3367fc7117c8a6b825cadebe80f3e94c321dda73e9e240b98188a1d5c071c60a195097c8d1fb85ce03a2e1b6964846edee5aa2c3f46",
+ "Name": "marcin-2-balanced",
+ "Gas": 996,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244cfffffffffffffffffffffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95",
+ "Expected": "4004762c491606a5132134da6086284f74cc8e14b08f18b90fc09f31bca3d78f",
+ "Name": "marcin-3-base-heavy",
+ "Gas": 677,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000018000102030405060708090a0b0c0d0e0f1011121314151617ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "000000000000000000000000000000000000000000000000",
+ "Name": "marcin-3-exp-heavy",
+ "Gas": 765,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95",
+ "Expected": "2d3feee20d394af68dd6744b86a8aca6a4a0b7f01bbcd3c3eec768245ca6acee",
+ "Name": "marcin-3-balanced",
+ "Gas": 1360,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000000800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffff",
+ "Name": "mod-8-exp-648",
+ "Gas": 215,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffff",
+ "Name": "mod-8-exp-896",
+ "Gas": 298,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-32",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-36",
+ "Gas": 200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-40",
+ "Gas": 208,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-64",
+ "Gas": 336,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-65",
+ "Gas": 341,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-128",
+ "Gas": 677,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "02fd01000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03feffffffffff",
+ "Name": "mod-256-exp-2",
+ "Gas": 341,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffff00",
+ "Expected": "0100fefffffffffffff710f80000000006f108000000000000feffffffffffff0100fefffffffffffef90ff80000000105f008ffffffffff02fdffffffffffff0100feffffffffff00f80ff80000010101f407fffffffd06fc0000000000fd020000feffffffff00fff80ff8000101fa08f207fffffb0afa0000000001fb03000000feffffff00fffff80ff80102f80405f207fff90ef80000000002f90400000000feffff00fffffff80ff903f6050005f207f712f60000000003f7050000000000feff00fffffffff810fcf406000005f1fd16f40000000004f506000000000000fe00fffffffffff915ea0700000005e522f20000000005f306ffffffffffffffffffffffffff",
+ "Name": "mod-264-exp-2",
+ "Gas": 363,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000040000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02feffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-1024-exp-2",
+ "Gas": 5461,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000008ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "2a02d5f86c2375ff",
+ "Name": "pawel-1-exp-heavy",
+ "Gas": 298,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000010ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "823ef7dc60d6d9616756c48f69b7c4ff",
+ "Name": "pawel-2-exp-heavy",
+ "Gas": 425,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000018ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "c817dd5aa60a41948eed409706c2aa97be3000d4da0261ff",
+ "Name": "pawel-3-exp-heavy",
+ "Gas": 501,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "2defaca0137d6edacbbd5d36d6ed70cbf8a998ffb19fc270d45a18d37e0f35ff",
+ "Name": "pawel-4-exp-heavy",
+ "Gas": 506,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000017bffffffffffffffffffffffffffffffffffffffffffffbffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffe",
+ "Expected": "200f14de1d474710c1c979920452e0ffc2ac6f618afba5",
+ "Name": "mod_vul_pawel_3_exp_8",
+ "Gas": 200,
+ "NoBenchmark": false
}
]
\ No newline at end of file
diff --git a/core/vm/testdata/precompiles/modexp_eip7883.json b/core/vm/testdata/precompiles/modexp_eip7883.json
index 85e9ad1849..fb3169d148 100644
--- a/core/vm/testdata/precompiles/modexp_eip7883.json
+++ b/core/vm/testdata/precompiles/modexp_eip7883.json
@@ -103,5 +103,215 @@
"Name": "nagydani-5-pow0x10001",
"Gas": 524288,
"NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c1000000000000000000000000000000000000000000000000000000000000000cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000007d7d7d83828282348286877d7d827d407d797d7d7d7d7d7d7d7d7d7d7d5b00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000000cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4000007d7d7d83828282348286877d7d82",
+ "Expected": "36a385a417859b5e178d3ab9",
+ "Name": "marius-1-even",
+ "Gas": 45296,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d80000000000000000000000000000000000000000000000000000000000000010ffffffffffffffff76ffffffffffffff1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c76ec7c7c7c7ffffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7ffffffffffffc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c76ec7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7ffffffffff3f000000000000000000000000",
+ "Expected": "c3745de81615f80088ffffffffffffff",
+ "Name": "guido-1-even",
+ "Gas": 51136,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000d80000000000000000000000000000000000000000000000000000000000000010e0060000a921212121212121ff0000212b212121ffff1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f00feffff212121212121ffffffff1fe1e0e0e01e1f1f169f1f1f1f490afcefffffffffffffffff82828282828282828282828282828282828282828200ffff28ff2b212121ffff1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1fffffffffff0afceffffff7ffffffffff7c8282828282a1828282828282828282828282828200ffff28ff2b212121ffff1f1f1f1f1f1fd11f1f1f1f1f1f1f1f1f1f1fffffffffffffffff21212121212121fb2121212121ffff1f1f1f1f1f1f1f1fffaf82828282828200ffff28ff2b21828200",
+ "Expected": "458ef0af2549d46d24c89079499479e1",
+ "Name": "guido-2-even",
+ "Gas": 51152,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001e7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002cb0193585a48e18aad777e9c1b54221a0f58140392e4f091cd5f42b2e8644a9384fbd58ae1edec2477ebf7edbf7c0a3f8bd21d1890ee87646feab3c47be716f842cc3da9b940af312dc54450a960e3fc0b86e56abddd154068e10571a96fff6259431632bc15695c6c8679057e66c2c25c127e97e64ee5de6ea1fc0a4a0e431343fed1daafa072c238a45841da86a9806680bc9f298411173210790359209cd454b5af7b4d5688b4403924e5f863d97e2c5349e1a04b54fcf385b1e9d7714bab8fbf5835f6ff9ed575e77dff7af5cbb641db5d537933bae1fa6555d6c12d6fb31ca27b57771f4aebfbe0bf95e8990c0108ffe7cbdaf370be52cf3ade594543af75ad9329d2d11a402270b5b9a6bf4b83307506e118fca4862749d04e916fc7a039f0d13f2a02e0eedb800199ec95df15b4ccd8669b52586879624d51219e72102fad810b5909b1e372ddf33888fb9beb09b416e4164966edbabd89e4a286be36277fc576ed519a15643dac602e92b63d0b9121f0491da5b16ef793a967f096d80b6c81ecaaffad7e3f06a4a5ac2796f1ed9f68e6a0fd5cf191f0c5c2eec338952ff8d31abc68bf760febeb57e088995ba1d7726a2fdd6d8ca28a181378b8b4ab699bfd4b696739bbf17a9eb2df6251143046137fdbbfacac312ebf67a67da9741b596000000000000419a2917c61722b0713d3b00a2f0e1dd5aebbbe09615de424700eea3c3020fe6e9ea5de9fa1ace781df28b21f746d2ab61d0da496e08473c90ff7dfe25b43bcde76f4bafb82e0975bea75f5a0591dba80ba2fff80a07d8853bea5be13ab326ba70c57b153acc646151948d1cf061ca31b02d4719fac710e7c723ca44f5b1737824b7ccc74ba5bff980aabdbf267621cafc3d6dcc29d0ca9c16839a92ed34de136da7900aa3ee43d21aa57498981124357cf0ca9b86f9a8d3f9c604ca00c726e48f7a9945021ea6dfff92d6b2d6514693169ca133e993541bfa4c4c191de806aa80c48109bcfc9901eccfdeb2395ab75fe63c67de900829d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "Expected": "1194e971c875bb45f030316793bc6916343335b18670dfad7a4646fba99749b30283b78b818836de7400ff1a68ddad1a2dd850ec0f227441e2d4d13f5ee4b5d7a856db0a9ad1f86987e1f117d70f9e6a1a2b8d083fa82653aa16f1773b6deb2ed8a1f9e7f3a5db121c4a0c91cb954e2ec53e63422efe86c7984d79cd0e7b5e3eb8ca4980551d63f302c7d72500a84baf12c82fc7bd9b5c2ab8b9c33baf1df28b2031c58a8b2928a42c9f456e98874e22fe13cf17aa5915b11bb108b6ae40842d434604ccddcb4f64324c67b2dde32e6cd759d964f17d9cdf0046cd0ed3588e1fc4b88f67a5d4f3a870aad1cba89ead265d6ad327c8ea7ff54fe4b5e7dbe87c5c59c468543eab3675751111bfa1d6c51daf789d41dc21fd8ba9e05490f881a973a3c1567ff3129a49aa6658cf06f0a79530a7256ce5a07c2a77b4306383d538866bba376d90621c4f82d1f5f32304ee2b7170805d42418fc6967642e5648d8c64fe9c0fdff2d7c114a47add7767c8fccb8808de8c3c6e1a8880c05e16fafc1513fded8eba222dcaaa809bdb36999cc27ab8d0055009e9690e8a35b859df865dc510d25c7812d8eebbb35607ad595573f0fabd1b57970a2bc113ac6f0ca01e985032b9c2c139316ac099ed1632d2bc0fcc341343d303db2a9c3cf2ad572c6c43084b08d458bf822e92da16079f39cdb0dd10ef47f87ecae404117fc72660372cee9ea42266e7f8d973e7f6b09930ca5f96e04976bf23b9d356bbd2429597b04b7663e0e1a1228f4dfda3b854233e4888dc60c6886c1e0e8aec1705f681027b1e0b3017337557f107ef5cd272df5fd31dfec2bdffe163a8369895ffe124c0aa0ee00ca0fe1db4d5cf37b4af0e49bd73a89d88ced3d88f8e6f00d8e61ad09946d0e72cd3e25bc688a021a83758b5023daae7c269a6cbbd447aba5da7629b75801e1654ce85b8e21ccb9865654f8662e538625d75fea31000000000000000000000000000000000000000000000",
+ "Name": "guido-3-even",
+ "Gas": 32400,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000181000000000000000000000000000000000000000000000000000000000000000801ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2cffffffffffffffffffffffffffffffffffffffffffffffffffffffff3b10000000006c01ffffffffffffffffffffffffffffffffffffffffffffffdffffb97ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3bffffffffffffffffffffffffffffffffffffffffffffffffffffffffebafd93b37ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5bb6affffffff3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2a",
+ "Expected": "0000000000000001",
+ "Name": "guido-4-even",
+ "Gas": 94448,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c51f81bcdfc324a0dff2b5bec9d92e21cbebc4d5e29d3a3d30de3e03fbeab8d7f2ee5f854d076701c8753d72779187e404f9b2fb705c495137d78551250314a463ef5a213fe22de1cea28d60f518364ff95fe0b73660793e3efcfbe31bda68aeccc21cc9477a6aea5df8cae73422b700c47e54d892691e099167e77befc94780a920ae4155769cd69c30626f054134b5f003772473f57f84837402df6d166e66303f01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c954b27ac388a17c8e9a7ba12a968f288f3308d6fe7bcdf28e685e9a2e00d8be1af19726b7662016d6404f9336493ad633777feb88c9d02a1d2428e566ac38f42c0bb66d2962ec349088ce0d03b35bf27f6114414ef558c87ad8e543754a352f7dffcaca429690688595ab1d1b349d9295b480a82f43ac5c9112fe40720545cc78501cd8b42f3605212fe06a835c9cbc0328e07e94aedb2ac11f6d6649e7fcd8c43",
+ "Expected": "120cf297dbe810911c7d060e109e03699ccefa00a257d296c5a14b4180776c5f7c0d7f1cd789c694807689729af267b53f00373f395dee264a3daba11fcac1fa8875aee0950acd8fa656f1fc58077a7549d794dd160506ecea1acc9c0cda13795749c94f9973b683ce2162866e8d6b5b1165a4c7fa4234964d394d6ec4e0113698b89d173e24a962dd7a41a1819b0fef188ef64e7ee264595dce0d76fbc3ba42d5de833b143c8744366effede8bc8197e8f747ff8cdbc0bf1a93560bec960ca9",
+ "Name": "marcin-1-base-heavy",
+ "Gas": 1152,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000080001020304050607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001020304050607",
+ "Expected": "0000000000000000",
+ "Name": "marcin-1-exp-heavy",
+ "Gas": 16624,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000028e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c000102030405060701fffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c950001020304050607",
+ "Expected": "1abce71dc2205cce4eb6934397a88136f94641342e283cbcd30e929e85605c6718ed67f475192ffd",
+ "Name": "marcin-1-balanced",
+ "Gas": 1200,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000019800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000198e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c51f81bcdfc324a0dff2b5bec9d92e21cbebc4d5e29d3a3d30de3e03fbeab8d7f2ee5f854d076701c8753d72779187e404f9b2fb705c495137d78551250314a463ef5a213fe22de1cea28d60f518364ff95fe0b73660793e3efcfbe31bda68aeccc21cc9477a6aea5df8cae73422b700c47e54d892691e099167e77befc94780a920ae4155769cd69c30626f054134b5f003772473f57f84837402df6d166e663c29021b0e084f7dc16f6ec88cc597f1aea9f8e0b9501e0f7a546805d2a20eeda0bf080aeb3ed7ea6f9174d804bd242f0b31ff1ea24800344abb580cd87f61ca75a013a87733553966400242399dee3760877fead2cd87287747155e47a854acb50fe07922f57ae3b4553201bfd7c11aca85e1541f91db8e62dca9c418dc5feae086c9487350539c884510044efce5e3f2aaffca4215c12b9044506375097fecd9b22e2ef46f01f1af8aff742aebf96bdcaf55a341600971dc62555376b9e98a8000102030405060708090a0b0c0d0e0f101112131415161703f01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c954b27ac388a17c8e9a7ba12a968f288f3308d6fe7bcdf28e685e9a2e00d8be1af19726b7662016d6404f9336493ad633777feb88c9d02a1d2428e566ac38f42c0bb66d2962ec349088ce0d03b35bf27f6114414ef558c87ad8e543754a352f7dffcaca429690688595ab1d1b349d9295b480a82f43ac5c9112fe40720545cc78501cd8b42f3605212fe06a835c9cbc0328e07e94aedb2ac11f6d6649e7fcd8c43ddce2bd0cdc6c22c4dcd345735040d5bfe3f09b7c61362089f728e2222db96cab2f2c2ccf43574f9e119f4860fd0f1b6036a43ad9db8a428ea09a4ee385112f3fe9c6656ea2cec604cbb5a9227526653bfa7035e4ae80010b1ba16a76608d5dde0a62bc019e9047b5ec05b1005fd017366130a4ba555e7be654561ee3f539c93cb2c9988fca71bf0ad9c4a426b924641a28e1e4adb93609bfa5b2bc81714cbba1110208b86d7b87be28bdf63a62e33ae81dbcc43de9192bd192c40e85faab539000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "817d05c4d540ace3f250fd082e2deb8c2097410fcfe4ce40862cfa015b7f62a7bb72ec1af2915cad66294447b45d177fe759eb80370b0dbd3c0e1c448d54db81eadc11e40c19e394d066a5c019c443798a98d4afd116fc220593d42fbf191b6af0ae75410badb641187ba24a0b968f742a75e2822853f137151d9ea972fd1f36b7c7cc4e71355ecf50648aec094b864cfae9316c0a7be3ddb8ab2d0050b2a029ee956c2366d49430c8f889f29ab514aea8e5b8dec40ba1b49432e30aee32ec45e96dd548205a79d8f8f918eed46acb2115c59086b1011b1d2b093cea723535c3d95efc8e51a7da43b80586d69eb7f213dfb06f7a8e789a9472392bd224411b50f8ca6f2862bcd63431912d1ff99c8d76408245da9e4bea649f0eb930b32922f2d0a345a206160be44d418f1a6c74bd49c4618392ef9350b264a461dfc684c7343211e27675b027054f1cb3d4a5b1a066d3a3ea2eed9caf13251d8be936818f15274e8e3d7539b7c5f216cef327a270fd2a886fbf679c163fb5806249f2c74da5ee0e3ffe9ad1fde2634b29b35da6da6d184ab6ae70199229",
+ "Name": "marcin-2-base-heavy",
+ "Gas": 5202,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000010000102030405060708090a0b0c0d0e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000102030405060708090a0b0c0d0e0f",
+ "Expected": "00000000000000000000000000000000",
+ "Name": "marcin-2-exp-heavy",
+ "Gas": 16368,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000038e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c000102030405060708090a0b0c0d0e0f10111213141516172bfffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "86bef3367fc7117c8a6b825cadebe80f3e94c321dda73e9e240b98188a1d5c071c60a195097c8d1fb85ce03a2e1b6964846edee5aa2c3f46",
+ "Name": "marcin-2-balanced",
+ "Gas": 5978,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244cfffffffffffffffffffffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95",
+ "Expected": "4004762c491606a5132134da6086284f74cc8e14b08f18b90fc09f31bca3d78f",
+ "Name": "marcin-3-base-heavy",
+ "Gas": 2032,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000018000102030405060708090a0b0c0d0e0f1011121314151617ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000102030405060708090a0b0c0d0e0f1011121314151617",
+ "Expected": "000000000000000000000000000000000000000000000000",
+ "Name": "marcin-3-exp-heavy",
+ "Gas": 4080,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020e8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01681d2220bfea4bb888a5543db8c0916274ddb1ea93b144c042c01d8164c95",
+ "Expected": "2d3feee20d394af68dd6744b86a8aca6a4a0b7f01bbcd3c3eec768245ca6acee",
+ "Name": "marcin-3-balanced",
+ "Gas": 4080,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000000000000000000000800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffff",
+ "Name": "mod-8-exp-648",
+ "Gas": 16624,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000000800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffff",
+ "Name": "mod-8-exp-896",
+ "Gas": 24560,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-32",
+ "Gas": 500,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-36",
+ "Gas": 560,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-40",
+ "Gas": 624,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-64",
+ "Gas": 1008,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-65",
+ "Gas": 1024,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-32-exp-128",
+ "Gas": 2032,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "02fd01000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03ff0000000000000000000000000000000000000000000000fefffffffffffd03feffffffffff",
+ "Name": "mod-256-exp-2",
+ "Gas": 2048,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010800ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffff00",
+ "Expected": "0100fefffffffffffff710f80000000006f108000000000000feffffffffffff0100fefffffffffffef90ff80000000105f008ffffffffff02fdffffffffffff0100feffffffffff00f80ff80000010101f407fffffffd06fc0000000000fd020000feffffffff00fff80ff8000101fa08f207fffffb0afa0000000001fb03000000feffffff00fffff80ff80102f80405f207fff90ef80000000002f90400000000feffff00fffffff80ff903f6050005f207f712f60000000003f7050000000000feff00fffffffff810fcf406000005f1fd16f40000000004f506000000000000fe00fffffffffff915ea0700000005e522f20000000005f306ffffffffffffffffffffffffff",
+ "Name": "mod-264-exp-2",
+ "Gas": 2178,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "00000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000040000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00",
+ "Expected": "00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02fefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02feffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Name": "mod-1024-exp-2",
+ "Gas": 32768,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000008ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "2a02d5f86c2375ff",
+ "Name": "pawel-1-exp-heavy",
+ "Gas": 24560,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000010ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "823ef7dc60d6d9616756c48f69b7c4ff",
+ "Name": "pawel-2-exp-heavy",
+ "Gas": 6128,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000018ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "c817dd5aa60a41948eed409706c2aa97be3000d4da0261ff",
+ "Name": "pawel-3-exp-heavy",
+ "Gas": 2672,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "Expected": "2defaca0137d6edacbbd5d36d6ed70cbf8a998ffb19fc270d45a18d37e0f35ff",
+ "Name": "pawel-4-exp-heavy",
+ "Gas": 1520,
+ "NoBenchmark": false
+ },
+ {
+ "Input": "000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000017bffffffffffffffffffffffffffffffffffffffffffffbffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffe",
+ "Expected": "200f14de1d474710c1c979920452e0ffc2ac6f618afba5",
+ "Name": "mod_vul_pawel_3_exp_8",
+ "Gas": 1008,
+ "NoBenchmark": false
}
]
diff --git a/crypto/blake2b/blake2b.go b/crypto/blake2b/blake2b.go
index c24a88b99d..e00ee2e6d2 100644
--- a/crypto/blake2b/blake2b.go
+++ b/crypto/blake2b/blake2b.go
@@ -302,7 +302,7 @@ func appendUint64(b []byte, x uint64) []byte {
return append(b, a[:]...)
}
-//nolint:unused,deadcode
+//nolint:unused
func appendUint32(b []byte, x uint32) []byte {
var a [4]byte
binary.BigEndian.PutUint32(a[:], x)
@@ -314,7 +314,7 @@ func consumeUint64(b []byte) ([]byte, uint64) {
return b[8:], x
}
-//nolint:unused,deadcode
+//nolint:unused
func consumeUint32(b []byte) ([]byte, uint32) {
x := binary.BigEndian.Uint32(b)
return b[4:], x
diff --git a/crypto/blake2b/blake2b_generic.go b/crypto/blake2b/blake2b_generic.go
index 61e678fdf5..4d3f69d292 100644
--- a/crypto/blake2b/blake2b_generic.go
+++ b/crypto/blake2b/blake2b_generic.go
@@ -25,7 +25,7 @@ var precomputed = [10][16]byte{
{10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
}
-// nolint:unused,deadcode
+// nolint:unused
func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
var m [16]uint64
c0, c1 := c[0], c[1]
diff --git a/crypto/blake2b/blake2b_test.go b/crypto/blake2b/blake2b_test.go
index 9d24444a27..8f210445fc 100644
--- a/crypto/blake2b/blake2b_test.go
+++ b/crypto/blake2b/blake2b_test.go
@@ -303,8 +303,7 @@ func benchmarkSum(b *testing.B, size int, sse4, avx, avx2 bool) {
data := make([]byte, size)
b.SetBytes(int64(size))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Sum512(data)
}
}
@@ -319,8 +318,7 @@ func benchmarkWrite(b *testing.B, size int, sse4, avx, avx2 bool) {
data := make([]byte, size)
h, _ := New512(nil)
b.SetBytes(int64(size))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
h.Write(data)
}
}
diff --git a/crypto/bn256/bn256_fast.go b/crypto/bn256/bn256_fast.go
index e3c9b60518..93a2eef879 100644
--- a/crypto/bn256/bn256_fast.go
+++ b/crypto/bn256/bn256_fast.go
@@ -9,18 +9,18 @@
package bn256
import (
- bn256cf "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
+ gnark "github.com/ethereum/go-ethereum/crypto/bn256/gnark"
)
// G1 is an abstract cyclic group. The zero value is suitable for use as the
// output of an operation, but cannot be used as an input.
-type G1 = bn256cf.G1
+type G1 = gnark.G1
// G2 is an abstract cyclic group. The zero value is suitable for use as the
// output of an operation, but cannot be used as an input.
-type G2 = bn256cf.G2
+type G2 = gnark.G2
// PairingCheck calculates the Optimal Ate pairing for a set of points.
func PairingCheck(a []*G1, b []*G2) bool {
- return bn256cf.PairingCheck(a, b)
+ return gnark.PairingCheck(a, b)
}
diff --git a/crypto/bn256/cloudflare/gfp_decl.go b/crypto/bn256/cloudflare/gfp_decl.go
index 1954d14a4a..b7dd1a8aac 100644
--- a/crypto/bn256/cloudflare/gfp_decl.go
+++ b/crypto/bn256/cloudflare/gfp_decl.go
@@ -10,7 +10,7 @@ import (
"golang.org/x/sys/cpu"
)
-//nolint:varcheck,unused,deadcode
+//nolint:unused
var hasBMI2 = cpu.X86.HasBMI2
//go:noescape
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index e620d6ee3a..d803ab27c5 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -60,7 +60,7 @@ func TestToECDSAErrors(t *testing.T) {
func BenchmarkSha3(b *testing.B) {
a := []byte("hello world")
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Keccak256(a)
}
}
@@ -310,7 +310,7 @@ func BenchmarkKeccak256Hash(b *testing.B) {
rand.Read(input[:])
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Keccak256Hash(input[:])
}
}
@@ -329,7 +329,7 @@ func BenchmarkHashData(b *testing.B) {
rand.Read(input[:])
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
HashData(buffer, input[:])
}
}
diff --git a/crypto/ecies/ecies_test.go b/crypto/ecies/ecies_test.go
index e3da71010e..e822db2783 100644
--- a/crypto/ecies/ecies_test.go
+++ b/crypto/ecies/ecies_test.go
@@ -164,7 +164,7 @@ func TestTooBigSharedKey(t *testing.T) {
// Benchmark the generation of P256 keys.
func BenchmarkGenerateKeyP256(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil {
b.Fatal(err)
}
@@ -177,8 +177,7 @@ func BenchmarkGenSharedKeyP256(b *testing.B) {
if err != nil {
b.Fatal(err)
}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
_, err := prv.GenerateShared(&prv.PublicKey, 16, 16)
if err != nil {
b.Fatal(err)
@@ -192,8 +191,7 @@ func BenchmarkGenSharedKeyS256(b *testing.B) {
if err != nil {
b.Fatal(err)
}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
_, err := prv.GenerateShared(&prv.PublicKey, 16, 16)
if err != nil {
b.Fatal(err)
diff --git a/crypto/kzg4844/kzg4844_test.go b/crypto/kzg4844/kzg4844_test.go
index 7e73efd850..743a277199 100644
--- a/crypto/kzg4844/kzg4844_test.go
+++ b/crypto/kzg4844/kzg4844_test.go
@@ -105,8 +105,7 @@ func benchmarkBlobToCommitment(b *testing.B, ckzg bool) {
blob := randBlob()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
BlobToCommitment(blob)
}
}
@@ -125,8 +124,7 @@ func benchmarkComputeProof(b *testing.B, ckzg bool) {
point = randFieldElement()
)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
ComputeProof(blob, point)
}
}
@@ -147,8 +145,7 @@ func benchmarkVerifyProof(b *testing.B, ckzg bool) {
proof, claim, _ = ComputeProof(blob, point)
)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
VerifyProof(commitment, point, claim, proof)
}
}
@@ -167,8 +164,7 @@ func benchmarkComputeBlobProof(b *testing.B, ckzg bool) {
commitment, _ = BlobToCommitment(blob)
)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
ComputeBlobProof(blob, commitment)
}
}
@@ -188,8 +184,7 @@ func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) {
proof, _ = ComputeBlobProof(blob, commitment)
)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
VerifyBlobProof(blob, commitment, proof)
}
}
@@ -230,3 +225,31 @@ func testKZGCells(t *testing.T, ckzg bool) {
t.Fatalf("failed to verify KZG proof at point: %v", err)
}
}
+
+// goos: darwin
+// goarch: arm64
+// pkg: github.com/ethereum/go-ethereum/crypto/kzg4844
+// cpu: Apple M1 Pro
+// BenchmarkGOKZGComputeCellProofs
+// BenchmarkGOKZGComputeCellProofs-8 8 139012286 ns/op
+func BenchmarkGOKZGComputeCellProofs(b *testing.B) { benchmarkComputeCellProofs(b, false) }
+func BenchmarkCKZGComputeCellProofs(b *testing.B) { benchmarkComputeCellProofs(b, true) }
+
+func benchmarkComputeCellProofs(b *testing.B, ckzg bool) {
+ if ckzg && !ckzgAvailable {
+ b.Skip("CKZG unavailable in this test build")
+ }
+ defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load())
+ useCKZG.Store(ckzg)
+
+ blob := randBlob()
+ _, _ = ComputeCellProofs(blob) // for kzg initialization
+ b.ResetTimer()
+
+ for b.Loop() {
+ _, err := ComputeCellProofs(blob)
+ if err != nil {
+ b.Fatalf("failed to create KZG proof at point: %v", err)
+ }
+ }
+}
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
index 4827cc5b25..c7485bca08 100644
--- a/crypto/secp256k1/secp256_test.go
+++ b/crypto/secp256k1/secp256_test.go
@@ -221,9 +221,7 @@ func TestRecoverSanity(t *testing.T) {
func BenchmarkSign(b *testing.B) {
_, seckey := generateKeyPair()
msg := csprngEntropy(32)
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
Sign(msg, seckey)
}
}
@@ -232,9 +230,7 @@ func BenchmarkRecover(b *testing.B) {
msg := csprngEntropy(32)
_, seckey := generateKeyPair()
sig, _ := Sign(msg, seckey)
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
RecoverPubkey(msg, sig)
}
}
diff --git a/crypto/signature_test.go b/crypto/signature_test.go
index 74d683b507..b1f2960254 100644
--- a/crypto/signature_test.go
+++ b/crypto/signature_test.go
@@ -135,7 +135,7 @@ func TestPubkeyRandom(t *testing.T) {
}
func BenchmarkEcrecoverSignature(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
if _, err := Ecrecover(testmsg, testsig); err != nil {
b.Fatal("ecrecover error", err)
}
@@ -144,7 +144,7 @@ func BenchmarkEcrecoverSignature(b *testing.B) {
func BenchmarkVerifySignature(b *testing.B) {
sig := testsig[:len(testsig)-1] // remove recovery id
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
if !VerifySignature(testpubkey, testmsg, sig) {
b.Fatal("verify error")
}
@@ -152,7 +152,7 @@ func BenchmarkVerifySignature(b *testing.B) {
}
func BenchmarkDecompressPubkey(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
if _, err := DecompressPubkey(testpubkeyc); err != nil {
b.Fatal(err)
}
diff --git a/eth/api_backend_test.go b/eth/api_backend_test.go
index b425ec7233..9446aae863 100644
--- a/eth/api_backend_test.go
+++ b/eth/api_backend_test.go
@@ -20,6 +20,7 @@ import (
"context"
"crypto/ecdsa"
"errors"
+ "math"
"math/big"
"testing"
"time"
@@ -130,6 +131,27 @@ func TestSendTx(t *testing.T) {
testSendTx(t, true)
}
+func TestSendTxEIP2681(t *testing.T) {
+ b := initBackend(false)
+
+ // Test EIP-2681: nonce overflow should be rejected
+ tx := makeTx(uint64(math.MaxUint64), nil, nil, key) // max uint64 nonce
+ err := b.SendTx(context.Background(), tx)
+ if err == nil {
+ t.Fatal("Expected EIP-2681 nonce overflow error, but transaction was accepted")
+ }
+ if !errors.Is(err, core.ErrNonceMax) {
+ t.Errorf("Expected core.ErrNonceMax, got: %v", err)
+ }
+
+ // Test normal case: should succeed
+ normalTx := makeTx(0, nil, nil, key)
+ err = b.SendTx(context.Background(), normalTx)
+ if err != nil {
+ t.Errorf("Normal transaction should succeed, got error: %v", err)
+ }
+}
+
func testSendTx(t *testing.T, withLocal bool) {
b := initBackend(withLocal)
diff --git a/eth/api_debug.go b/eth/api_debug.go
index 3ca4c775da..6680d692ca 100644
--- a/eth/api_debug.go
+++ b/eth/api_debug.go
@@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless"
@@ -449,45 +448,90 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
return api.eth.blockchain.GetTrieFlushInterval().String(), nil
}
-func (api *DebugAPI) ExecutionWitness(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*stateless.ExecutionWitness, error) {
- block, err := api.eth.APIBackend.BlockByNumberOrHash(ctx, blockNrOrHash)
- if err != nil {
- return nil, fmt.Errorf("failed to retrieve block: %w", err)
+// StateSize returns the current state size statistics from the state size tracker.
+// Returns an error if the state size tracker is not initialized or if stats are not ready.
+func (api *DebugAPI) StateSize(blockHashOrNumber *rpc.BlockNumberOrHash) (interface{}, error) {
+ sizer := api.eth.blockchain.StateSizer()
+ if sizer == nil {
+ return nil, errors.New("state size tracker is not enabled")
}
- if block == nil {
- return nil, fmt.Errorf("block not found: %s", blockNrOrHash.String())
+ var (
+ err error
+ stats *state.SizeStats
+ )
+ if blockHashOrNumber == nil {
+ stats, err = sizer.Query(nil)
+ } else {
+ header, herr := api.eth.APIBackend.HeaderByNumberOrHash(context.Background(), *blockHashOrNumber)
+ if herr != nil || header == nil {
+ return nil, fmt.Errorf("block %s is unknown", blockHashOrNumber)
+ }
+ stats, err = sizer.Query(&header.Root)
}
-
- witness, err := generateWitness(api.eth.blockchain, block)
- return witness.ToExecutionWitness(), err
+ if err != nil {
+ return nil, err
+ }
+ if stats == nil {
+ var s string
+ if blockHashOrNumber == nil {
+ s = "chain head"
+ } else {
+ s = blockHashOrNumber.String()
+ }
+ return nil, fmt.Errorf("state size of %s is not available", s)
+ }
+ return map[string]interface{}{
+ "stateRoot": stats.StateRoot,
+ "blockNumber": hexutil.Uint64(stats.BlockNumber),
+ "accounts": hexutil.Uint64(stats.Accounts),
+ "accountBytes": hexutil.Uint64(stats.AccountBytes),
+ "storages": hexutil.Uint64(stats.Storages),
+ "storageBytes": hexutil.Uint64(stats.StorageBytes),
+ "accountTrienodes": hexutil.Uint64(stats.AccountTrienodes),
+ "accountTrienodeBytes": hexutil.Uint64(stats.AccountTrienodeBytes),
+ "storageTrienodes": hexutil.Uint64(stats.StorageTrienodes),
+ "storageTrienodeBytes": hexutil.Uint64(stats.StorageTrienodeBytes),
+ "contractCodes": hexutil.Uint64(stats.ContractCodes),
+ "contractCodeBytes": hexutil.Uint64(stats.ContractCodeBytes),
+ }, nil
}
-func generateWitness(blockchain *core.BlockChain, block *types.Block) (*stateless.Witness, error) {
- witness, err := stateless.NewWitness(block.Header(), blockchain)
+func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumber) (*stateless.ExtWitness, error) {
+ bc := api.eth.blockchain
+ block, err := api.eth.APIBackend.BlockByNumber(context.Background(), bn)
if err != nil {
- return nil, fmt.Errorf("failed to create witness: %w", err)
+ return &stateless.ExtWitness{}, fmt.Errorf("block number %v not found", bn)
+ }
+
+ parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
+ if parent == nil {
+ return &stateless.ExtWitness{}, fmt.Errorf("block number %v found, but parent missing", bn)
}
- parentHeader := witness.Headers[0]
- statedb, err := blockchain.StateAt(parentHeader.Root)
+ result, err := bc.ProcessBlock(parent.Root, block, false, true)
if err != nil {
- return nil, fmt.Errorf("failed to retrieve parent state: %w", err)
+ return nil, err
}
- statedb.StartPrefetcher("debug_execution_witness", witness, nil)
- defer statedb.StopPrefetcher()
+ return result.Witness().ToExtWitness(), nil
+}
- res, err := blockchain.Processor().Process(block, statedb, *blockchain.GetVMConfig())
- if err != nil {
- return nil, fmt.Errorf("failed to process block %d: %w", block.Number(), err)
+func (api *DebugAPI) ExecutionWitnessByHash(hash common.Hash) (*stateless.ExtWitness, error) {
+ bc := api.eth.blockchain
+ block := bc.GetBlockByHash(hash)
+ if block == nil {
+ return &stateless.ExtWitness{}, fmt.Errorf("block hash %x not found", hash)
+ }
+
+ parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
+ if parent == nil {
+ return &stateless.ExtWitness{}, fmt.Errorf("block number %x found, but parent missing", hash)
}
- // OP-Stack warning: below has the side-effect of including the withdrawals storage-root
- // into the execution witness through the storage lookup by ValidateState, triggering the pre-fetcher.
- // The Process function only runs through Finalize steps, not through FinalizeAndAssemble, missing merkleization.
- if err := blockchain.Validator().ValidateState(block, statedb, res, false); err != nil {
- return nil, fmt.Errorf("failed to validate block %d: %w", block.Number(), err)
+ result, err := bc.ProcessBlock(parent.Root, block, false, true)
+ if err != nil {
+ return nil, err
}
- return witness, nil
+ return result.Witness().ToExtWitness(), nil
}
diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go
index fe1fcef68c..034026b366 100644
--- a/eth/api_debug_test.go
+++ b/eth/api_debug_test.go
@@ -40,7 +40,6 @@ import (
"github.com/ethereum/go-ethereum/triedb"
"github.com/holiman/uint256"
"github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
)
var dumper = spew.ConfigState{Indent: " "}
@@ -336,30 +335,3 @@ func TestGetModifiedAccounts(t *testing.T) {
}
})
}
-
-func TestExecutionWitness(t *testing.T) {
- t.Parallel()
-
- // Create a database pre-initialize with a genesis block
- db := rawdb.NewMemoryDatabase()
- gspec := &core.Genesis{
- Config: params.TestChainConfig,
- Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
- }
- chain, _ := core.NewBlockChain(db, gspec, ethash.NewFaker(), nil)
-
- blockNum := 10
- _, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blockNum, nil)
- if _, err := chain.InsertChain(bs); err != nil {
- panic(err)
- }
-
- block := chain.GetBlockByNumber(uint64(blockNum - 1))
- require.NotNil(t, block)
-
- witness, err := generateWitness(chain, block)
- require.NoError(t, err)
-
- _, _, err = core.ExecuteStateless(params.TestChainConfig, *chain.GetVMConfig(), block, witness)
- require.NoError(t, err)
-}
diff --git a/eth/backend.go b/eth/backend.go
index c8f7578311..9c4cac1ee7 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -252,12 +252,15 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)),
VmConfig: vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
+ EnableWitnessStats: config.EnableWitnessStats,
+ StatelessSelfValidation: config.StatelessSelfValidation,
},
// Enables file journaling for the trie database. The journal files will be stored
// within the data directory. The corresponding paths will be either:
// - DATADIR/triedb/merkle.journal
// - DATADIR/triedb/verkle.journal
TrieJournalDirectory: stack.ResolvePath("triedb"),
+ StateSizeTracking: config.EnableStateSizeTracking,
}
)
if config.VMTrace != "" {
@@ -276,6 +279,12 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.OverrideOsaka != nil {
overrides.OverrideOsaka = config.OverrideOsaka
}
+ if config.OverrideBPO1 != nil {
+ overrides.OverrideBPO1 = config.OverrideBPO1
+ }
+ if config.OverrideBPO2 != nil {
+ overrides.OverrideBPO2 = config.OverrideBPO2
+ }
if config.OverrideVerkle != nil {
overrides.OverrideVerkle = config.OverrideVerkle
}
diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go
index 2a9f3a68f9..a263f41f0b 100644
--- a/eth/catalyst/api.go
+++ b/eth/catalyst/api.go
@@ -214,8 +214,8 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
return engine.STATUS_INVALID, attributesErr("missing withdrawals")
case params.BeaconRoot == nil:
return engine.STATUS_INVALID, attributesErr("missing beacon root")
- case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka):
- return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads")
+ case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+ return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun/prague/osaka payloads")
}
}
// TODO(matt): the spec requires that fcu is applied when called on a valid
@@ -446,13 +446,21 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
// GetPayloadV2 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ // executionPayload: ExecutionPayloadV1 | ExecutionPayloadV2 where:
+ //
+ // - ExecutionPayloadV1 MUST be returned if the payload timestamp is lower
+ // than the Shanghai timestamp
+ //
+ // - ExecutionPayloadV2 MUST be returned if the payload timestamp is greater
+ // or equal to the Shanghai timestamp
if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) {
return nil, engine.UnsupportedFork
}
return api.getPayload(payloadID, false)
}
-// GetPayloadV3 returns a cached payload by id.
+// GetPayloadV3 returns a cached payload by id. This endpoint should only
+// be used for the Cancun fork.
func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
if !payloadID.Is(engine.PayloadV3) {
return nil, engine.UnsupportedFork
@@ -460,7 +468,8 @@ func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.Execu
return api.getPayload(payloadID, false)
}
-// GetPayloadV4 returns a cached payload by id.
+// GetPayloadV4 returns a cached payload by id. This endpoint should only
+// be used for the Prague fork.
func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
if !payloadID.Is(engine.PayloadV3) {
return nil, engine.UnsupportedFork
@@ -468,7 +477,11 @@ func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.Execu
return api.getPayload(payloadID, false)
}
-// GetPayloadV5 returns a cached payload by id.
+// GetPayloadV5 returns a cached payload by id. This endpoint should only
+// be used after the Osaka fork.
+//
+// This method follows the same specification as engine_getPayloadV4 with
+// changes of returning BlobsBundleV2 with BlobSidecar version 1.
func (api *ConsensusAPI) GetPayloadV5(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
if !payloadID.Is(engine.PayloadV3) {
return nil, engine.UnsupportedFork
@@ -486,16 +499,40 @@ func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*eng
}
// GetBlobsV1 returns a blob from the transaction pool.
+//
+// Specification:
+//
+// Given an array of blob versioned hashes client software MUST respond with an
+// array of BlobAndProofV1 objects with matching versioned hashes, respecting the
+// order of versioned hashes in the input array.
+//
+// Client software MUST place responses in the order given in the request, using
+// null for any missing blobs. For instance:
+//
+// if the request is [A_versioned_hash, B_versioned_hash, C_versioned_hash] and
+// client software has data for blobs A and C, but doesn't have data for B, the
+// response MUST be [A, null, C].
+//
+// Client software MUST support request sizes of at least 128 blob versioned hashes.
+// The client MUST return -38004: Too large request error if the number of requested
+// blobs is too large.
+//
+// Client software MAY return an array of all null entries if syncing or otherwise
+// unable to serve blob pool data.
func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProofV1, error) {
if len(hashes) > 128 {
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes)))
}
- blobs, _, proofs, err := api.eth.BlobTxPool().GetBlobs(hashes, types.BlobSidecarVersion0)
+ blobs, _, proofs, err := api.eth.BlobTxPool().GetBlobs(hashes, types.BlobSidecarVersion0, false)
if err != nil {
return nil, engine.InvalidParams.With(err)
}
res := make([]*engine.BlobAndProofV1, len(hashes))
for i := 0; i < len(blobs); i++ {
+ // Skip the non-existing blob
+ if blobs[i] == nil {
+ continue
+ }
res[i] = &engine.BlobAndProofV1{
Blob: blobs[i][:],
Proof: proofs[i][0][:],
@@ -505,6 +542,33 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo
}
// GetBlobsV2 returns a blob from the transaction pool.
+//
+// Specification:
+// Refer to the specification for engine_getBlobsV1 with changes of the following:
+//
+// Given an array of blob versioned hashes client software MUST respond with an
+// array of BlobAndProofV2 objects with matching versioned hashes, respecting
+// the order of versioned hashes in the input array.
+//
+// Client software MUST return null in case of any missing or older version blobs.
+// For instance,
+//
+// - if the request is [A_versioned_hash, B_versioned_hash, C_versioned_hash] and
+// client software has data for blobs A and C, but doesn't have data for B, the
+// response MUST be null.
+//
+// - if the request is [A_versioned_hash_for_blob_with_blob_proof], the response
+// MUST be null as well.
+//
+// Note, geth internally make the conversion from old version to new one, so the
+// data will be returned normally.
+//
+// Client software MUST support request sizes of at least 128 blob versioned
+// hashes. The client MUST return -38004: Too large request error if the number
+// of requested blobs is too large.
+//
+// Client software MUST return null if syncing or otherwise unable to serve
+// blob pool data.
func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProofV2, error) {
if len(hashes) > 128 {
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes)))
@@ -518,12 +582,21 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo
getBlobsV2RequestMiss.Inc(1)
return nil, nil
}
- getBlobsV2RequestHit.Inc(1)
- blobs, _, proofs, err := api.eth.BlobTxPool().GetBlobs(hashes, types.BlobSidecarVersion1)
+ blobs, _, proofs, err := api.eth.BlobTxPool().GetBlobs(hashes, types.BlobSidecarVersion1, false)
if err != nil {
return nil, engine.InvalidParams.With(err)
}
+
+ // To comply with API spec, check again that we really got all data needed
+ for _, blob := range blobs {
+ if blob == nil {
+ getBlobsV2RequestMiss.Inc(1)
+ return nil, nil
+ }
+ }
+ getBlobsV2RequestHit.Inc(1)
+
res := make([]*engine.BlobAndProofV2, len(hashes))
for i := 0; i < len(blobs); i++ {
var cellProofs []hexutil.Bytes
@@ -600,30 +673,24 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
// NewPayloadV4 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, executionRequests []hexutil.Bytes) (engine.PayloadStatusV1, error) {
- if params.Withdrawals == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
- }
- if params.ExcessBlobGas == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
- }
- if params.BlobGasUsed == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
+ switch {
+ case params.Withdrawals == nil:
+ return invalidStatus, paramsErr("nil withdrawals post-shanghai")
+ case params.ExcessBlobGas == nil:
+ return invalidStatus, paramsErr("nil excessBlobGas post-cancun")
+ case params.BlobGasUsed == nil:
+ return invalidStatus, paramsErr("nil blobGasUsed post-cancun")
+ case versionedHashes == nil:
+ return invalidStatus, paramsErr("nil versionedHashes post-cancun")
+ case beaconRoot == nil:
+ return invalidStatus, paramsErr("nil beaconRoot post-cancun")
+ case executionRequests == nil:
+ return invalidStatus, paramsErr("nil executionRequests post-prague")
+ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka):
+ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
+ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads")
}
-
- if versionedHashes == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
- }
- if beaconRoot == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
- }
- if executionRequests == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague"))
- }
-
- if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads"))
- }
-
requests := convertRequests(executionRequests)
if err := validateRequests(requests); err != nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(err)
diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go
index 5bb10436ee..d538a57c1c 100644
--- a/eth/catalyst/api_test.go
+++ b/eth/catalyst/api_test.go
@@ -19,7 +19,9 @@ package catalyst
import (
"bytes"
"context"
+ "crypto/ecdsa"
crand "crypto/rand"
+ "crypto/sha256"
"errors"
"fmt"
"math/big"
@@ -42,6 +44,7 @@ import (
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
@@ -49,6 +52,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
var (
@@ -114,7 +118,7 @@ func TestEth2AssembleBlock(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks)
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
signer := types.NewEIP155Signer(ethservice.BlockChain().Config().ChainID)
tx, err := types.SignTx(types.NewTransaction(uint64(10), blocks[9].Coinbase(), big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey)
if err != nil {
@@ -153,7 +157,7 @@ func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks[:9])
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// Put the 10th block's tx in the pool and produce a new block
txs := blocks[9].Transactions()
@@ -175,7 +179,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks[:9])
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// Put the 10th block's tx in the pool and produce a new block
txs := blocks[9].Transactions()
@@ -241,8 +245,9 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close()
+
var (
- api = NewConsensusAPI(ethservice)
+ api = newConsensusAPIWithoutHeartbeat(ethservice)
parent = ethservice.BlockChain().CurrentBlock()
)
tests := []struct {
@@ -284,7 +289,7 @@ func TestEth2NewBlock(t *testing.T) {
defer n.Close()
var (
- api = NewConsensusAPI(ethservice)
+ api = newConsensusAPIWithoutHeartbeat(ethservice)
parent = preMergeBlocks[len(preMergeBlocks)-1]
// This EVM code generates a log when the contract is created.
@@ -467,6 +472,7 @@ func TestFullAPI(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close()
+
var (
parent = ethservice.BlockChain().CurrentBlock()
// This EVM code generates a log when the contract is created.
@@ -484,7 +490,7 @@ func TestFullAPI(t *testing.T) {
}
func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal, beaconRoots []common.Hash) []*types.Header {
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
var blocks []*types.Header
for i := 0; i < n; i++ {
callback(parent)
@@ -532,7 +538,7 @@ func TestExchangeTransitionConfig(t *testing.T) {
defer n.Close()
// invalid ttd
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
config := engine.TransitionConfigurationV1{
TerminalTotalDifficulty: (*hexutil.Big)(big.NewInt(0)),
TerminalBlockHash: common.Hash{},
@@ -593,7 +599,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
defer n.Close()
var (
- api = NewConsensusAPI(ethservice)
+ api = newConsensusAPIWithoutHeartbeat(ethservice)
parent = ethservice.BlockChain().CurrentBlock()
signer = types.LatestSigner(ethservice.BlockChain().Config())
// This EVM code generates a log when the contract is created.
@@ -698,7 +704,7 @@ func TestEmptyBlocks(t *testing.T) {
defer n.Close()
commonAncestor := ethservice.BlockChain().CurrentBlock()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// Setup 10 blocks on the canonical chain
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil, nil)
@@ -824,8 +830,8 @@ func TestTrickRemoteBlockCache(t *testing.T) {
}
nodeA.Server().AddPeer(nodeB.Server().Self())
nodeB.Server().AddPeer(nodeA.Server().Self())
- apiA := NewConsensusAPI(ethserviceA)
- apiB := NewConsensusAPI(ethserviceB)
+ apiA := newConsensusAPIWithoutHeartbeat(ethserviceA)
+ apiB := newConsensusAPIWithoutHeartbeat(ethserviceB)
commonAncestor := ethserviceA.BlockChain().CurrentBlock()
@@ -882,7 +888,7 @@ func TestInvalidBloom(t *testing.T) {
defer n.Close()
commonAncestor := ethservice.BlockChain().CurrentBlock()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// Setup 10 blocks on the canonical chain
setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil, nil)
@@ -908,7 +914,7 @@ func TestSimultaneousNewBlock(t *testing.T) {
defer n.Close()
var (
- api = NewConsensusAPI(ethservice)
+ api = newConsensusAPIWithoutHeartbeat(ethservice)
parent = preMergeBlocks[len(preMergeBlocks)-1]
)
for i := 0; i < 10; i++ {
@@ -998,7 +1004,7 @@ func TestWithdrawals(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks)
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// 10: Build Shanghai block with no withdrawals.
parent := ethservice.BlockChain().CurrentHeader()
@@ -1120,7 +1126,7 @@ func TestNilWithdrawals(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks)
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
parent := ethservice.BlockChain().CurrentHeader()
aa := common.Address{0xaa}
@@ -1318,7 +1324,7 @@ func allBodies(blocks []*types.Block) []*types.Body {
func TestGetBlockBodiesByHash(t *testing.T) {
node, eth, blocks := setupBodies(t)
- api := NewConsensusAPI(eth)
+ api := newConsensusAPIWithoutHeartbeat(eth)
defer node.Close()
tests := []struct {
@@ -1374,7 +1380,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
func TestGetBlockBodiesByRange(t *testing.T) {
node, eth, blocks := setupBodies(t)
- api := NewConsensusAPI(eth)
+ api := newConsensusAPIWithoutHeartbeat(eth)
defer node.Close()
tests := []struct {
@@ -1455,7 +1461,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
node, eth, _ := setupBodies(t)
- api := NewConsensusAPI(eth)
+ api := newConsensusAPIWithoutHeartbeat(eth)
defer node.Close()
tests := []struct {
start hexutil.Uint64
@@ -1567,7 +1573,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks)
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// 11: Build Shanghai block with no withdrawals.
parent := ethservice.BlockChain().CurrentHeader()
@@ -1662,7 +1668,7 @@ func TestWitnessCreationAndConsumption(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks[:9])
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
// Put the 10th block's tx in the pool and produce a new block
txs := blocks[9].Transactions()
@@ -1755,7 +1761,7 @@ func TestGetClientVersion(t *testing.T) {
n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close()
- api := NewConsensusAPI(ethservice)
+ api := newConsensusAPIWithoutHeartbeat(ethservice)
info := engine.ClientVersionV1{
Code: "TT",
Name: "test",
@@ -1829,3 +1835,245 @@ func TestValidateRequests(t *testing.T) {
})
}
}
+
+var (
+ testBlobs []*kzg4844.Blob
+ testBlobCommits []kzg4844.Commitment
+ testBlobProofs []kzg4844.Proof
+ testBlobCellProofs [][]kzg4844.Proof
+ testBlobVHashes [][32]byte
+)
+
+func init() {
+ for i := 0; i < 6; i++ {
+ testBlob := &kzg4844.Blob{byte(i)}
+ testBlobs = append(testBlobs, testBlob)
+
+ testBlobCommit, _ := kzg4844.BlobToCommitment(testBlob)
+ testBlobCommits = append(testBlobCommits, testBlobCommit)
+
+ testBlobProof, _ := kzg4844.ComputeBlobProof(testBlob, testBlobCommit)
+ testBlobProofs = append(testBlobProofs, testBlobProof)
+
+ testBlobCellProof, _ := kzg4844.ComputeCellProofs(testBlob)
+ testBlobCellProofs = append(testBlobCellProofs, testBlobCellProof)
+
+ testBlobVHash := kzg4844.CalcBlobHashV1(sha256.New(), &testBlobCommit)
+ testBlobVHashes = append(testBlobVHashes, testBlobVHash)
+ }
+}
+
+// makeMultiBlobTx is a utility method to construct a random blob tx with
+// certain number of blobs in its sidecar.
+func makeMultiBlobTx(chainConfig *params.ChainConfig, nonce uint64, blobCount int, blobOffset int, key *ecdsa.PrivateKey, version byte) *types.Transaction {
+ var (
+ blobs []kzg4844.Blob
+ blobHashes []common.Hash
+ commitments []kzg4844.Commitment
+ proofs []kzg4844.Proof
+ )
+ for i := 0; i < blobCount; i++ {
+ blobs = append(blobs, *testBlobs[blobOffset+i])
+ commitments = append(commitments, testBlobCommits[blobOffset+i])
+ if version == types.BlobSidecarVersion0 {
+ proofs = append(proofs, testBlobProofs[blobOffset+i])
+ } else {
+ cellProofs, _ := kzg4844.ComputeCellProofs(testBlobs[blobOffset+i])
+ proofs = append(proofs, cellProofs...)
+ }
+ blobHashes = append(blobHashes, testBlobVHashes[blobOffset+i])
+ }
+ blobtx := &types.BlobTx{
+ ChainID: uint256.MustFromBig(chainConfig.ChainID),
+ Nonce: nonce,
+ GasTipCap: uint256.NewInt(1),
+ GasFeeCap: uint256.NewInt(1000),
+ Gas: 21000,
+ BlobFeeCap: uint256.NewInt(1000),
+ BlobHashes: blobHashes,
+ Value: uint256.NewInt(100),
+ Sidecar: types.NewBlobTxSidecar(version, blobs, commitments, proofs),
+ }
+ return types.MustSignNewTx(key, types.LatestSigner(chainConfig), blobtx)
+}
+
+func newGetBlobEnv(t *testing.T, version byte) (*node.Node, *ConsensusAPI) {
+ var (
+ // Create a database pre-initialize with a genesis block
+ config = *params.MergedTestChainConfig
+
+ key1, _ = crypto.GenerateKey()
+ key2, _ = crypto.GenerateKey()
+ key3, _ = crypto.GenerateKey()
+
+ addr1 = crypto.PubkeyToAddress(key1.PublicKey)
+ addr2 = crypto.PubkeyToAddress(key2.PublicKey)
+ addr3 = crypto.PubkeyToAddress(key3.PublicKey)
+ )
+ // Disable Osaka fork for GetBlobsV1
+ if version == 0 {
+ config.OsakaTime = nil
+ }
+ gspec := &core.Genesis{
+ Config: &config,
+ Alloc: types.GenesisAlloc{
+ testAddr: {Balance: testBalance},
+ addr1: {Balance: testBalance},
+ addr2: {Balance: testBalance},
+ addr3: {Balance: testBalance},
+ },
+ Difficulty: common.Big0,
+ }
+ n, ethServ := startEthService(t, gspec, nil)
+
+ // fill blob txs into the pool
+ tx1 := makeMultiBlobTx(&config, 0, 2, 0, key1, version) // blob[0, 2)
+ tx2 := makeMultiBlobTx(&config, 0, 2, 2, key2, version) // blob[2, 4)
+ tx3 := makeMultiBlobTx(&config, 0, 2, 4, key3, version) // blob[4, 6)
+ ethServ.TxPool().Add([]*types.Transaction{tx1, tx2, tx3}, true)
+
+ api := newConsensusAPIWithoutHeartbeat(ethServ)
+ return n, api
+}
+
+func TestGetBlobsV1(t *testing.T) {
+ n, api := newGetBlobEnv(t, 0)
+ defer n.Close()
+
+ suites := []struct {
+ start int
+ limit int
+ fillRandom bool
+ }{
+ {
+ start: 0, limit: 1,
+ },
+ {
+ start: 0, limit: 1, fillRandom: true,
+ },
+ {
+ start: 0, limit: 2,
+ },
+ {
+ start: 0, limit: 2, fillRandom: true,
+ },
+ {
+ start: 1, limit: 3,
+ },
+ {
+ start: 1, limit: 3, fillRandom: true,
+ },
+ {
+ start: 0, limit: 6,
+ },
+ {
+ start: 0, limit: 6, fillRandom: true,
+ },
+ {
+ start: 1, limit: 5,
+ },
+ {
+ start: 1, limit: 5, fillRandom: true,
+ },
+ }
+ for i, suite := range suites {
+ // Fill the request for retrieving blobs
+ var (
+ vhashes []common.Hash
+ expect []*engine.BlobAndProofV1
+ )
+ // fill missing blob at the beginning
+ if suite.fillRandom {
+ vhashes = append(vhashes, testrand.Hash())
+ expect = append(expect, nil)
+ }
+ for j := suite.start; j < suite.limit; j++ {
+ vhashes = append(vhashes, testBlobVHashes[j])
+ expect = append(expect, &engine.BlobAndProofV1{
+ Blob: testBlobs[j][:],
+ Proof: testBlobProofs[j][:],
+ })
+
+ // fill missing blobs in the middle
+ if suite.fillRandom && rand.Intn(2) == 0 {
+ vhashes = append(vhashes, testrand.Hash())
+ expect = append(expect, nil)
+ }
+ }
+ // fill missing blobs at the end
+ if suite.fillRandom {
+ vhashes = append(vhashes, testrand.Hash())
+ expect = append(expect, nil)
+ }
+ result, err := api.GetBlobsV1(vhashes)
+ if err != nil {
+ t.Errorf("Unexpected error for case %d, %v", i, err)
+ }
+ if !reflect.DeepEqual(result, expect) {
+ t.Fatalf("Unexpected result for case %d", i)
+ }
+ }
+}
+
+func TestGetBlobsV2(t *testing.T) {
+ n, api := newGetBlobEnv(t, 1)
+ defer n.Close()
+
+ suites := []struct {
+ start int
+ limit int
+ fillRandom bool
+ }{
+ {
+ start: 0, limit: 1,
+ },
+ {
+ start: 0, limit: 2,
+ },
+ {
+ start: 1, limit: 3,
+ },
+ {
+ start: 0, limit: 6,
+ },
+ {
+ start: 1, limit: 5,
+ },
+ {
+ start: 0, limit: 6, fillRandom: true,
+ },
+ }
+ for i, suite := range suites {
+ // Fill the request for retrieving blobs
+ var (
+ vhashes []common.Hash
+ expect []*engine.BlobAndProofV2
+ )
+ // fill missing blob
+ if suite.fillRandom {
+ vhashes = append(vhashes, testrand.Hash())
+ }
+ for j := suite.start; j < suite.limit; j++ {
+ vhashes = append(vhashes, testBlobVHashes[j])
+ var cellProofs []hexutil.Bytes
+ for _, proof := range testBlobCellProofs[j] {
+ cellProofs = append(cellProofs, proof[:])
+ }
+ expect = append(expect, &engine.BlobAndProofV2{
+ Blob: testBlobs[j][:],
+ CellProofs: cellProofs,
+ })
+ }
+ result, err := api.GetBlobsV2(vhashes)
+ if err != nil {
+ t.Errorf("Unexpected error for case %d, %v", i, err)
+ }
+ // null is responded if any blob is missing
+ if suite.fillRandom {
+ expect = nil
+ }
+ if !reflect.DeepEqual(result, expect) {
+ t.Fatalf("Unexpected result for case %d", i)
+ }
+ }
+}
diff --git a/eth/catalyst/witness.go b/eth/catalyst/witness.go
index 104a5f1465..c6b4a99d88 100644
--- a/eth/catalyst/witness.go
+++ b/eth/catalyst/witness.go
@@ -73,8 +73,8 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.Forkchoice
return engine.STATUS_INVALID, attributesErr("missing withdrawals")
case params.BeaconRoot == nil:
return engine.STATUS_INVALID, attributesErr("missing beacon root")
- case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague):
- return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun or prague payloads")
+ case !api.checkFork(params.Timestamp, forks.Cancun, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+ return engine.STATUS_INVALID, unsupportedForkErr("fcuV3 must only be called for cancun/prague/osaka payloads")
}
}
// TODO(matt): the spec requires that fcu is applied when called on a valid
@@ -151,8 +151,8 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, v
return invalidStatus, paramsErr("nil beaconRoot post-cancun")
case executionRequests == nil:
return invalidStatus, paramsErr("nil executionRequests post-prague")
- case !api.checkFork(params.Timestamp, forks.Prague):
- return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
+ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+ return invalidStatus, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads")
}
requests := convertRequests(executionRequests)
if err := validateRequests(requests); err != nil {
@@ -228,8 +228,8 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData,
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil beaconRoot post-cancun")
case executionRequests == nil:
return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, paramsErr("nil executionRequests post-prague")
- case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka):
- return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV4 must only be called for prague payloads")
+ case !api.checkFork(params.Timestamp, forks.Prague, forks.Osaka, forks.BPO1, forks.BPO2, forks.BPO3, forks.BPO4, forks.BPO5):
+ return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, unsupportedForkErr("newPayloadV4 must only be called for prague/osaka payloads")
}
requests := convertRequests(executionRequests)
if err := validateRequests(requests); err != nil {
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index e2968bcdef..c8e7848c8a 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -63,6 +63,7 @@ var Defaults = Config{
TrieTimeout: 60 * time.Minute,
SnapshotCache: 102,
FilterLogCacheSize: 32,
+ LogQueryLimit: 1000,
Miner: miner.DefaultConfig,
TxPool: legacypool.DefaultConfig,
BlobPool: blobpool.DefaultConfig,
@@ -132,6 +133,10 @@ type Config struct {
// This is the number of blocks for which logs will be cached in the filter system.
FilterLogCacheSize int
+ // This is the maximum number of addresses or topics allowed in filter criteria
+ // for eth_getLogs.
+ LogQueryLimit int
+
// Mining options
Miner miner.Config
@@ -145,6 +150,15 @@ type Config struct {
// Enables tracking of SHA3 preimages in the VM
EnablePreimageRecording bool
+ // Enables collection of witness trie access statistics
+ EnableWitnessStats bool
+
+ // Generate execution witnesses and self-check against them (testing purpose)
+ StatelessSelfValidation bool
+
+ // Enables tracking of state size
+ EnableStateSizeTracking bool
+
// Enables VM tracing
VMTrace string
VMTraceJsonConfig string
@@ -162,6 +176,12 @@ type Config struct {
// OverrideOsaka (TODO: remove after the fork)
OverrideOsaka *uint64 `toml:",omitempty"`
+ // OverrideBPO1 (TODO: remove after the fork)
+ OverrideBPO1 *uint64 `toml:",omitempty"`
+
+ // OverrideBPO2 (TODO: remove after the fork)
+ OverrideBPO2 *uint64 `toml:",omitempty"`
+
// OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"`
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index b24ca23881..30ec163a88 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -44,17 +44,23 @@ func (c Config) MarshalTOML() (interface{}, error) {
SnapshotCache int
Preimages bool
FilterLogCacheSize int
+ LogQueryLimit int
Miner miner.Config
TxPool legacypool.Config
BlobPool blobpool.Config
GPO gasprice.Config
EnablePreimageRecording bool
+ EnableWitnessStats bool
+ StatelessSelfValidation bool
+ EnableStateSizeTracking bool
VMTrace string
VMTraceJsonConfig string
RPCGasCap uint64
RPCEVMTimeout time.Duration
RPCTxFeeCap float64
OverrideOsaka *uint64 `toml:",omitempty"`
+ OverrideBPO1 *uint64 `toml:",omitempty"`
+ OverrideBPO2 *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"`
OverrideOptimismCanyon *uint64 `toml:",omitempty"`
OverrideOptimismEcotone *uint64 `toml:",omitempty"`
@@ -106,17 +112,23 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.SnapshotCache = c.SnapshotCache
enc.Preimages = c.Preimages
enc.FilterLogCacheSize = c.FilterLogCacheSize
+ enc.LogQueryLimit = c.LogQueryLimit
enc.Miner = c.Miner
enc.TxPool = c.TxPool
enc.BlobPool = c.BlobPool
enc.GPO = c.GPO
enc.EnablePreimageRecording = c.EnablePreimageRecording
+ enc.EnableWitnessStats = c.EnableWitnessStats
+ enc.StatelessSelfValidation = c.StatelessSelfValidation
+ enc.EnableStateSizeTracking = c.EnableStateSizeTracking
enc.VMTrace = c.VMTrace
enc.VMTraceJsonConfig = c.VMTraceJsonConfig
enc.RPCGasCap = c.RPCGasCap
enc.RPCEVMTimeout = c.RPCEVMTimeout
enc.RPCTxFeeCap = c.RPCTxFeeCap
enc.OverrideOsaka = c.OverrideOsaka
+ enc.OverrideBPO1 = c.OverrideBPO1
+ enc.OverrideBPO2 = c.OverrideBPO2
enc.OverrideVerkle = c.OverrideVerkle
enc.OverrideOptimismCanyon = c.OverrideOptimismCanyon
enc.OverrideOptimismEcotone = c.OverrideOptimismEcotone
@@ -172,17 +184,23 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
SnapshotCache *int
Preimages *bool
FilterLogCacheSize *int
+ LogQueryLimit *int
Miner *miner.Config
TxPool *legacypool.Config
BlobPool *blobpool.Config
GPO *gasprice.Config
EnablePreimageRecording *bool
+ EnableWitnessStats *bool
+ StatelessSelfValidation *bool
+ EnableStateSizeTracking *bool
VMTrace *string
VMTraceJsonConfig *string
RPCGasCap *uint64
RPCEVMTimeout *time.Duration
RPCTxFeeCap *float64
OverrideOsaka *uint64 `toml:",omitempty"`
+ OverrideBPO1 *uint64 `toml:",omitempty"`
+ OverrideBPO2 *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"`
OverrideOptimismCanyon *uint64 `toml:",omitempty"`
OverrideOptimismEcotone *uint64 `toml:",omitempty"`
@@ -291,6 +309,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.FilterLogCacheSize != nil {
c.FilterLogCacheSize = *dec.FilterLogCacheSize
}
+ if dec.LogQueryLimit != nil {
+ c.LogQueryLimit = *dec.LogQueryLimit
+ }
if dec.Miner != nil {
c.Miner = *dec.Miner
}
@@ -306,6 +327,15 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.EnablePreimageRecording != nil {
c.EnablePreimageRecording = *dec.EnablePreimageRecording
}
+ if dec.EnableWitnessStats != nil {
+ c.EnableWitnessStats = *dec.EnableWitnessStats
+ }
+ if dec.StatelessSelfValidation != nil {
+ c.StatelessSelfValidation = *dec.StatelessSelfValidation
+ }
+ if dec.EnableStateSizeTracking != nil {
+ c.EnableStateSizeTracking = *dec.EnableStateSizeTracking
+ }
if dec.VMTrace != nil {
c.VMTrace = *dec.VMTrace
}
@@ -324,6 +354,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.OverrideOsaka != nil {
c.OverrideOsaka = dec.OverrideOsaka
}
+ if dec.OverrideBPO1 != nil {
+ c.OverrideBPO1 = dec.OverrideBPO1
+ }
+ if dec.OverrideBPO2 != nil {
+ c.OverrideBPO2 = dec.OverrideBPO2
+ }
if dec.OverrideVerkle != nil {
c.OverrideVerkle = dec.OverrideVerkle
}
diff --git a/eth/filters/api.go b/eth/filters/api.go
index c929810a12..d678c40389 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -42,12 +42,10 @@ var (
errBlockHashWithRange = errors.New("can't specify fromBlock/toBlock with blockHash")
errPendingLogsUnsupported = errors.New("pending logs are not supported")
errExceedMaxTopics = errors.New("exceed max topics")
- errExceedMaxAddresses = errors.New("exceed max addresses")
+ errExceedLogQueryLimit = errors.New("exceed max addresses or topics per search position")
)
const (
- // The maximum number of addresses allowed in a filter criteria
- maxAddresses = 1000
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
maxTopics = 4
// The maximum number of allowed topics within a topic criteria
@@ -70,20 +68,22 @@ type filter struct {
// FilterAPI offers support to create and manage filters. This will allow external clients to retrieve various
// information related to the Ethereum protocol such as blocks, transactions and logs.
type FilterAPI struct {
- sys *FilterSystem
- events *EventSystem
- filtersMu sync.Mutex
- filters map[rpc.ID]*filter
- timeout time.Duration
+ sys *FilterSystem
+ events *EventSystem
+ filtersMu sync.Mutex
+ filters map[rpc.ID]*filter
+ timeout time.Duration
+ logQueryLimit int
}
// NewFilterAPI returns a new FilterAPI instance.
func NewFilterAPI(system *FilterSystem) *FilterAPI {
api := &FilterAPI{
- sys: system,
- events: NewEventSystem(system),
- filters: make(map[rpc.ID]*filter),
- timeout: system.cfg.Timeout,
+ sys: system,
+ events: NewEventSystem(system),
+ filters: make(map[rpc.ID]*filter),
+ timeout: system.cfg.Timeout,
+ logQueryLimit: system.cfg.LogQueryLimit,
}
go api.timeoutLoop(system.cfg.Timeout)
@@ -347,8 +347,15 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
if len(crit.Topics) > maxTopics {
return nil, errExceedMaxTopics
}
- if len(crit.Addresses) > maxAddresses {
- return nil, errExceedMaxAddresses
+ if api.logQueryLimit != 0 {
+ if len(crit.Addresses) > api.logQueryLimit {
+ return nil, errExceedLogQueryLimit
+ }
+ for _, topics := range crit.Topics {
+ if len(topics) > api.logQueryLimit {
+ return nil, errExceedLogQueryLimit
+ }
+ }
}
var filter *Filter
@@ -545,9 +552,6 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
// raw.Address can contain a single address or an array of addresses
switch rawAddr := raw.Addresses.(type) {
case []interface{}:
- if len(rawAddr) > maxAddresses {
- return errExceedMaxAddresses
- }
for i, addr := range rawAddr {
if strAddr, ok := addr.(string); ok {
addr, err := decodeAddress(strAddr)
diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go
index 2eb3ee97b3..822bc826f6 100644
--- a/eth/filters/api_test.go
+++ b/eth/filters/api_test.go
@@ -19,7 +19,6 @@ package filters
import (
"encoding/json"
"fmt"
- "strings"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -183,15 +182,4 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) {
if len(test7.Topics[2]) != 0 {
t.Fatalf("expected 0 topics, got %d topics", len(test7.Topics[2]))
}
-
- // multiple address exceeding max
- var test8 FilterCriteria
- addresses := make([]string, maxAddresses+1)
- for i := 0; i < maxAddresses+1; i++ {
- addresses[i] = fmt.Sprintf(`"%s"`, common.HexToAddress(fmt.Sprintf("0x%x", i)).Hex())
- }
- vector = fmt.Sprintf(`{"address": [%s]}`, strings.Join(addresses, ", "))
- if err := json.Unmarshal([]byte(vector), &test8); err != errExceedMaxAddresses {
- t.Fatal("expected errExceedMaxAddresses, got", err)
- }
}
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 751cd417e8..ecf1c870c1 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -41,8 +41,9 @@ import (
// Config represents the configuration of the filter system.
type Config struct {
- LogCacheSize int // maximum number of cached blocks (default: 32)
- Timeout time.Duration // how long filters stay active (default: 5min)
+ LogCacheSize int // maximum number of cached blocks (default: 32)
+ Timeout time.Duration // how long filters stay active (default: 5min)
+ LogQueryLimit int // maximum number of addresses allowed in filter criteria (default: 1000)
}
func (cfg Config) withDefaults() Config {
@@ -291,8 +292,15 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
if len(crit.Topics) > maxTopics {
return nil, errExceedMaxTopics
}
- if len(crit.Addresses) > maxAddresses {
- return nil, errExceedMaxAddresses
+ if es.sys.cfg.LogQueryLimit != 0 {
+ if len(crit.Addresses) > es.sys.cfg.LogQueryLimit {
+ return nil, errExceedLogQueryLimit
+ }
+ for _, topics := range crit.Topics {
+ if len(topics) > es.sys.cfg.LogQueryLimit {
+ return nil, errExceedLogQueryLimit
+ }
+ }
}
var from, to rpc.BlockNumber
if crit.FromBlock == nil {
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index 013c1ae527..0048e74995 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/ethereum/go-ethereum/triedb"
)
type testBackend struct {
@@ -424,7 +425,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
- _, sys = newTestFilterSystem(db, Config{})
+ _, sys = newTestFilterSystem(db, Config{LogQueryLimit: 1000})
api = NewFilterAPI(sys)
)
@@ -435,7 +436,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
- 4: {Addresses: make([]common.Address, maxAddresses+1)},
+ 4: {Addresses: make([]common.Address, api.logQueryLimit+1)},
}
for i, test := range testCases {
@@ -455,7 +456,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
BaseFee: big.NewInt(params.InitialBaseFee),
}
db, blocks, _ = core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 10, func(i int, gen *core.BlockGen) {})
- _, sys = newTestFilterSystem(db, Config{})
+ _, sys = newTestFilterSystem(db, Config{LogQueryLimit: 10})
api = NewFilterAPI(sys)
blockHash = blocks[0].Hash()
unknownBlockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
@@ -500,8 +501,8 @@ func TestInvalidGetLogsRequest(t *testing.T) {
err: errExceedMaxTopics,
},
{
- f: FilterCriteria{BlockHash: &blockHash, Addresses: make([]common.Address, maxAddresses+1)},
- err: errExceedMaxAddresses,
+ f: FilterCriteria{BlockHash: &blockHash, Addresses: make([]common.Address, api.logQueryLimit+1)},
+ err: errExceedLogQueryLimit,
},
}
@@ -528,6 +529,92 @@ func TestInvalidGetRangeLogsRequest(t *testing.T) {
}
}
+// TestExceedLogQueryLimit tests getLogs with too many addresses or topics
+func TestExceedLogQueryLimit(t *testing.T) {
+ t.Parallel()
+
+ // Test with custom config (LogQueryLimit = 5 for easier testing)
+ var (
+ db = rawdb.NewMemoryDatabase()
+ backend, sys = newTestFilterSystem(db, Config{LogQueryLimit: 5})
+ api = NewFilterAPI(sys)
+ gspec = &core.Genesis{
+ Config: params.TestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ }
+ )
+
+ _, err := gspec.Commit(db, triedb.NewDatabase(db, nil))
+ if err != nil {
+ t.Fatal(err)
+ }
+ chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) {})
+
+ options := core.DefaultConfig().WithStateScheme(rawdb.HashScheme)
+ options.TxLookupLimit = 0 // index all txs
+ bc, err := core.NewBlockChain(db, gspec, ethash.NewFaker(), options)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = bc.InsertChain(chain[:600])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ backend.startFilterMaps(200, false, filtermaps.RangeTestParams)
+ defer backend.stopFilterMaps()
+
+ addresses := make([]common.Address, 6)
+ for i := range addresses {
+ addresses[i] = common.HexToAddress("0x1234567890123456789012345678901234567890")
+ }
+
+ topics := make([]common.Hash, 6)
+ for i := range topics {
+ topics[i] = common.HexToHash("0x123456789012345678901234567890123456789001234567890012345678901234")
+ }
+
+ // Test that 5 addresses do not result in error
+ // Add FromBlock and ToBlock to make it similar to other invalid tests
+ if _, err := api.GetLogs(context.Background(), FilterCriteria{
+ FromBlock: big.NewInt(0),
+ ToBlock: big.NewInt(100),
+ Addresses: addresses[:5],
+ }); err != nil {
+ t.Errorf("Expected GetLogs with 5 addresses to return with no error, got: %v", err)
+ }
+
+ // Test that 6 addresses fails with correct error
+ if _, err := api.GetLogs(context.Background(), FilterCriteria{
+ FromBlock: big.NewInt(0),
+ ToBlock: big.NewInt(100),
+ Addresses: addresses,
+ }); err != errExceedLogQueryLimit {
+ t.Errorf("Expected GetLogs with 6 addresses to return errExceedLogQueryLimit, got: %v", err)
+ }
+
+ // Test that 5 topics at one position do not result in error
+ if _, err := api.GetLogs(context.Background(), FilterCriteria{
+ FromBlock: big.NewInt(0),
+ ToBlock: big.NewInt(100),
+ Addresses: addresses[:1],
+ Topics: [][]common.Hash{topics[:5]},
+ }); err != nil {
+ t.Errorf("Expected GetLogs with 5 topics at one position to return with no error, got: %v", err)
+ }
+
+ // Test that 6 topics at one position fails with correct error
+ if _, err := api.GetLogs(context.Background(), FilterCriteria{
+ FromBlock: big.NewInt(0),
+ ToBlock: big.NewInt(100),
+ Addresses: addresses[:1],
+ Topics: [][]common.Hash{topics},
+ }); err != errExceedLogQueryLimit {
+ t.Errorf("Expected GetLogs with 6 topics at one position to return errExceedLogQueryLimit, got: %v", err)
+ }
+}
+
// TestLogFilter tests whether log filters match the correct logs that are posted to the event feed.
func TestLogFilter(t *testing.T) {
t.Parallel()
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index e99b2f6caa..edec3e027f 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -109,11 +109,8 @@ func benchmarkFilters(b *testing.B, history uint64, noHistory bool) {
backend.startFilterMaps(history, noHistory, filtermaps.DefaultParams)
defer backend.stopFilterMaps()
- b.ResetTimer()
-
filter := sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{addr1, addr2, addr3, addr4}, nil)
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
filter.begin = 0
logs, _ := filter.Logs(context.Background())
if len(logs) != 4 {
diff --git a/eth/protocols/snap/gentrie_test.go b/eth/protocols/snap/gentrie_test.go
index 2da4f3c866..5998840b52 100644
--- a/eth/protocols/snap/gentrie_test.go
+++ b/eth/protocols/snap/gentrie_test.go
@@ -239,7 +239,6 @@ func TestPartialGentree(t *testing.T) {
{1, len(entries) - 1}, // no left
{2, len(entries) - 1}, // no left
{2, len(entries) - 2}, // no left and right
- {2, len(entries) - 2}, // no left and right
{len(entries) / 2, len(entries) / 2}, // single
{0, 0}, // single first
{len(entries) - 1, len(entries) - 1}, // single last
@@ -348,7 +347,6 @@ func TestGentreeDanglingClearing(t *testing.T) {
{1, len(entries) - 1}, // no left
{2, len(entries) - 1}, // no left
{2, len(entries) - 2}, // no left and right
- {2, len(entries) - 2}, // no left and right
{len(entries) / 2, len(entries) / 2}, // single
{0, 0}, // single first
{len(entries) - 1, len(entries) - 1}, // single last
diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go
index d599e7ecc3..713b358ff8 100644
--- a/eth/protocols/snap/sync_test.go
+++ b/eth/protocols/snap/sync_test.go
@@ -106,13 +106,13 @@ func BenchmarkHashing(b *testing.B) {
}
b.Run("old", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
old()
}
})
b.Run("new", func(b *testing.B) {
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
new()
}
})
@@ -597,7 +597,6 @@ func testSyncBloatedProof(t *testing.T, scheme string) {
proof := trienode.NewProofSet()
if err := t.accountTrie.Prove(origin[:], proof); err != nil {
t.logger.Error("Could not prove origin", "origin", origin, "error", err)
- t.logger.Error("Could not prove origin", "origin", origin, "error", err)
}
// The bloat: add proof of every single element
for _, entry := range t.accountValues {
diff --git a/eth/sync.go b/eth/sync.go
index 61f2b2b376..ddae8443a3 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -25,7 +25,7 @@ import (
// syncTransactions starts sending all currently pending transactions to the given peer.
func (h *handler) syncTransactions(p *eth.Peer) {
var hashes []common.Hash
- for _, batch := range h.txpool.Pending(txpool.PendingFilter{OnlyPlainTxs: true}) {
+ for _, batch := range h.txpool.Pending(txpool.PendingFilter{BlobTxs: false}) {
for _, tx := range batch {
hashes = append(hashes, tx.Hash)
}
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 9e31aca39b..2a641b4081 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -1032,7 +1032,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
return nil, err
}
var (
- msg = args.ToMessage(blockContext.BaseFee, true, true)
+ msg = args.ToMessage(blockContext.BaseFee, true)
tx = args.ToTransaction(types.LegacyTxType)
traceConfig *TraceConfig
)
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index c1e034125d..9bec57305d 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -211,11 +211,9 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
}
b.ReportAllocs()
- b.ResetTimer()
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{})
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
snap := state.StateDB.Snapshot()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config)
if err != nil {
diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go
index 171daa28ce..d46e6a554f 100644
--- a/eth/tracers/internal/tracetest/flat_calltrace_test.go
+++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go
@@ -200,7 +200,7 @@ func BenchmarkFlatCallTracer(b *testing.B) {
for _, file := range files {
filename := strings.TrimPrefix(file, "testdata/call_tracer_flat/")
b.Run(camel(strings.TrimSuffix(filename, ".json")), func(b *testing.B) {
- for n := 0; n < b.N; n++ {
+ for b.Loop() {
err := flatCallTracerTestRunner("flatCallTracer", filename, "call_tracer_flat", b)
if err != nil {
b.Fatal(err)
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index a72dbf6ee6..06edeaf698 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -84,10 +84,8 @@ func BenchmarkTransactionTraceV2(b *testing.B) {
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
- b.ResetTimer()
b.ReportAllocs()
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
tracer := logger.NewStructLogger(&logger.Config{}).Hooks()
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
evm.Config.Tracer = tracer
diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go
index 2370d4654f..8abe7d4bc7 100644
--- a/ethdb/pebble/pebble.go
+++ b/ethdb/pebble/pebble.go
@@ -218,9 +218,10 @@ func New(file string, cache int, handles int, namespace string, readonly bool) (
memTableSize = maxMemTableSize - 1
}
db := &Database{
- fn: file,
- log: logger,
- quitChan: make(chan chan error),
+ fn: file,
+ log: logger,
+ quitChan: make(chan chan error),
+ namespace: namespace,
// Use asynchronous write mode by default. Otherwise, the overhead of frequent fsync
// operations can be significant, especially on platforms with slow fsync performance
diff --git a/go.mod b/go.mod
index 3197ca1877..8b147c68af 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/ethereum/go-ethereum
-go 1.23.0
+go 1.24.0
require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
@@ -15,7 +15,7 @@ require (
github.com/cloudflare/cloudflare-go v0.114.0
github.com/cockroachdb/pebble v1.1.5
github.com/consensys/gnark-crypto v0.18.0
- github.com/crate-crypto/go-eth-kzg v1.3.0
+ github.com/crate-crypto/go-eth-kzg v1.4.0
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/dchest/siphash v1.2.3
@@ -24,10 +24,10 @@ require (
github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
github.com/ethereum/c-kzg-4844/v2 v2.1.5
+ github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab
github.com/ethereum/go-verkle v0.2.2
github.com/fatih/color v1.16.0
github.com/ferranbt/fastssz v0.1.4
- github.com/fjl/gencodec v0.1.0
github.com/fsnotify/fsnotify v1.6.0
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
github.com/gofrs/flock v0.12.1
@@ -46,7 +46,6 @@ require (
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
github.com/jackpal/go-nat-pmp v1.0.2
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
- github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52
github.com/klauspost/compress v1.17.11
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-colorable v0.1.13
@@ -62,7 +61,7 @@ require (
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
github.com/status-im/keycard-go v0.2.0
github.com/stretchr/testify v1.10.0
- github.com/supranational/blst v0.3.15
+ github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/urfave/cli/v2 v2.27.5
go.uber.org/automaxprocs v1.5.2
@@ -70,7 +69,7 @@ require (
golang.org/x/crypto v0.36.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/sync v0.12.0
- golang.org/x/sys v0.31.0
+ golang.org/x/sys v0.36.0
golang.org/x/text v0.23.0
golang.org/x/time v0.9.0
golang.org/x/tools v0.29.0
@@ -105,6 +104,7 @@ require (
github.com/deepmap/oapi-codegen v1.6.0 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/emicklei/dot v1.6.2 // indirect
+ github.com/fjl/gencodec v0.1.0 // indirect
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect
github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
@@ -148,3 +148,9 @@ require (
golang.org/x/net v0.38.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
+
+tool (
+ github.com/fjl/gencodec
+ golang.org/x/tools/cmd/stringer
+ google.golang.org/protobuf/cmd/protoc-gen-go
+)
diff --git a/go.sum b/go.sum
index e036aa0532..099b1a6f15 100644
--- a/go.sum
+++ b/go.sum
@@ -80,8 +80,8 @@ github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEf
github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI=
-github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
+github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg=
+github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -117,6 +117,8 @@ github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s=
github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs=
+github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab h1:rvv6MJhy07IMfEKuARQ9TKojGqLVNxQajaXEp/BoqSk=
+github.com/ethereum/go-bigmodexpfix v0.0.0-20250911101455-f9e208c548ab/go.mod h1:IuLm4IsPipXKF7CW5Lzf68PIbZ5yl7FFd74l/E0o9A8=
github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=
github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
@@ -216,8 +218,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=
-github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8=
github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -355,8 +355,8 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/supranational/blst v0.3.15 h1:rd9viN6tfARE5wv3KZJ9H8e1cg0jXW8syFCcsbHa76o=
-github.com/supranational/blst v0.3.15/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw=
+github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
@@ -455,8 +455,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
-golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
diff --git a/internal/build/util.go b/internal/build/util.go
index aee8bf0fc8..6e6632c750 100644
--- a/internal/build/util.go
+++ b/internal/build/util.go
@@ -21,8 +21,6 @@ import (
"bytes"
"flag"
"fmt"
- "go/parser"
- "go/token"
"io"
"log"
"os"
@@ -39,6 +37,9 @@ var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
// MustRun executes the given command and exits the host process for
// any error.
func MustRun(cmd *exec.Cmd) {
+ if cmd.Dir != "" && cmd.Dir != "." {
+ fmt.Printf("(in %s) ", cmd.Dir)
+ }
fmt.Println(">>>", printArgs(cmd.Args))
if !*DryRunFlag {
cmd.Stderr = os.Stderr
@@ -71,6 +72,13 @@ func MustRunCommand(cmd string, args ...string) {
// printed while it runs. This is useful for CI builds where the process will be stopped
// when there is no output.
func MustRunCommandWithOutput(cmd string, args ...string) {
+ MustRunWithOutput(exec.Command(cmd, args...))
+}
+
+// MustRunWithOutput runs the given command, and ensures that some output will be printed
+// while it runs. This is useful for CI builds where the process will be stopped when
+// there is no output.
+func MustRunWithOutput(cmd *exec.Cmd) {
interval := time.NewTicker(time.Minute)
done := make(chan struct{})
defer interval.Stop()
@@ -85,7 +93,7 @@ func MustRunCommandWithOutput(cmd string, args ...string) {
}
}
}()
- MustRun(exec.Command(cmd, args...))
+ MustRun(cmd)
}
var warnedAboutGit bool
@@ -209,28 +217,18 @@ func UploadSFTP(identityFile, host, dir string, files []string) error {
// FindMainPackages finds all 'main' packages in the given directory and returns their
// package paths.
-func FindMainPackages(dir string) []string {
- var commands []string
- cmds, err := os.ReadDir(dir)
+func FindMainPackages(tc *GoToolchain, pattern string) []string {
+ list := tc.Go("list", "-f", `{{if eq .Name "main"}}{{.ImportPath}}{{end}}`, pattern)
+ output, err := list.Output()
if err != nil {
- log.Fatal(err)
+ log.Fatal("go list failed:", err)
}
- for _, cmd := range cmds {
- pkgdir := filepath.Join(dir, cmd.Name())
- if !cmd.IsDir() {
- continue
- }
- pkgs, err := parser.ParseDir(token.NewFileSet(), pkgdir, nil, parser.PackageClauseOnly)
- if err != nil {
- log.Fatal(err)
- }
- for name := range pkgs {
- if name == "main" {
- path := "./" + filepath.ToSlash(pkgdir)
- commands = append(commands, path)
- break
- }
+ var result []string
+ for l := range bytes.Lines(output) {
+ l = bytes.TrimSpace(l)
+ if len(l) > 0 {
+ result = append(result, string(l))
}
}
- return commands
+ return result
}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index fc0b606716..697f5ef149 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -784,15 +784,15 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
} else {
gp.AddGas(globalGasCap)
}
- return applyMessage(ctx, b, args, state, header, timeout, gp, &blockCtx, &vm.Config{NoBaseFee: true}, precompiles, true)
+ return applyMessage(ctx, b, args, state, header, timeout, gp, &blockCtx, &vm.Config{NoBaseFee: true}, precompiles)
}
-func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts, skipChecks bool) (*core.ExecutionResult, error) {
+func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts) (*core.ExecutionResult, error) {
// Get a new instance of the EVM.
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
return nil, err
}
- msg := args.ToMessage(header.BaseFee, skipChecks, skipChecks)
+ msg := args.ToMessage(header.BaseFee, true)
// Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap).
if msg.GasPrice.Sign() == 0 {
@@ -962,7 +962,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
return 0, err
}
- call := args.ToMessage(header.BaseFee, true, true)
+ call := args.ToMessage(header.BaseFee, true)
// Run the gas estimation and wrap any revertals into a custom return
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
@@ -1486,7 +1486,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
statedb := db.Copy()
// Set the accesslist to the last al
args.AccessList = &accessList
- msg := args.ToMessage(header.BaseFee, true, true)
+ msg := args.ToMessage(header.BaseFee, true)
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, addressesToExclude)
diff --git a/internal/ethapi/override/override.go b/internal/ethapi/override/override.go
index 0bcf3c444d..9d57a78651 100644
--- a/internal/ethapi/override/override.go
+++ b/internal/ethapi/override/override.go
@@ -91,7 +91,7 @@ func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.Precompi
}
// Override account(contract) code.
if account.Code != nil {
- statedb.SetCode(addr, *account.Code)
+ statedb.SetCode(addr, *account.Code, tracing.CodeChangeUnspecified)
}
// Override account balance.
if account.Balance != nil {
diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go
index 4152b01d62..dcfc85ec05 100644
--- a/internal/ethapi/simulate.go
+++ b/internal/ethapi/simulate.go
@@ -301,7 +301,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
tracer.reset(txHash, uint(i))
sim.state.SetTxContext(txHash, i)
// EoA check is always skipped, even in validation mode.
- msg := call.ToMessage(header.BaseFee, !sim.validate, true)
+ msg := call.ToMessage(header.BaseFee, !sim.validate)
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
if err != nil {
txErr := txValidationError(err)
@@ -488,22 +488,30 @@ func (sim *simulator) makeHeaders(blocks []simBlock) ([]*types.Header, error) {
overrides := block.BlockOverrides
var withdrawalsHash *common.Hash
- if sim.chainConfig.IsShanghai(overrides.Number.ToInt(), (uint64)(*overrides.Time)) {
+ number := overrides.Number.ToInt()
+ timestamp := (uint64)(*overrides.Time)
+ if sim.chainConfig.IsShanghai(number, timestamp) {
withdrawalsHash = &types.EmptyWithdrawalsHash
}
var parentBeaconRoot *common.Hash
- if sim.chainConfig.IsCancun(overrides.Number.ToInt(), (uint64)(*overrides.Time)) {
+ if sim.chainConfig.IsCancun(number, timestamp) {
parentBeaconRoot = &common.Hash{}
if overrides.BeaconRoot != nil {
parentBeaconRoot = overrides.BeaconRoot
}
}
+ // Set difficulty to zero if the given block is post-merge. Without this, all post-merge hardforks would remain inactive.
+ // For example, calling eth_simulateV1(..., blockParameter: 0x0) on hoodi network will cause all blocks to have a difficulty of 1 and be treated as pre-merge.
+ difficulty := header.Difficulty
+ if sim.chainConfig.IsPostMerge(number.Uint64(), timestamp) {
+ difficulty = big.NewInt(0)
+ }
header = overrides.MakeHeader(&types.Header{
UncleHash: types.EmptyUncleHash,
ReceiptHash: types.EmptyReceiptsHash,
TxHash: types.EmptyTxsHash,
Coinbase: header.Coinbase,
- Difficulty: header.Difficulty,
+ Difficulty: difficulty,
GasLimit: header.GasLimit,
WithdrawalsHash: withdrawalsHash,
ParentBeaconRoot: parentBeaconRoot,
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index f80ef6d080..23aa8e5947 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -443,7 +443,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
// core evm. This method is used in calls and traces that do not require a real
// live transaction.
// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
-func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message {
+func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck bool) *core.Message {
var (
gasPrice *big.Int
gasFeeCap *big.Int
@@ -491,7 +491,7 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoA
BlobHashes: args.BlobHashes,
SetCodeAuthorizations: args.AuthorizationList,
SkipNonceChecks: skipNonceCheck,
- SkipFromEOACheck: skipEoACheck,
+ SkipTransactionChecks: true,
}
}
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index 6dd9efd685..0f0ce83773 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -468,6 +468,12 @@ web3._extend({
call: 'debug_sync',
params: 1
}),
+ new web3._extend.Method({
+ name: 'stateSize',
+ call: 'debug_stateSize',
+ params: 1,
+ inputFormatter: [null],
+ }),
],
properties: []
});
diff --git a/log/format_test.go b/log/format_test.go
index d4c1df4abc..bb740ceb84 100644
--- a/log/format_test.go
+++ b/log/format_test.go
@@ -10,7 +10,7 @@ var sink []byte
func BenchmarkPrettyInt64Logfmt(b *testing.B) {
buf := make([]byte, 100)
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
sink = appendInt64(buf, rand.Int63())
}
}
@@ -18,7 +18,7 @@ func BenchmarkPrettyInt64Logfmt(b *testing.B) {
func BenchmarkPrettyUint64Logfmt(b *testing.B) {
buf := make([]byte, 100)
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
sink = appendUint64(buf, rand.Uint64(), false)
}
}
diff --git a/log/logger_test.go b/log/logger_test.go
index 13c0db9850..de301b943e 100644
--- a/log/logger_test.go
+++ b/log/logger_test.go
@@ -130,9 +130,10 @@ func TestJSONHandler(t *testing.T) {
func BenchmarkTraceLogging(b *testing.B) {
SetDefault(NewLogger(NewTerminalHandler(io.Discard, true)))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ i := 0
+ for b.Loop() {
Trace("a message", "v", i)
+ i++
}
}
@@ -159,8 +160,8 @@ func benchmarkLogger(b *testing.B, l Logger) {
err = errors.New("oh nooes it's crap")
)
b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
+ i := 0
+ for b.Loop() {
l.Info("This is a message",
"foo", int16(i),
"bytes", bb,
@@ -169,8 +170,8 @@ func benchmarkLogger(b *testing.B, l Logger) {
"bigint", bigint,
"nilbig", nilbig,
"err", err)
+ i++
}
- b.StopTimer()
}
func TestLoggerOutput(t *testing.T) {
@@ -221,18 +222,18 @@ const termTimeFormat = "01-02|15:04:05.000"
func BenchmarkAppendFormat(b *testing.B) {
var now = time.Now()
b.Run("fmt time.Format", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
fmt.Fprintf(io.Discard, "%s", now.Format(termTimeFormat))
}
})
b.Run("time.AppendFormat", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
now.AppendFormat(nil, termTimeFormat)
}
})
var buf = new(bytes.Buffer)
b.Run("time.Custom", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
writeTimeTermFormat(buf, now)
buf.Reset()
}
diff --git a/metrics/runtimehistogram.go b/metrics/runtimehistogram.go
index 0ab8914602..efbed498af 100644
--- a/metrics/runtimehistogram.go
+++ b/metrics/runtimehistogram.go
@@ -204,7 +204,7 @@ func (h *runtimeHistogramSnapshot) Percentiles(ps []float64) []float64 {
thresholds := make([]float64, len(ps))
indexes := make([]int, len(ps))
for i, percentile := range ps {
- thresholds[i] = count * math.Max(0, math.Min(1.0, percentile))
+ thresholds[i] = count * max(0, min(1.0, percentile))
indexes[i] = i
}
sort.Sort(floatsAscendingKeepingIndex{thresholds, indexes})
diff --git a/miner/miner.go b/miner/miner.go
index 1f2625b238..eff79fa472 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -83,7 +83,7 @@ type Config struct {
// DefaultConfig contains default settings for miner.
var DefaultConfig = Config{
- GasCeil: 45_000_000,
+ GasCeil: 60_000_000,
GasPrice: big.NewInt(params.Wei),
// The default recommit time is chosen as two seconds since
diff --git a/miner/worker.go b/miner/worker.go
index 2bab122a20..ad49f6fa1b 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -704,10 +704,15 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) {
filter.GasLimitCap = params.MaxTxGas
}
- filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
+ filter.BlobTxs = false
pendingPlainTxs := miner.txpool.Pending(filter)
- filter.OnlyPlainTxs, filter.OnlyBlobTxs = false, true
+ filter.BlobTxs = true
+ if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) {
+ filter.BlobVersion = types.BlobSidecarVersion1
+ } else {
+ filter.BlobVersion = types.BlobSidecarVersion0
+ }
pendingBlobTxs := miner.txpool.Pending(filter)
// Split the pending transactions into locals and remotes.
diff --git a/p2p/discover/lookup.go b/p2p/discover/lookup.go
index 09808b71e0..9cca0118ac 100644
--- a/p2p/discover/lookup.go
+++ b/p2p/discover/lookup.go
@@ -27,6 +27,7 @@ import (
// lookup performs a network search for nodes close to the given target. It approaches the
// target by querying nodes that are closer to it on each iteration. The given target does
// not need to be an actual node identifier.
+// lookup on an empty table will return immediately with no nodes.
type lookup struct {
tab *Table
queryfunc queryFunc
@@ -49,11 +50,15 @@ func newLookup(ctx context.Context, tab *Table, target enode.ID, q queryFunc) *l
result: nodesByDistance{target: target},
replyCh: make(chan []*enode.Node, alpha),
cancelCh: ctx.Done(),
- queries: -1,
}
// Don't query further if we hit ourself.
// Unlikely to happen often in practice.
it.asked[tab.self().ID()] = true
+ it.seen[tab.self().ID()] = true
+
+ // Initialize the lookup with nodes from table.
+ closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
+ it.addNodes(closest.entries)
return it
}
@@ -64,22 +69,19 @@ func (it *lookup) run() []*enode.Node {
return it.result.entries
}
+func (it *lookup) empty() bool {
+ return len(it.replyBuffer) == 0
+}
+
// advance advances the lookup until any new nodes have been found.
// It returns false when the lookup has ended.
func (it *lookup) advance() bool {
for it.startQueries() {
select {
case nodes := <-it.replyCh:
- it.replyBuffer = it.replyBuffer[:0]
- for _, n := range nodes {
- if n != nil && !it.seen[n.ID()] {
- it.seen[n.ID()] = true
- it.result.push(n, bucketSize)
- it.replyBuffer = append(it.replyBuffer, n)
- }
- }
it.queries--
- if len(it.replyBuffer) > 0 {
+ it.addNodes(nodes)
+ if !it.empty() {
return true
}
case <-it.cancelCh:
@@ -89,6 +91,17 @@ func (it *lookup) advance() bool {
return false
}
+func (it *lookup) addNodes(nodes []*enode.Node) {
+ it.replyBuffer = it.replyBuffer[:0]
+ for _, n := range nodes {
+ if n != nil && !it.seen[n.ID()] {
+ it.seen[n.ID()] = true
+ it.result.push(n, bucketSize)
+ it.replyBuffer = append(it.replyBuffer, n)
+ }
+ }
+}
+
func (it *lookup) shutdown() {
for it.queries > 0 {
<-it.replyCh
@@ -103,20 +116,6 @@ func (it *lookup) startQueries() bool {
return false
}
- // The first query returns nodes from the local table.
- if it.queries == -1 {
- closest := it.tab.findnodeByID(it.result.target, bucketSize, false)
- // Avoid finishing the lookup too quickly if table is empty. It'd be better to wait
- // for the table to fill in this case, but there is no good mechanism for that
- // yet.
- if len(closest.entries) == 0 {
- it.slowdown()
- }
- it.queries = 1
- it.replyCh <- closest.entries
- return true
- }
-
// Ask the closest nodes that we haven't asked yet.
for i := 0; i < len(it.result.entries) && it.queries < alpha; i++ {
n := it.result.entries[i]
@@ -130,15 +129,6 @@ func (it *lookup) startQueries() bool {
return it.queries > 0
}
-func (it *lookup) slowdown() {
- sleep := time.NewTimer(1 * time.Second)
- defer sleep.Stop()
- select {
- case <-sleep.C:
- case <-it.tab.closeReq:
- }
-}
-
func (it *lookup) query(n *enode.Node, reply chan<- []*enode.Node) {
r, err := it.queryfunc(n)
if !errors.Is(err, errClosed) { // avoid recording failures on shutdown.
@@ -153,12 +143,16 @@ func (it *lookup) query(n *enode.Node, reply chan<- []*enode.Node) {
// lookupIterator performs lookup operations and iterates over all seen nodes.
// When a lookup finishes, a new one is created through nextLookup.
+// LookupIterator waits for table initialization and triggers a table refresh
+// when necessary.
+
type lookupIterator struct {
- buffer []*enode.Node
- nextLookup lookupFunc
- ctx context.Context
- cancel func()
- lookup *lookup
+ buffer []*enode.Node
+ nextLookup lookupFunc
+ ctx context.Context
+ cancel func()
+ lookup *lookup
+ tabRefreshing <-chan struct{}
}
type lookupFunc func(ctx context.Context) *lookup
@@ -182,6 +176,7 @@ func (it *lookupIterator) Next() bool {
if len(it.buffer) > 0 {
it.buffer = it.buffer[1:]
}
+
// Advance the lookup to refill the buffer.
for len(it.buffer) == 0 {
if it.ctx.Err() != nil {
@@ -191,17 +186,55 @@ func (it *lookupIterator) Next() bool {
}
if it.lookup == nil {
it.lookup = it.nextLookup(it.ctx)
+ if it.lookup.empty() {
+ // If the lookup is empty right after creation, it means the local table
+ // is in a degraded state, and we need to wait for it to fill again.
+ it.lookupFailed(it.lookup.tab, 1*time.Minute)
+ it.lookup = nil
+ continue
+ }
+ // Yield the initial nodes from the iterator before advancing the lookup.
+ it.buffer = it.lookup.replyBuffer
continue
}
- if !it.lookup.advance() {
+
+ newNodes := it.lookup.advance()
+ it.buffer = it.lookup.replyBuffer
+ if !newNodes {
it.lookup = nil
- continue
}
- it.buffer = it.lookup.replyBuffer
}
return true
}
+// lookupFailed handles failed lookup attempts. This can be called when the table has
+// exited, or when it runs out of nodes.
+func (it *lookupIterator) lookupFailed(tab *Table, timeout time.Duration) {
+ tout, cancel := context.WithTimeout(it.ctx, timeout)
+ defer cancel()
+
+ // Wait for Table initialization to complete, in case it is still in progress.
+ select {
+ case <-tab.initDone:
+ case <-tout.Done():
+ return
+ }
+
+ // Wait for ongoing refresh operation, or trigger one.
+ if it.tabRefreshing == nil {
+ it.tabRefreshing = tab.refresh()
+ }
+ select {
+ case <-it.tabRefreshing:
+ it.tabRefreshing = nil
+ case <-tout.Done():
+ return
+ }
+
+ // Wait for the table to fill.
+ tab.waitForNodes(tout, 1)
+}
+
// Close ends the iterator.
func (it *lookupIterator) Close() {
it.cancel()
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index b6c35aaaa9..6a1c7494ee 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -84,6 +85,7 @@ type Table struct {
closeReq chan struct{}
closed chan struct{}
+ nodeFeed event.FeedOf[*enode.Node]
nodeAddedHook func(*bucket, *tableNode)
nodeRemovedHook func(*bucket, *tableNode)
}
@@ -567,6 +569,8 @@ func (tab *Table) nodeAdded(b *bucket, n *tableNode) {
}
n.addedToBucket = time.Now()
tab.revalidation.nodeAdded(tab, n)
+
+ tab.nodeFeed.Send(n.Node)
if tab.nodeAddedHook != nil {
tab.nodeAddedHook(b, n)
}
@@ -702,3 +706,38 @@ func (tab *Table) deleteNode(n *enode.Node) {
b := tab.bucket(n.ID())
tab.deleteInBucket(b, n.ID())
}
+
+// waitForNodes blocks until the table contains at least n nodes.
+func (tab *Table) waitForNodes(ctx context.Context, n int) error {
+ getlength := func() (count int) {
+ for _, b := range &tab.buckets {
+ count += len(b.entries)
+ }
+ return count
+ }
+
+ var ch chan *enode.Node
+ for {
+ tab.mutex.Lock()
+ if getlength() >= n {
+ tab.mutex.Unlock()
+ return nil
+ }
+ if ch == nil {
+ // Init subscription.
+ ch = make(chan *enode.Node)
+ sub := tab.nodeFeed.Subscribe(ch)
+ defer sub.Unsubscribe()
+ }
+ tab.mutex.Unlock()
+
+ // Wait for a node add event.
+ select {
+ case <-ch:
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-tab.closeReq:
+ return errClosed
+ }
+ }
+}
diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go
index 1af31f4f1b..44863183fa 100644
--- a/p2p/discover/v4_udp_test.go
+++ b/p2p/discover/v4_udp_test.go
@@ -24,10 +24,12 @@ import (
"errors"
"fmt"
"io"
+ "maps"
"math/rand"
"net"
"net/netip"
"reflect"
+ "slices"
"sync"
"testing"
"time"
@@ -509,18 +511,26 @@ func TestUDPv4_smallNetConvergence(t *testing.T) {
// they have all found each other.
status := make(chan error, len(nodes))
for i := range nodes {
- node := nodes[i]
+ self := nodes[i]
go func() {
- found := make(map[enode.ID]bool, len(nodes))
- it := node.RandomNodes()
+ missing := make(map[enode.ID]bool, len(nodes))
+ for _, n := range nodes {
+ if n.Self().ID() == self.Self().ID() {
+ continue // skip self
+ }
+ missing[n.Self().ID()] = true
+ }
+
+ it := self.RandomNodes()
for it.Next() {
- found[it.Node().ID()] = true
- if len(found) == len(nodes) {
+ delete(missing, it.Node().ID())
+ if len(missing) == 0 {
status <- nil
return
}
}
- status <- fmt.Errorf("node %s didn't find all nodes", node.Self().ID().TerminalString())
+ missingIDs := slices.Collect(maps.Keys(missing))
+ status <- fmt.Errorf("node %s didn't find all nodes, missing %v", self.Self().ID().TerminalString(), missingIDs)
}()
}
@@ -537,7 +547,6 @@ func TestUDPv4_smallNetConvergence(t *testing.T) {
received++
if err != nil {
t.Error("ERROR:", err)
- return
}
}
}
diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go
index 9679f5c61a..c13032e1af 100644
--- a/p2p/discover/v5_udp.go
+++ b/p2p/discover/v5_udp.go
@@ -328,12 +328,6 @@ func (t *UDPv5) TalkRequestToID(id enode.ID, addr netip.AddrPort, protocol strin
// RandomNodes returns an iterator that finds random nodes in the DHT.
func (t *UDPv5) RandomNodes() enode.Iterator {
- if t.tab.len() == 0 {
- // All nodes were dropped, refresh. The very first query will hit this
- // case and run the bootstrapping logic.
- <-t.tab.refresh()
- }
-
return newLookupIterator(t.closeCtx, t.newRandomLookup)
}
diff --git a/p2p/discover/v5wire/encoding_test.go b/p2p/discover/v5wire/encoding_test.go
index 2304d0f132..5774cb3d8c 100644
--- a/p2p/discover/v5wire/encoding_test.go
+++ b/p2p/discover/v5wire/encoding_test.go
@@ -477,10 +477,9 @@ func BenchmarkV5_DecodeHandshakePingSecp256k1(b *testing.B) {
b.Fatal("can't encode handshake packet")
}
challenge.Node = nil // force ENR signature verification in decoder
- b.ResetTimer()
input := make([]byte, len(enc))
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
copy(input, enc)
net.nodeB.c.sc.storeSentHandshake(idA, "", challenge)
_, _, _, err := net.nodeB.c.Decode(input, "")
@@ -507,10 +506,9 @@ func BenchmarkV5_DecodePing(b *testing.B) {
if err != nil {
b.Fatalf("can't encode: %v", err)
}
- b.ResetTimer()
input := make([]byte, len(enc))
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
copy(input, enc)
_, _, packet, _ := net.nodeB.c.Decode(input, addrB)
if _, ok := packet.(*Ping); !ok {
diff --git a/p2p/netutil/net_test.go b/p2p/netutil/net_test.go
index 569c7ac454..8c810f494f 100644
--- a/p2p/netutil/net_test.go
+++ b/p2p/netutil/net_test.go
@@ -187,7 +187,7 @@ func TestCheckRelayIP(t *testing.T) {
func BenchmarkCheckRelayIP(b *testing.B) {
sender := parseIP("23.55.1.242")
addr := parseIP("23.55.1.2")
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
CheckRelayIP(sender, addr)
}
}
diff --git a/p2p/rlpx/rlpx_test.go b/p2p/rlpx/rlpx_test.go
index 27d51546e7..a02c1dc2cc 100644
--- a/p2p/rlpx/rlpx_test.go
+++ b/p2p/rlpx/rlpx_test.go
@@ -369,8 +369,7 @@ func TestHandshakeForwardCompatibility(t *testing.T) {
func BenchmarkHandshakeRead(b *testing.B) {
var input = unhex(eip8HandshakeAuthTests[0].input)
-
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
var (
h handshakeState
r = bytes.NewReader(input)
@@ -427,7 +426,7 @@ func BenchmarkThroughput(b *testing.B) {
// Read N messages.
b.SetBytes(int64(len(msgdata)))
b.ReportAllocs()
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
_, _, _, err := conn2.Read()
if err != nil {
b.Fatal("read error:", err)
diff --git a/params/config.go b/params/config.go
index e585e66d8c..79d7a7c2ab 100644
--- a/params/config.go
+++ b/params/config.go
@@ -599,33 +599,33 @@ func (c *ChainConfig) Description() string {
// makes sense for mainnet should be optional at printing to avoid bloating
// the output for testnets and private networks.
banner += "Pre-Merge hard forks (block based):\n"
- banner += fmt.Sprintf(" - Homestead: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)\n", c.HomesteadBlock)
+ banner += fmt.Sprintf(" - Homestead: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/homestead/__init__.py.html)\n", c.HomesteadBlock)
if c.DAOForkBlock != nil {
- banner += fmt.Sprintf(" - DAO Fork: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)\n", c.DAOForkBlock)
- }
- banner += fmt.Sprintf(" - Tangerine Whistle (EIP 150): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)\n", c.EIP150Block)
- banner += fmt.Sprintf(" - Spurious Dragon/1 (EIP 155): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block)
- banner += fmt.Sprintf(" - Spurious Dragon/2 (EIP 158): #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)\n", c.EIP155Block)
- banner += fmt.Sprintf(" - Byzantium: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)\n", c.ByzantiumBlock)
- banner += fmt.Sprintf(" - Constantinople: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)\n", c.ConstantinopleBlock)
- banner += fmt.Sprintf(" - Petersburg: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)\n", c.PetersburgBlock)
- banner += fmt.Sprintf(" - Istanbul: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)\n", c.IstanbulBlock)
+ banner += fmt.Sprintf(" - DAO Fork: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/dao_fork/__init__.py.html)\n", c.DAOForkBlock)
+ }
+ banner += fmt.Sprintf(" - Tangerine Whistle (EIP 150): #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/tangerine_whistle/__init__.py.html)\n", c.EIP150Block)
+ banner += fmt.Sprintf(" - Spurious Dragon/1 (EIP 155): #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/spurious_dragon/__init__.py.html)\n", c.EIP155Block)
+ banner += fmt.Sprintf(" - Spurious Dragon/2 (EIP 158): #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/spurious_dragon/__init__.py.html)\n", c.EIP155Block)
+ banner += fmt.Sprintf(" - Byzantium: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/byzantium/__init__.py.html)\n", c.ByzantiumBlock)
+ banner += fmt.Sprintf(" - Constantinople: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/constantinople/__init__.py.html)\n", c.ConstantinopleBlock)
+ banner += fmt.Sprintf(" - Petersburg: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/constantinople/__init__.py.html)\n", c.PetersburgBlock)
+ banner += fmt.Sprintf(" - Istanbul: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/istanbul/__init__.py.html)\n", c.IstanbulBlock)
if c.MuirGlacierBlock != nil {
- banner += fmt.Sprintf(" - Muir Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)\n", c.MuirGlacierBlock)
+ banner += fmt.Sprintf(" - Muir Glacier: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/muir_glacier/__init__.py.html)\n", c.MuirGlacierBlock)
}
- banner += fmt.Sprintf(" - Berlin: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md)\n", c.BerlinBlock)
- banner += fmt.Sprintf(" - London: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md)\n", c.LondonBlock)
+ banner += fmt.Sprintf(" - Berlin: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/berlin/__init__.py.html)\n", c.BerlinBlock)
+ banner += fmt.Sprintf(" - London: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/london/__init__.py.html)\n", c.LondonBlock)
if c.ArrowGlacierBlock != nil {
- banner += fmt.Sprintf(" - Arrow Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md)\n", c.ArrowGlacierBlock)
+ banner += fmt.Sprintf(" - Arrow Glacier: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/arrow_glacier/__init__.py.html)\n", c.ArrowGlacierBlock)
}
if c.GrayGlacierBlock != nil {
- banner += fmt.Sprintf(" - Gray Glacier: #%-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)\n", c.GrayGlacierBlock)
+ banner += fmt.Sprintf(" - Gray Glacier: #%-8v (https://ethereum.github.io/execution-specs/src/ethereum/forks/gray_glacier/__init__.py.html)\n", c.GrayGlacierBlock)
}
banner += "\n"
// Add a special section for the merge as it's non-obvious
banner += "Merge configured:\n"
- banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n"
+ banner += " - Hard-fork specification: https://ethereum.github.io/execution-specs/src/ethereum/forks/paris/__init__.py.html\n"
banner += " - Network known to be merged\n"
banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty)
if c.MergeNetsplitBlock != nil {
@@ -636,34 +636,34 @@ func (c *ChainConfig) Description() string {
// Create a list of forks post-merge
banner += "Post-Merge hard forks (timestamp based):\n"
if c.ShanghaiTime != nil {
- banner += fmt.Sprintf(" - Shanghai: @%-10v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)\n", *c.ShanghaiTime)
+ banner += fmt.Sprintf(" - Shanghai: @%-10v (https://ethereum.github.io/execution-specs/src/ethereum/forks/shanghai/__init__.py.html)\n", *c.ShanghaiTime)
}
if c.CancunTime != nil {
- banner += fmt.Sprintf(" - Cancun: @%-10v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md)\n", *c.CancunTime)
+ banner += fmt.Sprintf(" - Cancun: @%-10v (https://ethereum.github.io/execution-specs/src/ethereum/forks/cancun/__init__.py.html)\n", *c.CancunTime)
}
if c.PragueTime != nil {
- banner += fmt.Sprintf(" - Prague: @%-10v\n", *c.PragueTime)
+ banner += fmt.Sprintf(" - Prague: @%-10v (https://ethereum.github.io/execution-specs/src/ethereum/forks/prague/__init__.py.html)\n", *c.PragueTime)
}
if c.OsakaTime != nil {
- banner += fmt.Sprintf(" - Osaka: @%-10v\n", *c.OsakaTime)
+ banner += fmt.Sprintf(" - Osaka: @%-10v (https://ethereum.github.io/execution-specs/src/ethereum/forks/osaka/__init__.py.html)\n", *c.OsakaTime)
}
if c.VerkleTime != nil {
banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime)
}
if c.BPO1Time != nil {
- banner += fmt.Sprintf(" - BPO1: @%-10v\n", *c.BPO1Time)
+ banner += fmt.Sprintf(" - BPO1: @%-10v\n", *c.BPO1Time)
}
if c.BPO2Time != nil {
- banner += fmt.Sprintf(" - BPO2: @%-10v\n", *c.BPO2Time)
+ banner += fmt.Sprintf(" - BPO2: @%-10v\n", *c.BPO2Time)
}
if c.BPO3Time != nil {
- banner += fmt.Sprintf(" - BPO3: @%-10v\n", *c.BPO3Time)
+ banner += fmt.Sprintf(" - BPO3: @%-10v\n", *c.BPO3Time)
}
if c.BPO4Time != nil {
- banner += fmt.Sprintf(" - BPO4: @%-10v\n", *c.BPO4Time)
+ banner += fmt.Sprintf(" - BPO4: @%-10v\n", *c.BPO4Time)
}
if c.BPO5Time != nil {
- banner += fmt.Sprintf(" - BPO5: @%-10v\n", *c.BPO5Time)
+ banner += fmt.Sprintf(" - BPO5: @%-10v\n", *c.BPO5Time)
}
if c.RegolithTime != nil {
banner += fmt.Sprintf(" - Regolith: @%-10v\n", *c.RegolithTime)
@@ -795,6 +795,18 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0
}
+// IsPostMerge reports whether the given block number is assumed to be post-merge.
+// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
+// PoA chain for unit testing purposes.
+func (c *ChainConfig) IsPostMerge(blockNum uint64, timestamp uint64) bool {
+ mergedAtGenesis := c.TerminalTotalDifficulty != nil && c.TerminalTotalDifficulty.Sign() == 0
+ return mergedAtGenesis ||
+ c.MergeNetsplitBlock != nil && blockNum >= c.MergeNetsplitBlock.Uint64() ||
+ c.ShanghaiTime != nil && timestamp >= *c.ShanghaiTime ||
+ // If OP-Stack then bedrock activation number determines when TTD (eth Merge) has been reached.
+ c.IsOptimismBedrock(new(big.Int).SetUint64(blockNum))
+}
+
// IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time)
diff --git a/params/forks/forks.go b/params/forks/forks.go
index aab0a54ab7..adb65c8624 100644
--- a/params/forks/forks.go
+++ b/params/forks/forks.go
@@ -77,4 +77,9 @@ var forkToString = map[Fork]string{
Cancun: "Cancun",
Prague: "Prague",
Osaka: "Osaka",
+ BPO1: "BPO1",
+ BPO2: "BPO2",
+ BPO3: "BPO3",
+ BPO4: "BPO4",
+ BPO5: "BPO5",
}
diff --git a/rlp/decode_test.go b/rlp/decode_test.go
index 3e492188e8..4b3a322873 100644
--- a/rlp/decode_test.go
+++ b/rlp/decode_test.go
@@ -350,7 +350,7 @@ func TestDecodeErrors(t *testing.T) {
}
if err := Decode(r, new(uint)); err != io.EOF {
- t.Errorf("Decode(r, new(int)) error mismatch, got %q, want %q", err, io.EOF)
+ t.Errorf("Decode(r, new(uint)) error mismatch, got %q, want %q", err, io.EOF)
}
}
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index 314958eb56..e63ea319b4 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -317,7 +317,6 @@ var encTests = []encTest{
{val: &optionalAndTailField{A: 1}, output: "C101"},
{val: &optionalAndTailField{A: 1, B: 2}, output: "C20102"},
{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
- {val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
{val: &optionalBigIntField{A: 1}, output: "C101"},
{val: &optionalPtrField{A: 1}, output: "C101"},
{val: &optionalPtrFieldNil{A: 1}, output: "C101"},
diff --git a/tests/block_test.go b/tests/block_test.go
index 91d9f2e653..c718b304b6 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -81,8 +81,9 @@ func TestExecutionSpecBlocktests(t *testing.T) {
}
bt := new(testMatcher)
- bt.skipLoad(".*prague/eip7251_consolidations/contract_deployment/system_contract_deployment.json")
- bt.skipLoad(".*prague/eip7002_el_triggerable_withdrawals/contract_deployment/system_contract_deployment.json")
+ // These tests require us to handle scenarios where a system contract is not deployed at a fork
+ bt.skipLoad(".*prague/eip7251_consolidations/test_system_contract_deployment.json")
+ bt.skipLoad(".*prague/eip7002_el_triggerable_withdrawals/test_system_contract_deployment.json")
bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
execBlockTest(t, bt, test)
diff --git a/tests/state_test.go b/tests/state_test.go
index d5572f88db..a0c3c701cc 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -156,8 +156,8 @@ func execStateTest(t *testing.T, st *testMatcher, test *StateTest) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error
test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, state *StateTestState) {
- if state.Snapshots != nil && state.StateDB != nil {
- if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
+ if state.TrieDB != nil && state.StateDB != nil {
+ if err := state.TrieDB.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
result = err
return
}
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 755264057a..8ab9381f2d 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -511,7 +511,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
sdb := state.NewDatabase(triedb, nil)
statedb, _ := state.New(types.EmptyRootHash, sdb)
for addr, a := range accounts {
- statedb.SetCode(addr, a.Code)
+ statedb.SetCode(addr, a.Code, tracing.CodeChangeUnspecified)
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeUnspecified)
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified)
for k, v := range a.Storage {
@@ -523,7 +523,7 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bo
// If snapshot is requested, initialize the snapshotter and use it in state.
var snaps *snapshot.Tree
- if snapshotter {
+ if snapshotter && scheme == rawdb.HashScheme {
snapconfig := snapshot.Config{
CacheSize: 1,
Recovery: false,
diff --git a/tests/transaction_test.go b/tests/transaction_test.go
index 6260df0f3f..73ee3aa16a 100644
--- a/tests/transaction_test.go
+++ b/tests/transaction_test.go
@@ -70,7 +70,7 @@ func TestExecutionSpecTransaction(t *testing.T) {
st := new(testMatcher)
// Emptiness of authorization list is only validated during the tx precheck
- st.skipLoad("^prague/eip7702_set_code_tx/invalid_tx/empty_authorization_list.json")
+ st.skipLoad("^prague/eip7702_set_code_tx/test_empty_authorization_list.json")
st.walk(t, executionSpecTransactionTestDir, func(t *testing.T, name string, test *TransactionTest) {
if err := st.checkFailure(t, test.Run()); err != nil {
diff --git a/trie/iterator.go b/trie/iterator.go
index 80298ce48f..3d3191ffba 100644
--- a/trie/iterator.go
+++ b/trie/iterator.go
@@ -836,3 +836,91 @@ func (it *unionIterator) Error() error {
}
return nil
}
+
+// subTreeIterator wraps nodeIterator to traverse a trie within a predefined
+// start and limit range.
+type subtreeIterator struct {
+ NodeIterator
+
+ stopPath []byte // Precomputed hex path for stopKey (without terminator), nil means no limit
+ exhausted bool // Flag whether the iterator has been exhausted
+}
+
+// newSubtreeIterator creates an iterator that only traverses nodes within a subtree
+// defined by the given startKey and stopKey. This supports general range iteration
+// where startKey is inclusive and stopKey is exclusive.
+//
+// The iterator will only visit nodes whose keys k satisfy: startKey <= k < stopKey,
+// where comparisons are performed in lexicographic order of byte keys (internally
+// implemented via hex-nibble path comparisons for efficiency).
+//
+// If startKey is nil, iteration starts from the beginning. If stopKey is nil,
+// iteration continues to the end of the trie.
+func newSubtreeIterator(trie *Trie, startKey, stopKey []byte) (NodeIterator, error) {
+ it, err := trie.NodeIterator(startKey)
+ if err != nil {
+ return nil, err
+ }
+ if startKey == nil && stopKey == nil {
+ return it, nil
+ }
+ // Precompute nibble paths for efficient comparison
+ var stopPath []byte
+ if stopKey != nil {
+ stopPath = keybytesToHex(stopKey)
+ if hasTerm(stopPath) {
+ stopPath = stopPath[:len(stopPath)-1]
+ }
+ }
+ return &subtreeIterator{
+ NodeIterator: it,
+ stopPath: stopPath,
+ }, nil
+}
+
+// nextKey returns the next possible key after the given prefix.
+// For example, "abc" -> "abd", "ab\xff" -> "ac", etc.
+func nextKey(prefix []byte) []byte {
+ if len(prefix) == 0 {
+ return nil
+ }
+ // Make a copy to avoid modifying the original
+ next := make([]byte, len(prefix))
+ copy(next, prefix)
+
+ // Increment the last byte that isn't 0xff
+ for i := len(next) - 1; i >= 0; i-- {
+ if next[i] < 0xff {
+ next[i]++
+ return next
+ }
+ // If it's 0xff, we need to carry over
+ // Trim trailing 0xff bytes
+ next = next[:i]
+ }
+ // If all bytes were 0xff, return nil (no upper bound)
+ return nil
+}
+
+// newPrefixIterator creates an iterator that only traverses nodes with the given prefix.
+// This ensures that only keys starting with the prefix are visited.
+func newPrefixIterator(trie *Trie, prefix []byte) (NodeIterator, error) {
+ return newSubtreeIterator(trie, prefix, nextKey(prefix))
+}
+
+// Next moves the iterator to the next node. If the parameter is false, any child
+// nodes will be skipped.
+func (it *subtreeIterator) Next(descend bool) bool {
+ if it.exhausted {
+ return false
+ }
+ if !it.NodeIterator.Next(descend) {
+ it.exhausted = true
+ return false
+ }
+ if it.stopPath != nil && reachedPath(it.NodeIterator.Path(), it.stopPath) {
+ it.exhausted = true
+ return false
+ }
+ return true
+}
diff --git a/trie/iterator_test.go b/trie/iterator_test.go
index 74a1aa378c..3e0ef126be 100644
--- a/trie/iterator_test.go
+++ b/trie/iterator_test.go
@@ -19,7 +19,9 @@ package trie
import (
"bytes"
"fmt"
+ "maps"
"math/rand"
+ "slices"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -624,6 +626,540 @@ func isTrieNode(scheme string, key, val []byte) (bool, []byte, common.Hash) {
return true, path, hash
}
+func TestSubtreeIterator(t *testing.T) {
+ var (
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ tr = NewEmpty(db)
+ )
+ vals := []struct{ k, v string }{
+ {"do", "verb"},
+ {"dog", "puppy"},
+ {"doge", "coin"},
+ {"dog\xff", "value6"},
+ {"dog\xff\xff", "value7"},
+ {"horse", "stallion"},
+ {"house", "building"},
+ {"houses", "multiple"},
+ {"xyz", "value"},
+ {"xyz\xff", "value"},
+ {"xyz\xff\xff", "value"},
+ }
+ all := make(map[string]string)
+ for _, val := range vals {
+ all[val.k] = val.v
+ tr.MustUpdate([]byte(val.k), []byte(val.v))
+ }
+ root, nodes := tr.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+
+ allNodes := make(map[string][]byte)
+ tr, _ = New(TrieID(root), db)
+ it, err := tr.NodeIterator(nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for it.Next(true) {
+ allNodes[string(it.Path())] = it.NodeBlob()
+ }
+ allKeys := slices.Collect(maps.Keys(all))
+
+ suites := []struct {
+ start []byte
+ end []byte
+ expected []string
+ }{
+ // entire key range
+ {
+ start: nil,
+ end: nil,
+ expected: allKeys,
+ },
+ {
+ start: nil,
+ end: bytes.Repeat([]byte{0xff}, 32),
+ expected: allKeys,
+ },
+ {
+ start: bytes.Repeat([]byte{0x0}, 32),
+ end: bytes.Repeat([]byte{0xff}, 32),
+ expected: allKeys,
+ },
+ // key range with start
+ {
+ start: []byte("do"),
+ end: nil,
+ expected: allKeys,
+ },
+ {
+ start: []byte("doe"),
+ end: nil,
+ expected: allKeys[1:],
+ },
+ {
+ start: []byte("dog"),
+ end: nil,
+ expected: allKeys[1:],
+ },
+ {
+ start: []byte("doge"),
+ end: nil,
+ expected: allKeys[2:],
+ },
+ {
+ start: []byte("dog\xff"),
+ end: nil,
+ expected: allKeys[3:],
+ },
+ {
+ start: []byte("dog\xff\xff"),
+ end: nil,
+ expected: allKeys[4:],
+ },
+ {
+ start: []byte("dog\xff\xff\xff"),
+ end: nil,
+ expected: allKeys[5:],
+ },
+ // key range with limit
+ {
+ start: nil,
+ end: []byte("xyz"),
+ expected: allKeys[:len(allKeys)-3],
+ },
+ {
+ start: nil,
+ end: []byte("xyz\xff"),
+ expected: allKeys[:len(allKeys)-2],
+ },
+ {
+ start: nil,
+ end: []byte("xyz\xff\xff"),
+ expected: allKeys[:len(allKeys)-1],
+ },
+ {
+ start: nil,
+ end: []byte("xyz\xff\xff\xff"),
+ expected: allKeys,
+ },
+ }
+ for _, suite := range suites {
+ // We need to re-open the trie from the committed state
+ tr, _ = New(TrieID(root), db)
+ it, err := newSubtreeIterator(tr, suite.start, suite.end)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ found := make(map[string]string)
+ for it.Next(true) {
+ if it.Leaf() {
+ found[string(it.LeafKey())] = string(it.LeafBlob())
+ }
+ }
+ if len(found) != len(suite.expected) {
+ t.Errorf("wrong number of values: got %d, want %d", len(found), len(suite.expected))
+ }
+ for k, v := range found {
+ if all[k] != v {
+ t.Errorf("wrong value for %s: got %s, want %s", k, found[k], all[k])
+ }
+ }
+
+ expectedNodes := make(map[string][]byte)
+ for path, blob := range allNodes {
+ if suite.start != nil {
+ hexStart := keybytesToHex(suite.start)
+ hexStart = hexStart[:len(hexStart)-1]
+ if !reachedPath([]byte(path), hexStart) {
+ continue
+ }
+ }
+ if suite.end != nil {
+ hexEnd := keybytesToHex(suite.end)
+ hexEnd = hexEnd[:len(hexEnd)-1]
+ if reachedPath([]byte(path), hexEnd) {
+ continue
+ }
+ }
+ expectedNodes[path] = bytes.Clone(blob)
+ }
+
+ // Compare the result yield from the subtree iterator
+ var (
+ subCount int
+ subIt, _ = newSubtreeIterator(tr, suite.start, suite.end)
+ )
+ for subIt.Next(true) {
+ blob, ok := expectedNodes[string(subIt.Path())]
+ if !ok {
+ t.Errorf("Unexpected node iterated, path: %v", subIt.Path())
+ }
+ subCount++
+
+ if !bytes.Equal(blob, subIt.NodeBlob()) {
+ t.Errorf("Unexpected node blob, path: %v, want: %v, got: %v", subIt.Path(), blob, subIt.NodeBlob())
+ }
+ }
+ if subCount != len(expectedNodes) {
+ t.Errorf("Unexpected node being iterated, want: %d, got: %d", len(expectedNodes), subCount)
+ }
+ }
+}
+
+func TestPrefixIterator(t *testing.T) {
+ // Create a new trie
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+
+ // Insert test data
+ testData := map[string]string{
+ "key1": "value1",
+ "key2": "value2",
+ "key10": "value10",
+ "key11": "value11",
+ "different": "value_different",
+ }
+
+ for key, value := range testData {
+ trie.Update([]byte(key), []byte(value))
+ }
+
+ // Test prefix iteration for "key1" prefix
+ prefix := []byte("key1")
+ iter, err := trie.NodeIteratorWithPrefix(prefix)
+ if err != nil {
+ t.Fatalf("Failed to create prefix iterator: %v", err)
+ }
+
+ var foundKeys [][]byte
+ for iter.Next(true) {
+ if iter.Leaf() {
+ foundKeys = append(foundKeys, iter.LeafKey())
+ }
+ }
+
+ if err := iter.Error(); err != nil {
+ t.Fatalf("Iterator error: %v", err)
+ }
+
+ // Verify only keys starting with "key1" were found
+ expectedCount := 3 // "key1", "key10", "key11"
+ if len(foundKeys) != expectedCount {
+ t.Errorf("Expected %d keys, found %d", expectedCount, len(foundKeys))
+ }
+
+ for _, key := range foundKeys {
+ keyStr := string(key)
+ if !bytes.HasPrefix(key, prefix) {
+ t.Errorf("Found key %s doesn't have prefix %s", keyStr, string(prefix))
+ }
+ }
+}
+
+func TestPrefixIteratorVsFullIterator(t *testing.T) {
+ // Create a new trie with more structured data
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+
+ // Insert structured test data
+ testData := map[string]string{
+ "aaa": "value_aaa",
+ "aab": "value_aab",
+ "aba": "value_aba",
+ "bbb": "value_bbb",
+ }
+
+ for key, value := range testData {
+ trie.Update([]byte(key), []byte(value))
+ }
+
+ // Test that prefix iterator stops at boundary
+ prefix := []byte("aa")
+ prefixIter, err := trie.NodeIteratorWithPrefix(prefix)
+ if err != nil {
+ t.Fatalf("Failed to create prefix iterator: %v", err)
+ }
+
+ var prefixKeys [][]byte
+ for prefixIter.Next(true) {
+ if prefixIter.Leaf() {
+ prefixKeys = append(prefixKeys, prefixIter.LeafKey())
+ }
+ }
+
+ // Should only find "aaa" and "aab", not "aba" or "bbb"
+ if len(prefixKeys) != 2 {
+ t.Errorf("Expected 2 keys with prefix 'aa', found %d", len(prefixKeys))
+ }
+
+ // Verify no keys outside prefix were found
+ for _, key := range prefixKeys {
+ if !bytes.HasPrefix(key, prefix) {
+ t.Errorf("Prefix iterator returned key %s outside prefix %s", string(key), string(prefix))
+ }
+ }
+}
+
+func TestEmptyPrefixIterator(t *testing.T) {
+ // Test with empty trie
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+
+ iter, err := trie.NodeIteratorWithPrefix([]byte("nonexistent"))
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+
+ if iter.Next(true) {
+ t.Error("Expected no results from empty trie")
+ }
+}
+
+// TestPrefixIteratorEdgeCases tests various edge cases for prefix iteration
+func TestPrefixIteratorEdgeCases(t *testing.T) {
+ // Create a trie with test data
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+ testData := map[string]string{
+ "abc": "value1",
+ "abcd": "value2",
+ "abce": "value3",
+ "abd": "value4",
+ "dog": "value5",
+ "dog\xff": "value6", // Test with 0xff byte
+ "dog\xff\xff": "value7", // Multiple 0xff bytes
+ }
+ for key, value := range testData {
+ trie.Update([]byte(key), []byte(value))
+ }
+
+ // Test 1: Prefix not present in trie
+ t.Run("NonexistentPrefix", func(t *testing.T) {
+ iter, err := trie.NodeIteratorWithPrefix([]byte("xyz"))
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+ count := 0
+ for iter.Next(true) {
+ if iter.Leaf() {
+ count++
+ }
+ }
+ if count != 0 {
+ t.Errorf("Expected 0 results for nonexistent prefix, got %d", count)
+ }
+ })
+
+ // Test 2: Prefix exactly equals an existing key
+ t.Run("ExactKeyPrefix", func(t *testing.T) {
+ iter, err := trie.NodeIteratorWithPrefix([]byte("abc"))
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+ found := make(map[string]bool)
+ for iter.Next(true) {
+ if iter.Leaf() {
+ found[string(iter.LeafKey())] = true
+ }
+ }
+ // Should find "abc", "abcd", "abce" but not "abd"
+ if !found["abc"] || !found["abcd"] || !found["abce"] {
+ t.Errorf("Missing expected keys: got %v", found)
+ }
+ if found["abd"] {
+ t.Errorf("Found unexpected key 'abd' with prefix 'abc'")
+ }
+ })
+
+ // Test 3: Prefix with trailing 0xff
+ t.Run("TrailingFFPrefix", func(t *testing.T) {
+ iter, err := trie.NodeIteratorWithPrefix([]byte("dog\xff"))
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+ found := make(map[string]bool)
+ for iter.Next(true) {
+ if iter.Leaf() {
+ found[string(iter.LeafKey())] = true
+ }
+ }
+ // Should find "dog\xff" and "dog\xff\xff"
+ if !found["dog\xff"] || !found["dog\xff\xff"] {
+ t.Errorf("Missing expected keys with 0xff: got %v", found)
+ }
+ if found["dog"] {
+ t.Errorf("Found unexpected key 'dog' with prefix 'dog\\xff'")
+ }
+ })
+
+ // Test 4: All 0xff case (edge case for nextKey)
+ t.Run("AllFFPrefix", func(t *testing.T) {
+ // Add a key with all 0xff bytes
+ allFF := []byte{0xff, 0xff}
+ trie.Update(allFF, []byte("all_ff_value"))
+ trie.Update(append(allFF, 0x00), []byte("all_ff_plus"))
+
+ iter, err := trie.NodeIteratorWithPrefix(allFF)
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+ count := 0
+ for iter.Next(true) {
+ if iter.Leaf() {
+ count++
+ }
+ }
+ // Should find exactly the two keys with the all-0xff prefix
+ if count != 2 {
+ t.Errorf("Expected 2 results for all-0xff prefix, got %d", count)
+ }
+ })
+
+ // Test 5: Empty prefix (should iterate entire trie)
+ t.Run("EmptyPrefix", func(t *testing.T) {
+ iter, err := trie.NodeIteratorWithPrefix([]byte{})
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+ count := 0
+ for iter.Next(true) {
+ if iter.Leaf() {
+ count++
+ }
+ }
+ // Should find all keys in the trie
+ expectedCount := len(testData) + 2 // +2 for the extra keys added in test 4
+ if count != expectedCount {
+ t.Errorf("Expected %d results for empty prefix, got %d", expectedCount, count)
+ }
+ })
+}
+
+// TestGeneralRangeIteration tests NewSubtreeIterator with arbitrary start/stop ranges
+func TestGeneralRangeIteration(t *testing.T) {
+ // Create a trie with test data
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+ testData := map[string]string{
+ "apple": "fruit1",
+ "apricot": "fruit2",
+ "banana": "fruit3",
+ "cherry": "fruit4",
+ "date": "fruit5",
+ "fig": "fruit6",
+ "grape": "fruit7",
+ }
+ for key, value := range testData {
+ trie.Update([]byte(key), []byte(value))
+ }
+
+ // Test range iteration from "banana" to "fig" (exclusive)
+ t.Run("RangeIteration", func(t *testing.T) {
+ iter, _ := newSubtreeIterator(trie, []byte("banana"), []byte("fig"))
+ found := make(map[string]bool)
+ for iter.Next(true) {
+ if iter.Leaf() {
+ found[string(iter.LeafKey())] = true
+ }
+ }
+ // Should find "banana", "cherry", "date" but not "fig"
+ if !found["banana"] || !found["cherry"] || !found["date"] {
+ t.Errorf("Missing expected keys in range: got %v", found)
+ }
+ if found["apple"] || found["apricot"] || found["fig"] || found["grape"] {
+ t.Errorf("Found unexpected keys outside range: got %v", found)
+ }
+ })
+
+ // Test with nil stopKey (iterate to end)
+ t.Run("NilStopKey", func(t *testing.T) {
+ iter, _ := newSubtreeIterator(trie, []byte("date"), nil)
+ found := make(map[string]bool)
+ for iter.Next(true) {
+ if iter.Leaf() {
+ found[string(iter.LeafKey())] = true
+ }
+ }
+ // Should find "date", "fig", "grape"
+ if !found["date"] || !found["fig"] || !found["grape"] {
+ t.Errorf("Missing expected keys from 'date' to end: got %v", found)
+ }
+ if found["apple"] || found["banana"] || found["cherry"] {
+ t.Errorf("Found unexpected keys before 'date': got %v", found)
+ }
+ })
+
+ // Test with nil startKey (iterate from beginning)
+ t.Run("NilStartKey", func(t *testing.T) {
+ iter, _ := newSubtreeIterator(trie, nil, []byte("cherry"))
+ found := make(map[string]bool)
+ for iter.Next(true) {
+ if iter.Leaf() {
+ found[string(iter.LeafKey())] = true
+ }
+ }
+ // Should find "apple", "apricot", "banana" but not "cherry" or later
+ if !found["apple"] || !found["apricot"] || !found["banana"] {
+ t.Errorf("Missing expected keys before 'cherry': got %v", found)
+ }
+ if found["cherry"] || found["date"] || found["fig"] || found["grape"] {
+ t.Errorf("Found unexpected keys at or after 'cherry': got %v", found)
+ }
+ })
+}
+
+// TestPrefixIteratorWithDescend tests prefix iteration with descend=false
+func TestPrefixIteratorWithDescend(t *testing.T) {
+ // Create a trie with nested structure
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
+ testData := map[string]string{
+ "a": "value_a",
+ "a/b": "value_ab",
+ "a/b/c": "value_abc",
+ "a/b/d": "value_abd",
+ "a/e": "value_ae",
+ "b": "value_b",
+ }
+ for key, value := range testData {
+ trie.Update([]byte(key), []byte(value))
+ }
+
+ // Test skipping subtrees with descend=false
+ t.Run("SkipSubtrees", func(t *testing.T) {
+ iter, err := trie.NodeIteratorWithPrefix([]byte("a"))
+ if err != nil {
+ t.Fatalf("Failed to create iterator: %v", err)
+ }
+
+ // Count nodes at each level
+ nodesVisited := 0
+ leafsFound := make(map[string]bool)
+
+ // First call with descend=true to enter the "a" subtree
+ if !iter.Next(true) {
+ t.Fatal("Expected to find at least one node")
+ }
+ nodesVisited++
+
+ // Continue iteration, sometimes with descend=false
+ descendPattern := []bool{false, true, false, true, true}
+ for i := 0; iter.Next(descendPattern[i%len(descendPattern)]); i++ {
+ nodesVisited++
+ if iter.Leaf() {
+ leafsFound[string(iter.LeafKey())] = true
+ }
+ }
+
+ // We should still respect the prefix boundary even when skipping
+ prefix := []byte("a")
+ for key := range leafsFound {
+ if !bytes.HasPrefix([]byte(key), prefix) {
+ t.Errorf("Found key outside prefix when using descend=false: %s", key)
+ }
+ }
+
+ // Should not have found "b" even if we skip some subtrees
+ if leafsFound["b"] {
+ t.Error("Iterator leaked outside prefix boundary with descend=false")
+ }
+ })
+}
+
func BenchmarkIterator(b *testing.B) {
diskDb, srcDb, tr, _ := makeTestTrie(rawdb.HashScheme)
root := tr.Hash()
diff --git a/trie/proof_test.go b/trie/proof_test.go
index b3c9dd753c..40c49f358b 100644
--- a/trie/proof_test.go
+++ b/trie/proof_test.go
@@ -109,7 +109,7 @@ func TestOneElementProof(t *testing.T) {
t.Fatalf("prover %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
}
if !bytes.Equal(val, []byte("v")) {
- t.Fatalf("prover %d: verified value mismatch: have %x, want 'k'", i, val)
+ t.Fatalf("prover %d: verified value mismatch: have %x, want 'v'", i, val)
}
}
}
diff --git a/trie/trie.go b/trie/trie.go
index 630462f8ca..36cc732ee8 100644
--- a/trie/trie.go
+++ b/trie/trie.go
@@ -134,6 +134,34 @@ func (t *Trie) NodeIterator(start []byte) (NodeIterator, error) {
return newNodeIterator(t, start), nil
}
+// NodeIteratorWithPrefix returns an iterator that returns nodes of the trie
+// whose leaf keys start with the given prefix. Iteration includes all keys
+// where prefix <= k < nextKey(prefix), effectively returning only keys that
+// have the prefix. The iteration stops once it would encounter a key that
+// doesn't start with the prefix.
+//
+// For example, with prefix "dog", the iterator will return "dog", "dogcat",
+// "dogfish" but not "dot" or "fog". An empty prefix iterates the entire trie.
+func (t *Trie) NodeIteratorWithPrefix(prefix []byte) (NodeIterator, error) {
+ // Short circuit if the trie is already committed and not usable.
+ if t.committed {
+ return nil, ErrCommitted
+ }
+ // Use the dedicated prefix iterator which handles prefix checking correctly
+ return newPrefixIterator(t, prefix)
+}
+
+// NodeIteratorWithRange returns an iterator over trie nodes whose leaf keys
+// fall within the specified range. It includes all keys where start <= k < end.
+// Iteration stops once a key beyond the end boundary is encountered.
+func (t *Trie) NodeIteratorWithRange(start, end []byte) (NodeIterator, error) {
+ // Short circuit if the trie is already committed and not usable.
+ if t.committed {
+ return nil, ErrCommitted
+ }
+ return newSubtreeIterator(t, start, end)
+}
+
// MustGet is a wrapper of Get and will omit any encountered error but just
// print out an error message.
func (t *Trie) MustGet(key []byte) []byte {
diff --git a/trie/trienode/node.go b/trie/trienode/node.go
index c83dc27cef..228a64f04c 100644
--- a/trie/trienode/node.go
+++ b/trie/trienode/node.go
@@ -259,11 +259,24 @@ func (set *MergedNodeSet) Merge(other *NodeSet) error {
return nil
}
-// Flatten returns a two-dimensional map for internal nodes.
-func (set *MergedNodeSet) Flatten() map[common.Hash]map[string]*Node {
+// Nodes returns a two-dimensional map for internal nodes.
+func (set *MergedNodeSet) Nodes() map[common.Hash]map[string]*Node {
nodes := make(map[common.Hash]map[string]*Node, len(set.Sets))
for owner, set := range set.Sets {
nodes[owner] = set.Nodes
}
return nodes
}
+
+// NodeAndOrigins returns a two-dimensional map for internal nodes along with
+// their original values.
+func (set *MergedNodeSet) NodeAndOrigins() (map[common.Hash]map[string]*Node, map[common.Hash]map[string][]byte) {
+ var (
+ nodes = make(map[common.Hash]map[string]*Node, len(set.Sets))
+ origins = make(map[common.Hash]map[string][]byte, len(set.Sets))
+ )
+ for owner, set := range set.Sets {
+ nodes[owner], origins[owner] = set.Nodes, set.Origins
+ }
+ return nodes, origins
+}
diff --git a/triedb/database.go b/triedb/database.go
index e2f4334d6e..d2637bd909 100644
--- a/triedb/database.go
+++ b/triedb/database.go
@@ -375,3 +375,12 @@ func (db *Database) IsVerkle() bool {
func (db *Database) Disk() ethdb.Database {
return db.disk
}
+
+// SnapshotCompleted returns the indicator if the snapshot is completed.
+func (db *Database) SnapshotCompleted() bool {
+ pdb, ok := db.backend.(*pathdb.Database)
+ if !ok {
+ return false
+ }
+ return pdb.SnapshotCompleted()
+}
diff --git a/triedb/pathdb/config.go b/triedb/pathdb/config.go
new file mode 100644
index 0000000000..3745a63edd
--- /dev/null
+++ b/triedb/pathdb/config.go
@@ -0,0 +1,118 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package pathdb
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+const (
+ // defaultTrieCleanSize is the default memory allowance of clean trie cache.
+ defaultTrieCleanSize = 16 * 1024 * 1024
+
+ // defaultStateCleanSize is the default memory allowance of clean state cache.
+ defaultStateCleanSize = 16 * 1024 * 1024
+
+ // maxBufferSize is the maximum memory allowance of node buffer.
+ // Too large buffer will cause the system to pause for a long
+ // time when write happens. Also, the largest batch that pebble can
+ // support is 4GB, node will panic if batch size exceeds this limit.
+ maxBufferSize = 256 * 1024 * 1024
+
+ // defaultBufferSize is the default memory allowance of node buffer
+ // that aggregates the writes from above until it's flushed into the
+ // disk. It's meant to be used once the initial sync is finished.
+ // Do not increase the buffer size arbitrarily, otherwise the system
+ // pause time will increase when the database writes happen.
+ defaultBufferSize = 64 * 1024 * 1024
+)
+
+var (
+ // maxDiffLayers is the maximum diff layers allowed in the layer tree.
+ maxDiffLayers = 128
+)
+
+// Defaults contains default settings for Ethereum mainnet.
+var Defaults = &Config{
+ StateHistory: params.FullImmutabilityThreshold,
+ EnableStateIndexing: false,
+ TrieCleanSize: defaultTrieCleanSize,
+ StateCleanSize: defaultStateCleanSize,
+ WriteBufferSize: defaultBufferSize,
+}
+
+// ReadOnly is the config in order to open database in read only mode.
+var ReadOnly = &Config{
+ ReadOnly: true,
+ TrieCleanSize: defaultTrieCleanSize,
+ StateCleanSize: defaultStateCleanSize,
+}
+
+// Config contains the settings for database.
+type Config struct {
+ StateHistory uint64 // Number of recent blocks to maintain state history for, 0: full chain
+ EnableStateIndexing bool // Whether to enable state history indexing for external state access
+ TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie data
+ StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data
+ WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer
+ ReadOnly bool // Flag whether the database is opened in read only mode
+ JournalDirectory string // Absolute path of journal directory (null means the journal data is persisted in key-value store)
+
+ // Testing configurations
+ SnapshotNoBuild bool // Flag Whether the state generation is disabled
+ NoAsyncFlush bool // Flag whether the background buffer flushing is disabled
+ NoAsyncGeneration bool // Flag whether the background generation is disabled
+}
+
+// sanitize checks the provided user configurations and changes anything that's
+// unreasonable or unworkable.
+func (c *Config) sanitize() *Config {
+ conf := *c
+ if conf.WriteBufferSize > maxBufferSize {
+ log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.WriteBufferSize), "updated", common.StorageSize(maxBufferSize))
+ conf.WriteBufferSize = maxBufferSize
+ }
+ return &conf
+}
+
+// fields returns a list of attributes of config for printing.
+func (c *Config) fields() []interface{} {
+ var list []interface{}
+ if c.ReadOnly {
+ list = append(list, "readonly", true)
+ }
+ list = append(list, "triecache", common.StorageSize(c.TrieCleanSize))
+ list = append(list, "statecache", common.StorageSize(c.StateCleanSize))
+ list = append(list, "buffer", common.StorageSize(c.WriteBufferSize))
+
+ if c.StateHistory == 0 {
+ list = append(list, "state-history", "entire chain")
+ } else {
+ list = append(list, "state-history", fmt.Sprintf("last %d blocks", c.StateHistory))
+ }
+ if c.EnableStateIndexing {
+ list = append(list, "index-history", true)
+ }
+ if c.JournalDirectory != "" {
+ list = append(list, "journal-dir", c.JournalDirectory)
+ }
+ return list
+}
diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go
index f438c64aa2..546d2e0301 100644
--- a/triedb/pathdb/database.go
+++ b/triedb/pathdb/database.go
@@ -31,37 +31,10 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-verkle"
)
-const (
- // defaultTrieCleanSize is the default memory allowance of clean trie cache.
- defaultTrieCleanSize = 16 * 1024 * 1024
-
- // defaultStateCleanSize is the default memory allowance of clean state cache.
- defaultStateCleanSize = 16 * 1024 * 1024
-
- // maxBufferSize is the maximum memory allowance of node buffer.
- // Too large buffer will cause the system to pause for a long
- // time when write happens. Also, the largest batch that pebble can
- // support is 4GB, node will panic if batch size exceeds this limit.
- maxBufferSize = 256 * 1024 * 1024
-
- // defaultBufferSize is the default memory allowance of node buffer
- // that aggregates the writes from above until it's flushed into the
- // disk. It's meant to be used once the initial sync is finished.
- // Do not increase the buffer size arbitrarily, otherwise the system
- // pause time will increase when the database writes happen.
- defaultBufferSize = 64 * 1024 * 1024
-)
-
-var (
- // maxDiffLayers is the maximum diff layers allowed in the layer tree.
- maxDiffLayers = 128
-)
-
// layer is the interface implemented by all state layers which includes some
// public methods and some additional methods for internal usage.
type layer interface {
@@ -105,7 +78,7 @@ type layer interface {
// the provided dirty trie nodes along with the state change set.
//
// Note, the maps are retained by the method to avoid copying everything.
- update(root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer
+ update(root common.Hash, id uint64, block uint64, nodes *nodeSetWithOrigin, states *StateSetWithOrigin) *diffLayer
// journal commits an entire diff hierarchy to disk into a single journal entry.
// This is meant to be used during shutdown to persist the layer without
@@ -113,68 +86,6 @@ type layer interface {
journal(w io.Writer) error
}
-// Config contains the settings for database.
-type Config struct {
- StateHistory uint64 // Number of recent blocks to maintain state history for
- EnableStateIndexing bool // Whether to enable state history indexing for external state access
- TrieCleanSize int // Maximum memory allowance (in bytes) for caching clean trie nodes
- StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data
- WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer
- ReadOnly bool // Flag whether the database is opened in read only mode
- JournalDirectory string // Absolute path of journal directory (null means the journal data is persisted in key-value store)
-
- // Testing configurations
- SnapshotNoBuild bool // Flag Whether the state generation is allowed
- NoAsyncFlush bool // Flag whether the background buffer flushing is allowed
- NoAsyncGeneration bool // Flag whether the background generation is allowed
-}
-
-// sanitize checks the provided user configurations and changes anything that's
-// unreasonable or unworkable.
-func (c *Config) sanitize() *Config {
- conf := *c
- if conf.WriteBufferSize > maxBufferSize {
- log.Warn("Sanitizing invalid node buffer size", "provided", common.StorageSize(conf.WriteBufferSize), "updated", common.StorageSize(maxBufferSize))
- conf.WriteBufferSize = maxBufferSize
- }
- return &conf
-}
-
-// fields returns a list of attributes of config for printing.
-func (c *Config) fields() []interface{} {
- var list []interface{}
- if c.ReadOnly {
- list = append(list, "readonly", true)
- }
- if c.SnapshotNoBuild {
- list = append(list, "snapshot", false)
- }
- list = append(list, "triecache", common.StorageSize(c.TrieCleanSize))
- list = append(list, "statecache", common.StorageSize(c.StateCleanSize))
- list = append(list, "buffer", common.StorageSize(c.WriteBufferSize))
-
- if c.StateHistory == 0 {
- list = append(list, "history", "entire chain")
- } else {
- list = append(list, "history", fmt.Sprintf("last %d blocks", c.StateHistory))
- }
- if c.JournalDirectory != "" {
- list = append(list, "journal-dir", c.JournalDirectory)
- }
- return list
-}
-
-// Defaults contains default settings for Ethereum mainnet.
-var Defaults = &Config{
- StateHistory: params.FullImmutabilityThreshold,
- TrieCleanSize: defaultTrieCleanSize,
- StateCleanSize: defaultStateCleanSize,
- WriteBufferSize: defaultBufferSize,
-}
-
-// ReadOnly is the config in order to open database in read only mode.
-var ReadOnly = &Config{ReadOnly: true}
-
// nodeHasher is the function to compute the hash of supplied node blob.
type nodeHasher func([]byte) (common.Hash, error)
@@ -278,7 +189,7 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
}
// TODO (rjl493456442) disable the background indexing in read-only mode
if db.stateFreezer != nil && db.config.EnableStateIndexing {
- db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID())
+ db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID(), typeStateHistory)
log.Info("Enabled state history indexing")
}
fields := config.fields()
@@ -334,7 +245,7 @@ func (db *Database) repairHistory() error {
}
// Truncate the extra state histories above in freezer in case it's not
// aligned with the disk layer. It might happen after a unclean shutdown.
- pruned, err := truncateFromHead(db.stateFreezer, id)
+ pruned, err := truncateFromHead(db.stateFreezer, typeStateHistory, id)
if err != nil {
log.Crit("Failed to truncate extra state histories", "err", err)
}
@@ -422,7 +333,8 @@ func (db *Database) Update(root common.Hash, parentRoot common.Hash, block uint6
if err := db.modifyAllowed(); err != nil {
return err
}
- if err := db.tree.add(root, parentRoot, block, nodes, states); err != nil {
+ // TODO(rjl493456442) tracking the origins in the following PRs.
+ if err := db.tree.add(root, parentRoot, block, NewNodeSetWithOrigin(nodes.Nodes(), nil), states); err != nil {
return err
}
// Keep 128 diff layers in the memory, persistent layer is 129th.
@@ -536,7 +448,7 @@ func (db *Database) Enable(root common.Hash) error {
// 2. Re-initialize the indexer so it starts indexing from the new state root.
if db.stateIndexer != nil && db.stateFreezer != nil && db.config.EnableStateIndexing {
db.stateIndexer.close()
- db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID())
+ db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID(), typeStateHistory)
log.Info("Re-enabled state history indexing")
}
log.Info("Rebuilt trie database", "root", root)
@@ -590,7 +502,7 @@ func (db *Database) Recover(root common.Hash) error {
if err := db.diskdb.SyncKeyValue(); err != nil {
return err
}
- _, err := truncateFromHead(db.stateFreezer, dl.stateID())
+ _, err := truncateFromHead(db.stateFreezer, typeStateHistory, dl.stateID())
if err != nil {
return err
}
@@ -769,3 +681,14 @@ func (db *Database) StorageIterator(root common.Hash, account common.Hash, seek
}
return newFastStorageIterator(db, root, account, seek)
}
+
+// SnapshotCompleted returns the flag indicating if the snapshot generation is completed.
+func (db *Database) SnapshotCompleted() bool {
+ db.lock.RLock()
+ wait := db.waitSync
+ db.lock.RUnlock()
+ if wait {
+ return false
+ }
+ return db.tree.bottom().genComplete()
+}
diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go
index 47d13e54a4..8cca7b1b3c 100644
--- a/triedb/pathdb/database_test.go
+++ b/triedb/pathdb/database_test.go
@@ -36,9 +36,10 @@ import (
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/holiman/uint256"
+ "golang.org/x/exp/maps"
)
-func updateTrie(db *Database, stateRoot common.Hash, addrHash common.Hash, root common.Hash, dirties map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
+func updateTrie(db *Database, stateRoot common.Hash, addrHash common.Hash, root common.Hash, entries map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
var id *trie.ID
if addrHash == (common.Hash{}) {
id = trie.StateTrieID(stateRoot)
@@ -49,13 +50,17 @@ func updateTrie(db *Database, stateRoot common.Hash, addrHash common.Hash, root
if err != nil {
panic(fmt.Errorf("failed to load trie, err: %w", err))
}
- for key, val := range dirties {
+ var deletes []common.Hash
+ for key, val := range entries {
if len(val) == 0 {
- tr.Delete(key.Bytes())
+ deletes = append(deletes, key)
} else {
tr.Update(key.Bytes(), val)
}
}
+ for _, key := range deletes {
+ tr.Delete(key.Bytes())
+ }
return tr.Commit(false)
}
@@ -72,16 +77,18 @@ const (
createAccountOp int = iota
modifyAccountOp
deleteAccountOp
+ resurrectAccountOp
opLen
)
+// genctx carries the generation context used within a single state transition.
type genctx struct {
stateRoot common.Hash
accounts map[common.Hash][]byte // Keyed by the hash of account address
storages map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
accountOrigin map[common.Address][]byte // Keyed by the account address
storageOrigin map[common.Address]map[common.Hash][]byte // Keyed by the account address and the hash of storage key
- nodes *trienode.MergedNodeSet
+ nodes *trienode.MergedNodeSet // Trie nodes produced from the state transition
}
func newCtx(stateRoot common.Hash) *genctx {
@@ -114,6 +121,8 @@ func (ctx *genctx) storageOriginSet(rawStorageKey bool, t *tester) map[common.Ad
type tester struct {
db *Database
roots []common.Hash
+ nodes []*trienode.MergedNodeSet
+ states []*StateSetWithOrigin
preimages map[common.Hash][]byte
// current state set
@@ -123,20 +132,57 @@ type tester struct {
// state snapshots
snapAccounts map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address
snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
+
+ // trienode snapshots
+ snapNodes map[common.Hash]*trienode.MergedNodeSet
+}
+
+// testerConfig holds configuration parameters for running a test scenario.
+type testerConfig struct {
+ stateHistory uint64 // Number of historical states to retain
+ layers int // Number of state transitions to generate for
+ enableIndex bool // Enable state history indexing or not
+ journalDir string // Directory path for persisting journal files
+ isVerkle bool // Enables Verkle trie mode if true
+
+ writeBuffer *int // Optional, the size of memory allocated for write buffer
+ trieCache *int // Optional, the size of memory allocated for trie cache
+ stateCache *int // Optional, the size of memory allocated for state cache
+}
+
+func (c *testerConfig) trieCacheSize() int {
+ if c.trieCache != nil {
+ return *c.trieCache
+ }
+ return 256 * 1024
+}
+
+func (c *testerConfig) stateCacheSize() int {
+ if c.stateCache != nil {
+ return *c.stateCache
+ }
+ return 256 * 1024
+}
+
+func (c *testerConfig) writeBufferSize() int {
+ if c.writeBuffer != nil {
+ return *c.writeBuffer
+ }
+ return 256 * 1024
}
-func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, enableIndex bool, journalDir string) *tester {
+func newTester(t *testing.T, config *testerConfig) *tester {
var (
disk, _ = rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()})
db = New(disk, &Config{
- StateHistory: historyLimit,
- EnableStateIndexing: enableIndex,
- TrieCleanSize: 256 * 1024,
- StateCleanSize: 256 * 1024,
- WriteBufferSize: 256 * 1024,
+ StateHistory: config.stateHistory,
+ EnableStateIndexing: config.enableIndex,
+ TrieCleanSize: config.trieCacheSize(),
+ StateCleanSize: config.stateCacheSize(),
+ WriteBufferSize: config.writeBufferSize(),
NoAsyncFlush: true,
- JournalDirectory: journalDir,
- }, isVerkle)
+ JournalDirectory: config.journalDir,
+ }, config.isVerkle)
obj = &tester{
db: db,
@@ -145,9 +191,10 @@ func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, ena
storages: make(map[common.Hash]map[common.Hash][]byte),
snapAccounts: make(map[common.Hash]map[common.Hash][]byte),
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte),
+ snapNodes: make(map[common.Hash]*trienode.MergedNodeSet),
}
)
- for i := 0; i < layers; i++ {
+ for i := 0; i < config.layers; i++ {
var parent = types.EmptyRootHash
if len(obj.roots) != 0 {
parent = obj.roots[len(obj.roots)-1]
@@ -158,6 +205,8 @@ func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, ena
panic(fmt.Errorf("failed to update state changes, err: %w", err))
}
obj.roots = append(obj.roots, root)
+ obj.nodes = append(obj.nodes, nodes)
+ obj.states = append(obj.states, states)
}
return obj
}
@@ -181,6 +230,8 @@ func (t *tester) extend(layers int) {
panic(fmt.Errorf("failed to update state changes, err: %w", err))
}
t.roots = append(t.roots, root)
+ t.nodes = append(t.nodes, nodes)
+ t.states = append(t.states, states)
}
}
@@ -270,10 +321,53 @@ func (t *tester) clearStorage(ctx *genctx, addr common.Address, root common.Hash
return root
}
+func (t *tester) resurrectStorage(ctx *genctx, addr common.Address, old map[common.Hash][]byte) common.Hash {
+ var (
+ addrHash = crypto.Keccak256Hash(addr.Bytes())
+ storage = make(map[common.Hash][]byte)
+ origin = make(map[common.Hash][]byte)
+ )
+ for i := 0; i < 3; i++ {
+ v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
+ key := testrand.Bytes(32)
+ hash := crypto.Keccak256Hash(key)
+ t.preimages[hash] = key
+
+ storage[hash] = v
+ origin[hash] = nil
+ }
+ var cnt int
+ for khash := range old {
+ cnt += 1
+ v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
+
+ storage[khash] = v
+ origin[khash] = old[khash]
+ if cnt >= 3 {
+ break
+ }
+ }
+ root, set := updateTrie(t.db, ctx.stateRoot, addrHash, types.EmptyRootHash, storage)
+
+ maps.Copy(ctx.storages[addrHash], storage)
+ if ctx.storageOrigin[addr] == nil {
+ ctx.storageOrigin[addr] = make(map[common.Hash][]byte)
+ }
+ for k, v := range origin {
+ if _, exists := ctx.storageOrigin[addr][k]; !exists {
+ ctx.storageOrigin[addr][k] = v
+ }
+ }
+ ctx.nodes.Merge(set)
+ return root
+}
+
func (t *tester) generate(parent common.Hash, rawStorageKey bool) (common.Hash, *trienode.MergedNodeSet, *StateSetWithOrigin) {
var (
- ctx = newCtx(parent)
- dirties = make(map[common.Hash]struct{})
+ ctx = newCtx(parent)
+ dirties = make(map[common.Hash]struct{})
+ deleted = make(map[common.Address]struct{})
+ resurrect = make(map[common.Address]struct{})
)
for i := 0; i < 20; i++ {
// Start with account creation always
@@ -336,6 +430,7 @@ func (t *tester) generate(parent common.Hash, rawStorageKey bool) (common.Hash,
continue
}
dirties[addrHash] = struct{}{}
+ deleted[addr] = struct{}{}
acct, _ := types.FullAccount(account)
if acct.Root != types.EmptyRootHash {
@@ -343,6 +438,25 @@ func (t *tester) generate(parent common.Hash, rawStorageKey bool) (common.Hash,
}
ctx.accounts[addrHash] = nil
ctx.accountOrigin[addr] = account
+
+ case resurrectAccountOp:
+ if len(deleted) == 0 {
+ continue
+ }
+ addresses := maps.Keys(deleted)
+ addr := addresses[rand.Intn(len(addresses))]
+ if _, exist := resurrect[addr]; exist {
+ continue
+ }
+ resurrect[addr] = struct{}{}
+
+ addrHash := crypto.Keccak256Hash(addr.Bytes())
+ root := t.resurrectStorage(ctx, addr, t.storages[addrHash])
+ ctx.accounts[addrHash] = types.SlimAccountRLP(generateAccount(root))
+ if _, exist := ctx.accountOrigin[addr]; !exist {
+ ctx.accountOrigin[addr] = nil
+ }
+ t.preimages[addrHash] = addr.Bytes()
}
}
root, set := updateTrie(t.db, parent, common.Hash{}, parent, ctx.accounts)
@@ -351,6 +465,7 @@ func (t *tester) generate(parent common.Hash, rawStorageKey bool) (common.Hash,
// Save state snapshot before commit
t.snapAccounts[parent] = copyAccounts(t.accounts)
t.snapStorages[parent] = copyStorages(t.storages)
+ t.snapNodes[parent] = ctx.nodes
// Commit all changes to live state set
for addrHash, account := range ctx.accounts {
@@ -470,8 +585,7 @@ func TestDatabaseRollback(t *testing.T) {
maxDiffLayers = 128
}()
- // Verify state histories
- tester := newTester(t, 0, false, 32, false, "")
+ tester := newTester(t, &testerConfig{layers: 32})
defer tester.release()
if err := tester.verifyHistory(); err != nil {
@@ -505,7 +619,7 @@ func TestDatabaseRecoverable(t *testing.T) {
}()
var (
- tester = newTester(t, 0, false, 12, false, "")
+ tester = newTester(t, &testerConfig{layers: 12})
index = tester.bottomIndex()
)
defer tester.release()
@@ -526,7 +640,7 @@ func TestDatabaseRecoverable(t *testing.T) {
// Layers below current disk layer are recoverable
{tester.roots[index-1], true},
- // Disklayer itself is not recoverable, since it's
+ // Disk layer itself is not recoverable, since it's
// available for accessing.
{tester.roots[index], false},
@@ -542,6 +656,59 @@ func TestDatabaseRecoverable(t *testing.T) {
}
}
+func TestExecuteRollback(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
+ tester := newTester(t, &testerConfig{layers: 32})
+ defer tester.release()
+
+ // Revert database from top to bottom
+ for i := tester.bottomIndex(); i >= 0; i-- {
+ dl := tester.db.tree.bottom()
+ h, err := readStateHistory(tester.db.stateFreezer, dl.stateID())
+ if err != nil {
+ t.Fatalf("Failed to read history, err: %v", err)
+ }
+ nodes, err := apply(tester.db, h.meta.parent, h.meta.root, h.meta.version == stateHistoryV1, h.accounts, h.storages)
+ if err != nil {
+ t.Fatalf("Failed to apply history, err: %v", err)
+ }
+
+ // Verify the produced node set, ensuring they are aligned with the
+ // tracked dirty nodes.
+ want := tester.snapNodes[h.meta.parent]
+ if len(nodes) != len(want.Sets) {
+ t.Fatalf("Unexpected node sets, want: %d, got: %d", len(want.Sets), len(nodes))
+ }
+ for owner, setA := range nodes {
+ setB, ok := want.Sets[owner]
+ if !ok {
+ t.Fatalf("Excessive nodeset, %x", owner)
+ }
+ if len(setA) != len(setB.Origins) {
+ t.Fatalf("Unexpected origins, want: %d, got: %d", len(setA), len(setB.Origins))
+ }
+ for k, nA := range setA {
+ nB, ok := setB.Origins[k]
+ if !ok {
+ t.Fatalf("Excessive node, %v", []byte(k))
+ }
+ if !bytes.Equal(nA.Blob, nB) {
+ t.Fatalf("Unexpected node value, want: %v, got: %v", nA.Blob, nB)
+ }
+ }
+ }
+
+ if err := tester.db.Recover(h.meta.parent); err != nil {
+ t.Fatalf("Failed to recover db, err: %v", err)
+ }
+ }
+}
+
func TestDisable(t *testing.T) {
// Redefine the diff layer depth allowance for faster testing.
maxDiffLayers = 4
@@ -549,7 +716,7 @@ func TestDisable(t *testing.T) {
maxDiffLayers = 128
}()
- tester := newTester(t, 0, false, 32, false, "")
+ tester := newTester(t, &testerConfig{layers: 32})
defer tester.release()
stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil))
@@ -563,10 +730,6 @@ func TestDisable(t *testing.T) {
t.Fatalf("Failed to activate database: %v", err)
}
- // Ensure journal is deleted from disk
- if blob := rawdb.ReadTrieJournal(tester.db.diskdb); len(blob) != 0 {
- t.Fatal("Failed to clean journal")
- }
// Ensure all trie histories are removed
n, err := tester.db.stateFreezer.Ancients()
if err != nil {
@@ -591,7 +754,7 @@ func TestCommit(t *testing.T) {
maxDiffLayers = 128
}()
- tester := newTester(t, 0, false, 12, false, "")
+ tester := newTester(t, &testerConfig{layers: 12})
defer tester.release()
if err := tester.db.Commit(tester.lastHash(), false); err != nil {
@@ -626,7 +789,7 @@ func testJournal(t *testing.T, journalDir string) {
maxDiffLayers = 128
}()
- tester := newTester(t, 0, false, 12, false, journalDir)
+ tester := newTester(t, &testerConfig{layers: 12, journalDir: journalDir})
defer tester.release()
if err := tester.db.Journal(tester.lastHash()); err != nil {
@@ -673,7 +836,7 @@ func testCorruptedJournal(t *testing.T, journalDir string, modifyFn func(databas
maxDiffLayers = 128
}()
- tester := newTester(t, 0, false, 12, false, journalDir)
+ tester := newTester(t, &testerConfig{layers: 12, journalDir: journalDir})
defer tester.release()
if err := tester.db.Journal(tester.lastHash()); err != nil {
@@ -718,7 +881,7 @@ func TestTailTruncateHistory(t *testing.T) {
maxDiffLayers = 128
}()
- tester := newTester(t, 10, false, 12, false, "")
+ tester := newTester(t, &testerConfig{layers: 12, stateHistory: 10})
defer tester.release()
tester.db.Close()
@@ -754,3 +917,107 @@ func copyStorages(set map[common.Hash]map[common.Hash][]byte) map[common.Hash]ma
}
return copied
}
+
+func TestDatabaseIndexRecovery(t *testing.T) {
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
+ //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
+ writeBuffer := 512 * 1024
+ config := &testerConfig{
+ layers: 64,
+ enableIndex: true,
+ writeBuffer: &writeBuffer,
+ }
+ env := newTester(t, config)
+ defer env.release()
+
+ // Ensure the buffer in disk layer is not empty
+ var (
+ bRoot = env.db.tree.bottom().rootHash()
+ dRoot = crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(env.db.diskdb, nil))
+ )
+ for dRoot == bRoot {
+ env.extend(1)
+
+ bRoot = env.db.tree.bottom().rootHash()
+ dRoot = crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(env.db.diskdb, nil))
+ }
+ waitIndexing(env.db)
+
+ var (
+ dIndex int
+ roots = env.roots
+ hr = newHistoryReader(env.db.diskdb, env.db.stateFreezer)
+ )
+ for i, root := range roots {
+ if root == dRoot {
+ dIndex = i
+ }
+ if root == bRoot {
+ break
+ }
+ if err := checkHistoricalState(env, root, uint64(i+1), hr); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Terminate the database and mutate the journal, it's for simulating
+ // the unclean shutdown
+ env.db.Journal(env.lastHash())
+ env.db.Close()
+
+ // Mutate the journal in disk, it should be regarded as invalid
+ blob := rawdb.ReadTrieJournal(env.db.diskdb)
+ blob[0] = 0xa
+ rawdb.WriteTrieJournal(env.db.diskdb, blob)
+
+ // Reload the database, the extra state histories should be removed
+ env.db = New(env.db.diskdb, env.db.config, false)
+
+ for i := range roots {
+ _, err := readStateHistory(env.db.stateFreezer, uint64(i+1))
+ if i <= dIndex && err != nil {
+ t.Fatalf("State history is not found, %d", i)
+ }
+ if i > dIndex && err == nil {
+ t.Fatalf("Unexpected state history found, %d", i)
+ }
+ }
+ remain, err := env.db.IndexProgress()
+ if err != nil {
+ t.Fatalf("Failed to obtain the progress, %v", err)
+ }
+ if remain == 0 {
+ t.Fatalf("Unexpected progress remain, %d", remain)
+ }
+
+ // Apply new states on top, ensuring state indexing can respond correctly
+ for i := dIndex + 1; i < len(roots); i++ {
+ if err := env.db.Update(roots[i], roots[i-1], uint64(i), env.nodes[i], env.states[i]); err != nil {
+ panic(fmt.Errorf("failed to update state changes, err: %w", err))
+ }
+ }
+ remain, err = env.db.IndexProgress()
+ if err != nil {
+ t.Fatalf("Failed to obtain the progress, %v", err)
+ }
+ if remain != 0 {
+ t.Fatalf("Unexpected progress remain, %d", remain)
+ }
+ waitIndexing(env.db)
+
+ // Ensure the truncated state histories become accessible
+ bRoot = env.db.tree.bottom().rootHash()
+ hr = newHistoryReader(env.db.diskdb, env.db.stateFreezer)
+ for i, root := range roots {
+ if root == bRoot {
+ break
+ }
+ if err := checkHistoricalState(env, root, uint64(i+1), hr); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/triedb/pathdb/difflayer.go b/triedb/pathdb/difflayer.go
index ac05b4a0fb..ae523c979c 100644
--- a/triedb/pathdb/difflayer.go
+++ b/triedb/pathdb/difflayer.go
@@ -34,7 +34,7 @@ type diffLayer struct {
root common.Hash // Root hash to which this layer diff belongs to
id uint64 // Corresponding state id
block uint64 // Associated block number
- nodes *nodeSet // Cached trie nodes indexed by owner and path
+ nodes *nodeSetWithOrigin // Cached trie nodes indexed by owner and path
states *StateSetWithOrigin // Associated state changes along with origin value
parent layer // Parent layer modified by this one, never nil, **can be changed**
@@ -42,7 +42,7 @@ type diffLayer struct {
}
// newDiffLayer creates a new diff layer on top of an existing layer.
-func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer {
+func newDiffLayer(parent layer, root common.Hash, id uint64, block uint64, nodes *nodeSetWithOrigin, states *StateSetWithOrigin) *diffLayer {
dl := &diffLayer{
root: root,
id: id,
@@ -151,7 +151,7 @@ func (dl *diffLayer) storage(accountHash, storageHash common.Hash, depth int) ([
// update implements the layer interface, creating a new layer on top of the
// existing layer tree with the specified data items.
-func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer {
+func (dl *diffLayer) update(root common.Hash, id uint64, block uint64, nodes *nodeSetWithOrigin, states *StateSetWithOrigin) *diffLayer {
return newDiffLayer(dl, root, id, block, nodes, states)
}
diff --git a/triedb/pathdb/difflayer_test.go b/triedb/pathdb/difflayer_test.go
index 83ed833486..0484fd9644 100644
--- a/triedb/pathdb/difflayer_test.go
+++ b/triedb/pathdb/difflayer_test.go
@@ -76,7 +76,7 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
nblob = common.CopyBytes(blob)
}
}
- return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ return newDiffLayer(parent, common.Hash{}, 0, 0, NewNodeSetWithOrigin(nodes, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
}
var layer layer
layer = emptyLayer()
@@ -118,7 +118,7 @@ func BenchmarkPersist(b *testing.B) {
)
nodes[common.Hash{}][string(path)] = node
}
- return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ return newDiffLayer(parent, common.Hash{}, 0, 0, NewNodeSetWithOrigin(nodes, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
}
for i := 0; i < b.N; i++ {
b.StopTimer()
@@ -156,7 +156,7 @@ func BenchmarkJournal(b *testing.B) {
)
nodes[common.Hash{}][string(path)] = node
}
- return newDiffLayer(parent, common.Hash{}, 0, 0, newNodeSet(nodes), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ return newDiffLayer(parent, common.Hash{}, 0, 0, NewNodeSetWithOrigin(nodes, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
}
var layer layer
layer = emptyLayer()
diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go
index 13df6251e8..76f3f5a46e 100644
--- a/triedb/pathdb/disklayer.go
+++ b/triedb/pathdb/disklayer.go
@@ -319,7 +319,7 @@ func (dl *diskLayer) storage(accountHash, storageHash common.Hash, depth int) ([
// update implements the layer interface, returning a new diff layer on top
// with the given state set.
-func (dl *diskLayer) update(root common.Hash, id uint64, block uint64, nodes *nodeSet, states *StateSetWithOrigin) *diffLayer {
+func (dl *diskLayer) update(root common.Hash, id uint64, block uint64, nodes *nodeSetWithOrigin, states *StateSetWithOrigin) *diffLayer {
return newDiffLayer(dl, root, id, block, nodes, states)
}
@@ -378,7 +378,7 @@ func (dl *diskLayer) writeStateHistory(diff *diffLayer) (bool, error) {
log.Debug("Skip tail truncation", "persistentID", persistentID, "tailID", tail+1, "headID", diff.stateID(), "limit", limit)
return true, nil
}
- pruned, err := truncateFromTail(dl.db.stateFreezer, newFirst-1)
+ pruned, err := truncateFromTail(dl.db.stateFreezer, typeStateHistory, newFirst-1)
if err != nil {
return false, err
}
@@ -413,7 +413,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
// Merge the trie nodes and flat states of the bottom-most diff layer into the
// buffer as the combined layer.
- combined := dl.buffer.commit(bottom.nodes, bottom.states.stateSet)
+ combined := dl.buffer.commit(bottom.nodes.nodeSet, bottom.states.stateSet)
// Terminate the background state snapshot generation before mutating the
// persistent state.
diff --git a/triedb/pathdb/execute.go b/triedb/pathdb/execute.go
index aa4bd8b44b..4c1cafec12 100644
--- a/triedb/pathdb/execute.go
+++ b/triedb/pathdb/execute.go
@@ -59,13 +59,19 @@ func apply(db database.NodeDatabase, prevRoot common.Hash, postRoot common.Hash,
rawStorageKey: rawStorageKey,
nodes: trienode.NewMergedNodeSet(),
}
+ var deletes []common.Address
for addr, account := range accounts {
- var err error
if len(account) == 0 {
- err = deleteAccount(ctx, db, addr)
+ deletes = append(deletes, addr)
} else {
- err = updateAccount(ctx, db, addr)
+ err := updateAccount(ctx, db, addr)
+ if err != nil {
+ return nil, fmt.Errorf("failed to revert state, err: %w", err)
+ }
}
+ }
+ for _, addr := range deletes {
+ err := deleteAccount(ctx, db, addr)
if err != nil {
return nil, fmt.Errorf("failed to revert state, err: %w", err)
}
@@ -77,7 +83,7 @@ func apply(db database.NodeDatabase, prevRoot common.Hash, postRoot common.Hash,
if err := ctx.nodes.Merge(result); err != nil {
return nil, err
}
- return ctx.nodes.Flatten(), nil
+ return ctx.nodes.Nodes(), nil
}
// updateAccount the account was present in prev-state, and may or may not
@@ -108,17 +114,23 @@ func updateAccount(ctx *context, db database.NodeDatabase, addr common.Address)
if err != nil {
return err
}
+ var deletes []common.Hash
for key, val := range ctx.storages[addr] {
tkey := key
if ctx.rawStorageKey {
tkey = crypto.Keccak256Hash(key.Bytes())
}
- var err error
if len(val) == 0 {
- err = st.Delete(tkey.Bytes())
+ deletes = append(deletes, tkey)
} else {
- err = st.Update(tkey.Bytes(), val)
+ err := st.Update(tkey.Bytes(), val)
+ if err != nil {
+ return err
+ }
}
+ }
+ for _, tkey := range deletes {
+ err := st.Delete(tkey.Bytes())
if err != nil {
return err
}
diff --git a/triedb/pathdb/history.go b/triedb/pathdb/history.go
index bbedd52f34..81b843d9f1 100644
--- a/triedb/pathdb/history.go
+++ b/triedb/pathdb/history.go
@@ -19,11 +19,147 @@ package pathdb
import (
"errors"
"fmt"
+ "iter"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
)
+// historyType represents the category of historical data.
+type historyType uint8
+
+const (
+ // typeStateHistory indicates history data related to account or storage changes.
+ typeStateHistory historyType = 0
+)
+
+// String returns the string format representation.
+func (h historyType) String() string {
+ switch h {
+ case typeStateHistory:
+ return "state"
+ default:
+ return fmt.Sprintf("unknown type: %d", h)
+ }
+}
+
+// elementType represents the category of state element.
+type elementType uint8
+
+const (
+ typeAccount elementType = 0 // represents the account data
+ typeStorage elementType = 1 // represents the storage slot data
+)
+
+// String returns the string format representation.
+func (e elementType) String() string {
+ switch e {
+ case typeAccount:
+ return "account"
+ case typeStorage:
+ return "storage"
+ default:
+ return fmt.Sprintf("unknown element type: %d", e)
+ }
+}
+
+// toHistoryType maps an element type to its corresponding history type.
+func toHistoryType(typ elementType) historyType {
+ if typ == typeAccount || typ == typeStorage {
+ return typeStateHistory
+ }
+ panic(fmt.Sprintf("unknown element type %v", typ))
+}
+
+// stateIdent represents the identifier of a state element, which can be
+// an account or a storage slot.
+type stateIdent struct {
+ typ elementType
+
+ // The hash of the account address. This is used instead of the raw account
+ // address is to align the traversal order with the Merkle-Patricia-Trie.
+ addressHash common.Hash
+
+ // The hash of the storage slot key. This is used instead of the raw slot key
+ // because, in legacy state histories (prior to the Cancun fork), the slot
+ // identifier is the hash of the key, and the original key (preimage) cannot
+ // be recovered. To maintain backward compatibility, the key hash is used.
+ //
+ // Meanwhile, using the storage key hash also preserve the traversal order
+ // with Merkle-Patricia-Trie.
+ //
+ // This field is null if the identifier refers to an account or a trie node.
+ storageHash common.Hash
+}
+
+// String returns the string format state identifier.
+func (ident stateIdent) String() string {
+ if ident.typ == typeAccount {
+ return ident.addressHash.Hex()
+ }
+ return ident.addressHash.Hex() + ident.storageHash.Hex()
+}
+
+// newAccountIdent constructs a state identifier for an account.
+func newAccountIdent(addressHash common.Hash) stateIdent {
+ return stateIdent{
+ typ: typeAccount,
+ addressHash: addressHash,
+ }
+}
+
+// newStorageIdent constructs a state identifier for a storage slot.
+// The address denotes the address hash of the associated account;
+// the storageHash denotes the hash of the raw storage slot key;
+func newStorageIdent(addressHash common.Hash, storageHash common.Hash) stateIdent {
+ return stateIdent{
+ typ: typeStorage,
+ addressHash: addressHash,
+ storageHash: storageHash,
+ }
+}
+
+// stateIdentQuery is the extension of stateIdent by adding the account address
+// and raw storage key.
+type stateIdentQuery struct {
+ stateIdent
+
+ address common.Address
+ storageKey common.Hash
+}
+
+// newAccountIdentQuery constructs a state identifier for an account.
+func newAccountIdentQuery(address common.Address, addressHash common.Hash) stateIdentQuery {
+ return stateIdentQuery{
+ stateIdent: newAccountIdent(addressHash),
+ address: address,
+ }
+}
+
+// newStorageIdentQuery constructs a state identifier for a storage slot.
+// the address denotes the address of the associated account;
+// the addressHash denotes the address hash of the associated account;
+// the storageKey denotes the raw storage slot key;
+// the storageHash denotes the hash of the raw storage slot key;
+func newStorageIdentQuery(address common.Address, addressHash common.Hash, storageKey common.Hash, storageHash common.Hash) stateIdentQuery {
+ return stateIdentQuery{
+ stateIdent: newStorageIdent(addressHash, storageHash),
+ address: address,
+ storageKey: storageKey,
+ }
+}
+
+// history defines the interface of historical data, implemented by stateHistory
+// and trienodeHistory (in the near future).
+type history interface {
+ // typ returns the historical data type held in the history.
+ typ() historyType
+
+ // forEach returns an iterator to traverse the state entries in the history.
+ forEach() iter.Seq[stateIdent]
+}
+
var (
errHeadTruncationOutOfRange = errors.New("history head truncation out of range")
errTailTruncationOutOfRange = errors.New("history tail truncation out of range")
@@ -31,7 +167,7 @@ var (
// truncateFromHead removes excess elements from the head of the freezer based
// on the given parameters. It returns the number of items that were removed.
-func truncateFromHead(store ethdb.AncientStore, nhead uint64) (int, error) {
+func truncateFromHead(store ethdb.AncientStore, typ historyType, nhead uint64) (int, error) {
ohead, err := store.Ancients()
if err != nil {
return 0, err
@@ -40,16 +176,16 @@ func truncateFromHead(store ethdb.AncientStore, nhead uint64) (int, error) {
if err != nil {
return 0, err
}
- log.Info("Truncating from head", "ohead", ohead, "tail", otail, "nhead", nhead)
-
// Ensure that the truncation target falls within the valid range.
if ohead < nhead || nhead < otail {
- return 0, fmt.Errorf("%w, tail: %d, head: %d, target: %d", errHeadTruncationOutOfRange, otail, ohead, nhead)
+ return 0, fmt.Errorf("%w, %s, tail: %d, head: %d, target: %d", errHeadTruncationOutOfRange, typ, otail, ohead, nhead)
}
// Short circuit if nothing to truncate.
if ohead == nhead {
return 0, nil
}
+ log.Info("Truncating from head", "type", typ.String(), "ohead", ohead, "tail", otail, "nhead", nhead)
+
ohead, err = store.TruncateHead(nhead)
if err != nil {
return 0, err
@@ -61,7 +197,7 @@ func truncateFromHead(store ethdb.AncientStore, nhead uint64) (int, error) {
// truncateFromTail removes excess elements from the end of the freezer based
// on the given parameters. It returns the number of items that were removed.
-func truncateFromTail(store ethdb.AncientStore, ntail uint64) (int, error) {
+func truncateFromTail(store ethdb.AncientStore, typ historyType, ntail uint64) (int, error) {
ohead, err := store.Ancients()
if err != nil {
return 0, err
@@ -72,7 +208,7 @@ func truncateFromTail(store ethdb.AncientStore, ntail uint64) (int, error) {
}
// Ensure that the truncation target falls within the valid range.
if otail > ntail || ntail > ohead {
- return 0, fmt.Errorf("%w, tail: %d, head: %d, target: %d", errTailTruncationOutOfRange, otail, ohead, ntail)
+ return 0, fmt.Errorf("%w, %s, tail: %d, head: %d, target: %d", errTailTruncationOutOfRange, typ, otail, ohead, ntail)
}
// Short circuit if nothing to truncate.
if otail == ntail {
diff --git a/triedb/pathdb/history_index.go b/triedb/pathdb/history_index.go
index e781a898e1..47cee9820d 100644
--- a/triedb/pathdb/history_index.go
+++ b/triedb/pathdb/history_index.go
@@ -78,12 +78,7 @@ type indexReader struct {
// loadIndexData loads the index data associated with the specified state.
func loadIndexData(db ethdb.KeyValueReader, state stateIdent) ([]*indexBlockDesc, error) {
- var blob []byte
- if state.account {
- blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
- } else {
- blob = rawdb.ReadStorageHistoryIndex(db, state.addressHash, state.storageHash)
- }
+ blob := readStateIndex(state, db)
if len(blob) == 0 {
return nil, nil
}
@@ -137,15 +132,8 @@ func (r *indexReader) readGreaterThan(id uint64) (uint64, error) {
br, ok := r.readers[desc.id]
if !ok {
- var (
- err error
- blob []byte
- )
- if r.state.account {
- blob = rawdb.ReadAccountHistoryIndexBlock(r.db, r.state.addressHash, desc.id)
- } else {
- blob = rawdb.ReadStorageHistoryIndexBlock(r.db, r.state.addressHash, r.state.storageHash, desc.id)
- }
+ var err error
+ blob := readStateIndexBlock(r.state, r.db, desc.id)
br, err = newBlockReader(blob)
if err != nil {
return 0, err
@@ -174,12 +162,7 @@ type indexWriter struct {
// newIndexWriter constructs the index writer for the specified state.
func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, error) {
- var blob []byte
- if state.account {
- blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
- } else {
- blob = rawdb.ReadStorageHistoryIndex(db, state.addressHash, state.storageHash)
- }
+ blob := readStateIndex(state, db)
if len(blob) == 0 {
desc := newIndexBlockDesc(0)
bw, _ := newBlockWriter(nil, desc)
@@ -194,15 +177,8 @@ func newIndexWriter(db ethdb.KeyValueReader, state stateIdent) (*indexWriter, er
if err != nil {
return nil, err
}
- var (
- indexBlock []byte
- lastDesc = descList[len(descList)-1]
- )
- if state.account {
- indexBlock = rawdb.ReadAccountHistoryIndexBlock(db, state.addressHash, lastDesc.id)
- } else {
- indexBlock = rawdb.ReadStorageHistoryIndexBlock(db, state.addressHash, state.storageHash, lastDesc.id)
- }
+ lastDesc := descList[len(descList)-1]
+ indexBlock := readStateIndexBlock(state, db, lastDesc.id)
bw, err := newBlockWriter(indexBlock, lastDesc)
if err != nil {
return nil, err
@@ -270,11 +246,7 @@ func (w *indexWriter) finish(batch ethdb.Batch) {
return // nothing to commit
}
for _, bw := range writers {
- if w.state.account {
- rawdb.WriteAccountHistoryIndexBlock(batch, w.state.addressHash, bw.desc.id, bw.finish())
- } else {
- rawdb.WriteStorageHistoryIndexBlock(batch, w.state.addressHash, w.state.storageHash, bw.desc.id, bw.finish())
- }
+ writeStateIndexBlock(w.state, batch, bw.desc.id, bw.finish())
}
w.frozen = nil // release all the frozen writers
@@ -282,11 +254,7 @@ func (w *indexWriter) finish(batch ethdb.Batch) {
for _, desc := range descList {
buf = append(buf, desc.encode()...)
}
- if w.state.account {
- rawdb.WriteAccountHistoryIndex(batch, w.state.addressHash, buf)
- } else {
- rawdb.WriteStorageHistoryIndex(batch, w.state.addressHash, w.state.storageHash, buf)
- }
+ writeStateIndex(w.state, batch, buf)
}
// indexDeleter is responsible for deleting index data for a specific state.
@@ -301,12 +269,7 @@ type indexDeleter struct {
// newIndexDeleter constructs the index deleter for the specified state.
func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter, error) {
- var blob []byte
- if state.account {
- blob = rawdb.ReadAccountHistoryIndex(db, state.addressHash)
- } else {
- blob = rawdb.ReadStorageHistoryIndex(db, state.addressHash, state.storageHash)
- }
+ blob := readStateIndex(state, db)
if len(blob) == 0 {
// TODO(rjl493456442) we can probably return an error here,
// deleter with no data is meaningless.
@@ -323,15 +286,8 @@ func newIndexDeleter(db ethdb.KeyValueReader, state stateIdent) (*indexDeleter,
if err != nil {
return nil, err
}
- var (
- indexBlock []byte
- lastDesc = descList[len(descList)-1]
- )
- if state.account {
- indexBlock = rawdb.ReadAccountHistoryIndexBlock(db, state.addressHash, lastDesc.id)
- } else {
- indexBlock = rawdb.ReadStorageHistoryIndexBlock(db, state.addressHash, state.storageHash, lastDesc.id)
- }
+ lastDesc := descList[len(descList)-1]
+ indexBlock := readStateIndexBlock(state, db, lastDesc.id)
bw, err := newBlockWriter(indexBlock, lastDesc)
if err != nil {
return nil, err
@@ -376,15 +332,8 @@ func (d *indexDeleter) pop(id uint64) error {
d.descList = d.descList[:len(d.descList)-1]
// Open the previous block writer for deleting
- var (
- indexBlock []byte
- lastDesc = d.descList[len(d.descList)-1]
- )
- if d.state.account {
- indexBlock = rawdb.ReadAccountHistoryIndexBlock(d.db, d.state.addressHash, lastDesc.id)
- } else {
- indexBlock = rawdb.ReadStorageHistoryIndexBlock(d.db, d.state.addressHash, d.state.storageHash, lastDesc.id)
- }
+ lastDesc := d.descList[len(d.descList)-1]
+ indexBlock := readStateIndexBlock(d.state, d.db, lastDesc.id)
bw, err := newBlockWriter(indexBlock, lastDesc)
if err != nil {
return err
@@ -399,38 +348,100 @@ func (d *indexDeleter) pop(id uint64) error {
// This function is safe to be called multiple times.
func (d *indexDeleter) finish(batch ethdb.Batch) {
for _, id := range d.dropped {
- if d.state.account {
- rawdb.DeleteAccountHistoryIndexBlock(batch, d.state.addressHash, id)
- } else {
- rawdb.DeleteStorageHistoryIndexBlock(batch, d.state.addressHash, d.state.storageHash, id)
- }
+ deleteStateIndexBlock(d.state, batch, id)
}
d.dropped = nil
// Flush the content of last block writer, regardless it's dirty or not
if !d.bw.empty() {
- if d.state.account {
- rawdb.WriteAccountHistoryIndexBlock(batch, d.state.addressHash, d.bw.desc.id, d.bw.finish())
- } else {
- rawdb.WriteStorageHistoryIndexBlock(batch, d.state.addressHash, d.state.storageHash, d.bw.desc.id, d.bw.finish())
- }
+ writeStateIndexBlock(d.state, batch, d.bw.desc.id, d.bw.finish())
}
// Flush the index metadata into the supplied batch
if d.empty() {
- if d.state.account {
- rawdb.DeleteAccountHistoryIndex(batch, d.state.addressHash)
- } else {
- rawdb.DeleteStorageHistoryIndex(batch, d.state.addressHash, d.state.storageHash)
- }
+ deleteStateIndex(d.state, batch)
} else {
buf := make([]byte, 0, indexBlockDescSize*len(d.descList))
for _, desc := range d.descList {
buf = append(buf, desc.encode()...)
}
- if d.state.account {
- rawdb.WriteAccountHistoryIndex(batch, d.state.addressHash, buf)
- } else {
- rawdb.WriteStorageHistoryIndex(batch, d.state.addressHash, d.state.storageHash, buf)
- }
+ writeStateIndex(d.state, batch, buf)
+ }
+}
+
+// readStateIndex retrieves the index metadata for the given state identifier.
+// This function is shared by accounts and storage slots.
+func readStateIndex(ident stateIdent, db ethdb.KeyValueReader) []byte {
+ switch ident.typ {
+ case typeAccount:
+ return rawdb.ReadAccountHistoryIndex(db, ident.addressHash)
+ case typeStorage:
+ return rawdb.ReadStorageHistoryIndex(db, ident.addressHash, ident.storageHash)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
+ }
+}
+
+// writeStateIndex writes the provided index metadata into database with the
+// given state identifier. This function is shared by accounts and storage slots.
+func writeStateIndex(ident stateIdent, db ethdb.KeyValueWriter, data []byte) {
+ switch ident.typ {
+ case typeAccount:
+ rawdb.WriteAccountHistoryIndex(db, ident.addressHash, data)
+ case typeStorage:
+ rawdb.WriteStorageHistoryIndex(db, ident.addressHash, ident.storageHash, data)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
+ }
+}
+
+// deleteStateIndex removes the index metadata for the given state identifier.
+// This function is shared by accounts and storage slots.
+func deleteStateIndex(ident stateIdent, db ethdb.KeyValueWriter) {
+ switch ident.typ {
+ case typeAccount:
+ rawdb.DeleteAccountHistoryIndex(db, ident.addressHash)
+ case typeStorage:
+ rawdb.DeleteStorageHistoryIndex(db, ident.addressHash, ident.storageHash)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
+ }
+}
+
+// readStateIndexBlock retrieves the index block for the given state identifier
+// and block ID. This function is shared by accounts and storage slots.
+func readStateIndexBlock(ident stateIdent, db ethdb.KeyValueReader, id uint32) []byte {
+ switch ident.typ {
+ case typeAccount:
+ return rawdb.ReadAccountHistoryIndexBlock(db, ident.addressHash, id)
+ case typeStorage:
+ return rawdb.ReadStorageHistoryIndexBlock(db, ident.addressHash, ident.storageHash, id)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
+ }
+}
+
+// writeStateIndexBlock writes the provided index block into database with the
+// given state identifier. This function is shared by accounts and storage slots.
+func writeStateIndexBlock(ident stateIdent, db ethdb.KeyValueWriter, id uint32, data []byte) {
+ switch ident.typ {
+ case typeAccount:
+ rawdb.WriteAccountHistoryIndexBlock(db, ident.addressHash, id, data)
+ case typeStorage:
+ rawdb.WriteStorageHistoryIndexBlock(db, ident.addressHash, ident.storageHash, id, data)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
+ }
+}
+
+// deleteStateIndexBlock removes the index block from database with the given
+// state identifier. This function is shared by accounts and storage slots.
+func deleteStateIndexBlock(ident stateIdent, db ethdb.KeyValueWriter, id uint32) {
+ switch ident.typ {
+ case typeAccount:
+ rawdb.DeleteAccountHistoryIndexBlock(db, ident.addressHash, id)
+ case typeStorage:
+ rawdb.DeleteStorageHistoryIndexBlock(db, ident.addressHash, ident.storageHash, id)
+ default:
+ panic(fmt.Errorf("unknown type: %v", ident.typ))
}
}
diff --git a/triedb/pathdb/history_index_test.go b/triedb/pathdb/history_index_test.go
index c83c33ffbd..be9b7c4049 100644
--- a/triedb/pathdb/history_index_test.go
+++ b/triedb/pathdb/history_index_test.go
@@ -179,7 +179,7 @@ func TestIndexWriterDelete(t *testing.T) {
func TestBatchIndexerWrite(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
- batch = newBatchIndexer(db, false)
+ batch = newBatchIndexer(db, false, typeStateHistory)
histories = makeStateHistories(10)
)
for i, h := range histories {
@@ -190,7 +190,7 @@ func TestBatchIndexerWrite(t *testing.T) {
if err := batch.finish(true); err != nil {
t.Fatalf("Failed to finish batch indexer, %v", err)
}
- metadata := loadIndexMetadata(db)
+ metadata := loadIndexMetadata(db, typeStateHistory)
if metadata == nil || metadata.Last != uint64(10) {
t.Fatal("Unexpected index position")
}
@@ -256,7 +256,7 @@ func TestBatchIndexerWrite(t *testing.T) {
func TestBatchIndexerDelete(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
- bw = newBatchIndexer(db, false)
+ bw = newBatchIndexer(db, false, typeStateHistory)
histories = makeStateHistories(10)
)
// Index histories
@@ -270,7 +270,7 @@ func TestBatchIndexerDelete(t *testing.T) {
}
// Unindex histories
- bd := newBatchIndexer(db, true)
+ bd := newBatchIndexer(db, true, typeStateHistory)
for i := len(histories) - 1; i >= 0; i-- {
if err := bd.process(histories[i], uint64(i+1)); err != nil {
t.Fatalf("Failed to process history, %v", err)
@@ -280,7 +280,7 @@ func TestBatchIndexerDelete(t *testing.T) {
t.Fatalf("Failed to finish batch indexer, %v", err)
}
- metadata := loadIndexMetadata(db)
+ metadata := loadIndexMetadata(db, typeStateHistory)
if metadata != nil {
t.Fatal("Unexpected index position")
}
diff --git a/triedb/pathdb/history_indexer.go b/triedb/pathdb/history_indexer.go
index 14b9af5367..d618585929 100644
--- a/triedb/pathdb/history_indexer.go
+++ b/triedb/pathdb/history_indexer.go
@@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
@@ -41,13 +40,32 @@ const (
stateIndexVersion = stateIndexV0 // the current state index version
)
+// indexVersion returns the latest index version for the given history type.
+// It panics if the history type is unknown.
+func indexVersion(typ historyType) uint8 {
+ switch typ {
+ case typeStateHistory:
+ return stateIndexVersion
+ default:
+ panic(fmt.Errorf("unknown history type: %d", typ))
+ }
+}
+
+// indexMetadata describes the metadata of the historical data index.
type indexMetadata struct {
Version uint8
Last uint64
}
-func loadIndexMetadata(db ethdb.KeyValueReader) *indexMetadata {
- blob := rawdb.ReadStateHistoryIndexMetadata(db)
+// loadIndexMetadata reads the metadata of the specific history index.
+func loadIndexMetadata(db ethdb.KeyValueReader, typ historyType) *indexMetadata {
+ var blob []byte
+ switch typ {
+ case typeStateHistory:
+ blob = rawdb.ReadStateHistoryIndexMetadata(db)
+ default:
+ panic(fmt.Errorf("unknown history type %d", typ))
+ }
if len(blob) == 0 {
return nil
}
@@ -59,91 +77,94 @@ func loadIndexMetadata(db ethdb.KeyValueReader) *indexMetadata {
return &m
}
-func storeIndexMetadata(db ethdb.KeyValueWriter, last uint64) {
- var m indexMetadata
- m.Version = stateIndexVersion
- m.Last = last
+// storeIndexMetadata stores the metadata of the specific history index.
+func storeIndexMetadata(db ethdb.KeyValueWriter, typ historyType, last uint64) {
+ m := indexMetadata{
+ Version: indexVersion(typ),
+ Last: last,
+ }
blob, err := rlp.EncodeToBytes(m)
if err != nil {
- log.Crit("Failed to encode index metadata", "err", err)
+ panic(fmt.Errorf("fail to encode index metadata, %v", err))
+ }
+ switch typ {
+ case typeStateHistory:
+ rawdb.WriteStateHistoryIndexMetadata(db, blob)
+ default:
+ panic(fmt.Errorf("unknown history type %d", typ))
+ }
+ log.Debug("Written index metadata", "type", typ, "last", last)
+}
+
+// deleteIndexMetadata deletes the metadata of the specific history index.
+func deleteIndexMetadata(db ethdb.KeyValueWriter, typ historyType) {
+ switch typ {
+ case typeStateHistory:
+ rawdb.DeleteStateHistoryIndexMetadata(db)
+ default:
+ panic(fmt.Errorf("unknown history type %d", typ))
}
- rawdb.WriteStateHistoryIndexMetadata(db, blob)
+ log.Debug("Deleted index metadata", "type", typ)
}
-// batchIndexer is a structure designed to perform batch indexing or unindexing
-// of state histories atomically.
+// batchIndexer is responsible for performing batch indexing or unindexing
+// of historical data (e.g., state or trie node changes) atomically.
type batchIndexer struct {
- accounts map[common.Hash][]uint64 // History ID list, Keyed by the hash of account address
- storages map[common.Hash]map[common.Hash][]uint64 // History ID list, Keyed by the hash of account address and the hash of raw storage key
- counter int // The counter of processed states
- delete bool // Index or unindex mode
- lastID uint64 // The ID of latest processed history
- db ethdb.KeyValueStore
+ index map[stateIdent][]uint64 // List of history IDs for tracked state entry
+ pending int // Number of entries processed in the current batch.
+ delete bool // Operation mode: true for unindex, false for index.
+ lastID uint64 // ID of the most recently processed history.
+ typ historyType // Type of history being processed (e.g., state or trienode).
+ db ethdb.KeyValueStore // Key-value database used to store or delete index data.
}
// newBatchIndexer constructs the batch indexer with the supplied mode.
-func newBatchIndexer(db ethdb.KeyValueStore, delete bool) *batchIndexer {
+func newBatchIndexer(db ethdb.KeyValueStore, delete bool, typ historyType) *batchIndexer {
return &batchIndexer{
- accounts: make(map[common.Hash][]uint64),
- storages: make(map[common.Hash]map[common.Hash][]uint64),
- delete: delete,
- db: db,
+ index: make(map[stateIdent][]uint64),
+ delete: delete,
+ typ: typ,
+ db: db,
}
}
-// process iterates through the accounts and their associated storage slots in the
-// state history, tracking the mapping between state and history IDs.
-func (b *batchIndexer) process(h *stateHistory, historyID uint64) error {
- for _, address := range h.accountList {
- addrHash := crypto.Keccak256Hash(address.Bytes())
- b.counter += 1
- b.accounts[addrHash] = append(b.accounts[addrHash], historyID)
-
- for _, slotKey := range h.storageList[address] {
- b.counter += 1
- if _, ok := b.storages[addrHash]; !ok {
- b.storages[addrHash] = make(map[common.Hash][]uint64)
- }
- // The hash of the storage slot key is used as the identifier because the
- // legacy history does not include the raw storage key, therefore, the
- // conversion from storage key to hash is necessary for non-v0 histories.
- slotHash := slotKey
- if h.meta.version != stateHistoryV0 {
- slotHash = crypto.Keccak256Hash(slotKey.Bytes())
- }
- b.storages[addrHash][slotHash] = append(b.storages[addrHash][slotHash], historyID)
- }
+// process traverses the state entries within the provided history and tracks the mutation
+// records for them.
+func (b *batchIndexer) process(h history, id uint64) error {
+ for ident := range h.forEach() {
+ b.index[ident] = append(b.index[ident], id)
+ b.pending++
}
- b.lastID = historyID
+ b.lastID = id
+
return b.finish(false)
}
// finish writes the accumulated state indexes into the disk if either the
// memory limitation is reached or it's requested forcibly.
func (b *batchIndexer) finish(force bool) error {
- if b.counter == 0 {
+ if b.pending == 0 {
return nil
}
- if !force && b.counter < historyIndexBatch {
+ if !force && b.pending < historyIndexBatch {
return nil
}
var (
- batch = b.db.NewBatch()
- batchMu sync.RWMutex
- storages int
- start = time.Now()
- eg errgroup.Group
+ batch = b.db.NewBatch()
+ batchMu sync.RWMutex
+ start = time.Now()
+ eg errgroup.Group
)
eg.SetLimit(runtime.NumCPU())
- for addrHash, idList := range b.accounts {
+ for ident, list := range b.index {
eg.Go(func() error {
if !b.delete {
- iw, err := newIndexWriter(b.db, newAccountIdent(addrHash))
+ iw, err := newIndexWriter(b.db, ident)
if err != nil {
return err
}
- for _, n := range idList {
+ for _, n := range list {
if err := iw.append(n); err != nil {
return err
}
@@ -152,11 +173,11 @@ func (b *batchIndexer) finish(force bool) error {
iw.finish(batch)
batchMu.Unlock()
} else {
- id, err := newIndexDeleter(b.db, newAccountIdent(addrHash))
+ id, err := newIndexDeleter(b.db, ident)
if err != nil {
return err
}
- for _, n := range idList {
+ for _, n := range list {
if err := id.pop(n); err != nil {
return err
}
@@ -168,72 +189,36 @@ func (b *batchIndexer) finish(force bool) error {
return nil
})
}
- for addrHash, slots := range b.storages {
- storages += len(slots)
- for storageHash, idList := range slots {
- eg.Go(func() error {
- if !b.delete {
- iw, err := newIndexWriter(b.db, newStorageIdent(addrHash, storageHash))
- if err != nil {
- return err
- }
- for _, n := range idList {
- if err := iw.append(n); err != nil {
- return err
- }
- }
- batchMu.Lock()
- iw.finish(batch)
- batchMu.Unlock()
- } else {
- id, err := newIndexDeleter(b.db, newStorageIdent(addrHash, storageHash))
- if err != nil {
- return err
- }
- for _, n := range idList {
- if err := id.pop(n); err != nil {
- return err
- }
- }
- batchMu.Lock()
- id.finish(batch)
- batchMu.Unlock()
- }
- return nil
- })
- }
- }
if err := eg.Wait(); err != nil {
return err
}
// Update the position of last indexed state history
if !b.delete {
- storeIndexMetadata(batch, b.lastID)
+ storeIndexMetadata(batch, b.typ, b.lastID)
} else {
if b.lastID == 1 {
- rawdb.DeleteStateHistoryIndexMetadata(batch)
+ deleteIndexMetadata(batch, b.typ)
} else {
- storeIndexMetadata(batch, b.lastID-1)
+ storeIndexMetadata(batch, b.typ, b.lastID-1)
}
}
if err := batch.Write(); err != nil {
return err
}
- log.Debug("Committed batch indexer", "accounts", len(b.accounts), "storages", storages, "records", b.counter, "elapsed", common.PrettyDuration(time.Since(start)))
- b.counter = 0
- b.accounts = make(map[common.Hash][]uint64)
- b.storages = make(map[common.Hash]map[common.Hash][]uint64)
+ log.Debug("Committed batch indexer", "type", b.typ, "entries", len(b.index), "records", b.pending, "elapsed", common.PrettyDuration(time.Since(start)))
+ b.pending = 0
+ b.index = make(map[stateIdent][]uint64)
return nil
}
// indexSingle processes the state history with the specified ID for indexing.
-func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader) error {
+func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error {
start := time.Now()
defer func() {
indexHistoryTimer.UpdateSince(start)
}()
- metadata := loadIndexMetadata(db)
+ metadata := loadIndexMetadata(db, typ)
if metadata == nil || metadata.Last+1 != historyID {
last := "null"
if metadata != nil {
@@ -241,29 +226,37 @@ func indexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancient
}
return fmt.Errorf("history indexing is out of order, last: %s, requested: %d", last, historyID)
}
- h, err := readStateHistory(freezer, historyID)
+ var (
+ err error
+ h history
+ b = newBatchIndexer(db, false, typ)
+ )
+ if typ == typeStateHistory {
+ h, err = readStateHistory(freezer, historyID)
+ } else {
+ // h, err = readTrienodeHistory(freezer, historyID)
+ }
if err != nil {
return err
}
- b := newBatchIndexer(db, false)
if err := b.process(h, historyID); err != nil {
return err
}
if err := b.finish(true); err != nil {
return err
}
- log.Debug("Indexed state history", "id", historyID, "elapsed", common.PrettyDuration(time.Since(start)))
+ log.Debug("Indexed history", "type", typ, "id", historyID, "elapsed", common.PrettyDuration(time.Since(start)))
return nil
}
// unindexSingle processes the state history with the specified ID for unindexing.
-func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader) error {
+func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.AncientReader, typ historyType) error {
start := time.Now()
defer func() {
unindexHistoryTimer.UpdateSince(start)
}()
- metadata := loadIndexMetadata(db)
+ metadata := loadIndexMetadata(db, typ)
if metadata == nil || metadata.Last != historyID {
last := "null"
if metadata != nil {
@@ -271,18 +264,26 @@ func unindexSingle(historyID uint64, db ethdb.KeyValueStore, freezer ethdb.Ancie
}
return fmt.Errorf("history unindexing is out of order, last: %s, requested: %d", last, historyID)
}
- h, err := readStateHistory(freezer, historyID)
+ var (
+ err error
+ h history
+ )
+ b := newBatchIndexer(db, true, typ)
+ if typ == typeStateHistory {
+ h, err = readStateHistory(freezer, historyID)
+ } else {
+ // h, err = readTrienodeHistory(freezer, historyID)
+ }
if err != nil {
return err
}
- b := newBatchIndexer(db, true)
if err := b.process(h, historyID); err != nil {
return err
}
if err := b.finish(true); err != nil {
return err
}
- log.Debug("Unindexed state history", "id", historyID, "elapsed", common.PrettyDuration(time.Since(start)))
+ log.Debug("Unindexed history", "type", typ, "id", historyID, "elapsed", common.PrettyDuration(time.Since(start)))
return nil
}
@@ -305,6 +306,8 @@ type indexIniter struct {
interrupt chan *interruptSignal
done chan struct{}
closed chan struct{}
+ typ historyType
+ log log.Logger // Contextual logger with the history type injected
// indexing progress
indexed atomic.Uint64 // the id of latest indexed state
@@ -313,24 +316,33 @@ type indexIniter struct {
wg sync.WaitGroup
}
-func newIndexIniter(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastID uint64) *indexIniter {
+func newIndexIniter(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, typ historyType, lastID uint64) *indexIniter {
initer := &indexIniter{
disk: disk,
freezer: freezer,
interrupt: make(chan *interruptSignal),
done: make(chan struct{}),
closed: make(chan struct{}),
+ typ: typ,
+ log: log.New("type", typ.String()),
}
// Load indexing progress
+ var recover bool
initer.last.Store(lastID)
- metadata := loadIndexMetadata(disk)
+ metadata := loadIndexMetadata(disk, typ)
if metadata != nil {
initer.indexed.Store(metadata.Last)
+ recover = metadata.Last > lastID
}
// Launch background indexer
initer.wg.Add(1)
- go initer.run(lastID)
+ if recover {
+ log.Info("History indexer is recovering", "history", lastID, "indexed", metadata.Last)
+ go initer.recover(lastID)
+ } else {
+ go initer.run(lastID)
+ }
return initer
}
@@ -364,8 +376,8 @@ func (i *indexIniter) remain() uint64 {
default:
last, indexed := i.last.Load(), i.indexed.Load()
if last < indexed {
- log.Error("Invalid state indexing range", "last", last, "indexed", indexed)
- return 0
+ i.log.Warn("State indexer is in recovery", "indexed", indexed, "last", last)
+ return indexed - last
}
return last - indexed
}
@@ -382,7 +394,7 @@ func (i *indexIniter) run(lastID uint64) {
// checkDone indicates whether all requested state histories
// have been fully indexed.
checkDone = func() bool {
- metadata := loadIndexMetadata(i.disk)
+ metadata := loadIndexMetadata(i.disk, i.typ)
return metadata != nil && metadata.Last == lastID
}
)
@@ -404,7 +416,7 @@ func (i *indexIniter) run(lastID uint64) {
if newLastID == lastID+1 {
lastID = newLastID
signal.result <- nil
- log.Debug("Extended state history range", "last", lastID)
+ i.log.Debug("Extended history range", "last", lastID)
continue
}
// The index limit is shortened by one, interrupt the current background
@@ -415,14 +427,14 @@ func (i *indexIniter) run(lastID uint64) {
// If all state histories, including the one to be reverted, have
// been fully indexed, unindex it here and shut down the initializer.
if checkDone() {
- log.Info("Truncate the extra history", "id", lastID)
- if err := unindexSingle(lastID, i.disk, i.freezer); err != nil {
+ i.log.Info("Truncate the extra history", "id", lastID)
+ if err := unindexSingle(lastID, i.disk, i.freezer, i.typ); err != nil {
signal.result <- err
return
}
close(i.done)
signal.result <- nil
- log.Info("State histories have been fully indexed", "last", lastID-1)
+ i.log.Info("Histories have been fully indexed", "last", lastID-1)
return
}
// Adjust the indexing target and relaunch the process
@@ -431,12 +443,12 @@ func (i *indexIniter) run(lastID uint64) {
done, interrupt = make(chan struct{}), new(atomic.Int32)
go i.index(done, interrupt, lastID)
- log.Debug("Shortened state history range", "last", lastID)
+ i.log.Debug("Shortened history range", "last", lastID)
case <-done:
if checkDone() {
close(i.done)
- log.Info("State histories have been fully indexed", "last", lastID)
+ i.log.Info("Histories have been fully indexed", "last", lastID)
return
}
// Relaunch the background runner if some tasks are left
@@ -445,7 +457,7 @@ func (i *indexIniter) run(lastID uint64) {
case <-i.closed:
interrupt.Store(1)
- log.Info("Waiting background history index initer to exit")
+ i.log.Info("Waiting background history index initer to exit")
<-done
if checkDone() {
@@ -465,14 +477,14 @@ func (i *indexIniter) next() (uint64, error) {
tailID := tail + 1 // compute the id of the oldest history
// Start indexing from scratch if nothing has been indexed
- metadata := loadIndexMetadata(i.disk)
+ metadata := loadIndexMetadata(i.disk, i.typ)
if metadata == nil {
- log.Debug("Initialize state history indexing from scratch", "id", tailID)
+ i.log.Debug("Initialize history indexing from scratch", "id", tailID)
return tailID, nil
}
// Resume indexing from the last interrupted position
if metadata.Last+1 >= tailID {
- log.Debug("Resume state history indexing", "id", metadata.Last+1, "tail", tailID)
+ i.log.Debug("Resume history indexing", "id", metadata.Last+1, "tail", tailID)
return metadata.Last + 1, nil
}
// History has been shortened without indexing. Discard the gapped segment
@@ -480,7 +492,7 @@ func (i *indexIniter) next() (uint64, error) {
//
// The missing indexes corresponding to the gapped histories won't be visible.
// It's fine to leave them unindexed.
- log.Info("History gap detected, discard old segment", "oldHead", metadata.Last, "newHead", tailID)
+ i.log.Info("History gap detected, discard old segment", "oldHead", metadata.Last, "newHead", tailID)
return tailID, nil
}
@@ -489,7 +501,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
beginID, err := i.next()
if err != nil {
- log.Error("Failed to find next state history for indexing", "err", err)
+ i.log.Error("Failed to find next history for indexing", "err", err)
return
}
// All available state histories have been indexed, and the last indexed one
@@ -504,36 +516,47 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
//
// This step is essential to avoid spinning up indexing thread
// endlessly until a history object is produced.
- storeIndexMetadata(i.disk, 0)
- log.Info("Initialized history indexing flag")
+ storeIndexMetadata(i.disk, i.typ, 0)
+ i.log.Info("Initialized history indexing flag")
} else {
- log.Debug("State history is fully indexed", "last", lastID)
+ i.log.Debug("History is fully indexed", "last", lastID)
}
return
}
- log.Info("Start history indexing", "beginID", beginID, "lastID", lastID)
+ i.log.Info("Start history indexing", "beginID", beginID, "lastID", lastID)
var (
current = beginID
start = time.Now()
logged = time.Now()
- batch = newBatchIndexer(i.disk, false)
+ batch = newBatchIndexer(i.disk, false, i.typ)
)
for current <= lastID {
count := lastID - current + 1
if count > historyReadBatch {
count = historyReadBatch
}
- histories, err := readStateHistories(i.freezer, current, count)
- if err != nil {
- // The history read might fall if the history is truncated from
- // head due to revert operation.
- log.Error("Failed to read history for indexing", "current", current, "count", count, "err", err)
- return
+ var histories []history
+ if i.typ == typeStateHistory {
+ histories, err = readStateHistories(i.freezer, current, count)
+ if err != nil {
+ // The history read might fall if the history is truncated from
+ // head due to revert operation.
+ i.log.Error("Failed to read history for indexing", "current", current, "count", count, "err", err)
+ return
+ }
+ } else {
+ // histories, err = readTrienodeHistories(i.freezer, current, count)
+ // if err != nil {
+ // // The history read might fall if the history is truncated from
+ // // head due to revert operation.
+ // i.log.Error("Failed to read history for indexing", "current", current, "count", count, "err", err)
+ // return
+ // }
}
for _, h := range histories {
if err := batch.process(h, current); err != nil {
- log.Error("Failed to index history", "err", err)
+ i.log.Error("Failed to index history", "err", err)
return
}
current += 1
@@ -547,7 +570,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
done = current - beginID
)
eta := common.CalculateETA(done, left, time.Since(start))
- log.Info("Indexing state history", "processed", done, "left", left, "elapsed", common.PrettyDuration(time.Since(start)), "eta", common.PrettyDuration(eta))
+ i.log.Info("Indexing state history", "processed", done, "left", left, "elapsed", common.PrettyDuration(time.Since(start)), "eta", common.PrettyDuration(eta))
}
}
i.indexed.Store(current - 1) // update indexing progress
@@ -556,7 +579,7 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
if interrupt != nil {
if signal := interrupt.Load(); signal != 0 {
if err := batch.finish(true); err != nil {
- log.Error("Failed to flush index", "err", err)
+ i.log.Error("Failed to flush index", "err", err)
}
log.Info("State indexing interrupted")
return
@@ -564,9 +587,52 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
}
}
if err := batch.finish(true); err != nil {
- log.Error("Failed to flush index", "err", err)
+ i.log.Error("Failed to flush index", "err", err)
+ }
+ i.log.Info("Indexed history", "from", beginID, "to", lastID, "elapsed", common.PrettyDuration(time.Since(start)))
+}
+
+// recover handles unclean shutdown recovery. After an unclean shutdown, any
+// extra histories are typically truncated, while the corresponding history index
+// entries may still have been written. Ideally, we would unindex these histories
+// in reverse order, but there is no guarantee that the required histories will
+// still be available.
+//
+// As a workaround, indexIniter waits until the missing histories are regenerated
+// by chain recovery, under the assumption that the recovered histories will be
+// identical to the lost ones. Fork-awareness should be added in the future to
+// correctly handle histories affected by reorgs.
+func (i *indexIniter) recover(lastID uint64) {
+ defer i.wg.Done()
+
+ for {
+ select {
+ case signal := <-i.interrupt:
+ newLastID := signal.newLastID
+ if newLastID != lastID+1 && newLastID != lastID-1 {
+ signal.result <- fmt.Errorf("invalid history id, last: %d, got: %d", lastID, newLastID)
+ continue
+ }
+
+ // Update the last indexed flag
+ lastID = newLastID
+ signal.result <- nil
+ i.last.Store(newLastID)
+ i.log.Debug("Updated history index flag", "last", lastID)
+
+ // Terminate the recovery routine once the histories are fully aligned
+ // with the index data, indicating that index initialization is complete.
+ metadata := loadIndexMetadata(i.disk, i.typ)
+ if metadata != nil && metadata.Last == lastID {
+ close(i.done)
+ i.log.Info("History indexer is recovered", "last", lastID)
+ return
+ }
+
+ case <-i.closed:
+ return
+ }
}
- log.Info("Indexed state history", "from", beginID, "to", lastID, "elapsed", common.PrettyDuration(time.Since(start)))
}
// historyIndexer manages the indexing and unindexing of state histories,
@@ -581,21 +647,31 @@ func (i *indexIniter) index(done chan struct{}, interrupt *atomic.Int32, lastID
// state history.
type historyIndexer struct {
initer *indexIniter
+ typ historyType
disk ethdb.KeyValueStore
freezer ethdb.AncientStore
}
// checkVersion checks whether the index data in the database matches the version.
-func checkVersion(disk ethdb.KeyValueStore) {
- blob := rawdb.ReadStateHistoryIndexMetadata(disk)
+func checkVersion(disk ethdb.KeyValueStore, typ historyType) {
+ var blob []byte
+ if typ == typeStateHistory {
+ blob = rawdb.ReadStateHistoryIndexMetadata(disk)
+ } else {
+ panic(fmt.Errorf("unknown history type: %v", typ))
+ }
+ // Short circuit if metadata is not found, re-index is required
+ // from scratch.
if len(blob) == 0 {
return
}
+ // Short circuit if the metadata is found and the version is matched
var m indexMetadata
err := rlp.DecodeBytes(blob, &m)
if err == nil && m.Version == stateIndexVersion {
return
}
+ // Version is not matched, prune the existing data and re-index from scratch
version := "unknown"
if err == nil {
version = fmt.Sprintf("%d", m.Version)
@@ -612,10 +688,11 @@ func checkVersion(disk ethdb.KeyValueStore) {
// newHistoryIndexer constructs the history indexer and launches the background
// initer to complete the indexing of any remaining state histories.
-func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64) *historyIndexer {
- checkVersion(disk)
+func newHistoryIndexer(disk ethdb.KeyValueStore, freezer ethdb.AncientStore, lastHistoryID uint64, typ historyType) *historyIndexer {
+ checkVersion(disk, typ)
return &historyIndexer{
- initer: newIndexIniter(disk, freezer, lastHistoryID),
+ initer: newIndexIniter(disk, freezer, typ, lastHistoryID),
+ typ: typ,
disk: disk,
freezer: freezer,
}
@@ -643,7 +720,7 @@ func (i *historyIndexer) extend(historyID uint64) error {
case <-i.initer.closed:
return errors.New("indexer is closed")
case <-i.initer.done:
- return indexSingle(historyID, i.disk, i.freezer)
+ return indexSingle(historyID, i.disk, i.freezer, i.typ)
case i.initer.interrupt <- signal:
return <-signal.result
}
@@ -660,7 +737,7 @@ func (i *historyIndexer) shorten(historyID uint64) error {
case <-i.initer.closed:
return errors.New("indexer is closed")
case <-i.initer.done:
- return unindexSingle(historyID, i.disk, i.freezer)
+ return unindexSingle(historyID, i.disk, i.freezer, i.typ)
case i.initer.interrupt <- signal:
return <-signal.result
}
diff --git a/triedb/pathdb/history_indexer_test.go b/triedb/pathdb/history_indexer_test.go
index 96c87ccb1b..f333d18d8b 100644
--- a/triedb/pathdb/history_indexer_test.go
+++ b/triedb/pathdb/history_indexer_test.go
@@ -38,7 +38,7 @@ func TestHistoryIndexerShortenDeadlock(t *testing.T) {
rawdb.WriteStateHistory(freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData)
}
// As a workaround, assign a future block to keep the initer running indefinitely
- indexer := newHistoryIndexer(db, freezer, 200)
+ indexer := newHistoryIndexer(db, freezer, 200, typeStateHistory)
defer indexer.close()
done := make(chan error, 1)
diff --git a/triedb/pathdb/history_reader.go b/triedb/pathdb/history_reader.go
index a11297b3f6..ce6aa693d1 100644
--- a/triedb/pathdb/history_reader.go
+++ b/triedb/pathdb/history_reader.go
@@ -29,88 +29,6 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
)
-// stateIdent represents the identifier of a state element, which can be
-// either an account or a storage slot.
-type stateIdent struct {
- account bool
-
- // The hash of the account address. This is used instead of the raw account
- // address is to align the traversal order with the Merkle-Patricia-Trie.
- addressHash common.Hash
-
- // The hash of the storage slot key. This is used instead of the raw slot key
- // because, in legacy state histories (prior to the Cancun fork), the slot
- // identifier is the hash of the key, and the original key (preimage) cannot
- // be recovered. To maintain backward compatibility, the key hash is used.
- //
- // Meanwhile, using the storage key hash also preserve the traversal order
- // with Merkle-Patricia-Trie.
- //
- // This field is null if the identifier refers to account data.
- storageHash common.Hash
-}
-
-// String returns the string format state identifier.
-func (ident stateIdent) String() string {
- if ident.account {
- return ident.addressHash.Hex()
- }
- return ident.addressHash.Hex() + ident.storageHash.Hex()
-}
-
-// newAccountIdent constructs a state identifier for an account.
-func newAccountIdent(addressHash common.Hash) stateIdent {
- return stateIdent{
- account: true,
- addressHash: addressHash,
- }
-}
-
-// newStorageIdent constructs a state identifier for a storage slot.
-// The address denotes the address of the associated account;
-// the storageHash denotes the hash of the raw storage slot key;
-func newStorageIdent(addressHash common.Hash, storageHash common.Hash) stateIdent {
- return stateIdent{
- addressHash: addressHash,
- storageHash: storageHash,
- }
-}
-
-// stateIdentQuery is the extension of stateIdent by adding the raw storage key.
-type stateIdentQuery struct {
- stateIdent
-
- address common.Address
- storageKey common.Hash
-}
-
-// newAccountIdentQuery constructs a state identifier for an account.
-func newAccountIdentQuery(address common.Address, addressHash common.Hash) stateIdentQuery {
- return stateIdentQuery{
- stateIdent: stateIdent{
- account: true,
- addressHash: addressHash,
- },
- address: address,
- }
-}
-
-// newStorageIdentQuery constructs a state identifier for a storage slot.
-// the address denotes the address of the associated account;
-// the addressHash denotes the address hash of the associated account;
-// the storageKey denotes the raw storage slot key;
-// the storageHash denotes the hash of the raw storage slot key;
-func newStorageIdentQuery(address common.Address, addressHash common.Hash, storageKey common.Hash, storageHash common.Hash) stateIdentQuery {
- return stateIdentQuery{
- stateIdent: stateIdent{
- addressHash: addressHash,
- storageHash: storageHash,
- },
- address: address,
- storageKey: storageKey,
- }
-}
-
// indexReaderWithLimitTag is a wrapper around indexReader that includes an
// additional index position. This position represents the ID of the last
// indexed state history at the time the reader was created, implying that
@@ -169,7 +87,7 @@ func (r *indexReaderWithLimitTag) readGreaterThan(id uint64, lastID uint64) (uin
// Given that it's very unlikely to occur and users try to perform historical
// state queries while reverting the states at the same time. Simply returning
// an error should be sufficient for now.
- metadata := loadIndexMetadata(r.db)
+ metadata := loadIndexMetadata(r.db, toHistoryType(r.reader.state.typ))
if metadata == nil || metadata.Last < lastID {
return 0, errors.New("state history hasn't been indexed yet")
}
@@ -331,7 +249,7 @@ func (r *historyReader) read(state stateIdentQuery, stateID uint64, lastID uint6
// To serve the request, all state histories from stateID+1 to lastID
// must be indexed. It's not supposed to happen unless system is very
// wrong.
- metadata := loadIndexMetadata(r.disk)
+ metadata := loadIndexMetadata(r.disk, toHistoryType(state.typ))
if metadata == nil || metadata.Last < lastID {
indexed := "null"
if metadata != nil {
@@ -364,7 +282,7 @@ func (r *historyReader) read(state stateIdentQuery, stateID uint64, lastID uint6
// that the associated state histories are no longer available due to a rollback.
// Such truncation should be captured by the state resolver below, rather than returning
// invalid data.
- if state.account {
+ if state.typ == typeAccount {
return r.readAccount(state.address, historyID)
}
return r.readStorage(state.address, state.storageKey, state.storageHash, historyID)
diff --git a/triedb/pathdb/history_reader_test.go b/triedb/pathdb/history_reader_test.go
index 9028a886ce..3e1a545ff3 100644
--- a/triedb/pathdb/history_reader_test.go
+++ b/triedb/pathdb/history_reader_test.go
@@ -29,7 +29,7 @@ import (
func waitIndexing(db *Database) {
for {
- metadata := loadIndexMetadata(db.diskdb)
+ metadata := loadIndexMetadata(db.diskdb, typeStateHistory)
if metadata != nil && metadata.Last >= db.tree.bottom().stateID() {
return
}
@@ -144,8 +144,13 @@ func testHistoryReader(t *testing.T, historyLimit uint64) {
maxDiffLayers = 128
}()
- // log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
- env := newTester(t, historyLimit, false, 64, true, "")
+ //log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
+ config := &testerConfig{
+ stateHistory: historyLimit,
+ layers: 64,
+ enableIndex: true,
+ }
+ env := newTester(t, config)
defer env.release()
waitIndexing(env.db)
@@ -184,7 +189,12 @@ func TestHistoricalStateReader(t *testing.T) {
}()
//log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
- env := newTester(t, 0, false, 64, true, "")
+ config := &testerConfig{
+ stateHistory: 0,
+ layers: 64,
+ enableIndex: true,
+ }
+ env := newTester(t, config)
defer env.release()
waitIndexing(env.db)
diff --git a/triedb/pathdb/history_state.go b/triedb/pathdb/history_state.go
index 3bb69a7f4d..9d1e4dfb09 100644
--- a/triedb/pathdb/history_state.go
+++ b/triedb/pathdb/history_state.go
@@ -21,6 +21,7 @@ import (
"encoding/binary"
"errors"
"fmt"
+ "iter"
"maps"
"slices"
"time"
@@ -275,6 +276,36 @@ func newStateHistory(root common.Hash, parent common.Hash, block uint64, account
}
}
+// typ implements the history interface, returning the historical data type held.
+func (h *stateHistory) typ() historyType {
+ return typeStateHistory
+}
+
+// forEach implements the history interface, returning an iterator to traverse the
+// state entries in the history.
+func (h *stateHistory) forEach() iter.Seq[stateIdent] {
+ return func(yield func(stateIdent) bool) {
+ for _, addr := range h.accountList {
+ addrHash := crypto.Keccak256Hash(addr.Bytes())
+ if !yield(newAccountIdent(addrHash)) {
+ return
+ }
+ for _, slotKey := range h.storageList[addr] {
+ // The hash of the storage slot key is used as the identifier because the
+ // legacy history does not include the raw storage key, therefore, the
+ // conversion from storage key to hash is necessary for non-v0 histories.
+ slotHash := slotKey
+ if h.meta.version != stateHistoryV0 {
+ slotHash = crypto.Keccak256Hash(slotKey.Bytes())
+ }
+ if !yield(newStorageIdent(addrHash, slotHash)) {
+ return
+ }
+ }
+ }
+ }
+}
+
// stateSet returns the state set, keyed by the hash of the account address
// and the hash of the storage slot key.
func (h *stateHistory) stateSet() (map[common.Hash][]byte, map[common.Hash]map[common.Hash][]byte) {
@@ -536,8 +567,8 @@ func readStateHistory(reader ethdb.AncientReader, id uint64) (*stateHistory, err
}
// readStateHistories reads a list of state history records within the specified range.
-func readStateHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]*stateHistory, error) {
- var histories []*stateHistory
+func readStateHistories(freezer ethdb.AncientReader, start uint64, count uint64) ([]history, error) {
+ var histories []history
metaList, aIndexList, sIndexList, aDataList, sDataList, err := rawdb.ReadStateHistoryList(freezer, start, count)
if err != nil {
return nil, err
diff --git a/triedb/pathdb/history_state_test.go b/triedb/pathdb/history_state_test.go
index 4a777111ea..5718081566 100644
--- a/triedb/pathdb/history_state_test.go
+++ b/triedb/pathdb/history_state_test.go
@@ -137,7 +137,7 @@ func TestTruncateHeadStateHistory(t *testing.T) {
rawdb.WriteStateHistory(freezer, uint64(i+1), hs[i].meta.encode(), accountIndex, storageIndex, accountData, storageData)
}
for size := len(hs); size > 0; size-- {
- pruned, err := truncateFromHead(freezer, uint64(size-1))
+ pruned, err := truncateFromHead(freezer, typeStateHistory, uint64(size-1))
if err != nil {
t.Fatalf("Failed to truncate from head %v", err)
}
@@ -161,7 +161,7 @@ func TestTruncateTailStateHistory(t *testing.T) {
rawdb.WriteStateHistory(freezer, uint64(i+1), hs[i].meta.encode(), accountIndex, storageIndex, accountData, storageData)
}
for newTail := 1; newTail < len(hs); newTail++ {
- pruned, _ := truncateFromTail(freezer, uint64(newTail))
+ pruned, _ := truncateFromTail(freezer, typeStateHistory, uint64(newTail))
if pruned != 1 {
t.Error("Unexpected pruned items", "want", 1, "got", pruned)
}
@@ -209,7 +209,7 @@ func TestTruncateTailStateHistories(t *testing.T) {
accountData, storageData, accountIndex, storageIndex := hs[i].encode()
rawdb.WriteStateHistory(freezer, uint64(i+1), hs[i].meta.encode(), accountIndex, storageIndex, accountData, storageData)
}
- pruned, _ := truncateFromTail(freezer, uint64(10)-c.limit)
+ pruned, _ := truncateFromTail(freezer, typeStateHistory, uint64(10)-c.limit)
if pruned != c.expPruned {
t.Error("Unexpected pruned items", "want", c.expPruned, "got", pruned)
}
@@ -233,7 +233,7 @@ func TestTruncateOutOfRange(t *testing.T) {
accountData, storageData, accountIndex, storageIndex := hs[i].encode()
rawdb.WriteStateHistory(freezer, uint64(i+1), hs[i].meta.encode(), accountIndex, storageIndex, accountData, storageData)
}
- truncateFromTail(freezer, uint64(len(hs)/2))
+ truncateFromTail(freezer, typeStateHistory, uint64(len(hs)/2))
// Ensure of-out-range truncations are rejected correctly.
head, _ := freezer.Ancients()
@@ -254,9 +254,9 @@ func TestTruncateOutOfRange(t *testing.T) {
for _, c := range cases {
var gotErr error
if c.mode == 0 {
- _, gotErr = truncateFromHead(freezer, c.target)
+ _, gotErr = truncateFromHead(freezer, typeStateHistory, c.target)
} else {
- _, gotErr = truncateFromTail(freezer, c.target)
+ _, gotErr = truncateFromTail(freezer, typeStateHistory, c.target)
}
if !errors.Is(gotErr, c.expErr) {
t.Errorf("Unexpected error, want: %v, got: %v", c.expErr, gotErr)
diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go
index 47a632fd37..02bdef5d34 100644
--- a/triedb/pathdb/journal.go
+++ b/triedb/pathdb/journal.go
@@ -229,7 +229,7 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) {
return nil, fmt.Errorf("load block number: %v", err)
}
// Read in-memory trie nodes from journal
- var nodes nodeSet
+ var nodes nodeSetWithOrigin
if err := nodes.decode(r); err != nil {
return nil, err
}
@@ -267,7 +267,7 @@ func (dl *diskLayer) journal(w io.Writer) error {
if err := dl.buffer.states.encode(w); err != nil {
return err
}
- log.Debug("Journaled pathdb disk layer", "root", dl.root)
+ log.Debug("Journaled pathdb disk layer", "root", dl.root, "id", dl.id)
return nil
}
diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go
index b2f3f7f37d..ec45257db5 100644
--- a/triedb/pathdb/layertree.go
+++ b/triedb/pathdb/layertree.go
@@ -22,7 +22,6 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/trie/trienode"
)
// layerTree is a group of state layers identified by the state root.
@@ -142,7 +141,7 @@ func (tree *layerTree) len() int {
}
// add inserts a new layer into the tree if it can be linked to an existing old parent.
-func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *trienode.MergedNodeSet, states *StateSetWithOrigin) error {
+func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint64, nodes *nodeSetWithOrigin, states *StateSetWithOrigin) error {
// Reject noop updates to avoid self-loops. This is a special case that can
// happen for clique networks and proof-of-stake networks where empty blocks
// don't modify the state (0 block subsidy).
@@ -156,7 +155,7 @@ func (tree *layerTree) add(root common.Hash, parentRoot common.Hash, block uint6
if parent == nil {
return fmt.Errorf("triedb parent [%#x] layer missing", parentRoot)
}
- l := parent.update(root, parent.stateID()+1, block, newNodeSet(nodes.Flatten()), states)
+ l := parent.update(root, parent.stateID()+1, block, nodes, states)
tree.lock.Lock()
defer tree.lock.Unlock()
diff --git a/triedb/pathdb/layertree_test.go b/triedb/pathdb/layertree_test.go
index a76d60ba5b..a74c6eb045 100644
--- a/triedb/pathdb/layertree_test.go
+++ b/triedb/pathdb/layertree_test.go
@@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/trie/trienode"
)
func newTestLayerTree() *layerTree {
@@ -45,9 +44,9 @@ func TestLayerCap(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -66,9 +65,9 @@ func TestLayerCap(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -86,9 +85,9 @@ func TestLayerCap(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -106,12 +105,12 @@ func TestLayerCap(t *testing.T) {
// ->C2'->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -131,12 +130,12 @@ func TestLayerCap(t *testing.T) {
// ->C2'->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -155,11 +154,11 @@ func TestLayerCap(t *testing.T) {
// ->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
// Chain:
@@ -213,8 +212,8 @@ func TestBaseLayer(t *testing.T) {
// C1->C2->C3 (HEAD)
{
func() {
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
},
common.Hash{0x1},
},
@@ -230,9 +229,9 @@ func TestBaseLayer(t *testing.T) {
// C4->C5->C6 (HEAD)
{
func() {
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x5}, common.Hash{0x4}, 4, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x6}, common.Hash{0x5}, 5, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x5}, common.Hash{0x4}, 4, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x6}, common.Hash{0x5}, 5, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
tr.cap(common.Hash{0x6}, 2)
},
common.Hash{0x4},
@@ -258,7 +257,7 @@ func TestDescendant(t *testing.T) {
// C1->C2 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -269,7 +268,7 @@ func TestDescendant(t *testing.T) {
// Chain:
// C1->C2->C3 (HEAD)
op: func(tr *layerTree) {
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
},
snapshotB: map[common.Hash]map[common.Hash]struct{}{
common.Hash{0x1}: {
@@ -286,9 +285,9 @@ func TestDescendant(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -325,9 +324,9 @@ func TestDescendant(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -360,9 +359,9 @@ func TestDescendant(t *testing.T) {
// C1->C2->C3->C4 (HEAD)
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -392,12 +391,12 @@ func TestDescendant(t *testing.T) {
// ->C2'->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -445,12 +444,12 @@ func TestDescendant(t *testing.T) {
// ->C2'->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2a}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2a}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2b}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2b}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -494,11 +493,11 @@ func TestDescendant(t *testing.T) {
// ->C3'->C4'
init: func() *layerTree {
tr := newTestLayerTree()
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
- tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, trienode.NewMergedNodeSet(), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3a}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4a}, common.Hash{0x3a}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x3b}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
+ tr.add(common.Hash{0x4b}, common.Hash{0x3b}, 3, NewNodeSetWithOrigin(nil, nil), NewStateSetWithOrigin(nil, nil, nil, nil, false))
return tr
},
snapshotA: map[common.Hash]map[common.Hash]struct{}{
@@ -580,11 +579,11 @@ func TestAccountLookup(t *testing.T) {
// Chain:
// C1->C2->C3->C4 (HEAD)
tr := newTestLayerTree() // base = 0x1
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xa"), nil, nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xb"), nil, nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xa", "0xc"), nil, nil, nil, false))
var cases = []struct {
@@ -734,11 +733,11 @@ func TestStorageLookup(t *testing.T) {
// Chain:
// C1->C2->C3->C4 (HEAD)
tr := newTestLayerTree() // base = 0x1
- tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x2}, common.Hash{0x1}, 1, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x1"}}, nil), nil, nil, false))
- tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x2"}}, nil), nil, nil, false))
- tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, trienode.NewMergedNodeSet(),
+ tr.add(common.Hash{0x4}, common.Hash{0x3}, 3, NewNodeSetWithOrigin(nil, nil),
NewStateSetWithOrigin(randomAccountSet("0xa"), randomStorageSet([]string{"0xa"}, [][]string{{"0x1", "0x3"}}, nil), nil, nil, false))
var cases = []struct {
diff --git a/triedb/pathdb/nodes.go b/triedb/pathdb/nodes.go
index f90bd0f01c..c6f9e7aece 100644
--- a/triedb/pathdb/nodes.go
+++ b/triedb/pathdb/nodes.go
@@ -18,6 +18,7 @@ package pathdb
import (
"bytes"
+ "errors"
"fmt"
"io"
"maps"
@@ -301,3 +302,125 @@ func (s *nodeSet) dbsize() int {
}
return m + int(s.size)
}
+
+// nodeSetWithOrigin wraps the node set with additional original values of the
+// mutated trie nodes.
+type nodeSetWithOrigin struct {
+ *nodeSet
+
+ // nodeOrigin represents the trie nodes before the state transition. It's keyed
+ // by the account address hash and node path. The nil value means the trie node
+ // was not present.
+ nodeOrigin map[common.Hash]map[string][]byte
+
+ // memory size of the state data (accountNodeOrigin and storageNodeOrigin)
+ size uint64
+}
+
+// NewNodeSetWithOrigin constructs the state set with the provided data.
+func NewNodeSetWithOrigin(nodes map[common.Hash]map[string]*trienode.Node, origins map[common.Hash]map[string][]byte) *nodeSetWithOrigin {
+ // Don't panic for the lazy callers, initialize the nil maps instead.
+ if origins == nil {
+ origins = make(map[common.Hash]map[string][]byte)
+ }
+ set := &nodeSetWithOrigin{
+ nodeSet: newNodeSet(nodes),
+ nodeOrigin: origins,
+ }
+ set.computeSize()
+ return set
+}
+
+// computeSize calculates the database size of the held trie nodes.
+func (s *nodeSetWithOrigin) computeSize() {
+ var size int
+ for owner, slots := range s.nodeOrigin {
+ prefixLen := common.HashLength
+ if owner == (common.Hash{}) {
+ prefixLen = 0
+ }
+ for path, data := range slots {
+ size += prefixLen + len(path) + len(data)
+ }
+ }
+ s.size = s.nodeSet.size + uint64(size)
+}
+
+// encode serializes the content of node set into the provided writer.
+func (s *nodeSetWithOrigin) encode(w io.Writer) error {
+ // Encode node set
+ if err := s.nodeSet.encode(w); err != nil {
+ return err
+ }
+ // Short circuit if the origins are not tracked
+ if len(s.nodeOrigin) == 0 {
+ return nil
+ }
+
+ // Encode node origins
+ nodes := make([]journalNodes, 0, len(s.nodeOrigin))
+ for owner, subset := range s.nodeOrigin {
+ entry := journalNodes{
+ Owner: owner,
+ Nodes: make([]journalNode, 0, len(subset)),
+ }
+ for path, node := range subset {
+ entry.Nodes = append(entry.Nodes, journalNode{
+ Path: []byte(path),
+ Blob: node,
+ })
+ }
+ nodes = append(nodes, entry)
+ }
+ return rlp.Encode(w, nodes)
+}
+
+// hasOrigin returns whether the origin data set exists in the rlp stream.
+// It's a workaround for backward compatibility.
+func (s *nodeSetWithOrigin) hasOrigin(r *rlp.Stream) (bool, error) {
+ kind, _, err := r.Kind()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return false, nil
+ }
+ return false, err
+ }
+ // If the type of next element in the RLP stream is:
+ // - `rlp.List`: represents the original value of trienodes;
+ // - others, like `boolean`: represent a field in the following state data set;
+ return kind == rlp.List, nil
+}
+
+// decode deserializes the content from the rlp stream into the node set.
+func (s *nodeSetWithOrigin) decode(r *rlp.Stream) error {
+ if s.nodeSet == nil {
+ s.nodeSet = &nodeSet{}
+ }
+ if err := s.nodeSet.decode(r); err != nil {
+ return err
+ }
+
+ // Decode node origins
+ s.nodeOrigin = make(map[common.Hash]map[string][]byte)
+ if hasOrigin, err := s.hasOrigin(r); err != nil {
+ return err
+ } else if hasOrigin {
+ var encoded []journalNodes
+ if err := r.Decode(&encoded); err != nil {
+ return fmt.Errorf("load nodes: %v", err)
+ }
+ for _, entry := range encoded {
+ subset := make(map[string][]byte, len(entry.Nodes))
+ for _, n := range entry.Nodes {
+ if len(n.Blob) > 0 {
+ subset[string(n.Path)] = n.Blob
+ } else {
+ subset[string(n.Path)] = nil
+ }
+ }
+ s.nodeOrigin[entry.Owner] = subset
+ }
+ }
+ s.computeSize()
+ return nil
+}
diff --git a/triedb/pathdb/nodes_test.go b/triedb/pathdb/nodes_test.go
new file mode 100644
index 0000000000..483dc4b1a6
--- /dev/null
+++ b/triedb/pathdb/nodes_test.go
@@ -0,0 +1,128 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package pathdb
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+)
+
+func TestNodeSetEncode(t *testing.T) {
+ nodes := make(map[common.Hash]map[string]*trienode.Node)
+ nodes[common.Hash{}] = map[string]*trienode.Node{
+ "": trienode.New(crypto.Keccak256Hash([]byte{0x0}), []byte{0x0}),
+ "1": trienode.New(crypto.Keccak256Hash([]byte{0x1}), []byte{0x1}),
+ "2": trienode.New(crypto.Keccak256Hash([]byte{0x2}), []byte{0x2}),
+ }
+ nodes[common.Hash{0x1}] = map[string]*trienode.Node{
+ "": trienode.New(crypto.Keccak256Hash([]byte{0x0}), []byte{0x0}),
+ "1": trienode.New(crypto.Keccak256Hash([]byte{0x1}), []byte{0x1}),
+ "2": trienode.New(crypto.Keccak256Hash([]byte{0x2}), []byte{0x2}),
+ }
+ s := newNodeSet(nodes)
+
+ buf := bytes.NewBuffer(nil)
+ if err := s.encode(buf); err != nil {
+ t.Fatalf("Failed to encode states, %v", err)
+ }
+ var dec nodeSet
+ if err := dec.decode(rlp.NewStream(buf, 0)); err != nil {
+ t.Fatalf("Failed to decode states, %v", err)
+ }
+ if !reflect.DeepEqual(s.accountNodes, dec.accountNodes) {
+ t.Fatal("Unexpected account data")
+ }
+ if !reflect.DeepEqual(s.storageNodes, dec.storageNodes) {
+ t.Fatal("Unexpected storage data")
+ }
+}
+
+func TestNodeSetWithOriginEncode(t *testing.T) {
+ nodes := make(map[common.Hash]map[string]*trienode.Node)
+ nodes[common.Hash{}] = map[string]*trienode.Node{
+ "": trienode.New(crypto.Keccak256Hash([]byte{0x0}), []byte{0x0}),
+ "1": trienode.New(crypto.Keccak256Hash([]byte{0x1}), []byte{0x1}),
+ "2": trienode.New(crypto.Keccak256Hash([]byte{0x2}), []byte{0x2}),
+ }
+ nodes[common.Hash{0x1}] = map[string]*trienode.Node{
+ "": trienode.New(crypto.Keccak256Hash([]byte{0x0}), []byte{0x0}),
+ "1": trienode.New(crypto.Keccak256Hash([]byte{0x1}), []byte{0x1}),
+ "2": trienode.New(crypto.Keccak256Hash([]byte{0x2}), []byte{0x2}),
+ }
+ origins := make(map[common.Hash]map[string][]byte)
+ origins[common.Hash{}] = map[string][]byte{
+ "": nil,
+ "1": {0x1},
+ "2": {0x2},
+ }
+ origins[common.Hash{0x1}] = map[string][]byte{
+ "": nil,
+ "1": {0x1},
+ "2": {0x2},
+ }
+
+ // Encode with origin set
+ s := NewNodeSetWithOrigin(nodes, origins)
+
+ buf := bytes.NewBuffer(nil)
+ if err := s.encode(buf); err != nil {
+ t.Fatalf("Failed to encode states, %v", err)
+ }
+ var dec nodeSetWithOrigin
+ if err := dec.decode(rlp.NewStream(buf, 0)); err != nil {
+ t.Fatalf("Failed to decode states, %v", err)
+ }
+ if !reflect.DeepEqual(s.accountNodes, dec.accountNodes) {
+ t.Fatal("Unexpected account data")
+ }
+ if !reflect.DeepEqual(s.storageNodes, dec.storageNodes) {
+ t.Fatal("Unexpected storage data")
+ }
+ if !reflect.DeepEqual(s.nodeOrigin, dec.nodeOrigin) {
+ t.Fatal("Unexpected node origin data")
+ }
+
+ // Encode without origin set
+ s = NewNodeSetWithOrigin(nodes, nil)
+
+ buf = bytes.NewBuffer(nil)
+ if err := s.encode(buf); err != nil {
+ t.Fatalf("Failed to encode states, %v", err)
+ }
+ var dec2 nodeSetWithOrigin
+ if err := dec2.decode(rlp.NewStream(buf, 0)); err != nil {
+ t.Fatalf("Failed to decode states, %v", err)
+ }
+ if !reflect.DeepEqual(s.accountNodes, dec2.accountNodes) {
+ t.Fatal("Unexpected account data")
+ }
+ if !reflect.DeepEqual(s.storageNodes, dec2.storageNodes) {
+ t.Fatal("Unexpected storage data")
+ }
+ if len(dec2.nodeOrigin) != 0 {
+ t.Fatal("unexpected node origin data")
+ }
+ if dec2.size != s.size {
+ t.Fatalf("Unexpected data size, got: %d, want: %d", dec2.size, s.size)
+ }
+}
diff --git a/version/version.go b/version/version.go
index 7fe1ba967d..c04d98cb8f 100644
--- a/version/version.go
+++ b/version/version.go
@@ -25,7 +25,7 @@ import (
const (
Major = 1 // Major version component of the current release
Minor = 16 // Minor version component of the current release
- Patch = 3 // Patch version component of the current release
+ Patch = 4 // Patch version component of the current release
Meta = "stable" // Version metadata to append to the version string
)